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