]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
Better fix for loop unrolling problem.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
6467930b 2 Copyright (C) 1989, 92-95, 1996 Free Software Foundation, Inc.
8d2733ca
MS
3 Contributed by Michael Tiemann <tiemann@cygnus.com>
4 Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
5 initial re-implementation courtesy Tad Hunt.
8d08fdba
MS
6
7This file is part of GNU CC.
8
9GNU CC is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2, or (at your option)
12any later version.
13
14GNU CC is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with GNU CC; see the file COPYING. If not, write to
e9fa0c7c
RK
21the Free Software Foundation, 59 Temple Place - Suite 330,
22Boston, MA 02111-1307, USA. */
8d08fdba
MS
23
24
8d08fdba 25#include "config.h"
da20811c 26#include <stdio.h>
8d08fdba
MS
27#include "tree.h"
28#include "rtl.h"
29#include "cp-tree.h"
30#include "flags.h"
8d2733ca
MS
31#include "obstack.h"
32#include "expr.h"
21451173 33#include "output.h"
6467930b
MS
34#include "except.h"
35#include "function.h"
0021b564 36#include "defaults.h"
8d08fdba 37
f30432d7 38rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
a3b49ccd 39
eb66be0e 40/* Holds the fndecl for __builtin_return_address. */
8d2733ca 41tree builtin_return_address_fndecl;
8d2733ca
MS
42
43/* A couple of backend routines from m88k.c */
44
49c249e1
JM
45static void easy_expand_asm PROTO((char *));
46static void push_eh_cleanup PROTO((void));
47static void do_unwind PROTO((rtx));
48static rtx do_function_call PROTO((tree, tree, tree));
49static tree build_eh_type_type PROTO((tree));
50static tree build_eh_type PROTO((tree));
51static void expand_end_eh_spec PROTO((tree));
8d2733ca 52
8d2733ca
MS
53static void
54easy_expand_asm (str)
55 char *str;
56{
57 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
58}
59
8d08fdba 60
8d2733ca 61#if 0
e92cc029 62/* This is the startup, and finish stuff per exception table. */
8d08fdba 63
8d2733ca
MS
64/* XXX - Tad: exception handling section */
65#ifndef EXCEPT_SECTION_ASM_OP
66#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
67#endif
8d08fdba 68
8d2733ca
MS
69#ifdef EXCEPT_SECTION_ASM_OP
70typedef struct {
6467930b
MS
71 void *start_region;
72 void *end_region;
8d2733ca
MS
73 void *exception_handler;
74 } exception_table;
75#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 76
8d2733ca 77#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 78
8d2733ca
MS
79 /* on machines which support it, the exception table lives in another section,
80 but it needs a label so we can reference it... This sets up that
81 label! */
82asm (EXCEPT_SECTION_ASM_OP);
83exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
84asm (TEXT_SECTION_ASM_OP);
8d08fdba 85
8d2733ca 86#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 87
8d2733ca
MS
88#ifdef EXCEPT_SECTION_ASM_OP
89
90 /* we need to know where the end of the exception table is... so this
91 is how we do it! */
92
93asm (EXCEPT_SECTION_ASM_OP);
94exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
95asm (TEXT_SECTION_ASM_OP);
96
97#endif /* EXCEPT_SECTION_ASM_OP */
98
99#endif
8d08fdba 100
8d2733ca 101#include "decl.h"
8d2733ca
MS
102#include "insn-flags.h"
103#include "obstack.h"
8d2733ca
MS
104
105/* ======================================================================
106 Briefly the algorithm works like this:
107
108 When a constructor or start of a try block is encountered,
109 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
110 new entry in the unwind protection stack and returns a label to
111 output to start the protection for that block.
112
113 When a destructor or end try block is encountered, pop_eh_entry
6467930b
MS
114 (&eh_stack) is called. Pop_eh_entry () returns the eh_entry it
115 created when push_eh_entry () was called. The eh_entry structure
8d2733ca
MS
116 contains three things at this point. The start protect label,
117 the end protect label, and the exception handler label. The end
118 protect label should be output before the call to the destructor
119 (if any). If it was a destructor, then its parse tree is stored
6467930b 120 in the finalization variable in the eh_entry structure. Otherwise
8d2733ca 121 the finalization variable is set to NULL to reflect the fact that
6467930b 122 is the the end of a try block. Next, this modified eh_entry node
8d2733ca
MS
123 is enqueued in the finalizations queue by calling
124 enqueue_eh_entry (&queue,entry).
125
126 +---------------------------------------------------------------+
127 |XXX: Will need modification to deal with partially |
128 | constructed arrays of objects |
129 | |
130 | Basically, this consists of keeping track of how many |
131 | of the objects have been constructed already (this |
132 | should be in a register though, so that shouldn't be a |
133 | problem. |
134 +---------------------------------------------------------------+
135
136 When a catch block is encountered, there is a lot of work to be
137 done.
138
139 Since we don't want to generate the catch block inline with the
140 regular flow of the function, we need to have some way of doing
f30432d7
MS
141 so. Luckily, we can use sequences to defer the catch sections.
142 When the start of a catch block is encountered, we start the
143 sequence. After the catch block is generated, we end the
144 sequence.
145
8d2733ca
MS
146 Next we must insure that when the catch block is executed, all
147 finalizations for the matching try block have been completed. If
148 any of those finalizations throw an exception, we must call
149 terminate according to the ARM (section r.15.6.1). What this
150 means is that we need to dequeue and emit finalizations for each
6467930b 151 entry in the eh_queue until we get to an entry with a NULL
8d2733ca
MS
152 finalization field. For any of the finalization entries, if it
153 is not a call to terminate (), we must protect it by giving it
154 another start label, end label, and exception handler label,
155 setting its finalization tree to be a call to terminate (), and
6467930b 156 enqueue'ing this new eh_entry to be output at an outer level.
8d2733ca
MS
157 Finally, after all that is done, we can get around to outputting
158 the catch block which basically wraps all the "catch (...) {...}"
159 statements in a big if/then/else construct that matches the
160 correct block to call.
161
162 ===================================================================== */
163
8d2733ca
MS
164/* local globals for function calls
165 ====================================================================== */
166
fb98cff6
JM
167/* Used to cache "terminate" and "__throw_type_match*". */
168static tree Terminate, CatchMatch;
8d2733ca 169
eb66be0e 170/* Used to cache __find_first_exception_table_match for throw. */
8d2733ca
MS
171static tree FirstExceptionMatch;
172
eb66be0e 173/* Used to cache a call to __unwind_function. */
8d2733ca
MS
174static tree Unwind;
175
8d2733ca
MS
176/* ====================================================================== */
177
178
8d2733ca
MS
179/* ========================================================================= */
180
181
182
183/* local globals - these local globals are for storing data necessary for
184 generating the exception table and code in the correct order.
185
186 ========================================================================= */
187
a3b49ccd 188/* Holds the pc for doing "throw" */
5566b478 189static tree saved_pc;
f30432d7 190
6467930b
MS
191extern int throw_used;
192extern rtx catch_clauses;
6c20b7e9 193extern tree const_ptr_type_node;
8d2733ca 194
8d2733ca
MS
195/* ========================================================================= */
196
6467930b 197/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 198
5566b478 199static rtx
f30432d7
MS
200do_function_call (func, params, return_type)
201 tree func, params, return_type;
202{
203 tree func_call;
204 func_call = build_function_call (func, params);
205 expand_call (func_call, NULL_RTX, 0);
206 if (return_type != NULL_TREE)
207 return hard_function_value (return_type, func_call);
208 return NULL_RTX;
209}
210
8d2733ca
MS
211/* ========================================================================= */
212
8d2733ca
MS
213/* sets up all the global eh stuff that needs to be initialized at the
214 start of compilation.
215
216 This includes:
6467930b 217 - Setting up all the function call trees. */
8d08fdba 218
8d08fdba 219void
8d2733ca 220init_exception_processing ()
8d08fdba 221{
f30432d7 222 tree d;
a3b49ccd 223
6633d636
MS
224 /* void vtype () */
225 tree vtype = build_function_type (void_type_node, void_list_node);
226
fb98cff6
JM
227 Terminate = auto_function (get_identifier ("terminate"),
228 vtype, NOT_BUILT_IN);
229 TREE_THIS_VOLATILE (Terminate) = 1;
8ccc31eb 230
8ccc31eb 231 push_lang_context (lang_name_c);
8d2733ca 232
fb98cff6 233 CatchMatch
beb53fb8
JM
234 = builtin_function (flag_rtti
235 ? "__throw_type_match_rtti"
236 : "__throw_type_match",
237 build_function_type (ptr_type_node,
6c20b7e9
JM
238 tree_cons (NULL_TREE, const_ptr_type_node,
239 tree_cons (NULL_TREE, const_ptr_type_node,
beb53fb8
JM
240 tree_cons (NULL_TREE, ptr_type_node,
241 void_list_node)))),
242 NOT_BUILT_IN, NULL_PTR);
fb98cff6 243 FirstExceptionMatch
beb53fb8
JM
244 = builtin_function ("__find_first_exception_table_match",
245 build_function_type (ptr_type_node,
246 tree_cons (NULL_TREE, ptr_type_node,
247 void_list_node)),
248 NOT_BUILT_IN, NULL_PTR);
fb98cff6 249 Unwind
beb53fb8
JM
250 = builtin_function ("__unwind_function",
251 build_function_type (void_type_node,
252 tree_cons (NULL_TREE, ptr_type_node,
253 void_list_node)),
254 NOT_BUILT_IN, NULL_PTR);
8d2733ca 255
8d2733ca 256 pop_lang_context ();
f30432d7 257
6874c264
JM
258 d = build_decl (VAR_DECL, get_identifier ("__eh_pc"), ptr_type_node);
259 TREE_PUBLIC (d) = 1;
260 DECL_EXTERNAL (d) = 1;
261 DECL_ARTIFICIAL (d) = 1;
262 cp_finish_decl (d, NULL_TREE, NULL_TREE, 0, 0);
263 saved_pc = d;
eb66be0e
MS
264
265 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
266 be protected with __terminate. */
267 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
268}
269
95e8dcba 270/* Retrieve a pointer to the cp_eh_info node for the current exception. */
6874c264 271
95e8dcba
JM
272static tree
273call_eh_info ()
6874c264 274{
95e8dcba 275 tree fn;
6874c264
JM
276
277 fn = get_identifier ("__cp_exception_info");
278 if (IDENTIFIER_GLOBAL_VALUE (fn))
279 fn = IDENTIFIER_GLOBAL_VALUE (fn);
280 else
281 {
20b90169 282 tree t, fields[6];
6874c264
JM
283
284 /* Declare cp_eh_info * __cp_exception_info (void),
285 as defined in exception.cc. */
286 push_obstacks_nochange ();
287 end_temporary_allocation ();
288
289 /* struct cp_eh_info. This must match exception.cc. Note that this
290 type is not pushed anywhere. */
291 t = make_lang_type (RECORD_TYPE);
292 fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("value"),
293 ptr_type_node);
294 fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("type"),
295 ptr_type_node);
296 fields[2] = build_lang_field_decl
297 (FIELD_DECL, get_identifier ("cleanup"),
298 build_pointer_type (build_function_type
299 (ptr_type_node, tree_cons
300 (NULL_TREE, ptr_type_node, void_list_node))));
301 fields[3] = build_lang_field_decl (FIELD_DECL, get_identifier ("caught"),
302 boolean_type_node);
303 fields[4] = build_lang_field_decl (FIELD_DECL, get_identifier ("next"),
304 build_pointer_type (t));
20b90169
JM
305 fields[5] = build_lang_field_decl
306 (FIELD_DECL, get_identifier ("handlers"), long_integer_type_node);
cf9d67e3
BK
307 /* N.B.: The fourth field LEN is expected to be
308 the number of fields - 1, not the total number of fields. */
20b90169 309 finish_builtin_type (t, "cp_eh_info", fields, 5, ptr_type_node);
6874c264
JM
310 t = build_pointer_type (t);
311
312 /* And now the function. */
313 fn = build_lang_decl (FUNCTION_DECL, fn,
314 build_function_type (t, void_list_node));
315 DECL_EXTERNAL (fn) = 1;
316 TREE_PUBLIC (fn) = 1;
317 DECL_ARTIFICIAL (fn) = 1;
318 pushdecl_top_level (fn);
319 make_function_rtl (fn);
320 assemble_external (fn);
321 pop_obstacks ();
322 }
95e8dcba
JM
323 return build_function_call (fn, NULL_TREE);
324}
325
326/* Retrieve a pointer to the cp_eh_info node for the current exception
327 and save it in the current binding level. */
328
329static void
330push_eh_info ()
331{
332 tree decl, fn = call_eh_info ();
6874c264
JM
333
334 /* Remember the pointer to the current exception info; it won't change
335 during this catch block. */
336 decl = build_decl (VAR_DECL, get_identifier ("__exception_info"),
337 TREE_TYPE (fn));
338 DECL_ARTIFICIAL (decl) = 1;
339 DECL_INITIAL (decl) = fn;
340 decl = pushdecl (decl);
341 cp_finish_decl (decl, fn, NULL_TREE, 0, 0);
342}
343
344/* Returns a reference to the cp_eh_info node for the current exception. */
345
346static tree
347get_eh_info ()
348{
349 /* Look for the pointer pushed in push_eh_info. */
350 tree t = lookup_name (get_identifier ("__exception_info"), 0);
351 return build_indirect_ref (t, NULL_PTR);
352}
353
354/* Returns a reference to the current exception object. */
355
356static tree
357get_eh_value ()
358{
359 return build_component_ref (get_eh_info (), get_identifier ("value"),
360 NULL_TREE, 0);
361}
362
363/* Returns a reference to the current exception type. */
364
365static tree
366get_eh_type ()
367{
368 return build_component_ref (get_eh_info (), get_identifier ("type"),
369 NULL_TREE, 0);
370}
371
372/* Returns a reference to whether or not the current exception
373 has been caught. */
374
375static tree
376get_eh_caught ()
377{
378 return build_component_ref (get_eh_info (), get_identifier ("caught"),
379 NULL_TREE, 0);
380}
381
20b90169
JM
382/* Returns a reference to whether or not the current exception
383 has been caught. */
384
385static tree
386get_eh_handlers ()
387{
388 return build_component_ref (get_eh_info (), get_identifier ("handlers"),
389 NULL_TREE, 0);
390}
391
f30432d7
MS
392/* Build a type value for use at runtime for a type that is matched
393 against by the exception handling system. */
6467930b 394
f30432d7
MS
395static tree
396build_eh_type_type (type)
397 tree type;
8d08fdba 398{
f30432d7
MS
399 char *typestring;
400 tree exp;
8d2733ca 401
f30432d7
MS
402 if (type == error_mark_node)
403 return error_mark_node;
8d2733ca 404
e92cc029 405 /* peel back references, so they match. */
f30432d7
MS
406 if (TREE_CODE (type) == REFERENCE_TYPE)
407 type = TREE_TYPE (type);
8d08fdba 408
e92cc029 409 /* Peel off cv qualifiers. */
f30432d7 410 type = TYPE_MAIN_VARIANT (type);
8d2733ca 411
f30432d7 412 if (flag_rtti)
8d08fdba 413 {
f30432d7 414 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 415 }
f30432d7
MS
416
417 typestring = build_overload_name (type, 1, 1);
418 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
419 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 420}
8d08fdba 421
faae18ab
MS
422/* Build a type value for use at runtime for a exp that is thrown or
423 matched against by the exception handling system. */
6467930b 424
faae18ab
MS
425static tree
426build_eh_type (exp)
427 tree exp;
428{
faae18ab
MS
429 if (flag_rtti)
430 {
431 exp = build_typeid (exp);
432 return build1 (ADDR_EXPR, ptr_type_node, exp);
433 }
f30432d7 434 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
435}
436
c7ae64f2
JM
437/* Build up a call to __cp_pop_exception, to destroy the exception object
438 for the current catch block. HANDLER is either true or false, telling
439 the library whether or not it is being called from an exception handler;
440 if it is, it avoids destroying the object on rethrow. */
6467930b 441
c7ae64f2
JM
442static tree
443do_pop_exception (handler)
444 tree handler;
72b7eeff 445{
6874c264 446 tree fn, cleanup;
6874c264
JM
447 fn = get_identifier ("__cp_pop_exception");
448 if (IDENTIFIER_GLOBAL_VALUE (fn))
449 fn = IDENTIFIER_GLOBAL_VALUE (fn);
450 else
451 {
c7ae64f2
JM
452 /* Declare void __cp_pop_exception (void *),
453 as defined in exception.cc. */
6874c264
JM
454 push_obstacks_nochange ();
455 end_temporary_allocation ();
c7ae64f2
JM
456 fn = build_lang_decl
457 (FUNCTION_DECL, fn,
458 build_function_type (void_type_node, tree_cons
459 (NULL_TREE, ptr_type_node, tree_cons
460 (NULL_TREE, boolean_type_node,
461 void_list_node))));
6874c264
JM
462 DECL_EXTERNAL (fn) = 1;
463 TREE_PUBLIC (fn) = 1;
464 DECL_ARTIFICIAL (fn) = 1;
465 pushdecl_top_level (fn);
466 make_function_rtl (fn);
467 assemble_external (fn);
468 pop_obstacks ();
469 }
72b7eeff
MS
470
471 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2
JM
472 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
473 cleanup = build_function_call (fn, expr_tree_cons
474 (NULL_TREE, cleanup, expr_tree_cons
475 (NULL_TREE, handler, NULL_TREE)));
c0700ea5 476 return cleanup;
c7ae64f2
JM
477}
478
479/* This routine creates the cleanup for the current exception. */
72b7eeff 480
c7ae64f2
JM
481static void
482push_eh_cleanup ()
483{
484 /* All cleanups must last longer than normal. */
485 int yes = suspend_momentary ();
486 expand_decl_cleanup_no_eh (NULL_TREE, do_pop_exception (boolean_false_node));
72b7eeff 487 resume_momentary (yes);
72b7eeff 488
20b90169
JM
489 expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
490 const0_rtx, VOIDmode, EXPAND_NORMAL);
491
c7ae64f2
JM
492 /* We don't destroy the exception object on rethrow, so we can't use
493 the normal cleanup mechanism for it. */
494 expand_eh_region_start ();
495}
72b7eeff 496
8d2733ca
MS
497/* call this to start a catch block. Typename is the typename, and identifier
498 is the variable to place the object in or NULL if the variable doesn't
499 matter. If typename is NULL, that means its a "catch (...)" or catch
500 everything. In that case we don't need to do any type checking.
501 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 502
8d08fdba 503void
a4443a08
MS
504expand_start_catch_block (declspecs, declarator)
505 tree declspecs, declarator;
8d08fdba 506{
8d2733ca 507 rtx false_label_rtx;
faae18ab 508 tree decl = NULL_TREE;
a3b49ccd 509 tree init;
8d2733ca 510
faf5394a
MS
511 if (processing_template_decl)
512 {
513 if (declspecs)
514 {
515 decl = grokdeclarator (declarator, declspecs, CATCHPARM,
516 1, NULL_TREE);
517 pushdecl (decl);
518 decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
519 copy_to_permanent (declspecs),
520 NULL_TREE);
521 add_tree (decl);
522 }
523 return;
524 }
525
8d2733ca
MS
526 if (! doing_eh (1))
527 return;
528
c7ae64f2
JM
529 /* If we are not doing setjmp/longjmp EH, because we are reordered
530 out of line, we arrange to rethrow in the outer context so as to
531 skip through the terminate region we are nested in, should we
532 encounter an exception in the catch handler. We also need to do
533 this because we are not physically within the try block, if any,
534 that contains this catch block.
535
536 Matches the end in expand_end_catch_block. */
25d5eb3f
JM
537 if (! exceptions_via_longjmp)
538 expand_eh_region_start ();
c7ae64f2
JM
539
540 /* Create a binding level for the eh_info and the exception object
541 cleanup. */
c11b6f21 542 pushlevel (0);
a3b49ccd
MS
543 expand_start_bindings (0);
544
f675499c 545 false_label_rtx = gen_label_rtx ();
72b7eeff 546 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 547
eb66be0e
MS
548 emit_line_note (input_filename, lineno);
549
6874c264
JM
550 push_eh_info ();
551
faae18ab 552 if (declspecs)
8d08fdba 553 {
c11b6f21 554 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
555
556 if (decl == NULL_TREE)
c7ae64f2
JM
557 error ("invalid catch parameter");
558 }
95e8dcba 559
c7ae64f2
JM
560 if (decl)
561 {
562 tree exp;
563 rtx call_rtx, return_value_rtx;
564 tree init_type;
faae18ab 565
be99da77
MS
566 /* Make sure we mark the catch param as used, otherwise we'll get
567 a warning about an unused ((anonymous)). */
568 TREE_USED (decl) = 1;
569
e92cc029 570 /* Figure out the type that the initializer is. */
faae18ab 571 init_type = TREE_TYPE (decl);
f30432d7
MS
572 if (TREE_CODE (init_type) != REFERENCE_TYPE
573 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
574 init_type = build_reference_type (init_type);
575
6874c264 576 exp = get_eh_value ();
92f5c135
JM
577
578 /* Since pointers are passed by value, initialize a reference to
579 pointer catch parm with the address of the value slot. */
580 if (TREE_CODE (init_type) == REFERENCE_TYPE
581 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
582 exp = build_unary_op (ADDR_EXPR, exp, 1);
583
e66d884e 584 exp = expr_tree_cons (NULL_TREE,
f30432d7 585 build_eh_type_type (TREE_TYPE (decl)),
e66d884e 586 expr_tree_cons (NULL_TREE,
6874c264 587 get_eh_type (),
e66d884e 588 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
faae18ab
MS
589 exp = build_function_call (CatchMatch, exp);
590 call_rtx = expand_call (exp, NULL_RTX, 0);
8d2733ca 591
faae18ab 592 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
593
594 /* did the throw type match function return TRUE? */
faae18ab 595 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
596 GET_MODE (return_value_rtx), 0, 0);
597
598 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
599 emit_jump_insn (gen_beq (false_label_rtx));
600
95e8dcba
JM
601 push_eh_cleanup ();
602
c7ae64f2
JM
603 /* Create a binding level for the parm. */
604 pushlevel (0);
605 expand_start_bindings (0);
606
607 init = convert_from_reference (make_tree (init_type, call_rtx));
608
609 /* If the constructor for the catch parm exits via an exception, we
610 must call terminate. See eh23.C. */
611 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
612 {
613 /* Generate the copy constructor call directly so we can wrap it.
614 See also expand_default_init. */
615 init = ocp_convert (TREE_TYPE (decl), init,
616 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
617 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
fb98cff6 618 build_function_call (Terminate, NULL_TREE));
c7ae64f2 619 }
faae18ab 620
b3417a04 621 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
622 DECL_INITIAL (decl) = init;
623 decl = pushdecl (decl);
c7ae64f2 624
b3417a04 625 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba 626 }
95e8dcba
JM
627 else
628 {
629 push_eh_cleanup ();
630
c7ae64f2
JM
631 /* Create a binding level for the parm. */
632 pushlevel (0);
633 expand_start_bindings (0);
634
95e8dcba
JM
635 /* Fall into the catch all section. */
636 }
72b7eeff 637
6874c264
JM
638 init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
639 expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
f30432d7 640
6467930b
MS
641 emit_line_note (input_filename, lineno);
642}
f30432d7 643
f30432d7 644
f30432d7 645
8d2733ca
MS
646/* Call this to end a catch block. Its responsible for emitting the
647 code to handle jumping back to the correct place, and for emitting
648 the label to jump to if this catch block didn't match. */
6467930b 649
824b9a4c
MS
650void
651expand_end_catch_block ()
8d08fdba 652{
f30432d7
MS
653 if (! doing_eh (1))
654 return;
8d2733ca 655
c7ae64f2
JM
656 /* Cleanup the EH parameter. */
657 expand_end_bindings (getdecls (), kept_level_p (), 0);
658 poplevel (kept_level_p (), 1, 0);
659
660 /* Matches push_eh_cleanup. */
661 expand_eh_region_end (do_pop_exception (boolean_true_node));
662
663 /* Cleanup the EH object. */
664 expand_end_bindings (getdecls (), kept_level_p (), 0);
665 poplevel (kept_level_p (), 1, 0);
eb66be0e 666
0b3ca5ee 667 if (! exceptions_via_longjmp)
eb66be0e
MS
668 {
669 /* If we are not doing setjmp/longjmp EH, we need an extra
670 region around the whole catch block to skip through the
671 terminate region we are nested in. */
672
25d5eb3f
JM
673 tree t = make_node (RTL_EXPR);
674 TREE_TYPE (t) = void_type_node;
675 RTL_EXPR_RTL (t) = const0_rtx;
676 TREE_SIDE_EFFECTS (t) = 1;
677 do_pending_stack_adjust ();
678 start_sequence_for_rtl_expr (t);
679
680 expand_internal_throw (outer_context_label_stack->u.rlabel);
eb66be0e 681
25d5eb3f
JM
682 do_pending_stack_adjust ();
683 RTL_EXPR_SEQUENCE (t) = get_insns ();
684 end_sequence ();
f30432d7 685
25d5eb3f
JM
686 /* For the rethrow region. */
687 expand_eh_region_end (t);
688 }
f30432d7 689
eb66be0e
MS
690 /* Fall to outside the try statement when done executing handler and
691 we fall off end of handler. This is jump Lresume in the
692 documentation. */
693 expand_goto (top_label_entry (&caught_return_label_stack));
694
6467930b 695 expand_leftover_cleanups ();
f30432d7 696
6467930b 697 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
698 /* This the closing } in the `if (eq) {' of the documentation. */
699 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 700}
8d08fdba 701
6467930b
MS
702/* unwind the stack. */
703
db5ae43f 704static void
f30432d7
MS
705do_unwind (inner_throw_label)
706 rtx inner_throw_label;
db5ae43f 707{
be99da77 708#if defined (SPARC_STACK_ALIGN) /* was sparc */
0021b564
JM
709 /* This doesn't work for the flat model sparc, nor does it need to
710 as the default unwinder is only used to unwind non-flat frames. */
db5ae43f
MS
711 tree fcall;
712 tree params;
6633d636 713 rtx next_pc;
f30432d7 714 rtx temp;
db5ae43f 715
eb66be0e 716 /* Call to __builtin_return_address. */
e66d884e 717 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 718 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 719 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 720 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 721 really the address of the call insn, not the next insn. */
f30432d7
MS
722 temp = gen_reg_rtx (Pmode);
723 emit_move_insn (temp, inner_throw_label);
6633d636 724 emit_move_insn (next_pc, plus_constant (temp, -8));
d11ad92e 725 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
726 easy_expand_asm ("ret");
727 easy_expand_asm ("restore");
728 emit_barrier ();
729#endif
be99da77 730#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
731 if (flag_omit_frame_pointer)
732 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 733
f30432d7
MS
734 emit_move_insn (stack_pointer_rtx,
735 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
736 emit_move_insn (hard_frame_pointer_rtx,
737 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 738#endif
be99da77 739#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
740 rtx temp_frame = frame_pointer_rtx;
741
742 temp_frame = memory_address (Pmode, temp_frame);
743 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
744
745 /* hopefully this will successfully pop the frame! */
746 emit_move_insn (frame_pointer_rtx, temp_frame);
747 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
748 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
749 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
750 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
751
752#if 0
753 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
754 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
755
756 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
757
758 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
759 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
760#endif
761#endif
be99da77 762#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
763 tree fcall;
764 tree params;
6633d636 765 rtx next_pc;
e1cd6e56 766
be99da77 767#if 0
e92cc029 768 /* I would like to do this here, but the move below doesn't seem to work. */
eb66be0e 769 /* Call to __builtin_return_address. */
e66d884e 770 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 771 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 772 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 773
6633d636 774 emit_move_insn (next_pc, inner_throw_label);
e92cc029 775 /* So, for now, just pass throw label to stack unwinder. */
f30432d7 776#endif
e66d884e 777 params = expr_tree_cons (NULL_TREE, make_tree (ptr_type_node,
f30432d7
MS
778 inner_throw_label), NULL_TREE);
779
780 do_function_call (Unwind, params, NULL_TREE);
f30432d7 781 emit_barrier ();
e1cd6e56 782#endif
db5ae43f 783}
8d08fdba 784
f30432d7 785
eb66be0e 786/* Is called from expand_exception_blocks to generate the code in a function
ddd5a7c1 787 to "throw" if anything in the function needs to perform a throw.
8d08fdba 788
ddd5a7c1 789 expands "throw" as the following pseudo code:
8d2733ca
MS
790
791 throw:
792 eh = find_first_exception_match (saved_pc);
793 if (!eh) goto gotta_rethrow_it;
794 goto eh;
795
796 gotta_rethrow_it:
797 saved_pc = __builtin_return_address (0);
798 pop_to_previous_level ();
6467930b 799 goto throw; */
8d2733ca 800
f30432d7 801void
8d2733ca
MS
802expand_builtin_throw ()
803{
0021b564 804#ifndef DWARF2_UNWIND_INFO
8d2733ca
MS
805 tree fcall;
806 tree params;
6633d636
MS
807 rtx handler;
808 rtx saved_pcnthrow;
809 rtx next_pc;
f30432d7
MS
810 rtx gotta_rethrow_it;
811 rtx gotta_call_terminate;
6633d636 812 rtx after_unwind;
f30432d7 813 rtx top_of_loop;
f30432d7 814 tree t;
6633d636 815 rtx x;
f30432d7
MS
816
817 if (! doing_eh (0))
818 return;
819
820 if (! throw_used)
821 return;
8d2733ca 822
f30432d7 823 params = void_list_node;
c11b6f21
MS
824 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
825 NULL_TREE);
6633d636
MS
826 start_function (decl_tree_cons (NULL_TREE,
827 get_identifier ("void"),
828 decl_tree_cons (NULL_TREE,
829 get_identifier ("static"),
830 NULL_TREE)),
c11b6f21 831 t, NULL_TREE, 0);
f30432d7
MS
832 store_parm_decls ();
833 pushlevel (0);
834 clear_last_expr ();
835 push_momentary ();
836 expand_start_bindings (0);
837
838 gotta_rethrow_it = gen_label_rtx ();
839 gotta_call_terminate = gen_label_rtx ();
f30432d7 840
a50f0918 841 /* These two can be frontend specific. If wanted, they can go in
e92cc029 842 expand_throw. */
a50f0918 843 /* Do we have a valid object we are throwing? */
95e8dcba
JM
844 t = call_eh_info ();
845 emit_cmp_insn (expand_expr (t, NULL_RTX, Pmode, 0),
846 const0_rtx, EQ, NULL_RTX,
5a0fa1de 847 GET_MODE (DECL_RTL (t)), 0, 0);
a50f0918
MS
848 emit_jump_insn (gen_beq (gotta_call_terminate));
849
8d2733ca 850 /* search for an exception handler for the saved_pc */
6633d636 851 handler = do_function_call (FirstExceptionMatch,
e66d884e 852 expr_tree_cons (NULL_TREE, saved_pc,
6633d636
MS
853 NULL_TREE),
854 ptr_type_node);
8d2733ca
MS
855
856 /* did we find one? */
6633d636
MS
857 emit_cmp_insn (handler, const0_rtx, EQ, NULL_RTX,
858 GET_MODE (handler), 0, 0);
8d2733ca
MS
859
860 /* if not, jump to gotta_rethrow_it */
861 emit_jump_insn (gen_beq (gotta_rethrow_it));
862
6633d636
MS
863 {
864 rtx ret_val, x;
865 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
866 0, hard_frame_pointer_rtx);
8d2733ca 867
6633d636
MS
868 /* Set it up so that we continue at the handler. */
869 emit_move_insn (ret_val, handler);
870#ifdef RETURN_ADDR_OFFSET
871 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
872 if (x != ret_val)
873 emit_move_insn (ret_val, x);
874#endif
8d2733ca 875
6633d636
MS
876 expand_null_return ();
877 }
878
879 top_of_loop = gen_label_rtx ();
880 emit_label (top_of_loop);
881
882#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
883 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
884 {
885 saved_pcnthrow = gen_reg_rtx (Pmode);
886 emit_move_insn (saved_pcnthrow, hard_function_value (ptr_type_node,
887 NULL_TREE));
888 }
889#endif
890
eb66be0e 891 /* Call to __builtin_return_address. */
be99da77
MS
892#if defined (ARM_FRAME_RTX) /* was __arm */
893 /* This should be moved into arm.h:RETURN_ADDR_RTX */
894 /* This replaces a 'call' to __builtin_return_address */
6633d636
MS
895 next_pc = gen_reg_rtx (Pmode);
896 emit_move_insn (next_pc,
897 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 898#else
e66d884e 899 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 900 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 901 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 902#endif
8d2733ca 903
eb66be0e 904 /* Did __builtin_return_address return a valid address? */
6633d636
MS
905 emit_cmp_insn (next_pc, const0_rtx, EQ, NULL_RTX,
906 GET_MODE (next_pc), 0, 0);
8d2733ca
MS
907
908 emit_jump_insn (gen_beq (gotta_call_terminate));
909
6633d636 910 next_pc = eh_outer_context (next_pc);
e1cd6e56 911
be99da77 912 /* Yes it did. */
6633d636
MS
913#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
914 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
915 {
916 rtx x;
917
918 x = validize_mem (gen_rtx (MEM, Pmode, saved_pcnthrow));
919 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode, x)),
920 next_pc);
921#ifdef FUNCTION_OUTGOING_VALUE
922 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
923 validize_mem (gen_rtx (MEM, Pmode,
924 plus_constant (saved_pcnthrow,
925 GET_MODE_SIZE (Pmode)))));
926 emit_insn (gen_rtx (USE, VOIDmode,
927 FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
928#endif
929 }
930 else
931#endif
932 emit_move_insn (eh_saved_pc_rtx, next_pc);
f30432d7 933
6633d636
MS
934 after_unwind = gen_label_rtx ();
935 do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
936
937 emit_label (after_unwind);
938
939#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
940 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
941 {
6874c264
JM
942 t = build_function_type (void_type_node, void_list_node);
943 t = make_tree (build_pointer_type (t),
6633d636
MS
944 hard_function_value (ptr_type_node,
945 NULL_TREE));
946 t = build_function_call (t, NULL_TREE);
947 expand_expr (t, const0_rtx, VOIDmode, 0);
948 }
949 else
950#endif
951 emit_throw ();
8d2733ca
MS
952
953 /* no it didn't --> therefore we need to call terminate */
954 emit_label (gotta_call_terminate);
955 do_function_call (Terminate, NULL_TREE, NULL_TREE);
f30432d7
MS
956
957 {
6633d636
MS
958 rtx ret_val, x;
959 /* code to deal with unwinding and looking for it again */
960 emit_label (gotta_rethrow_it);
f30432d7
MS
961 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
962 0, hard_frame_pointer_rtx);
963
964 /* Set it up so that we continue inside, at the top of the loop. */
965 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173 966#ifdef RETURN_ADDR_OFFSET
6633d636
MS
967 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
968 if (x != ret_val)
969 emit_move_insn (ret_val, x);
970#endif
971
972#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
973 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
974 {
975 rtx x = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode,
976 "__eh_pcnthrow"),
977 NULL_RTX, 1,
978 Pmode, 0);
979 /* This is to get a version of throw that will throw properly. */
980 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode,
981 plus_constant (x, GET_MODE_SIZE (Pmode)))),
982 throw_libfunc);
983#ifdef FUNCTION_OUTGOING_VALUE
984 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
985 x);
986 emit_insn (gen_rtx (USE, VOIDmode, FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
987#endif
988 }
f30432d7
MS
989#endif
990
e92cc029 991 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
992 }
993
fc378698 994 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
995 poplevel (1, 0, 0);
996 pop_momentary ();
997
998 finish_function (lineno, 0, 0);
0021b564 999#endif /* DWARF2_UNWIND_INFO */
8d08fdba 1000}
8d2733ca 1001
6c20b7e9
JM
1002/* An exception spec is implemented more or less like:
1003
1004 try {
1005 function body;
1006 } catch (...) {
1007 void *p[] = { typeid(raises) };
1008 __check_eh_spec (p, count);
1009 }
1010
1011 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 1012
f30432d7
MS
1013void
1014expand_start_eh_spec ()
1015{
6c20b7e9 1016 expand_start_try_stmts ();
f30432d7
MS
1017}
1018
5566b478 1019static void
f30432d7
MS
1020expand_end_eh_spec (raises)
1021 tree raises;
1022{
6c20b7e9
JM
1023 tree tmp, fn, decl, types = NULL_TREE;
1024 int count = 0;
f30432d7 1025
6c20b7e9
JM
1026 expand_start_all_catch ();
1027 expand_start_catch_block (NULL_TREE, NULL_TREE);
f30432d7 1028
6c20b7e9
JM
1029 /* Build up an array of type_infos. */
1030 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
1031 {
1032 types = expr_tree_cons
1033 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
1034 ++count;
1035 }
eb66be0e 1036
6c20b7e9
JM
1037 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
1038 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 1039
6c20b7e9
JM
1040 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
1041 tmp = build_array_type (const_ptr_type_node, NULL_TREE);
1042 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
1043 DECL_ARTIFICIAL (decl) = 1;
1044 DECL_INITIAL (decl) = types;
1045 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
1046
1047 decl = decay_conversion (decl);
6874c264 1048
6c20b7e9
JM
1049 fn = get_identifier ("__check_eh_spec");
1050 if (IDENTIFIER_GLOBAL_VALUE (fn))
1051 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1052 else
f30432d7 1053 {
6c20b7e9
JM
1054 push_obstacks_nochange ();
1055 end_temporary_allocation ();
f30432d7 1056
6c20b7e9
JM
1057 tmp = tree_cons
1058 (NULL_TREE, integer_type_node, tree_cons
1059 (NULL_TREE, TREE_TYPE (decl), void_list_node));
1060 tmp = build_function_type (void_type_node, tmp);
f30432d7 1061
6c20b7e9
JM
1062 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1063 DECL_EXTERNAL (fn) = 1;
1064 TREE_PUBLIC (fn) = 1;
1065 DECL_ARTIFICIAL (fn) = 1;
1066 TREE_THIS_VOLATILE (fn) = 1;
1067 pushdecl_top_level (fn);
1068 make_function_rtl (fn);
1069 assemble_external (fn);
1070 pop_obstacks ();
1071 }
1072
1073 tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
1074 (NULL_TREE, decl, NULL_TREE));
1075 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
1076 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
1077
1078 expand_end_catch_block ();
1079 expand_end_all_catch ();
f30432d7
MS
1080}
1081
8d2733ca
MS
1082/* This is called to expand all the toplevel exception handling
1083 finalization for a function. It should only be called once per
1084 function. */
6467930b 1085
8d08fdba 1086void
8d2733ca 1087expand_exception_blocks ()
8d08fdba 1088{
92b96838 1089 do_pending_stack_adjust ();
e00737d2 1090 push_to_sequence (catch_clauses);
8d2733ca 1091 expand_leftover_cleanups ();
92b96838 1092 do_pending_stack_adjust ();
e00737d2 1093 catch_clauses = get_insns ();
f30432d7 1094 end_sequence ();
eb448459 1095
eb448459
MS
1096 /* Do this after we expand leftover cleanups, so that the
1097 expand_eh_region_end that expand_end_eh_spec does will match the
1098 right expand_eh_region_start, and make sure it comes out before
1099 the terminate protected region. */
f30432d7
MS
1100 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
1101 {
eb448459 1102 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
92b96838 1103 do_pending_stack_adjust ();
e00737d2 1104 push_to_sequence (catch_clauses);
eb448459 1105 expand_leftover_cleanups ();
92b96838 1106 do_pending_stack_adjust ();
e00737d2 1107 catch_clauses = get_insns ();
eb448459 1108 end_sequence ();
f30432d7
MS
1109 }
1110
e00737d2 1111 if (catch_clauses)
f30432d7 1112 {
e00737d2
MS
1113 rtx funcend = gen_label_rtx ();
1114 emit_jump (funcend);
1115
eb66be0e
MS
1116 /* We cannot protect n regions this way if we must flow into the
1117 EH region through the top of the region, as we have to with
1118 the setjmp/longjmp approach. */
1119 if (exceptions_via_longjmp == 0)
fb98cff6 1120 expand_eh_region_start ();
f30432d7 1121
e00737d2
MS
1122 emit_insns (catch_clauses);
1123 catch_clauses = NULL_RTX;
eb66be0e
MS
1124
1125 if (exceptions_via_longjmp == 0)
fb98cff6 1126 expand_eh_region_end (build_function_call (Terminate, NULL_TREE));
eb66be0e 1127
6467930b 1128 expand_leftover_cleanups ();
f30432d7 1129
e00737d2
MS
1130 emit_label (funcend);
1131 }
8d08fdba
MS
1132}
1133
72b7eeff
MS
1134tree
1135start_anon_func ()
1136{
1137 static int counter = 0;
e92cc029 1138 int old_interface_unknown = interface_unknown;
72b7eeff
MS
1139 char name[32];
1140 tree params;
1141 tree t;
1142
1143 push_cp_function_context (NULL_TREE);
1144 push_to_top_level ();
1145
1146 /* No need to mangle this. */
1147 push_lang_context (lang_name_c);
1148
e92cc029
MS
1149 interface_unknown = 1;
1150
72b7eeff
MS
1151 params = void_list_node;
1152 /* tcf stands for throw clean funciton. */
1153 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
1154 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
1155 NULL_TREE);
72b7eeff
MS
1156 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1157 void_list_node),
c11b6f21 1158 t, NULL_TREE, 0);
72b7eeff
MS
1159 store_parm_decls ();
1160 pushlevel (0);
1161 clear_last_expr ();
1162 push_momentary ();
1163 expand_start_bindings (0);
1164 emit_line_note (input_filename, lineno);
1165
e92cc029
MS
1166 interface_unknown = old_interface_unknown;
1167
72b7eeff
MS
1168 pop_lang_context ();
1169
1170 return current_function_decl;
1171}
1172
1173void
1174end_anon_func ()
1175{
fc378698 1176 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1177 poplevel (1, 0, 0);
1178 pop_momentary ();
1179
1180 finish_function (lineno, 0, 0);
1181
1182 pop_from_top_level ();
1183 pop_cp_function_context (NULL_TREE);
1184}
8d2733ca 1185
6467930b 1186/* Expand a throw statement. This follows the following
8d2733ca
MS
1187 algorithm:
1188
1189 1. Allocate space to save the current PC onto the stack.
1190 2. Generate and emit a label and save its address into the
e1cd6e56 1191 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1192 3. If this is the first call to throw in this function:
1193 generate a label for the throw block
1194 4. jump to the throw block label. */
6467930b 1195
8d08fdba 1196void
8d2733ca
MS
1197expand_throw (exp)
1198 tree exp;
8d08fdba 1199{
8d2733ca 1200 rtx label;
6874c264
JM
1201 tree fn;
1202 static tree cleanup_type;
8d08fdba 1203
8d2733ca
MS
1204 if (! doing_eh (1))
1205 return;
8d08fdba 1206
8d2733ca
MS
1207 if (exp)
1208 {
faae18ab 1209 tree throw_type;
6874c264 1210 tree cleanup = NULL_TREE, e;
faae18ab 1211
a3b49ccd 1212 /* throw expression */
e92cc029 1213 /* First, decay it. */
f30432d7 1214 exp = decay_conversion (exp);
a3b49ccd 1215
6874c264
JM
1216 /* cleanup_type is void (*)(void *, int),
1217 the internal type of a destructor. */
1218 if (cleanup_type == NULL_TREE)
1219 {
1220 push_obstacks_nochange ();
1221 end_temporary_allocation ();
1222 cleanup_type = build_pointer_type
1223 (build_function_type
1224 (void_type_node, tree_cons
1225 (NULL_TREE, ptr_type_node, tree_cons
1226 (NULL_TREE, integer_type_node, void_list_node))));
1227 pop_obstacks ();
1228 }
1229
f30432d7
MS
1230 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1231 {
1232 throw_type = build_eh_type (exp);
1233 exp = build_reinterpret_cast (ptr_type_node, exp);
1234 }
1235 else
1236 {
72b7eeff 1237 tree object;
a50f0918 1238
f30432d7
MS
1239 /* Make a copy of the thrown object. WP 15.1.5 */
1240 exp = build_new (NULL_TREE, TREE_TYPE (exp),
e66d884e 1241 build_expr_list (NULL_TREE, exp),
f30432d7 1242 0);
faae18ab 1243
f30432d7
MS
1244 if (exp == error_mark_node)
1245 error (" in thrown expression");
faae18ab 1246
72b7eeff
MS
1247 object = build_indirect_ref (exp, NULL_PTR);
1248 throw_type = build_eh_type (object);
1249
6874c264
JM
1250 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
1251 {
1252 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
1253 dtor_identifier, 0);
1254 cleanup = TREE_VALUE (cleanup);
e872bb7a 1255 mark_used (cleanup);
6874c264
JM
1256 mark_addressable (cleanup);
1257 /* Pretend it's a normal function. */
1258 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
1259 }
f30432d7 1260 }
faae18ab 1261
6874c264
JM
1262 if (cleanup == NULL_TREE)
1263 {
1264 cleanup = build_int_2 (0, 0);
1265 TREE_TYPE (cleanup) = cleanup_type;
1266 }
72b7eeff 1267
6874c264
JM
1268 fn = get_identifier ("__cp_push_exception");
1269 if (IDENTIFIER_GLOBAL_VALUE (fn))
1270 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1271 else
1272 {
1273 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1274 as defined in exception.cc. */
1275 tree tmp;
1276 push_obstacks_nochange ();
1277 end_temporary_allocation ();
1278 tmp = tree_cons
1279 (NULL_TREE, ptr_type_node, tree_cons
1280 (NULL_TREE, ptr_type_node, tree_cons
1281 (NULL_TREE, cleanup_type, void_list_node)));
1282 fn = build_lang_decl (FUNCTION_DECL, fn,
1283 build_function_type (void_type_node, tmp));
1284 DECL_EXTERNAL (fn) = 1;
1285 TREE_PUBLIC (fn) = 1;
1286 DECL_ARTIFICIAL (fn) = 1;
1287 pushdecl_top_level (fn);
1288 make_function_rtl (fn);
1289 assemble_external (fn);
1290 pop_obstacks ();
1291 }
72b7eeff 1292
6874c264
JM
1293 /* The throw expression is a full-expression. */
1294 exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
1295 e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
1296 (NULL_TREE, throw_type, expr_tree_cons
1297 (NULL_TREE, cleanup, NULL_TREE)));
1298 e = build_function_call (fn, e);
1299 expand_expr (e, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1300 }
1301 else
a3b49ccd 1302 {
6874c264
JM
1303 /* rethrow current exception; note that it's no longer caught. */
1304
1305 tree fn = get_identifier ("__uncatch_exception");
1306 if (IDENTIFIER_GLOBAL_VALUE (fn))
1307 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1308 else
1309 {
1310 /* Declare void __uncatch_exception (void)
1311 as defined in exception.cc. */
1312 push_obstacks_nochange ();
1313 end_temporary_allocation ();
1314 fn = build_lang_decl (FUNCTION_DECL, fn,
1315 build_function_type (void_type_node,
1316 void_list_node));
1317 DECL_EXTERNAL (fn) = 1;
1318 TREE_PUBLIC (fn) = 1;
1319 DECL_ARTIFICIAL (fn) = 1;
1320 pushdecl_top_level (fn);
1321 make_function_rtl (fn);
1322 assemble_external (fn);
1323 pop_obstacks ();
1324 }
1325
1326 exp = build_function_call (fn, NULL_TREE);
1327 expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
a3b49ccd 1328 }
8d2733ca 1329
eb66be0e
MS
1330 if (exceptions_via_longjmp)
1331 emit_throw ();
1332 else
1333 {
1334 /* This is the label that represents where in the code we were, when
1335 we got an exception. This needs to be updated when we rethrow an
1336 exception, so that the matching routine knows to search out. */
1337 label = gen_label_rtx ();
1338 emit_label (label);
8d2733ca 1339
eb66be0e
MS
1340 expand_internal_throw (label);
1341 }
f376e137 1342}
8d2733ca
MS
1343
1344/* Build a throw expression. */
6467930b 1345
8d2733ca
MS
1346tree
1347build_throw (e)
1348 tree e;
1349{
db5ae43f
MS
1350 if (e != error_mark_node)
1351 {
5156628f 1352 if (processing_template_decl)
fc378698 1353 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1354 e = build1 (THROW_EXPR, void_type_node, e);
1355 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1356 TREE_USED (e) = 1;
db5ae43f 1357 }
8d2733ca 1358 return e;
8d08fdba 1359}
This page took 0.417768 seconds and 5 git commands to generate.