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