]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
h8300.c (notice_update_cc): Use CC_SET_ZN and CC_SET_ZNV.
[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
8d2733ca 243 /* void (*)() */
8ccc31eb
MS
244 tree PFV = build_pointer_type (build_function_type
245 (void_type_node, void_list_node));
8d08fdba 246
eb66be0e
MS
247 /* Arg list for the build_function_type call for set_terminate and
248 set_unexpected. */
8ccc31eb 249 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 250
8ccc31eb
MS
251 /* void (*pfvtype (void (*) ()))() */
252 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 253
8ccc31eb
MS
254 /* void vtype () */
255 tree vtype = build_function_type (void_type_node, void_list_node);
256
257 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
258 pfvtype, NOT_BUILT_IN);
259 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
260 pfvtype, NOT_BUILT_IN);
261 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
262 vtype, NOT_BUILT_IN);
263 terminate_fndecl = auto_function (get_identifier ("terminate"),
264 vtype, NOT_BUILT_IN);
265
8ccc31eb 266 push_lang_context (lang_name_c);
8d2733ca 267
8d2733ca 268 catch_match_fndecl =
72b7eeff
MS
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);
8d2733ca 278 find_first_exception_match_fndecl =
72b7eeff
MS
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);
8d2733ca 284 unwind_fndecl =
72b7eeff
MS
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);
72b7eeff
MS
290 empty_fndecl =
291 builtin_function ("__empty",
292 build_function_type (void_type_node, void_list_node),
293 NOT_BUILT_IN, NULL_PTR);
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;
613 rtx return_val_rtx;
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);
f30432d7 619 return_val_rtx = 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);
624 emit_move_insn (return_val_rtx, 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;
665 rtx return_val_rtx;
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);
672 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 673
f30432d7 674 emit_move_insn (return_val_rtx, 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;
707 rtx return_val_rtx;
f30432d7
MS
708 rtx gotta_rethrow_it;
709 rtx gotta_call_terminate;
f30432d7
MS
710 rtx top_of_loop;
711 rtx unwind_first;
712 tree t;
713
714 if (! doing_eh (0))
715 return;
716
717 if (! throw_used)
718 return;
8d2733ca 719
f30432d7 720 params = void_list_node;
c11b6f21
MS
721 t = make_call_declarator (get_identifier ("__throw"), params, NULL_TREE,
722 NULL_TREE);
f30432d7
MS
723 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
724 void_list_node),
c11b6f21 725 t, NULL_TREE, 0);
f30432d7
MS
726 store_parm_decls ();
727 pushlevel (0);
728 clear_last_expr ();
729 push_momentary ();
730 expand_start_bindings (0);
731
732 gotta_rethrow_it = gen_label_rtx ();
733 gotta_call_terminate = gen_label_rtx ();
f30432d7
MS
734 top_of_loop = gen_label_rtx ();
735 unwind_first = gen_label_rtx ();
736
a50f0918 737 /* These two can be frontend specific. If wanted, they can go in
e92cc029 738 expand_throw. */
a50f0918
MS
739 /* Do we have a valid object we are throwing? */
740 emit_cmp_insn (DECL_RTL (saved_throw_type), const0_rtx, EQ, NULL_RTX,
741 GET_MODE (DECL_RTL (saved_throw_type)), 0, 0);
742 emit_jump_insn (gen_beq (gotta_call_terminate));
743
f30432d7
MS
744 emit_jump (unwind_first);
745
746 emit_label (top_of_loop);
8d2733ca
MS
747
748 /* search for an exception handler for the saved_pc */
749 return_val_rtx = do_function_call (FirstExceptionMatch,
f30432d7 750 tree_cons (NULL_TREE, saved_pc, NULL_TREE),
8d2733ca 751 ptr_type_node);
e1cd6e56 752 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
753
754 /* did we find one? */
755 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
756 GET_MODE (return_val_rtx), 0, 0);
757
758 /* if not, jump to gotta_rethrow_it */
759 emit_jump_insn (gen_beq (gotta_rethrow_it));
760
761 /* we found it, so jump to it */
762 emit_indirect_jump (return_val_rtx);
763
764 /* code to deal with unwinding and looking for it again */
765 emit_label (gotta_rethrow_it);
766
eb66be0e 767 /* Call to __builtin_return_address. */
be99da77
MS
768#if defined (ARM_FRAME_RTX) /* was __arm */
769 /* This should be moved into arm.h:RETURN_ADDR_RTX */
770 /* This replaces a 'call' to __builtin_return_address */
e1cd6e56 771 return_val_rtx = gen_reg_rtx (Pmode);
f30432d7 772 emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 773#else
f30432d7 774 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 775 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 776 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 777#endif
8d2733ca 778
eb66be0e 779 /* Did __builtin_return_address return a valid address? */
8d2733ca
MS
780 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
781 GET_MODE (return_val_rtx), 0, 0);
782
783 emit_jump_insn (gen_beq (gotta_call_terminate));
784
be99da77 785 return_val_rtx = eh_outer_context (return_val_rtx);
e1cd6e56 786
be99da77 787 /* Yes it did. */
6467930b 788 emit_move_insn (eh_saved_pc_rtx, return_val_rtx);
f30432d7
MS
789
790 do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
791 emit_jump (top_of_loop);
8d2733ca
MS
792
793 /* no it didn't --> therefore we need to call terminate */
794 emit_label (gotta_call_terminate);
795 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 796 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
797
798 {
799 rtx ret_val, return_val_rtx;
800 emit_label (unwind_first);
801 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
802 0, hard_frame_pointer_rtx);
803
804 /* Set it up so that we continue inside, at the top of the loop. */
805 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173
MS
806#ifdef RETURN_ADDR_OFFSET
807 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
f30432d7
MS
808 if (return_val_rtx != ret_val)
809 emit_move_insn (ret_val, return_val_rtx);
810#endif
811
e92cc029 812 /* Fall into epilogue to unwind prologue. */
f30432d7
MS
813 }
814
fc378698 815 expand_end_bindings (getdecls (), 1, 0);
f30432d7
MS
816 poplevel (1, 0, 0);
817 pop_momentary ();
818
819 finish_function (lineno, 0, 0);
8d08fdba 820}
8d2733ca
MS
821
822
f30432d7
MS
823void
824expand_start_eh_spec ()
825{
6467930b 826 expand_eh_region_start ();
f30432d7
MS
827}
828
5566b478 829static void
f30432d7
MS
830expand_end_eh_spec (raises)
831 tree raises;
832{
833 tree expr, second_try;
834 rtx check = gen_label_rtx ();
835 rtx cont;
836 rtx ret = gen_reg_rtx (Pmode);
837 rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
838 rtx end = gen_label_rtx ();
839
840 expr = make_node (RTL_EXPR);
841 TREE_TYPE (expr) = void_type_node;
842 RTL_EXPR_RTL (expr) = const0_rtx;
843 TREE_SIDE_EFFECTS (expr) = 1;
844 start_sequence_for_rtl_expr (expr);
845 cont = gen_label_rtx ();
846 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
847 emit_jump (check);
848 emit_label (cont);
849 jumpif (make_tree (integer_type_node, flag), end);
850 do_function_call (Terminate, NULL_TREE, NULL_TREE);
851 assemble_external (TREE_OPERAND (Terminate, 0));
852 emit_barrier ();
853 RTL_EXPR_SEQUENCE (expr) = get_insns ();
854 end_sequence ();
855
856 second_try = expr;
857
858 expr = make_node (RTL_EXPR);
859 TREE_TYPE (expr) = void_type_node;
860 RTL_EXPR_RTL (expr) = const0_rtx;
861 TREE_SIDE_EFFECTS (expr) = 1;
862 start_sequence_for_rtl_expr (expr);
863
864 cont = gen_label_rtx ();
865 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
866 emit_jump (check);
867 emit_label (cont);
868 jumpif (make_tree (integer_type_node, flag), end);
6467930b 869 expand_eh_region_start ();
f30432d7
MS
870 do_function_call (Unexpected, NULL_TREE, NULL_TREE);
871 assemble_external (TREE_OPERAND (Unexpected, 0));
872 emit_barrier ();
eb66be0e 873
6467930b 874 expand_eh_region_end (second_try);
f30432d7
MS
875
876 emit_label (check);
877 emit_move_insn (flag, const1_rtx);
878 cont = gen_label_rtx ();
879 while (raises)
880 {
881 tree exp;
882 tree match_type = TREE_VALUE (raises);
883
884 if (match_type)
885 {
886 /* check TREE_VALUE (raises) here */
887 exp = saved_throw_value;
888 exp = tree_cons (NULL_TREE,
889 build_eh_type_type (match_type),
890 tree_cons (NULL_TREE,
891 saved_throw_type,
892 tree_cons (NULL_TREE, exp, NULL_TREE)));
893 exp = build_function_call (CatchMatch, exp);
894 assemble_external (TREE_OPERAND (CatchMatch, 0));
895
896 jumpif (exp, cont);
897 }
898
899 raises = TREE_CHAIN (raises);
900 }
901 emit_move_insn (flag, const0_rtx);
902 emit_label (cont);
903 emit_indirect_jump (ret);
904 emit_label (end);
905
906 RTL_EXPR_SEQUENCE (expr) = get_insns ();
907 end_sequence ();
908
6467930b 909 expand_eh_region_end (expr);
f30432d7
MS
910}
911
8d2733ca
MS
912/* This is called to expand all the toplevel exception handling
913 finalization for a function. It should only be called once per
914 function. */
6467930b 915
8d08fdba 916void
8d2733ca 917expand_exception_blocks ()
8d08fdba 918{
21451173 919 rtx funcend;
eb448459 920 rtx insns;
f30432d7
MS
921
922 start_sequence ();
8d2733ca
MS
923
924 funcend = gen_label_rtx ();
8d2733ca 925
f30432d7
MS
926 start_sequence ();
927
928 /* Add all the catch clauses here. */
929 emit_insns (catch_clauses);
930 catch_clauses = NULL_RTX;
8d2733ca
MS
931
932 expand_leftover_cleanups ();
933
f30432d7
MS
934 insns = get_insns ();
935 end_sequence ();
eb448459
MS
936
937#if 1
938 /* Do this after we expand leftover cleanups, so that the
939 expand_eh_region_end that expand_end_eh_spec does will match the
940 right expand_eh_region_start, and make sure it comes out before
941 the terminate protected region. */
f30432d7
MS
942 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
943 {
eb448459
MS
944 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
945 push_to_sequence (insns);
f30432d7 946
eb448459
MS
947 /* Now expand any new ones. */
948 expand_leftover_cleanups ();
f30432d7 949
eb448459
MS
950 insns = get_insns ();
951 end_sequence ();
f30432d7 952 }
eb448459
MS
953#endif
954
955 emit_jump (funcend);
f30432d7
MS
956
957 if (insns)
958 {
eb66be0e
MS
959 /* We cannot protect n regions this way if we must flow into the
960 EH region through the top of the region, as we have to with
961 the setjmp/longjmp approach. */
962 if (exceptions_via_longjmp == 0)
963 {
964 /* Is this necessary? */
965 assemble_external (TREE_OPERAND (Terminate, 0));
966
967 expand_eh_region_start ();
968 }
f30432d7 969
f30432d7 970 emit_insns (insns);
eb66be0e
MS
971
972 if (exceptions_via_longjmp == 0)
973 expand_eh_region_end (TerminateFunctionCall);
974
6467930b 975 expand_leftover_cleanups ();
f30432d7
MS
976 }
977
8d2733ca 978 emit_label (funcend);
f30432d7
MS
979
980 /* Only if we had previous insns do we want to emit the jump around
981 them. If there weren't any, then insns will remain NULL_RTX. */
982 if (insns)
983 insns = get_insns ();
984 end_sequence ();
985
eb448459 986 emit_insns (insns);
8d08fdba
MS
987}
988
72b7eeff
MS
989tree
990start_anon_func ()
991{
992 static int counter = 0;
e92cc029 993 int old_interface_unknown = interface_unknown;
72b7eeff
MS
994 char name[32];
995 tree params;
996 tree t;
997
998 push_cp_function_context (NULL_TREE);
999 push_to_top_level ();
1000
1001 /* No need to mangle this. */
1002 push_lang_context (lang_name_c);
1003
e92cc029
MS
1004 interface_unknown = 1;
1005
72b7eeff
MS
1006 params = void_list_node;
1007 /* tcf stands for throw clean funciton. */
1008 sprintf (name, "__tcf_%d", counter++);
c11b6f21
MS
1009 t = make_call_declarator (get_identifier (name), params, NULL_TREE,
1010 NULL_TREE);
72b7eeff
MS
1011 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1012 void_list_node),
c11b6f21 1013 t, NULL_TREE, 0);
72b7eeff
MS
1014 store_parm_decls ();
1015 pushlevel (0);
1016 clear_last_expr ();
1017 push_momentary ();
1018 expand_start_bindings (0);
1019 emit_line_note (input_filename, lineno);
1020
e92cc029
MS
1021 interface_unknown = old_interface_unknown;
1022
72b7eeff
MS
1023 pop_lang_context ();
1024
1025 return current_function_decl;
1026}
1027
1028void
1029end_anon_func ()
1030{
fc378698 1031 expand_end_bindings (getdecls (), 1, 0);
72b7eeff
MS
1032 poplevel (1, 0, 0);
1033 pop_momentary ();
1034
1035 finish_function (lineno, 0, 0);
1036
1037 pop_from_top_level ();
1038 pop_cp_function_context (NULL_TREE);
1039}
8d2733ca 1040
6467930b 1041/* Expand a throw statement. This follows the following
8d2733ca
MS
1042 algorithm:
1043
1044 1. Allocate space to save the current PC onto the stack.
1045 2. Generate and emit a label and save its address into the
e1cd6e56 1046 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1047 3. If this is the first call to throw in this function:
1048 generate a label for the throw block
1049 4. jump to the throw block label. */
6467930b 1050
8d08fdba 1051void
8d2733ca
MS
1052expand_throw (exp)
1053 tree exp;
8d08fdba 1054{
8d2733ca 1055 rtx label;
8d08fdba 1056
8d2733ca
MS
1057 if (! doing_eh (1))
1058 return;
8d08fdba 1059
8d2733ca
MS
1060 if (exp)
1061 {
faae18ab 1062 tree throw_type;
72b7eeff 1063 tree cleanup = empty_fndecl, e;
faae18ab 1064
a3b49ccd 1065 /* throw expression */
e92cc029 1066 /* First, decay it. */
f30432d7 1067 exp = decay_conversion (exp);
a3b49ccd 1068
f30432d7
MS
1069 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1070 {
1071 throw_type = build_eh_type (exp);
1072 exp = build_reinterpret_cast (ptr_type_node, exp);
1073 }
1074 else
1075 {
72b7eeff 1076 tree object;
a50f0918 1077
f30432d7
MS
1078 /* Make a copy of the thrown object. WP 15.1.5 */
1079 exp = build_new (NULL_TREE, TREE_TYPE (exp),
1080 build_tree_list (NULL_TREE, exp),
1081 0);
faae18ab 1082
f30432d7
MS
1083 if (exp == error_mark_node)
1084 error (" in thrown expression");
faae18ab 1085
72b7eeff
MS
1086 object = build_indirect_ref (exp, NULL_PTR);
1087 throw_type = build_eh_type (object);
1088
1089 start_sequence ();
1090 object = build_reinterpret_cast (TREE_TYPE (exp), saved_throw_value);
1091 object = build_indirect_ref (object, NULL_PTR);
c73964b2 1092 cleanup = maybe_build_cleanup_and_delete (object);
72b7eeff
MS
1093 end_sequence ();
1094
824b9a4c 1095 if (cleanup)
72b7eeff
MS
1096 {
1097 cleanup = start_anon_func ();
1098
c73964b2
MS
1099 expand_expr (maybe_build_cleanup_and_delete (object),
1100 const0_rtx, VOIDmode, 0);
72b7eeff
MS
1101
1102 end_anon_func ();
1103
1104 mark_addressable (cleanup);
1105 }
1106 else
1107 {
1108 cleanup = empty_fndecl;
1109 }
f30432d7 1110 }
faae18ab 1111
be99da77
MS
1112 if (cleanup == empty_fndecl)
1113 assemble_external (empty_fndecl);
1114
f30432d7
MS
1115 e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
1116 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff 1117
f30432d7
MS
1118 e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
1119 e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
1120 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff
MS
1121
1122 cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
1123 cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup);
1124 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1125 }
1126 else
a3b49ccd
MS
1127 {
1128 /* rethrow current exception */
8ccc31eb 1129 /* This part is easy, as we don't have to do anything else. */
a3b49ccd 1130 }
8d2733ca 1131
eb66be0e
MS
1132 if (exceptions_via_longjmp)
1133 emit_throw ();
1134 else
1135 {
1136 /* This is the label that represents where in the code we were, when
1137 we got an exception. This needs to be updated when we rethrow an
1138 exception, so that the matching routine knows to search out. */
1139 label = gen_label_rtx ();
1140 emit_label (label);
8d2733ca 1141
eb66be0e
MS
1142 expand_internal_throw (label);
1143 }
f376e137 1144}
8d2733ca
MS
1145
1146/* Build a throw expression. */
6467930b 1147
8d2733ca
MS
1148tree
1149build_throw (e)
1150 tree e;
1151{
db5ae43f
MS
1152 if (e != error_mark_node)
1153 {
5156628f 1154 if (processing_template_decl)
fc378698 1155 return build_min (THROW_EXPR, void_type_node, e);
db5ae43f
MS
1156 e = build1 (THROW_EXPR, void_type_node, e);
1157 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1158 TREE_USED (e) = 1;
db5ae43f 1159 }
8d2733ca 1160 return e;
8d08fdba 1161}
This page took 0.300946 seconds and 5 git commands to generate.