]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
expr.c (expand_increment): When enqueing a postincrement for a MEM...
[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
72b7eeff
MS
183static tree empty_fndecl;
184
8d2733ca
MS
185/* ====================================================================== */
186
187
8d2733ca
MS
188/* ========================================================================= */
189
190
191
192/* local globals - these local globals are for storing data necessary for
193 generating the exception table and code in the correct order.
194
195 ========================================================================= */
196
a3b49ccd 197/* Holds the pc for doing "throw" */
5566b478 198static tree saved_pc;
e92cc029 199/* Holds the type of the thing being thrown. */
5566b478 200static tree saved_throw_type;
a3b49ccd 201/* Holds the value being thrown. */
5566b478 202static tree saved_throw_value;
72b7eeff 203/* Holds the cleanup for the value being thrown. */
5566b478 204static tree saved_cleanup;
a50f0918
MS
205/* Indicates if we are in a catch clause. */
206static tree saved_in_catch;
f30432d7 207
6467930b
MS
208extern int throw_used;
209extern rtx catch_clauses;
8d2733ca 210
8d2733ca
MS
211/* ========================================================================= */
212
6467930b 213/* Cheesyness to save some typing. Returns the return value rtx. */
8d2733ca 214
5566b478 215static rtx
f30432d7
MS
216do_function_call (func, params, return_type)
217 tree func, params, return_type;
218{
219 tree func_call;
220 func_call = build_function_call (func, params);
221 expand_call (func_call, NULL_RTX, 0);
222 if (return_type != NULL_TREE)
223 return hard_function_value (return_type, func_call);
224 return NULL_RTX;
225}
226
8d2733ca
MS
227/* ========================================================================= */
228
8d2733ca
MS
229/* sets up all the global eh stuff that needs to be initialized at the
230 start of compilation.
231
232 This includes:
6467930b 233 - Setting up all the function call trees. */
8d08fdba 234
8d08fdba 235void
8d2733ca 236init_exception_processing ()
8d08fdba 237{
8d2733ca
MS
238 tree unexpected_fndecl, terminate_fndecl;
239 tree set_unexpected_fndecl, set_terminate_fndecl;
240 tree catch_match_fndecl;
241 tree find_first_exception_match_fndecl;
242 tree unwind_fndecl;
f30432d7
MS
243 tree declspecs;
244 tree d;
a3b49ccd 245
6633d636
MS
246 /* void vtype () */
247 tree vtype = build_function_type (void_type_node, void_list_node);
248
8d2733ca 249 /* void (*)() */
6633d636 250 tree PFV = build_pointer_type (vtype);
8d08fdba 251
eb66be0e
MS
252 /* Arg list for the build_function_type call for set_terminate and
253 set_unexpected. */
8ccc31eb 254 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 255
8ccc31eb
MS
256 /* void (*pfvtype (void (*) ()))() */
257 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 258
8ccc31eb
MS
259 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
260 pfvtype, NOT_BUILT_IN);
261 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
262 pfvtype, NOT_BUILT_IN);
263 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
264 vtype, NOT_BUILT_IN);
265 terminate_fndecl = auto_function (get_identifier ("terminate"),
266 vtype, NOT_BUILT_IN);
e00737d2 267 TREE_THIS_VOLATILE (terminate_fndecl) = 1;
8ccc31eb 268
8ccc31eb 269 push_lang_context (lang_name_c);
8d2733ca 270
beb53fb8
JM
271 catch_match_fndecl
272 = builtin_function (flag_rtti
273 ? "__throw_type_match_rtti"
274 : "__throw_type_match",
275 build_function_type (ptr_type_node,
276 tree_cons (NULL_TREE, ptr_type_node,
277 tree_cons (NULL_TREE, ptr_type_node,
278 tree_cons (NULL_TREE, ptr_type_node,
279 void_list_node)))),
280 NOT_BUILT_IN, NULL_PTR);
281 find_first_exception_match_fndecl
282 = builtin_function ("__find_first_exception_table_match",
283 build_function_type (ptr_type_node,
284 tree_cons (NULL_TREE, ptr_type_node,
285 void_list_node)),
286 NOT_BUILT_IN, NULL_PTR);
287 unwind_fndecl
288 = builtin_function ("__unwind_function",
289 build_function_type (void_type_node,
290 tree_cons (NULL_TREE, ptr_type_node,
291 void_list_node)),
292 NOT_BUILT_IN, NULL_PTR);
293 empty_fndecl
294 = builtin_function ("__empty",
6633d636 295 vtype,
beb53fb8 296 NOT_BUILT_IN, NULL_PTR);
72b7eeff
MS
297 DECL_EXTERNAL (empty_fndecl) = 1;
298 TREE_PUBLIC (empty_fndecl) = 1;
8d2733ca
MS
299
300 Unexpected = default_conversion (unexpected_fndecl);
301 Terminate = default_conversion (terminate_fndecl);
302 SetTerminate = default_conversion (set_terminate_fndecl);
303 SetUnexpected = default_conversion (set_unexpected_fndecl);
304 CatchMatch = default_conversion (catch_match_fndecl);
305 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
306 Unwind = default_conversion (unwind_fndecl);
307 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
308
309 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
310
311 pop_lang_context ();
f30432d7 312
f30432d7
MS
313 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
314 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
c11b6f21 315 d = start_decl (d, declspecs, 0);
f30432d7 316 DECL_COMMON (d) = 1;
9e9ff709 317 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
318 saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
319
320 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
321 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
c11b6f21 322 d = start_decl (d, declspecs, 0);
f30432d7 323 DECL_COMMON (d) = 1;
9e9ff709 324 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
325 saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
326
327 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
328 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
c11b6f21 329 d = start_decl (d, declspecs, 0);
f30432d7 330 DECL_COMMON (d) = 1;
9e9ff709 331 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7 332 saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
72b7eeff
MS
333
334 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
335 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_cleanup"));
c11b6f21
MS
336 d = make_call_declarator (d, void_list_node, NULL_TREE, NULL_TREE);
337 d = start_decl (d, declspecs, 0);
72b7eeff 338 DECL_COMMON (d) = 1;
9e9ff709 339 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
72b7eeff 340 saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0);
a50f0918
MS
341
342 declspecs = tree_cons (NULL_TREE, get_identifier ("bool"), NULL_TREE);
343 d = get_identifier ("__eh_in_catch");
c11b6f21 344 d = start_decl (d, declspecs, 0);
a50f0918
MS
345 DECL_COMMON (d) = 1;
346 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
347 saved_in_catch = lookup_name (get_identifier ("__eh_in_catch"), 0);
eb66be0e
MS
348
349 /* If we use setjmp/longjmp EH, arrange for all cleanup actions to
350 be protected with __terminate. */
351 protect_cleanup_actions_with_terminate = 1;
8d2733ca
MS
352}
353
f30432d7
MS
354/* Build a type value for use at runtime for a type that is matched
355 against by the exception handling system. */
6467930b 356
f30432d7
MS
357static tree
358build_eh_type_type (type)
359 tree type;
8d08fdba 360{
f30432d7
MS
361 char *typestring;
362 tree exp;
8d2733ca 363
f30432d7
MS
364 if (type == error_mark_node)
365 return error_mark_node;
8d2733ca 366
e92cc029 367 /* peel back references, so they match. */
f30432d7
MS
368 if (TREE_CODE (type) == REFERENCE_TYPE)
369 type = TREE_TYPE (type);
8d08fdba 370
e92cc029 371 /* Peel off cv qualifiers. */
f30432d7 372 type = TYPE_MAIN_VARIANT (type);
8d2733ca 373
f30432d7 374 if (flag_rtti)
8d08fdba 375 {
f30432d7 376 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 377 }
f30432d7
MS
378
379 typestring = build_overload_name (type, 1, 1);
380 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
381 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 382}
8d08fdba 383
faae18ab
MS
384/* Build a type value for use at runtime for a exp that is thrown or
385 matched against by the exception handling system. */
6467930b 386
faae18ab
MS
387static tree
388build_eh_type (exp)
389 tree exp;
390{
faae18ab
MS
391 if (flag_rtti)
392 {
393 exp = build_typeid (exp);
394 return build1 (ADDR_EXPR, ptr_type_node, exp);
395 }
f30432d7 396 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
397}
398
72b7eeff 399/* This routine creates the cleanup for the exception handling object. */
6467930b 400
5566b478 401static void
72b7eeff
MS
402push_eh_cleanup ()
403{
404 /* All cleanups must last longer than normal. */
405 int yes = suspend_momentary ();
406
407 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
408 tree cleanup = build_function_call (saved_cleanup, NULL_TREE);
a50f0918
MS
409 cleanup = build (COMPOUND_EXPR, void_type_node, cleanup,
410 build_modify_expr (saved_in_catch, NOP_EXPR,
411 build_modify_expr (saved_throw_type, NOP_EXPR, integer_zero_node)));
e349ee73 412 expand_decl_cleanup (NULL_TREE, cleanup);
72b7eeff
MS
413
414 resume_momentary (yes);
415}
416
417
8d2733ca
MS
418/* call this to start a catch block. Typename is the typename, and identifier
419 is the variable to place the object in or NULL if the variable doesn't
420 matter. If typename is NULL, that means its a "catch (...)" or catch
421 everything. In that case we don't need to do any type checking.
422 (ie: it ends up as the "else" clause rather than an "else if" clause) */
6467930b 423
8d08fdba 424void
a4443a08
MS
425expand_start_catch_block (declspecs, declarator)
426 tree declspecs, declarator;
8d08fdba 427{
8d2733ca 428 rtx false_label_rtx;
faae18ab 429 tree decl = NULL_TREE;
a3b49ccd 430 tree init;
8d2733ca 431
faf5394a
MS
432 if (processing_template_decl)
433 {
434 if (declspecs)
435 {
436 decl = grokdeclarator (declarator, declspecs, CATCHPARM,
437 1, NULL_TREE);
438 pushdecl (decl);
439 decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),
440 copy_to_permanent (declspecs),
441 NULL_TREE);
442 add_tree (decl);
443 }
444 return;
445 }
446
8d2733ca
MS
447 if (! doing_eh (1))
448 return;
449
a3b49ccd 450 /* Create a binding level for the parm. */
c11b6f21 451 pushlevel (0);
a3b49ccd
MS
452 expand_start_bindings (0);
453
f675499c 454 false_label_rtx = gen_label_rtx ();
72b7eeff 455 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
a3b49ccd 456
eb66be0e
MS
457 emit_line_note (input_filename, lineno);
458
faae18ab 459 if (declspecs)
8d08fdba 460 {
faae18ab 461 tree exp;
8d2733ca 462 rtx call_rtx, return_value_rtx;
faae18ab
MS
463 tree init_type;
464
c11b6f21 465 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
faae18ab
MS
466
467 if (decl == NULL_TREE)
468 {
469 error ("invalid catch parameter");
6467930b 470
eb66be0e
MS
471 /* This is cheap, but we want to maintain the data
472 structures. */
473
6467930b 474 expand_eh_region_start ();
eb66be0e 475
faae18ab
MS
476 return;
477 }
478
be99da77
MS
479 /* Make sure we mark the catch param as used, otherwise we'll get
480 a warning about an unused ((anonymous)). */
481 TREE_USED (decl) = 1;
482
e92cc029 483 /* Figure out the type that the initializer is. */
faae18ab 484 init_type = TREE_TYPE (decl);
f30432d7
MS
485 if (TREE_CODE (init_type) != REFERENCE_TYPE
486 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
487 init_type = build_reference_type (init_type);
488
f30432d7 489 exp = saved_throw_value;
e66d884e 490 exp = expr_tree_cons (NULL_TREE,
f30432d7 491 build_eh_type_type (TREE_TYPE (decl)),
e66d884e 492 expr_tree_cons (NULL_TREE,
f30432d7 493 saved_throw_type,
e66d884e 494 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
faae18ab
MS
495 exp = build_function_call (CatchMatch, exp);
496 call_rtx = expand_call (exp, NULL_RTX, 0);
e1cd6e56 497 assemble_external (TREE_OPERAND (CatchMatch, 0));
8d2733ca 498
faae18ab 499 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
500
501 /* did the throw type match function return TRUE? */
faae18ab 502 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
503 GET_MODE (return_value_rtx), 0, 0);
504
505 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
506 emit_jump_insn (gen_beq (false_label_rtx));
507
72b7eeff
MS
508 push_eh_cleanup ();
509
faae18ab
MS
510 init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
511
512 /* Do we need the below two lines? */
b3417a04 513 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
514 DECL_INITIAL (decl) = init;
515 decl = pushdecl (decl);
b3417a04 516 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba
MS
517 }
518 else
519 {
72b7eeff
MS
520 push_eh_cleanup ();
521
e92cc029 522 /* Fall into the catch all section. */
8d08fdba 523 }
a3b49ccd 524
a50f0918 525 emit_move_insn (DECL_RTL (saved_in_catch), const1_rtx);
f30432d7 526
eb66be0e
MS
527 /* If we are not doing setjmp/longjmp EH, because we are reordered
528 out of line, we arrange to rethrow in the outer context so as to
529 skip through the terminate region we are nested in, should we
530 encounter an exception in the catch handler.
f30432d7 531
eb66be0e
MS
532 If we are doing setjmp/longjmp EH, we need to skip through the EH
533 object cleanup region. This isn't quite right, as we really need
534 to clean the object up, but we cannot do that until we track
535 multiple EH objects.
536
537 Matches the end in expand_end_catch_block. */
6467930b 538 expand_eh_region_start ();
f30432d7 539
6467930b
MS
540 emit_line_note (input_filename, lineno);
541}
f30432d7 542
f30432d7 543
f30432d7 544
8d2733ca
MS
545/* Call this to end a catch block. Its responsible for emitting the
546 code to handle jumping back to the correct place, and for emitting
547 the label to jump to if this catch block didn't match. */
6467930b 548
824b9a4c
MS
549void
550expand_end_catch_block ()
8d08fdba 551{
6467930b
MS
552 rtx start_region_label_rtx;
553 rtx end_region_label_rtx;
554 tree decls, t;
a3b49ccd 555
f30432d7
MS
556 if (! doing_eh (1))
557 return;
8d2733ca 558
6467930b
MS
559 t = make_node (RTL_EXPR);
560 TREE_TYPE (t) = void_type_node;
561 RTL_EXPR_RTL (t) = const0_rtx;
562 TREE_SIDE_EFFECTS (t) = 1;
92b96838 563 do_pending_stack_adjust ();
6467930b 564 start_sequence_for_rtl_expr (t);
eb66be0e
MS
565
566 if (exceptions_via_longjmp)
567 {
568 /* If we are doing setjmp/longjmp EH, we need to skip through
569 the EH object cleanup region. This isn't quite right, as we
570 really need to clean the object up, but we cannot do that
571 until we track multiple EH objects. */
572
573 emit_library_call (sjpopnthrow_libfunc, 0, VOIDmode, 0);
574 emit_barrier ();
575 }
576 else
577 {
578 /* If we are not doing setjmp/longjmp EH, we need an extra
579 region around the whole catch block to skip through the
580 terminate region we are nested in. */
581
582 expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack)));
583 }
584
92b96838 585 do_pending_stack_adjust ();
6467930b
MS
586 RTL_EXPR_SEQUENCE (t) = get_insns ();
587 end_sequence ();
f30432d7 588
eb66be0e 589 /* Matches the start in expand_start_catch_block. */
6467930b 590 expand_eh_region_end (t);
f30432d7 591
eb66be0e
MS
592 /* Fall to outside the try statement when done executing handler and
593 we fall off end of handler. This is jump Lresume in the
594 documentation. */
595 expand_goto (top_label_entry (&caught_return_label_stack));
596
6467930b 597 expand_leftover_cleanups ();
f30432d7
MS
598
599 /* Cleanup the EH parameter. */
c11b6f21
MS
600 expand_end_bindings (getdecls (), kept_level_p (), 0);
601 poplevel (kept_level_p (), 1, 0);
a3b49ccd 602
6467930b 603 /* label we emit to jump to if this catch block didn't match. */
f30432d7
MS
604 /* This the closing } in the `if (eq) {' of the documentation. */
605 emit_label (pop_label_entry (&false_label_stack));
8d2733ca 606}
8d08fdba 607
6467930b
MS
608/* unwind the stack. */
609
db5ae43f 610static void
f30432d7
MS
611do_unwind (inner_throw_label)
612 rtx inner_throw_label;
db5ae43f 613{
be99da77 614#if defined (SPARC_STACK_ALIGN) /* was sparc */
0021b564
JM
615 /* This doesn't work for the flat model sparc, nor does it need to
616 as the default unwinder is only used to unwind non-flat frames. */
db5ae43f
MS
617 tree fcall;
618 tree params;
6633d636 619 rtx next_pc;
f30432d7 620 rtx temp;
db5ae43f 621
eb66be0e 622 /* Call to __builtin_return_address. */
e66d884e 623 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
db5ae43f 624 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 625 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 626 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 627 really the address of the call insn, not the next insn. */
f30432d7
MS
628 temp = gen_reg_rtx (Pmode);
629 emit_move_insn (temp, inner_throw_label);
6633d636 630 emit_move_insn (next_pc, plus_constant (temp, -8));
d11ad92e 631 emit_insn (gen_rtx (USE, VOIDmode, gen_rtx (REG, SImode, 31)));
db5ae43f
MS
632 easy_expand_asm ("ret");
633 easy_expand_asm ("restore");
634 emit_barrier ();
635#endif
be99da77 636#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
637 if (flag_omit_frame_pointer)
638 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 639
f30432d7
MS
640 emit_move_insn (stack_pointer_rtx,
641 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
642 emit_move_insn (hard_frame_pointer_rtx,
643 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 644#endif
be99da77 645#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
646 rtx temp_frame = frame_pointer_rtx;
647
648 temp_frame = memory_address (Pmode, temp_frame);
649 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
650
651 /* hopefully this will successfully pop the frame! */
652 emit_move_insn (frame_pointer_rtx, temp_frame);
653 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
654 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
655 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
656 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
657
658#if 0
659 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
660 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
661
662 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
663
664 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
665 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
666#endif
667#endif
be99da77 668#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
669 tree fcall;
670 tree params;
6633d636 671 rtx next_pc;
e1cd6e56 672
be99da77 673#if 0
e92cc029 674 /* I would like to do this here, but the move below doesn't seem to work. */
eb66be0e 675 /* Call to __builtin_return_address. */
e66d884e 676 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
f30432d7 677 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 678 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 679
6633d636 680 emit_move_insn (next_pc, inner_throw_label);
e92cc029 681 /* So, for now, just pass throw label to stack unwinder. */
f30432d7 682#endif
e66d884e 683 params = expr_tree_cons (NULL_TREE, make_tree (ptr_type_node,
f30432d7
MS
684 inner_throw_label), NULL_TREE);
685
686 do_function_call (Unwind, params, NULL_TREE);
687 assemble_external (TREE_OPERAND (Unwind, 0));
688 emit_barrier ();
e1cd6e56 689#endif
db5ae43f 690}
8d08fdba 691
f30432d7 692
eb66be0e 693/* Is called from expand_exception_blocks to generate the code in a function
ddd5a7c1 694 to "throw" if anything in the function needs to perform a throw.
8d08fdba 695
ddd5a7c1 696 expands "throw" as the following pseudo code:
8d2733ca
MS
697
698 throw:
699 eh = find_first_exception_match (saved_pc);
700 if (!eh) goto gotta_rethrow_it;
701 goto eh;
702
703 gotta_rethrow_it:
704 saved_pc = __builtin_return_address (0);
705 pop_to_previous_level ();
6467930b 706 goto throw; */
8d2733ca 707
f30432d7 708void
8d2733ca
MS
709expand_builtin_throw ()
710{
0021b564 711#ifndef DWARF2_UNWIND_INFO
8d2733ca
MS
712 tree fcall;
713 tree params;
6633d636
MS
714 rtx handler;
715 rtx saved_pcnthrow;
716 rtx next_pc;
f30432d7
MS
717 rtx gotta_rethrow_it;
718 rtx gotta_call_terminate;
6633d636 719 rtx after_unwind;
f30432d7 720 rtx top_of_loop;
f30432d7 721 tree t;
6633d636 722 rtx x;
f30432d7
MS
723
724 if (! doing_eh (0))
725 return;
726
727 if (! throw_used)
728 return;
8d2733ca 729
f30432d7 730 params = void_list_node;
c11b6f21
MS
731 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
732 NULL_TREE);
6633d636
MS
733 start_function (decl_tree_cons (NULL_TREE,
734 get_identifier ("void"),
735 decl_tree_cons (NULL_TREE,
736 get_identifier ("static"),
737 NULL_TREE)),
c11b6f21 738 t, NULL_TREE, 0);
f30432d7
MS
739 store_parm_decls ();
740 pushlevel (0);
741 clear_last_expr ();
742 push_momentary ();
743 expand_start_bindings (0);
744
745 gotta_rethrow_it = gen_label_rtx ();
746 gotta_call_terminate = gen_label_rtx ();
f30432d7 747
a50f0918 748 /* These two can be frontend specific. If wanted, they can go in
e92cc029 749 expand_throw. */
a50f0918
MS
750 /* Do we have a valid object we are throwing? */
751 emit_cmp_insn (DECL_RTL (saved_throw_type), const0_rtx, EQ, NULL_RTX,
752 GET_MODE (DECL_RTL (saved_throw_type)), 0, 0);
753 emit_jump_insn (gen_beq (gotta_call_terminate));
754
8d2733ca 755 /* search for an exception handler for the saved_pc */
6633d636 756 handler = do_function_call (FirstExceptionMatch,
e66d884e 757 expr_tree_cons (NULL_TREE, saved_pc,
6633d636
MS
758 NULL_TREE),
759 ptr_type_node);
e1cd6e56 760 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
761
762 /* did we find one? */
6633d636
MS
763 emit_cmp_insn (handler, const0_rtx, EQ, NULL_RTX,
764 GET_MODE (handler), 0, 0);
8d2733ca
MS
765
766 /* if not, jump to gotta_rethrow_it */
767 emit_jump_insn (gen_beq (gotta_rethrow_it));
768
6633d636
MS
769 {
770 rtx ret_val, x;
771 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
772 0, hard_frame_pointer_rtx);
8d2733ca 773
6633d636
MS
774 /* Set it up so that we continue at the handler. */
775 emit_move_insn (ret_val, handler);
776#ifdef RETURN_ADDR_OFFSET
777 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
778 if (x != ret_val)
779 emit_move_insn (ret_val, x);
780#endif
8d2733ca 781
6633d636
MS
782 expand_null_return ();
783 }
784
785 top_of_loop = gen_label_rtx ();
786 emit_label (top_of_loop);
787
788#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
789 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
790 {
791 saved_pcnthrow = gen_reg_rtx (Pmode);
792 emit_move_insn (saved_pcnthrow, hard_function_value (ptr_type_node,
793 NULL_TREE));
794 }
795#endif
796
eb66be0e 797 /* Call to __builtin_return_address. */
be99da77
MS
798#if defined (ARM_FRAME_RTX) /* was __arm */
799 /* This should be moved into arm.h:RETURN_ADDR_RTX */
800 /* This replaces a 'call' to __builtin_return_address */
6633d636
MS
801 next_pc = gen_reg_rtx (Pmode);
802 emit_move_insn (next_pc,
803 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 804#else
e66d884e 805 params = expr_tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 806 fcall = build_function_call (BuiltinReturnAddress, params);
6633d636 807 next_pc = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 808#endif
8d2733ca 809
eb66be0e 810 /* Did __builtin_return_address return a valid address? */
6633d636
MS
811 emit_cmp_insn (next_pc, const0_rtx, EQ, NULL_RTX,
812 GET_MODE (next_pc), 0, 0);
8d2733ca
MS
813
814 emit_jump_insn (gen_beq (gotta_call_terminate));
815
6633d636 816 next_pc = eh_outer_context (next_pc);
e1cd6e56 817
be99da77 818 /* Yes it did. */
6633d636
MS
819#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
820 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
821 {
822 rtx x;
823
824 x = validize_mem (gen_rtx (MEM, Pmode, saved_pcnthrow));
825 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode, x)),
826 next_pc);
827#ifdef FUNCTION_OUTGOING_VALUE
828 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
829 validize_mem (gen_rtx (MEM, Pmode,
830 plus_constant (saved_pcnthrow,
831 GET_MODE_SIZE (Pmode)))));
832 emit_insn (gen_rtx (USE, VOIDmode,
833 FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
834#endif
835 }
836 else
837#endif
838 emit_move_insn (eh_saved_pc_rtx, next_pc);
f30432d7 839
6633d636
MS
840 after_unwind = gen_label_rtx ();
841 do_unwind (gen_rtx (LABEL_REF, Pmode, after_unwind));
842
843 emit_label (after_unwind);
844
845#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
846 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
847 {
848 t = make_tree (build_pointer_type (TREE_TYPE (empty_fndecl)),
849 hard_function_value (ptr_type_node,
850 NULL_TREE));
851 t = build_function_call (t, NULL_TREE);
852 expand_expr (t, const0_rtx, VOIDmode, 0);
853 }
854 else
855#endif
856 emit_throw ();
8d2733ca
MS
857
858 /* no it didn't --> therefore we need to call terminate */
859 emit_label (gotta_call_terminate);
860 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 861 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
862
863 {
6633d636
MS
864 rtx ret_val, x;
865 /* code to deal with unwinding and looking for it again */
866 emit_label (gotta_rethrow_it);
f30432d7
MS
867 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
868 0, hard_frame_pointer_rtx);
869
870 /* Set it up so that we continue inside, at the top of the loop. */
871 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173 872#ifdef RETURN_ADDR_OFFSET
6633d636
MS
873 x = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
874 if (x != ret_val)
875 emit_move_insn (ret_val, x);
876#endif
877
878#ifdef DONT_ACCESS_GBLS_AFTER_EPILOGUE
879 if (DONT_ACCESS_GBLS_AFTER_EPILOGUE)
880 {
881 rtx x = emit_library_call_value (gen_rtx (SYMBOL_REF, Pmode,
882 "__eh_pcnthrow"),
883 NULL_RTX, 1,
884 Pmode, 0);
885 /* This is to get a version of throw that will throw properly. */
886 emit_move_insn (validize_mem (gen_rtx (MEM, Pmode,
887 plus_constant (x, GET_MODE_SIZE (Pmode)))),
888 throw_libfunc);
889#ifdef FUNCTION_OUTGOING_VALUE
890 emit_move_insn (FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE),
891 x);
892 emit_insn (gen_rtx (USE, VOIDmode, FUNCTION_OUTGOING_VALUE (ptr_type_node, NULL_TREE)));
893#endif
894 }
f30432d7
MS
895#endif
896
e92cc029 897 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
898 }
899
fc378698 900 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
901 poplevel (1, 0, 0);
902 pop_momentary ();
903
904 finish_function (lineno, 0, 0);
0021b564 905#endif /* DWARF2_UNWIND_INFO */
8d08fdba 906}
8d2733ca
MS
907
908
f30432d7
MS
909void
910expand_start_eh_spec ()
911{
6467930b 912 expand_eh_region_start ();
f30432d7
MS
913}
914
5566b478 915static void
f30432d7
MS
916expand_end_eh_spec (raises)
917 tree raises;
918{
919 tree expr, second_try;
920 rtx check = gen_label_rtx ();
921 rtx cont;
922 rtx ret = gen_reg_rtx (Pmode);
923 rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
924 rtx end = gen_label_rtx ();
925
926 expr = make_node (RTL_EXPR);
927 TREE_TYPE (expr) = void_type_node;
928 RTL_EXPR_RTL (expr) = const0_rtx;
929 TREE_SIDE_EFFECTS (expr) = 1;
92b96838 930 do_pending_stack_adjust ();
f30432d7
MS
931 start_sequence_for_rtl_expr (expr);
932 cont = gen_label_rtx ();
933 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
934 emit_jump (check);
935 emit_label (cont);
936 jumpif (make_tree (integer_type_node, flag), end);
937 do_function_call (Terminate, NULL_TREE, NULL_TREE);
938 assemble_external (TREE_OPERAND (Terminate, 0));
939 emit_barrier ();
92b96838 940 do_pending_stack_adjust ();
f30432d7
MS
941 RTL_EXPR_SEQUENCE (expr) = get_insns ();
942 end_sequence ();
943
944 second_try = expr;
945
946 expr = make_node (RTL_EXPR);
947 TREE_TYPE (expr) = void_type_node;
948 RTL_EXPR_RTL (expr) = const0_rtx;
949 TREE_SIDE_EFFECTS (expr) = 1;
92b96838 950 do_pending_stack_adjust ();
f30432d7
MS
951 start_sequence_for_rtl_expr (expr);
952
953 cont = gen_label_rtx ();
954 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
955 emit_jump (check);
956 emit_label (cont);
957 jumpif (make_tree (integer_type_node, flag), end);
6467930b 958 expand_eh_region_start ();
f30432d7
MS
959 do_function_call (Unexpected, NULL_TREE, NULL_TREE);
960 assemble_external (TREE_OPERAND (Unexpected, 0));
961 emit_barrier ();
eb66be0e 962
6467930b 963 expand_eh_region_end (second_try);
f30432d7
MS
964
965 emit_label (check);
966 emit_move_insn (flag, const1_rtx);
967 cont = gen_label_rtx ();
968 while (raises)
969 {
970 tree exp;
971 tree match_type = TREE_VALUE (raises);
972
973 if (match_type)
974 {
975 /* check TREE_VALUE (raises) here */
976 exp = saved_throw_value;
e66d884e 977 exp = expr_tree_cons (NULL_TREE,
f30432d7 978 build_eh_type_type (match_type),
e66d884e 979 expr_tree_cons (NULL_TREE,
f30432d7 980 saved_throw_type,
e66d884e 981 expr_tree_cons (NULL_TREE, exp, NULL_TREE)));
f30432d7
MS
982 exp = build_function_call (CatchMatch, exp);
983 assemble_external (TREE_OPERAND (CatchMatch, 0));
984
985 jumpif (exp, cont);
986 }
987
988 raises = TREE_CHAIN (raises);
989 }
990 emit_move_insn (flag, const0_rtx);
991 emit_label (cont);
992 emit_indirect_jump (ret);
993 emit_label (end);
994
92b96838 995 do_pending_stack_adjust ();
f30432d7
MS
996 RTL_EXPR_SEQUENCE (expr) = get_insns ();
997 end_sequence ();
998
6467930b 999 expand_eh_region_end (expr);
f30432d7
MS
1000}
1001
8d2733ca
MS
1002/* This is called to expand all the toplevel exception handling
1003 finalization for a function. It should only be called once per
1004 function. */
6467930b 1005
8d08fdba 1006void
8d2733ca 1007expand_exception_blocks ()
8d08fdba 1008{
92b96838 1009 do_pending_stack_adjust ();
e00737d2 1010 push_to_sequence (catch_clauses);
8d2733ca 1011 expand_leftover_cleanups ();
92b96838 1012 do_pending_stack_adjust ();
e00737d2 1013 catch_clauses = get_insns ();
f30432d7 1014 end_sequence ();
eb448459 1015
eb448459
MS
1016 /* Do this after we expand leftover cleanups, so that the
1017 expand_eh_region_end that expand_end_eh_spec does will match the
1018 right expand_eh_region_start, and make sure it comes out before
1019 the terminate protected region. */
f30432d7
MS
1020 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
1021 {
eb448459 1022 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
92b96838 1023 do_pending_stack_adjust ();
e00737d2 1024 push_to_sequence (catch_clauses);
eb448459 1025 expand_leftover_cleanups ();
92b96838 1026 do_pending_stack_adjust ();
e00737d2 1027 catch_clauses = get_insns ();
eb448459 1028 end_sequence ();
f30432d7
MS
1029 }
1030
e00737d2 1031 if (catch_clauses)
f30432d7 1032 {
e00737d2
MS
1033 rtx funcend = gen_label_rtx ();
1034 emit_jump (funcend);
1035
eb66be0e
MS
1036 /* We cannot protect n regions this way if we must flow into the
1037 EH region through the top of the region, as we have to with
1038 the setjmp/longjmp approach. */
1039 if (exceptions_via_longjmp == 0)
1040 {
1041 /* Is this necessary? */
1042 assemble_external (TREE_OPERAND (Terminate, 0));
1043
1044 expand_eh_region_start ();
1045 }
f30432d7 1046
e00737d2
MS
1047 emit_insns (catch_clauses);
1048 catch_clauses = NULL_RTX;
eb66be0e
MS
1049
1050 if (exceptions_via_longjmp == 0)
1051 expand_eh_region_end (TerminateFunctionCall);
1052
6467930b 1053 expand_leftover_cleanups ();
f30432d7 1054
e00737d2
MS
1055 emit_label (funcend);
1056 }
8d08fdba
MS
1057}
1058
72b7eeff
MS
1059tree
1060start_anon_func ()
1061{
1062 static int counter = 0;
e92cc029 1063 int old_interface_unknown = interface_unknown;
72b7eeff
MS
1064 char name[32];
1065 tree params;
1066 tree t;
1067
1068 push_cp_function_context (NULL_TREE);
1069 push_to_top_level ();
1070
1071 /* No need to mangle this. */
1072 push_lang_context (lang_name_c);
1073
e92cc029
MS
1074 interface_unknown = 1;
1075
72b7eeff
MS
1076 params = void_list_node;
1077 /* tcf stands for throw clean funciton. */
1078 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
1079 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
1080 NULL_TREE);
72b7eeff
MS
1081 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1082 void_list_node),
c11b6f21 1083 t, NULL_TREE, 0);
72b7eeff
MS
1084 store_parm_decls ();
1085 pushlevel (0);
1086 clear_last_expr ();
1087 push_momentary ();
1088 expand_start_bindings (0);
1089 emit_line_note (input_filename, lineno);
1090
e92cc029
MS
1091 interface_unknown = old_interface_unknown;
1092
72b7eeff
MS
1093 pop_lang_context ();
1094
1095 return current_function_decl;
1096}
1097
1098void
1099end_anon_func ()
1100{
fc378698 1101 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1102 poplevel (1, 0, 0);
1103 pop_momentary ();
1104
1105 finish_function (lineno, 0, 0);
1106
1107 pop_from_top_level ();
1108 pop_cp_function_context (NULL_TREE);
1109}
8d2733ca 1110
6467930b 1111/* Expand a throw statement. This follows the following
8d2733ca
MS
1112 algorithm:
1113
1114 1. Allocate space to save the current PC onto the stack.
1115 2. Generate and emit a label and save its address into the
e1cd6e56 1116 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1117 3. If this is the first call to throw in this function:
1118 generate a label for the throw block
1119 4. jump to the throw block label. */
6467930b 1120
8d08fdba 1121void
8d2733ca
MS
1122expand_throw (exp)
1123 tree exp;
8d08fdba 1124{
8d2733ca 1125 rtx label;
8d08fdba 1126
8d2733ca
MS
1127 if (! doing_eh (1))
1128 return;
8d08fdba 1129
8d2733ca
MS
1130 if (exp)
1131 {
faae18ab 1132 tree throw_type;
72b7eeff 1133 tree cleanup = empty_fndecl, e;
faae18ab 1134
a3b49ccd 1135 /* throw expression */
e92cc029 1136 /* First, decay it. */
f30432d7 1137 exp = decay_conversion (exp);
a3b49ccd 1138
f30432d7
MS
1139 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1140 {
1141 throw_type = build_eh_type (exp);
1142 exp = build_reinterpret_cast (ptr_type_node, exp);
1143 }
1144 else
1145 {
72b7eeff 1146 tree object;
a50f0918 1147
f30432d7
MS
1148 /* Make a copy of the thrown object. WP 15.1.5 */
1149 exp = build_new (NULL_TREE, TREE_TYPE (exp),
e66d884e 1150 build_expr_list (NULL_TREE, exp),
f30432d7 1151 0);
faae18ab 1152
f30432d7
MS
1153 if (exp == error_mark_node)
1154 error (" in thrown expression");
faae18ab 1155
72b7eeff
MS
1156 object = build_indirect_ref (exp, NULL_PTR);
1157 throw_type = build_eh_type (object);
1158
a2676865
JM
1159 /* Build __tcf_ function. */
1160 cleanup = start_anon_func ();
1161 object = build_delete (TREE_TYPE (exp), saved_throw_value,
1162 integer_three_node, LOOKUP_NORMAL|LOOKUP_DESTRUCTOR, 0);
1163 expand_expr (object, const0_rtx, VOIDmode, 0);
1164 end_anon_func ();
1165 mark_addressable (cleanup);
f30432d7 1166 }
faae18ab 1167
be99da77
MS
1168 if (cleanup == empty_fndecl)
1169 assemble_external (empty_fndecl);
1170
f30432d7
MS
1171 e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
1172 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff 1173
f30432d7
MS
1174 e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
1175 e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
1176 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff
MS
1177
1178 cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
1179 cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup);
1180 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1181 }
1182 else
a3b49ccd
MS
1183 {
1184 /* rethrow current exception */
8ccc31eb 1185 /* This part is easy, as we don't have to do anything else. */
a3b49ccd 1186 }
8d2733ca 1187
eb66be0e
MS
1188 if (exceptions_via_longjmp)
1189 emit_throw ();
1190 else
1191 {
1192 /* This is the label that represents where in the code we were, when
1193 we got an exception. This needs to be updated when we rethrow an
1194 exception, so that the matching routine knows to search out. */
1195 label = gen_label_rtx ();
1196 emit_label (label);
8d2733ca 1197
eb66be0e
MS
1198 expand_internal_throw (label);
1199 }
f376e137 1200}
8d2733ca
MS
1201
1202/* Build a throw expression. */
6467930b 1203
8d2733ca
MS
1204tree
1205build_throw (e)
1206 tree e;
1207{
db5ae43f
MS
1208 if (e != error_mark_node)
1209 {
5156628f 1210 if (processing_template_decl)
fc378698 1211 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1212 e = build1 (THROW_EXPR, void_type_node, e);
1213 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1214 TREE_USED (e) = 1;
db5ae43f 1215 }
8d2733ca 1216 return e;
8d08fdba 1217}
This page took 0.45595 seconds and 5 git commands to generate.