]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
tweak
[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 442static tree
de35891e 443do_pop_exception ()
72b7eeff 444{
6874c264 445 tree fn, cleanup;
6874c264
JM
446 fn = get_identifier ("__cp_pop_exception");
447 if (IDENTIFIER_GLOBAL_VALUE (fn))
448 fn = IDENTIFIER_GLOBAL_VALUE (fn);
449 else
450 {
c7ae64f2
JM
451 /* Declare void __cp_pop_exception (void *),
452 as defined in exception.cc. */
6874c264
JM
453 push_obstacks_nochange ();
454 end_temporary_allocation ();
c7ae64f2
JM
455 fn = build_lang_decl
456 (FUNCTION_DECL, fn,
457 build_function_type (void_type_node, tree_cons
de35891e 458 (NULL_TREE, ptr_type_node, void_list_node)));
6874c264
JM
459 DECL_EXTERNAL (fn) = 1;
460 TREE_PUBLIC (fn) = 1;
461 DECL_ARTIFICIAL (fn) = 1;
462 pushdecl_top_level (fn);
463 make_function_rtl (fn);
464 assemble_external (fn);
465 pop_obstacks ();
466 }
72b7eeff
MS
467
468 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
c7ae64f2
JM
469 cleanup = lookup_name (get_identifier ("__exception_info"), 0);
470 cleanup = build_function_call (fn, expr_tree_cons
de35891e 471 (NULL_TREE, cleanup, NULL_TREE));
c0700ea5 472 return cleanup;
c7ae64f2
JM
473}
474
475/* This routine creates the cleanup for the current exception. */
72b7eeff 476
c7ae64f2
JM
477static void
478push_eh_cleanup ()
479{
de35891e 480 int yes;
72b7eeff 481
20b90169
JM
482 expand_expr (build_unary_op (PREINCREMENT_EXPR, get_eh_handlers (), 1),
483 const0_rtx, VOIDmode, EXPAND_NORMAL);
484
de35891e
JM
485 yes = suspend_momentary ();
486 /* All cleanups must last longer than normal. */
487 expand_decl_cleanup (NULL_TREE, do_pop_exception ());
488 resume_momentary (yes);
c7ae64f2 489}
72b7eeff 490
8d2733ca
MS
491/* call this to start a catch block. Typename is the typename, and identifier
492 is the variable to place the object in or NULL if the variable doesn't
493 matter. If typename is NULL, that means its a "catch (...)" or catch
494 everything. In that case we don't need to do any type checking.
495 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 496
8d08fdba 497void
a4443a08
MS
498expand_start_catch_block (declspecs, declarator)
499 tree declspecs, declarator;
8d08fdba 500{
8d2733ca 501 rtx false_label_rtx;
faae18ab 502 tree decl = NULL_TREE;
a3b49ccd 503 tree init;
8d2733ca 504
faf5394a
MS
505 if (processing_template_decl)
506 {
507 if (declspecs)
508 {
509 decl = grokdeclarator (declarator, declspecs, CATCHPARM,
510 1, NULL_TREE);
511 pushdecl (decl);
512 decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
513 copy_to_permanent (declspecs),
514 NULL_TREE);
515 add_tree (decl);
516 }
517 return;
518 }
519
8d2733ca
MS
520 if (! doing_eh (1))
521 return;
522
c7ae64f2
JM
523 /* If we are not doing setjmp/longjmp EH, because we are reordered
524 out of line, we arrange to rethrow in the outer context so as to
525 skip through the terminate region we are nested in, should we
526 encounter an exception in the catch handler. We also need to do
527 this because we are not physically within the try block, if any,
528 that contains this catch block.
529
530 Matches the end in expand_end_catch_block. */
25d5eb3f
JM
531 if (! exceptions_via_longjmp)
532 expand_eh_region_start ();
c7ae64f2
JM
533
534 /* Create a binding level for the eh_info and the exception object
535 cleanup. */
c11b6f21 536 pushlevel (0);
a3b49ccd
MS
537 expand_start_bindings (0);
538
f675499c 539 false_label_rtx = gen_label_rtx ();
72b7eeff 540 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 541
eb66be0e
MS
542 emit_line_note (input_filename, lineno);
543
6874c264
JM
544 push_eh_info ();
545
faae18ab 546 if (declspecs)
8d08fdba 547 {
c11b6f21 548 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
549
550 if (decl == NULL_TREE)
c7ae64f2
JM
551 error ("invalid catch parameter");
552 }
95e8dcba 553
c7ae64f2
JM
554 if (decl)
555 {
556 tree exp;
557 rtx call_rtx, return_value_rtx;
558 tree init_type;
faae18ab 559
be99da77
MS
560 /* Make sure we mark the catch param as used, otherwise we'll get
561 a warning about an unused ((anonymous)). */
562 TREE_USED (decl) = 1;
563
e92cc029 564 /* Figure out the type that the initializer is. */
faae18ab 565 init_type = TREE_TYPE (decl);
f30432d7
MS
566 if (TREE_CODE (init_type) != REFERENCE_TYPE
567 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
568 init_type = build_reference_type (init_type);
569
6874c264 570 exp = get_eh_value ();
92f5c135
JM
571
572 /* Since pointers are passed by value, initialize a reference to
573 pointer catch parm with the address of the value slot. */
574 if (TREE_CODE (init_type) == REFERENCE_TYPE
575 && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)
576 exp = build_unary_op (ADDR_EXPR, exp, 1);
577
e66d884e 578 exp = expr_tree_cons (NULL_TREE,
f30432d7 579 build_eh_type_type (TREE_TYPE (decl)),
e66d884e 580 expr_tree_cons (NULL_TREE,
6874c264 581 get_eh_type (),
e66d884e 582 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
faae18ab
MS
583 exp = build_function_call (CatchMatch, exp);
584 call_rtx = expand_call (exp, NULL_RTX, 0);
8d2733ca 585
faae18ab 586 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
587
588 /* did the throw type match function return TRUE? */
faae18ab 589 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
590 GET_MODE (return_value_rtx), 0, 0);
591
592 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
593 emit_jump_insn (gen_beq (false_label_rtx));
594
95e8dcba
JM
595 push_eh_cleanup ();
596
c7ae64f2
JM
597 /* Create a binding level for the parm. */
598 pushlevel (0);
599 expand_start_bindings (0);
600
601 init = convert_from_reference (make_tree (init_type, call_rtx));
602
603 /* If the constructor for the catch parm exits via an exception, we
604 must call terminate. See eh23.C. */
605 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
606 {
607 /* Generate the copy constructor call directly so we can wrap it.
608 See also expand_default_init. */
609 init = ocp_convert (TREE_TYPE (decl), init,
610 CONV_IMPLICIT|CONV_FORCE_TEMP, 0);
611 init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,
fb98cff6 612 build_function_call (Terminate, NULL_TREE));
c7ae64f2 613 }
faae18ab 614
b3417a04 615 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
616 DECL_INITIAL (decl) = init;
617 decl = pushdecl (decl);
c7ae64f2 618
b3417a04 619 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba 620 }
95e8dcba
JM
621 else
622 {
623 push_eh_cleanup ();
624
c7ae64f2
JM
625 /* Create a binding level for the parm. */
626 pushlevel (0);
627 expand_start_bindings (0);
628
95e8dcba
JM
629 /* Fall into the catch all section. */
630 }
72b7eeff 631
6874c264
JM
632 init = build_modify_expr (get_eh_caught (), NOP_EXPR, integer_one_node);
633 expand_expr (init, const0_rtx, VOIDmode, EXPAND_NORMAL);
f30432d7 634
6467930b
MS
635 emit_line_note (input_filename, lineno);
636}
f30432d7 637
f30432d7 638
f30432d7 639
8d2733ca
MS
640/* Call this to end a catch block. Its responsible for emitting the
641 code to handle jumping back to the correct place, and for emitting
642 the label to jump to if this catch block didn't match. */
6467930b 643
824b9a4c
MS
644void
645expand_end_catch_block ()
8d08fdba 646{
f30432d7
MS
647 if (! doing_eh (1))
648 return;
8d2733ca 649
c7ae64f2
JM
650 /* Cleanup the EH parameter. */
651 expand_end_bindings (getdecls (), kept_level_p (), 0);
652 poplevel (kept_level_p (), 1, 0);
653
c7ae64f2
JM
654 /* Cleanup the EH object. */
655 expand_end_bindings (getdecls (), kept_level_p (), 0);
656 poplevel (kept_level_p (), 1, 0);
eb66be0e 657
0b3ca5ee 658 if (! exceptions_via_longjmp)
eb66be0e
MS
659 {
660 /* If we are not doing setjmp/longjmp EH, we need an extra
661 region around the whole catch block to skip through the
662 terminate region we are nested in. */
663
25d5eb3f
JM
664 tree t = make_node (RTL_EXPR);
665 TREE_TYPE (t) = void_type_node;
666 RTL_EXPR_RTL (t) = const0_rtx;
667 TREE_SIDE_EFFECTS (t) = 1;
668 do_pending_stack_adjust ();
669 start_sequence_for_rtl_expr (t);
670
671 expand_internal_throw (outer_context_label_stack->u.rlabel);
eb66be0e 672
25d5eb3f
JM
673 do_pending_stack_adjust ();
674 RTL_EXPR_SEQUENCE (t) = get_insns ();
675 end_sequence ();
f30432d7 676
25d5eb3f
JM
677 /* For the rethrow region. */
678 expand_eh_region_end (t);
679 }
f30432d7 680
eb66be0e
MS
681 /* Fall to outside the try statement when done executing handler and
682 we fall off end of handler. This is jump Lresume in the
683 documentation. */
684 expand_goto (top_label_entry (&caught_return_label_stack));
685
6467930b 686 expand_leftover_cleanups ();
f30432d7 687
6467930b 688 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
689 /* This the closing } in the `if (eq) {' of the documentation. */
690 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 691}
8d08fdba 692
6467930b
MS
693/* unwind the stack. */
694
db5ae43f 695static void
f30432d7
MS
696do_unwind (inner_throw_label)
697 rtx inner_throw_label;
db5ae43f 698{
be99da77 699#if defined (SPARC_STACK_ALIGN) /* was sparc */
0021b564
JM
700 /* This doesn't work for the flat model sparc, nor does it need to
701 as the default unwinder is only used to unwind non-flat frames. */
db5ae43f
MS
702 tree fcall;
703 tree params;
6633d636 704 rtx next_pc;
f30432d7 705 rtx temp;
db5ae43f 706
eb66be0e 707 /* Call to __builtin_return_address. */
e66d884e 708 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 709 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 710 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 711 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 712 really the address of the call insn, not the next insn. */
f30432d7
MS
713 temp = gen_reg_rtx (Pmode);
714 emit_move_insn (temp, inner_throw_label);
6633d636 715 emit_move_insn (next_pc, plus_constant (temp, -8));
d11ad92e 716 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
717 easy_expand_asm ("ret");
718 easy_expand_asm ("restore");
719 emit_barrier ();
720#endif
be99da77 721#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
722 if (flag_omit_frame_pointer)
723 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 724
f30432d7
MS
725 emit_move_insn (stack_pointer_rtx,
726 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
727 emit_move_insn (hard_frame_pointer_rtx,
728 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 729#endif
be99da77 730#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
731 rtx temp_frame = frame_pointer_rtx;
732
733 temp_frame = memory_address (Pmode, temp_frame);
734 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
735
736 /* hopefully this will successfully pop the frame! */
737 emit_move_insn (frame_pointer_rtx, temp_frame);
738 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
739 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
740 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
741 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
742
743#if 0
744 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
745 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
746
747 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
748
749 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
750 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
751#endif
752#endif
be99da77 753#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
754 tree fcall;
755 tree params;
6633d636 756 rtx next_pc;
e1cd6e56 757
be99da77 758#if 0
e92cc029 759 /* I would like to do this here, but the move below doesn't seem to work. */
eb66be0e 760 /* Call to __builtin_return_address. */
e66d884e 761 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 762 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 763 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 764
6633d636 765 emit_move_insn (next_pc, inner_throw_label);
e92cc029 766 /* So, for now, just pass throw label to stack unwinder. */
f30432d7 767#endif
e66d884e 768 params = expr_tree_cons (NULL_TREE, make_tree (ptr_type_node,
f30432d7
MS
769 inner_throw_label), NULL_TREE);
770
771 do_function_call (Unwind, params, NULL_TREE);
f30432d7 772 emit_barrier ();
e1cd6e56 773#endif
db5ae43f 774}
8d08fdba 775
f30432d7 776
eb66be0e 777/* Is called from expand_exception_blocks to generate the code in a function
ddd5a7c1 778 to "throw" if anything in the function needs to perform a throw.
8d08fdba 779
ddd5a7c1 780 expands "throw" as the following pseudo code:
8d2733ca
MS
781
782 throw:
783 eh = find_first_exception_match (saved_pc);
784 if (!eh) goto gotta_rethrow_it;
785 goto eh;
786
787 gotta_rethrow_it:
788 saved_pc = __builtin_return_address (0);
789 pop_to_previous_level ();
6467930b 790 goto throw; */
8d2733ca 791
f30432d7 792void
8d2733ca
MS
793expand_builtin_throw ()
794{
0021b564 795#ifndef DWARF2_UNWIND_INFO
8d2733ca
MS
796 tree fcall;
797 tree params;
6633d636
MS
798 rtx handler;
799 rtx saved_pcnthrow;
800 rtx next_pc;
f30432d7
MS
801 rtx gotta_rethrow_it;
802 rtx gotta_call_terminate;
6633d636 803 rtx after_unwind;
f30432d7 804 rtx top_of_loop;
f30432d7 805 tree t;
6633d636 806 rtx x;
f30432d7
MS
807
808 if (! doing_eh (0))
809 return;
810
811 if (! throw_used)
812 return;
8d2733ca 813
f30432d7 814 params = void_list_node;
c11b6f21
MS
815 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
816 NULL_TREE);
6633d636
MS
817 start_function (decl_tree_cons (NULL_TREE,
818 get_identifier ("void"),
819 decl_tree_cons (NULL_TREE,
820 get_identifier ("static"),
821 NULL_TREE)),
c11b6f21 822 t, NULL_TREE, 0);
f30432d7
MS
823 store_parm_decls ();
824 pushlevel (0);
825 clear_last_expr ();
826 push_momentary ();
827 expand_start_bindings (0);
828
829 gotta_rethrow_it = gen_label_rtx ();
830 gotta_call_terminate = gen_label_rtx ();
f30432d7 831
a50f0918 832 /* These two can be frontend specific. If wanted, they can go in
e92cc029 833 expand_throw. */
a50f0918 834 /* Do we have a valid object we are throwing? */
95e8dcba
JM
835 t = call_eh_info ();
836 emit_cmp_insn (expand_expr (t, NULL_RTX, Pmode, 0),
837 const0_rtx, EQ, NULL_RTX,
5a0fa1de 838 GET_MODE (DECL_RTL (t)), 0, 0);
a50f0918
MS
839 emit_jump_insn (gen_beq (gotta_call_terminate));
840
8d2733ca 841 /* search for an exception handler for the saved_pc */
6633d636 842 handler = do_function_call (FirstExceptionMatch,
e66d884e 843 expr_tree_cons (NULL_TREE, saved_pc,
6633d636
MS
844 NULL_TREE),
845 ptr_type_node);
8d2733ca
MS
846
847 /* did we find one? */
6633d636
MS
848 emit_cmp_insn (handler, const0_rtx, EQ, NULL_RTX,
849 GET_MODE (handler), 0, 0);
8d2733ca
MS
850
851 /* if not, jump to gotta_rethrow_it */
852 emit_jump_insn (gen_beq (gotta_rethrow_it));
853
6633d636
MS
854 {
855 rtx ret_val, x;
856 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
857 0, hard_frame_pointer_rtx);
8d2733ca 858
6633d636
MS
859 /* Set it up so that we continue at the handler. */
860 emit_move_insn (ret_val, handler);
861#ifdef RETURN_ADDR_OFFSET
862 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
863 if (x != ret_val)
864 emit_move_insn (ret_val, x);
865#endif
8d2733ca 866
6633d636
MS
867 expand_null_return ();
868 }
869
870 top_of_loop = gen_label_rtx ();
871 emit_label (top_of_loop);
872
873#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
874 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
875 {
876 saved_pcnthrow = gen_reg_rtx (Pmode);
877 emit_move_insn (saved_pcnthrow, hard_function_value (ptr_type_node,
878 NULL_TREE));
879 }
880#endif
881
eb66be0e 882 /* Call to __builtin_return_address. */
be99da77
MS
883#if defined (ARM_FRAME_RTX) /* was __arm */
884 /* This should be moved into arm.h:RETURN_ADDR_RTX */
885 /* This replaces a 'call' to __builtin_return_address */
6633d636
MS
886 next_pc = gen_reg_rtx (Pmode);
887 emit_move_insn (next_pc,
888 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 889#else
e66d884e 890 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
fb98cff6 891 fcall = build_function_call (builtin_return_address_fndecl, params);
6633d636 892 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 893#endif
8d2733ca 894
eb66be0e 895 /* Did __builtin_return_address return a valid address? */
6633d636
MS
896 emit_cmp_insn (next_pc, const0_rtx, EQ, NULL_RTX,
897 GET_MODE (next_pc), 0, 0);
8d2733ca
MS
898
899 emit_jump_insn (gen_beq (gotta_call_terminate));
900
6633d636 901 next_pc = eh_outer_context (next_pc);
e1cd6e56 902
be99da77 903 /* Yes it did. */
6633d636
MS
904#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
905 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
906 {
907 rtx x;
908
909 x = validize_mem (gen_rtx (MEM, Pmode, saved_pcnthrow));
910 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode, x)),
911 next_pc);
912#ifdef FUNCTION_OUTGOING_VALUE
913 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
914 validize_mem (gen_rtx (MEM, Pmode,
915 plus_constant (saved_pcnthrow,
916 GET_MODE_SIZE (Pmode)))));
917 emit_insn (gen_rtx (USE, VOIDmode,
918 FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
919#endif
920 }
921 else
922#endif
923 emit_move_insn (eh_saved_pc_rtx, next_pc);
f30432d7 924
6633d636
MS
925 after_unwind = gen_label_rtx ();
926 do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
927
928 emit_label (after_unwind);
929
930#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
931 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
932 {
6874c264
JM
933 t = build_function_type (void_type_node, void_list_node);
934 t = make_tree (build_pointer_type (t),
6633d636
MS
935 hard_function_value (ptr_type_node,
936 NULL_TREE));
937 t = build_function_call (t, NULL_TREE);
938 expand_expr (t, const0_rtx, VOIDmode, 0);
939 }
940 else
941#endif
942 emit_throw ();
8d2733ca
MS
943
944 /* no it didn't --> therefore we need to call terminate */
945 emit_label (gotta_call_terminate);
946 do_function_call (Terminate, NULL_TREE, NULL_TREE);
f30432d7
MS
947
948 {
6633d636
MS
949 rtx ret_val, x;
950 /* code to deal with unwinding and looking for it again */
951 emit_label (gotta_rethrow_it);
f30432d7
MS
952 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
953 0, hard_frame_pointer_rtx);
954
955 /* Set it up so that we continue inside, at the top of the loop. */
956 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173 957#ifdef RETURN_ADDR_OFFSET
6633d636
MS
958 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
959 if (x != ret_val)
960 emit_move_insn (ret_val, x);
961#endif
962
963#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
964 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
965 {
966 rtx x = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode,
967 "__eh_pcnthrow"),
968 NULL_RTX, 1,
969 Pmode, 0);
970 /* This is to get a version of throw that will throw properly. */
971 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode,
972 plus_constant (x, GET_MODE_SIZE (Pmode)))),
973 throw_libfunc);
974#ifdef FUNCTION_OUTGOING_VALUE
975 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
976 x);
977 emit_insn (gen_rtx (USE, VOIDmode, FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
978#endif
979 }
f30432d7
MS
980#endif
981
e92cc029 982 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
983 }
984
fc378698 985 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
986 poplevel (1, 0, 0);
987 pop_momentary ();
988
989 finish_function (lineno, 0, 0);
0021b564 990#endif /* DWARF2_UNWIND_INFO */
8d08fdba 991}
8d2733ca 992
6c20b7e9
JM
993/* An exception spec is implemented more or less like:
994
995 try {
996 function body;
997 } catch (...) {
998 void *p[] = { typeid(raises) };
999 __check_eh_spec (p, count);
1000 }
1001
1002 __check_eh_spec in exception.cc handles all the details. */
8d2733ca 1003
f30432d7
MS
1004void
1005expand_start_eh_spec ()
1006{
6c20b7e9 1007 expand_start_try_stmts ();
f30432d7
MS
1008}
1009
5566b478 1010static void
f30432d7
MS
1011expand_end_eh_spec (raises)
1012 tree raises;
1013{
6c20b7e9
JM
1014 tree tmp, fn, decl, types = NULL_TREE;
1015 int count = 0;
f30432d7 1016
6c20b7e9
JM
1017 expand_start_all_catch ();
1018 expand_start_catch_block (NULL_TREE, NULL_TREE);
f30432d7 1019
6c20b7e9
JM
1020 /* Build up an array of type_infos. */
1021 for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))
1022 {
1023 types = expr_tree_cons
1024 (NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);
1025 ++count;
1026 }
eb66be0e 1027
6c20b7e9
JM
1028 types = build_nt (CONSTRUCTOR, NULL_TREE, types);
1029 TREE_HAS_CONSTRUCTOR (types) = 1;
6874c264 1030
6c20b7e9
JM
1031 /* We can't pass the CONSTRUCTOR directly, so stick it in a variable. */
1032 tmp = build_array_type (const_ptr_type_node, NULL_TREE);
1033 decl = build_decl (VAR_DECL, NULL_TREE, tmp);
1034 DECL_ARTIFICIAL (decl) = 1;
1035 DECL_INITIAL (decl) = types;
1036 cp_finish_decl (decl, types, NULL_TREE, 0, 0);
1037
1038 decl = decay_conversion (decl);
6874c264 1039
6c20b7e9
JM
1040 fn = get_identifier ("__check_eh_spec");
1041 if (IDENTIFIER_GLOBAL_VALUE (fn))
1042 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1043 else
f30432d7 1044 {
6c20b7e9
JM
1045 push_obstacks_nochange ();
1046 end_temporary_allocation ();
f30432d7 1047
6c20b7e9
JM
1048 tmp = tree_cons
1049 (NULL_TREE, integer_type_node, tree_cons
1050 (NULL_TREE, TREE_TYPE (decl), void_list_node));
1051 tmp = build_function_type (void_type_node, tmp);
f30432d7 1052
6c20b7e9
JM
1053 fn = build_lang_decl (FUNCTION_DECL, fn, tmp);
1054 DECL_EXTERNAL (fn) = 1;
1055 TREE_PUBLIC (fn) = 1;
1056 DECL_ARTIFICIAL (fn) = 1;
1057 TREE_THIS_VOLATILE (fn) = 1;
1058 pushdecl_top_level (fn);
1059 make_function_rtl (fn);
1060 assemble_external (fn);
1061 pop_obstacks ();
1062 }
1063
1064 tmp = expr_tree_cons (NULL_TREE, build_int_2 (count, 0), expr_tree_cons
1065 (NULL_TREE, decl, NULL_TREE));
1066 tmp = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), tmp);
1067 expand_expr (tmp, const0_rtx, VOIDmode, EXPAND_NORMAL);
1068
1069 expand_end_catch_block ();
1070 expand_end_all_catch ();
f30432d7
MS
1071}
1072
8d2733ca
MS
1073/* This is called to expand all the toplevel exception handling
1074 finalization for a function. It should only be called once per
1075 function. */
6467930b 1076
8d08fdba 1077void
8d2733ca 1078expand_exception_blocks ()
8d08fdba 1079{
92b96838 1080 do_pending_stack_adjust ();
e00737d2 1081 push_to_sequence (catch_clauses);
8d2733ca 1082 expand_leftover_cleanups ();
92b96838 1083 do_pending_stack_adjust ();
e00737d2 1084 catch_clauses = get_insns ();
f30432d7 1085 end_sequence ();
eb448459 1086
eb448459
MS
1087 /* Do this after we expand leftover cleanups, so that the
1088 expand_eh_region_end that expand_end_eh_spec does will match the
1089 right expand_eh_region_start, and make sure it comes out before
1090 the terminate protected region. */
f30432d7
MS
1091 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
1092 {
eb448459 1093 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
92b96838 1094 do_pending_stack_adjust ();
e00737d2 1095 push_to_sequence (catch_clauses);
eb448459 1096 expand_leftover_cleanups ();
92b96838 1097 do_pending_stack_adjust ();
e00737d2 1098 catch_clauses = get_insns ();
eb448459 1099 end_sequence ();
f30432d7
MS
1100 }
1101
e00737d2 1102 if (catch_clauses)
f30432d7 1103 {
e00737d2
MS
1104 rtx funcend = gen_label_rtx ();
1105 emit_jump (funcend);
1106
eb66be0e
MS
1107 /* We cannot protect n regions this way if we must flow into the
1108 EH region through the top of the region, as we have to with
1109 the setjmp/longjmp approach. */
1110 if (exceptions_via_longjmp == 0)
fb98cff6 1111 expand_eh_region_start ();
f30432d7 1112
e00737d2
MS
1113 emit_insns (catch_clauses);
1114 catch_clauses = NULL_RTX;
eb66be0e
MS
1115
1116 if (exceptions_via_longjmp == 0)
fb98cff6 1117 expand_eh_region_end (build_function_call (Terminate, NULL_TREE));
eb66be0e 1118
6467930b 1119 expand_leftover_cleanups ();
f30432d7 1120
e00737d2
MS
1121 emit_label (funcend);
1122 }
8d08fdba
MS
1123}
1124
72b7eeff
MS
1125tree
1126start_anon_func ()
1127{
1128 static int counter = 0;
e92cc029 1129 int old_interface_unknown = interface_unknown;
72b7eeff
MS
1130 char name[32];
1131 tree params;
1132 tree t;
1133
1134 push_cp_function_context (NULL_TREE);
1135 push_to_top_level ();
1136
1137 /* No need to mangle this. */
1138 push_lang_context (lang_name_c);
1139
e92cc029
MS
1140 interface_unknown = 1;
1141
72b7eeff
MS
1142 params = void_list_node;
1143 /* tcf stands for throw clean funciton. */
1144 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
1145 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
1146 NULL_TREE);
72b7eeff
MS
1147 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1148 void_list_node),
c11b6f21 1149 t, NULL_TREE, 0);
72b7eeff
MS
1150 store_parm_decls ();
1151 pushlevel (0);
1152 clear_last_expr ();
1153 push_momentary ();
1154 expand_start_bindings (0);
1155 emit_line_note (input_filename, lineno);
1156
e92cc029
MS
1157 interface_unknown = old_interface_unknown;
1158
72b7eeff
MS
1159 pop_lang_context ();
1160
1161 return current_function_decl;
1162}
1163
1164void
1165end_anon_func ()
1166{
fc378698 1167 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1168 poplevel (1, 0, 0);
1169 pop_momentary ();
1170
1171 finish_function (lineno, 0, 0);
1172
1173 pop_from_top_level ();
1174 pop_cp_function_context (NULL_TREE);
1175}
8d2733ca 1176
6467930b 1177/* Expand a throw statement. This follows the following
8d2733ca
MS
1178 algorithm:
1179
1180 1. Allocate space to save the current PC onto the stack.
1181 2. Generate and emit a label and save its address into the
e1cd6e56 1182 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1183 3. If this is the first call to throw in this function:
1184 generate a label for the throw block
1185 4. jump to the throw block label. */
6467930b 1186
8d08fdba 1187void
8d2733ca
MS
1188expand_throw (exp)
1189 tree exp;
8d08fdba 1190{
8d2733ca 1191 rtx label;
6874c264
JM
1192 tree fn;
1193 static tree cleanup_type;
8d08fdba 1194
8d2733ca
MS
1195 if (! doing_eh (1))
1196 return;
8d08fdba 1197
8d2733ca
MS
1198 if (exp)
1199 {
faae18ab 1200 tree throw_type;
6874c264 1201 tree cleanup = NULL_TREE, e;
faae18ab 1202
a3b49ccd 1203 /* throw expression */
e92cc029 1204 /* First, decay it. */
f30432d7 1205 exp = decay_conversion (exp);
a3b49ccd 1206
6874c264
JM
1207 /* cleanup_type is void (*)(void *, int),
1208 the internal type of a destructor. */
1209 if (cleanup_type == NULL_TREE)
1210 {
1211 push_obstacks_nochange ();
1212 end_temporary_allocation ();
1213 cleanup_type = build_pointer_type
1214 (build_function_type
1215 (void_type_node, tree_cons
1216 (NULL_TREE, ptr_type_node, tree_cons
1217 (NULL_TREE, integer_type_node, void_list_node))));
1218 pop_obstacks ();
1219 }
1220
f30432d7
MS
1221 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1222 {
1223 throw_type = build_eh_type (exp);
1224 exp = build_reinterpret_cast (ptr_type_node, exp);
1225 }
1226 else
1227 {
72b7eeff 1228 tree object;
a50f0918 1229
f30432d7
MS
1230 /* Make a copy of the thrown object. WP 15.1.5 */
1231 exp = build_new (NULL_TREE, TREE_TYPE (exp),
e66d884e 1232 build_expr_list (NULL_TREE, exp),
f30432d7 1233 0);
faae18ab 1234
f30432d7
MS
1235 if (exp == error_mark_node)
1236 error (" in thrown expression");
faae18ab 1237
72b7eeff
MS
1238 object = build_indirect_ref (exp, NULL_PTR);
1239 throw_type = build_eh_type (object);
1240
6874c264
JM
1241 if (TYPE_HAS_DESTRUCTOR (TREE_TYPE (object)))
1242 {
1243 cleanup = lookup_fnfields (TYPE_BINFO (TREE_TYPE (object)),
1244 dtor_identifier, 0);
1245 cleanup = TREE_VALUE (cleanup);
e872bb7a 1246 mark_used (cleanup);
6874c264
JM
1247 mark_addressable (cleanup);
1248 /* Pretend it's a normal function. */
1249 cleanup = build1 (ADDR_EXPR, cleanup_type, cleanup);
1250 }
f30432d7 1251 }
faae18ab 1252
6874c264
JM
1253 if (cleanup == NULL_TREE)
1254 {
1255 cleanup = build_int_2 (0, 0);
1256 TREE_TYPE (cleanup) = cleanup_type;
1257 }
72b7eeff 1258
6874c264
JM
1259 fn = get_identifier ("__cp_push_exception");
1260 if (IDENTIFIER_GLOBAL_VALUE (fn))
1261 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1262 else
1263 {
1264 /* Declare __cp_push_exception (void*, void*, void (*)(void*, int)),
1265 as defined in exception.cc. */
1266 tree tmp;
1267 push_obstacks_nochange ();
1268 end_temporary_allocation ();
1269 tmp = tree_cons
1270 (NULL_TREE, ptr_type_node, tree_cons
1271 (NULL_TREE, ptr_type_node, tree_cons
1272 (NULL_TREE, cleanup_type, void_list_node)));
1273 fn = build_lang_decl (FUNCTION_DECL, fn,
1274 build_function_type (void_type_node, tmp));
1275 DECL_EXTERNAL (fn) = 1;
1276 TREE_PUBLIC (fn) = 1;
1277 DECL_ARTIFICIAL (fn) = 1;
1278 pushdecl_top_level (fn);
1279 make_function_rtl (fn);
1280 assemble_external (fn);
1281 pop_obstacks ();
1282 }
72b7eeff 1283
6874c264
JM
1284 /* The throw expression is a full-expression. */
1285 exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
1286 e = expr_tree_cons (NULL_TREE, exp, expr_tree_cons
1287 (NULL_TREE, throw_type, expr_tree_cons
1288 (NULL_TREE, cleanup, NULL_TREE)));
1289 e = build_function_call (fn, e);
1290 expand_expr (e, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1291 }
1292 else
a3b49ccd 1293 {
6874c264
JM
1294 /* rethrow current exception; note that it's no longer caught. */
1295
1296 tree fn = get_identifier ("__uncatch_exception");
1297 if (IDENTIFIER_GLOBAL_VALUE (fn))
1298 fn = IDENTIFIER_GLOBAL_VALUE (fn);
1299 else
1300 {
1301 /* Declare void __uncatch_exception (void)
1302 as defined in exception.cc. */
1303 push_obstacks_nochange ();
1304 end_temporary_allocation ();
1305 fn = build_lang_decl (FUNCTION_DECL, fn,
1306 build_function_type (void_type_node,
1307 void_list_node));
1308 DECL_EXTERNAL (fn) = 1;
1309 TREE_PUBLIC (fn) = 1;
1310 DECL_ARTIFICIAL (fn) = 1;
1311 pushdecl_top_level (fn);
1312 make_function_rtl (fn);
1313 assemble_external (fn);
1314 pop_obstacks ();
1315 }
1316
1317 exp = build_function_call (fn, NULL_TREE);
1318 expand_expr (exp, const0_rtx, VOIDmode, EXPAND_NORMAL);
a3b49ccd 1319 }
8d2733ca 1320
eb66be0e
MS
1321 if (exceptions_via_longjmp)
1322 emit_throw ();
1323 else
1324 {
1325 /* This is the label that represents where in the code we were, when
1326 we got an exception. This needs to be updated when we rethrow an
1327 exception, so that the matching routine knows to search out. */
1328 label = gen_label_rtx ();
1329 emit_label (label);
8d2733ca 1330
eb66be0e
MS
1331 expand_internal_throw (label);
1332 }
f376e137 1333}
8d2733ca
MS
1334
1335/* Build a throw expression. */
6467930b 1336
8d2733ca
MS
1337tree
1338build_throw (e)
1339 tree e;
1340{
db5ae43f
MS
1341 if (e != error_mark_node)
1342 {
5156628f 1343 if (processing_template_decl)
fc378698 1344 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1345 e = build1 (THROW_EXPR, void_type_node, e);
1346 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1347 TREE_USED (e) = 1;
db5ae43f 1348 }
8d2733ca 1349 return e;
8d08fdba 1350}
This page took 0.405295 seconds and 5 git commands to generate.