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