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