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