]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
83rd Cygnus<->FSF merge
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
b3417a04 2 Copyright (C) 1989, 1992, 1993, 1994, 1995 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
25/* High-level class interface. */
26
27#include "config.h"
28#include "tree.h"
29#include "rtl.h"
30#include "cp-tree.h"
31#include "flags.h"
8d2733ca
MS
32#include "obstack.h"
33#include "expr.h"
21451173 34#include "output.h"
8d08fdba 35
b7484fbe
MS
36tree protect_list;
37
a3b49ccd 38extern void (*interim_eh_hook) PROTO((tree));
f30432d7 39rtx expand_builtin_return_addr PROTO((enum built_in_function, int, rtx));
5566b478 40static void end_eh_unwinder PROTO((rtx));
a3b49ccd 41
8d2733ca
MS
42/* holds the fndecl for __builtin_return_address () */
43tree builtin_return_address_fndecl;
f30432d7 44tree throw_fndecl;
e1cd6e56 45
8d2733ca
MS
46static int
47doing_eh (do_warn)
48 int do_warn;
8d08fdba 49{
8d2733ca 50 if (! flag_handle_exceptions)
8d08fdba 51 {
8d2733ca
MS
52 static int warned = 0;
53 if (! warned && do_warn)
8d08fdba 54 {
8d2733ca
MS
55 error ("exception handling disabled, use -fhandle-exceptions to enable.");
56 warned = 1;
8d08fdba 57 }
8d2733ca 58 return 0;
8d08fdba 59 }
8d2733ca 60 return 1;
8d08fdba
MS
61}
62
8d08fdba 63
8d2733ca
MS
64/*
65NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
f30432d7 66to supporting exception handling as per ANSI C++ working draft.
8d2733ca
MS
67It is a complete rewrite of all the EH stuff that was here before
68 Shortcomings:
f30432d7 69 1. Throw specifications of functions still don't work.
8d2733ca
MS
70 Cool Things:
71 1. Destructors are called properly :-)
72 2. No overhead for the non-exception thrown case.
f30432d7 73 3. Fixing shortcoming 1 is simple.
8d2733ca
MS
74 -Tad Hunt (tad@mail.csh.rit.edu)
75
76*/
77
78/* A couple of backend routines from m88k.c */
79
80/* used to cache a call to __builtin_return_address () */
81static tree BuiltinReturnAddress;
f30432d7 82
8d2733ca
MS
83
84#include <stdio.h>
85
86/* XXX - Tad: for EH */
87/* output an exception table entry */
88
89static void
90output_exception_table_entry (file, start_label, end_label, eh_label)
91 FILE *file;
92 rtx start_label, end_label, eh_label;
8d08fdba 93{
f30432d7
MS
94 assemble_integer (start_label, GET_MODE_SIZE (Pmode), 1);
95 assemble_integer (end_label, GET_MODE_SIZE (Pmode), 1);
96 assemble_integer (eh_label, GET_MODE_SIZE (Pmode), 1);
8d2733ca
MS
97 putc ('\n', file); /* blank line */
98}
99
100static void
101easy_expand_asm (str)
102 char *str;
103{
104 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
105}
106
8d08fdba 107
8d2733ca
MS
108#if 0
109/* This is the startup, and finish stuff per exception table. */
8d08fdba 110
8d2733ca
MS
111/* XXX - Tad: exception handling section */
112#ifndef EXCEPT_SECTION_ASM_OP
113#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
114#endif
8d08fdba 115
8d2733ca
MS
116#ifdef EXCEPT_SECTION_ASM_OP
117typedef struct {
118 void *start_protect;
119 void *end_protect;
120 void *exception_handler;
121 } exception_table;
122#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 123
8d2733ca 124#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 125
8d2733ca
MS
126 /* on machines which support it, the exception table lives in another section,
127 but it needs a label so we can reference it... This sets up that
128 label! */
129asm (EXCEPT_SECTION_ASM_OP);
130exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
131asm (TEXT_SECTION_ASM_OP);
8d08fdba 132
8d2733ca 133#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 134
8d2733ca
MS
135#ifdef EXCEPT_SECTION_ASM_OP
136
137 /* we need to know where the end of the exception table is... so this
138 is how we do it! */
139
140asm (EXCEPT_SECTION_ASM_OP);
141exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
142asm (TEXT_SECTION_ASM_OP);
143
144#endif /* EXCEPT_SECTION_ASM_OP */
145
146#endif
8d08fdba 147
5566b478 148static void
8d2733ca 149exception_section ()
8d08fdba 150{
8d2733ca 151#ifdef ASM_OUTPUT_SECTION_NAME
e1cd6e56
MS
152 named_section (NULL_TREE, ".gcc_except_table");
153#else
154 if (flag_pic)
155 data_section ();
156 else
be99da77 157#if defined (TARGET_POWERPC) /* are we on a __rs6000? */
e1cd6e56 158 data_section ();
8d2733ca 159#else
e1cd6e56
MS
160 readonly_data_section ();
161#endif
8d08fdba 162#endif
8d08fdba
MS
163}
164
8d2733ca
MS
165
166
167
168/* from: my-cp-except.c */
169
170/* VI: ":set ts=4" */
171#if 0
172#include <stdio.h> */
173#include "config.h"
174#include "tree.h"
175#include "rtl.h"
176#include "cp-tree.h"
177#endif
178#include "decl.h"
179#if 0
180#include "flags.h"
181#endif
182#include "insn-flags.h"
183#include "obstack.h"
184#if 0
185#include "expr.h"
186#endif
187
188/* ======================================================================
189 Briefly the algorithm works like this:
190
191 When a constructor or start of a try block is encountered,
192 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
193 new entry in the unwind protection stack and returns a label to
194 output to start the protection for that block.
195
196 When a destructor or end try block is encountered, pop_eh_entry
197 (&eh_stack) is called. Pop_eh_entry () returns the ehEntry it
198 created when push_eh_entry () was called. The ehEntry structure
199 contains three things at this point. The start protect label,
200 the end protect label, and the exception handler label. The end
201 protect label should be output before the call to the destructor
202 (if any). If it was a destructor, then its parse tree is stored
203 in the finalization variable in the ehEntry structure. Otherwise
204 the finalization variable is set to NULL to reflect the fact that
205 is the the end of a try block. Next, this modified ehEntry node
206 is enqueued in the finalizations queue by calling
207 enqueue_eh_entry (&queue,entry).
208
209 +---------------------------------------------------------------+
210 |XXX: Will need modification to deal with partially |
211 | constructed arrays of objects |
212 | |
213 | Basically, this consists of keeping track of how many |
214 | of the objects have been constructed already (this |
215 | should be in a register though, so that shouldn't be a |
216 | problem. |
217 +---------------------------------------------------------------+
218
219 When a catch block is encountered, there is a lot of work to be
220 done.
221
222 Since we don't want to generate the catch block inline with the
223 regular flow of the function, we need to have some way of doing
f30432d7
MS
224 so. Luckily, we can use sequences to defer the catch sections.
225 When the start of a catch block is encountered, we start the
226 sequence. After the catch block is generated, we end the
227 sequence.
228
8d2733ca
MS
229 Next we must insure that when the catch block is executed, all
230 finalizations for the matching try block have been completed. If
231 any of those finalizations throw an exception, we must call
232 terminate according to the ARM (section r.15.6.1). What this
233 means is that we need to dequeue and emit finalizations for each
234 entry in the ehQueue until we get to an entry with a NULL
235 finalization field. For any of the finalization entries, if it
236 is not a call to terminate (), we must protect it by giving it
237 another start label, end label, and exception handler label,
238 setting its finalization tree to be a call to terminate (), and
239 enqueue'ing this new ehEntry to be output at an outer level.
240 Finally, after all that is done, we can get around to outputting
241 the catch block which basically wraps all the "catch (...) {...}"
242 statements in a big if/then/else construct that matches the
243 correct block to call.
244
245 ===================================================================== */
246
247extern rtx emit_insn PROTO((rtx));
248extern rtx gen_nop PROTO(());
8d2733ca
MS
249
250/* local globals for function calls
251 ====================================================================== */
252
253/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
f30432d7
MS
254 "set_unexpected ()" after default_conversion. (lib-except.c) */
255static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch, Throw;
8d2733ca
MS
256
257/* used to cache __find_first_exception_table_match ()
258 for throw (lib-except.c) */
259static tree FirstExceptionMatch;
260
f30432d7 261/* used to cache a call to __unwind_function () (lib-except.c) */
8d2733ca
MS
262static tree Unwind;
263
f30432d7 264/* holds a ready to emit call to "terminate ()". */
8d2733ca
MS
265static tree TerminateFunctionCall;
266
72b7eeff
MS
267static tree empty_fndecl;
268
8d2733ca
MS
269/* ====================================================================== */
270
271
272
273/* data structures for my various quick and dirty stacks and queues
274 Eventually, most of this should go away, because I think it can be
f30432d7 275 integrated with stuff already built into the compiler. */
8d2733ca
MS
276
277/* =================================================================== */
278
279struct labelNode {
72b7eeff
MS
280 union {
281 rtx rlabel;
282 tree tlabel;
283 } u;
8ccc31eb
MS
284 struct labelNode *chain;
285};
8d2733ca
MS
286
287
288/* this is the most important structure here. Basically this is how I store
289 an exception table entry internally. */
290struct ehEntry {
8ccc31eb
MS
291 rtx start_label;
292 rtx end_label;
293 rtx exception_handler_label;
8d2733ca 294
8ccc31eb
MS
295 tree finalization;
296 tree context;
297};
8d2733ca
MS
298
299struct ehNode {
8ccc31eb
MS
300 struct ehEntry *entry;
301 struct ehNode *chain;
302};
8d2733ca
MS
303
304struct ehStack {
8ccc31eb
MS
305 struct ehNode *top;
306};
8d2733ca
MS
307
308struct ehQueue {
8ccc31eb
MS
309 struct ehNode *head;
310 struct ehNode *tail;
311};
8d2733ca
MS
312/* ========================================================================= */
313
314
315
316/* local globals - these local globals are for storing data necessary for
317 generating the exception table and code in the correct order.
318
319 ========================================================================= */
320
a3b49ccd 321/* Holds the pc for doing "throw" */
5566b478 322static tree saved_pc;
a3b49ccd 323/* Holds the type of the thing being thrown. */
5566b478 324static tree saved_throw_type;
a3b49ccd 325/* Holds the value being thrown. */
5566b478 326static tree saved_throw_value;
72b7eeff 327/* Holds the cleanup for the value being thrown. */
5566b478 328static tree saved_cleanup;
f30432d7 329
5566b478 330static int throw_used;
8d2733ca 331
f30432d7 332static rtx catch_clauses;
8d2733ca
MS
333
334static struct ehStack ehstack;
335static struct ehQueue ehqueue;
336static struct ehQueue eh_table_output_queue;
8d2733ca
MS
337static struct labelNode *false_label_stack = NULL;
338static struct labelNode *caught_return_label_stack = NULL;
339/* ========================================================================= */
340
341/* function prototypes */
342static struct ehEntry *pop_eh_entry PROTO((struct ehStack *stack));
343static void enqueue_eh_entry PROTO((struct ehQueue *queue, struct ehEntry *entry));
8d2733ca
MS
344static rtx push_eh_entry PROTO((struct ehStack *stack));
345static struct ehEntry *dequeue_eh_entry PROTO((struct ehQueue *queue));
346static void new_eh_queue PROTO((struct ehQueue *queue));
347static void new_eh_stack PROTO((struct ehStack *stack));
72b7eeff 348static void push_label_entry PROTO((struct labelNode **labelstack, rtx rlabel, tree tlabel));
8d2733ca 349static rtx pop_label_entry PROTO((struct labelNode **labelstack));
72b7eeff 350static tree top_label_entry PROTO((struct labelNode **labelstack));
8d2733ca
MS
351static struct ehEntry *copy_eh_entry PROTO((struct ehEntry *entry));
352
353
21451173
MS
354/* Routines to save and restore eh context information. */
355struct eh_context {
356 struct ehStack ehstack;
357 struct ehQueue ehqueue;
358 rtx catch_clauses;
359 struct labelNode *false_label_stack;
360 struct labelNode *caught_return_label_stack;
361 tree protect_list;
362};
363
364/* Save the context and push into a new one. */
365void*
366push_eh_context ()
367{
368 struct eh_context *p
369 = (struct eh_context*)xmalloc (sizeof (struct eh_context));
370
371 p->ehstack = ehstack;
372 p->ehqueue = ehqueue;
373 p->catch_clauses = catch_clauses;
374 p->false_label_stack = false_label_stack;
375 p->caught_return_label_stack = caught_return_label_stack;
376 p->protect_list = protect_list;
377
378 new_eh_stack (&ehstack);
379 new_eh_queue (&ehqueue);
380 catch_clauses = NULL_RTX;
381 false_label_stack = NULL;
382 caught_return_label_stack = NULL;
383 protect_list = NULL_TREE;
384
385 return p;
386}
387
388/* Pop and restore the context. */
389void
390pop_eh_context (vp)
391 void *vp;
392{
393 struct eh_context *p = (struct eh_context *)vp;
394
395 protect_list = p->protect_list;
396 caught_return_label_stack = p->caught_return_label_stack;
397 false_label_stack = p->false_label_stack;
398 catch_clauses = p->catch_clauses;
399 ehqueue = p->ehqueue;
400 ehstack = p->ehstack;
401
402 free (p);
403}
404
405
8d2733ca
MS
406
407/* All my cheesy stack/queue/misc data structure handling routines
408
409 ========================================================================= */
410
411static void
72b7eeff 412push_label_entry (labelstack, rlabel, tlabel)
8d2733ca 413 struct labelNode **labelstack;
72b7eeff
MS
414 rtx rlabel;
415 tree tlabel;
8d08fdba 416{
8d2733ca
MS
417 struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
418
72b7eeff
MS
419 if (rlabel)
420 newnode->u.rlabel = rlabel;
421 else
422 newnode->u.tlabel = tlabel;
8d2733ca
MS
423 newnode->chain = *labelstack;
424 *labelstack = newnode;
8d08fdba 425}
8d08fdba 426
8d2733ca
MS
427static rtx
428pop_label_entry (labelstack)
429 struct labelNode **labelstack;
8d08fdba 430{
8d2733ca
MS
431 rtx label;
432 struct labelNode *tempnode;
8d08fdba 433
8d2733ca 434 if (! *labelstack) return NULL_RTX;
8d08fdba 435
8d2733ca 436 tempnode = *labelstack;
72b7eeff 437 label = tempnode->u.rlabel;
8d2733ca
MS
438 *labelstack = (*labelstack)->chain;
439 free (tempnode);
8d08fdba 440
8d2733ca
MS
441 return label;
442}
8d08fdba 443
72b7eeff 444static tree
8d2733ca
MS
445top_label_entry (labelstack)
446 struct labelNode **labelstack;
447{
72b7eeff 448 if (! *labelstack) return NULL_TREE;
8d08fdba 449
72b7eeff 450 return (*labelstack)->u.tlabel;
8d08fdba
MS
451}
452
8d2733ca
MS
453/* Push to permanent obstack for rtl generation.
454 One level only! */
455static struct obstack *saved_rtl_obstack;
5566b478
MS
456
457static void
8d2733ca 458push_rtl_perm ()
8d08fdba 459{
8d2733ca
MS
460 extern struct obstack permanent_obstack;
461 extern struct obstack *rtl_obstack;
462
463 saved_rtl_obstack = rtl_obstack;
464 rtl_obstack = &permanent_obstack;
465}
8d08fdba 466
8d2733ca
MS
467/* Pop back to normal rtl handling. */
468static void
469pop_rtl_from_perm ()
470{
8d2733ca 471 extern struct obstack *rtl_obstack;
8d2733ca
MS
472 rtl_obstack = saved_rtl_obstack;
473}
8d08fdba 474
8d2733ca
MS
475static rtx
476push_eh_entry (stack)
477 struct ehStack *stack;
478{
479 struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
480 struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
8d08fdba 481
8d2733ca
MS
482 /* These are saved for the exception table. */
483 push_rtl_perm ();
484 entry->start_label = gen_label_rtx ();
485 entry->end_label = gen_label_rtx ();
486 entry->exception_handler_label = gen_label_rtx ();
487 pop_rtl_from_perm ();
488
e1cd6e56
MS
489 LABEL_PRESERVE_P (entry->start_label) = 1;
490 LABEL_PRESERVE_P (entry->end_label) = 1;
491 LABEL_PRESERVE_P (entry->exception_handler_label) = 1;
492
8d2733ca 493 entry->finalization = NULL_TREE;
8ccc31eb 494 entry->context = current_function_decl;
8d08fdba 495
8d2733ca
MS
496 node->entry = entry;
497 node->chain = stack->top;
498 stack->top = node;
499
500 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
501
502 return entry->start_label;
8d08fdba
MS
503}
504
9e9ff709 505/* Pop an entry from the given STACK. */
8d2733ca
MS
506static struct ehEntry *
507pop_eh_entry (stack)
508 struct ehStack *stack;
8d08fdba 509{
8d2733ca
MS
510 struct ehNode *tempnode;
511 struct ehEntry *tempentry;
9e9ff709
MS
512
513 tempnode = stack->top;
514 tempentry = tempnode->entry;
515 stack->top = stack->top->chain;
516 free (tempnode);
8d2733ca 517
9e9ff709 518 return tempentry;
8d08fdba
MS
519}
520
8d2733ca
MS
521static struct ehEntry *
522copy_eh_entry (entry)
523 struct ehEntry *entry;
8d08fdba 524{
8d2733ca 525 struct ehEntry *newentry;
8d08fdba 526
8d2733ca
MS
527 newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
528 memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
8d08fdba 529
8d2733ca
MS
530 return newentry;
531}
8d08fdba 532
8d2733ca
MS
533static void
534enqueue_eh_entry (queue, entry)
535 struct ehQueue *queue;
536 struct ehEntry *entry;
537{
538 struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
8d08fdba 539
8d2733ca
MS
540 node->entry = entry;
541 node->chain = NULL;
8d08fdba 542
8d2733ca 543 if (queue->head == NULL)
8d08fdba 544 {
8d2733ca 545 queue->head = node;
8d08fdba 546 }
8d2733ca 547 else
8d08fdba 548 {
8d2733ca 549 queue->tail->chain = node;
8d08fdba 550 }
8d2733ca 551 queue->tail = node;
8d08fdba
MS
552}
553
8d2733ca
MS
554static struct ehEntry *
555dequeue_eh_entry (queue)
556 struct ehQueue *queue;
557{
558 struct ehNode *tempnode;
559 struct ehEntry *tempentry;
560
561 if (queue->head == NULL)
562 return NULL;
563
564 tempnode = queue->head;
565 queue->head = queue->head->chain;
566
567 tempentry = tempnode->entry;
568 free (tempnode);
569
570 return tempentry;
571}
572
573static void
574new_eh_queue (queue)
575 struct ehQueue *queue;
576{
577 queue->head = queue->tail = NULL;
578}
579
580static void
581new_eh_stack (stack)
582 struct ehStack *stack;
583{
584 stack->top = NULL;
585}
586
f30432d7 587/* cheesyness to save some typing. returns the return value rtx */
5566b478 588static rtx
f30432d7
MS
589do_function_call (func, params, return_type)
590 tree func, params, return_type;
591{
592 tree func_call;
593 func_call = build_function_call (func, params);
594 expand_call (func_call, NULL_RTX, 0);
595 if (return_type != NULL_TREE)
596 return hard_function_value (return_type, func_call);
597 return NULL_RTX;
598}
599
8d2733ca 600static void
f30432d7
MS
601expand_internal_throw (pc)
602 rtx pc;
8d2733ca 603{
f30432d7
MS
604 emit_move_insn (DECL_RTL (saved_pc), pc);
605#ifdef JUMP_TO_THROW
606 emit_indirect_jump (gen_rtx (SYMBOL_REF, Pmode, "__throw"));
607#else
608 do_function_call (Throw, NULL_TREE, NULL_TREE);
609#endif
610 throw_used = 1;
8d2733ca 611}
f30432d7 612
8d2733ca
MS
613/* ========================================================================= */
614
5566b478 615static void
a3b49ccd
MS
616lang_interim_eh (finalization)
617 tree finalization;
618{
619 if (finalization)
620 end_protect (finalization);
621 else
622 start_protect ();
623}
8d2733ca 624
8ccc31eb
MS
625extern tree auto_function PROTO((tree, tree, enum built_in_function));
626
8d2733ca
MS
627/* sets up all the global eh stuff that needs to be initialized at the
628 start of compilation.
629
630 This includes:
631 - Setting up all the function call trees
632 - Initializing the ehqueue
633 - Initializing the eh_table_output_queue
634 - Initializing the ehstack
8d2733ca 635*/
8d08fdba 636
8d08fdba 637void
8d2733ca 638init_exception_processing ()
8d08fdba 639{
8d2733ca
MS
640 extern tree define_function ();
641 tree unexpected_fndecl, terminate_fndecl;
642 tree set_unexpected_fndecl, set_terminate_fndecl;
643 tree catch_match_fndecl;
644 tree find_first_exception_match_fndecl;
645 tree unwind_fndecl;
f30432d7
MS
646 tree declspecs;
647 tree d;
a3b49ccd 648
8d2733ca 649 /* void (*)() */
8ccc31eb
MS
650 tree PFV = build_pointer_type (build_function_type
651 (void_type_node, void_list_node));
8d08fdba 652
8d2733ca
MS
653 /* arg list for the build_function_type call for set_terminate () and
654 set_unexpected () */
8ccc31eb 655 tree pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 656
8ccc31eb
MS
657 /* void (*pfvtype (void (*) ()))() */
658 tree pfvtype = build_function_type (PFV, pfvlist);
8d2733ca 659
8ccc31eb
MS
660 /* void vtype () */
661 tree vtype = build_function_type (void_type_node, void_list_node);
662
663 set_terminate_fndecl = auto_function (get_identifier ("set_terminate"),
664 pfvtype, NOT_BUILT_IN);
665 set_unexpected_fndecl = auto_function (get_identifier ("set_unexpected"),
666 pfvtype, NOT_BUILT_IN);
667 unexpected_fndecl = auto_function (get_identifier ("unexpected"),
668 vtype, NOT_BUILT_IN);
669 terminate_fndecl = auto_function (get_identifier ("terminate"),
670 vtype, NOT_BUILT_IN);
671
672 interim_eh_hook = lang_interim_eh;
673
674 push_lang_context (lang_name_c);
8d2733ca 675
8d2733ca 676 catch_match_fndecl =
72b7eeff
MS
677 builtin_function (flag_rtti
678 ? "__throw_type_match_rtti"
679 : "__throw_type_match",
680 build_function_type (ptr_type_node,
681 tree_cons (NULL_TREE, ptr_type_node,
682 tree_cons (NULL_TREE, ptr_type_node,
683 tree_cons (NULL_TREE, ptr_type_node,
684 void_list_node)))),
685 NOT_BUILT_IN, NULL_PTR);
8d2733ca 686 find_first_exception_match_fndecl =
72b7eeff
MS
687 builtin_function ("__find_first_exception_table_match",
688 build_function_type (ptr_type_node,
689 tree_cons (NULL_TREE, ptr_type_node,
690 void_list_node)),
691 NOT_BUILT_IN, NULL_PTR);
8d2733ca 692 unwind_fndecl =
72b7eeff
MS
693 builtin_function ("__unwind_function",
694 build_function_type (void_type_node,
695 tree_cons (NULL_TREE, ptr_type_node,
696 void_list_node)),
697 NOT_BUILT_IN, NULL_PTR);
f30432d7 698 throw_fndecl =
72b7eeff
MS
699 builtin_function ("__throw",
700 build_function_type (void_type_node, void_list_node),
701 NOT_BUILT_IN, NULL_PTR);
f30432d7
MS
702 DECL_EXTERNAL (throw_fndecl) = 0;
703 TREE_PUBLIC (throw_fndecl) = 0;
72b7eeff
MS
704 empty_fndecl =
705 builtin_function ("__empty",
706 build_function_type (void_type_node, void_list_node),
707 NOT_BUILT_IN, NULL_PTR);
708 DECL_EXTERNAL (empty_fndecl) = 1;
709 TREE_PUBLIC (empty_fndecl) = 1;
8d2733ca
MS
710
711 Unexpected = default_conversion (unexpected_fndecl);
712 Terminate = default_conversion (terminate_fndecl);
713 SetTerminate = default_conversion (set_terminate_fndecl);
714 SetUnexpected = default_conversion (set_unexpected_fndecl);
715 CatchMatch = default_conversion (catch_match_fndecl);
716 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
717 Unwind = default_conversion (unwind_fndecl);
f30432d7 718 Throw = default_conversion (throw_fndecl);
8d2733ca
MS
719 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
720
721 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
722
723 pop_lang_context ();
f30432d7 724
8d2733ca
MS
725 new_eh_queue (&ehqueue);
726 new_eh_queue (&eh_table_output_queue);
727 new_eh_stack (&ehstack);
f30432d7
MS
728
729 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
730 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_pc"));
731 d = start_decl (d, declspecs, 0, NULL_TREE);
732 DECL_COMMON (d) = 1;
9e9ff709 733 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
734 saved_pc = lookup_name (get_identifier ("__eh_pc"), 0);
735
736 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
737 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_type"));
738 d = start_decl (d, declspecs, 0, NULL_TREE);
739 DECL_COMMON (d) = 1;
9e9ff709 740 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7
MS
741 saved_throw_type = lookup_name (get_identifier ("__eh_type"), 0);
742
743 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
744 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_value"));
745 d = start_decl (d, declspecs, 0, NULL_TREE);
746 DECL_COMMON (d) = 1;
9e9ff709 747 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
f30432d7 748 saved_throw_value = lookup_name (get_identifier ("__eh_value"), 0);
72b7eeff
MS
749
750 declspecs = tree_cons (NULL_TREE, get_identifier ("void"), NULL_TREE);
751 d = build_parse_node (INDIRECT_REF, get_identifier ("__eh_cleanup"));
752 d = build_parse_node (CALL_EXPR, d, void_list_node, NULL_TREE);
753 d = start_decl (d, declspecs, 0, NULL_TREE);
754 DECL_COMMON (d) = 1;
9e9ff709 755 cp_finish_decl (d, NULL_TREE, NULL_TREE, 1, 0);
72b7eeff 756 saved_cleanup = lookup_name (get_identifier ("__eh_cleanup"), 0);
8d2733ca
MS
757}
758
759/* call this to begin a block of unwind protection (ie: when an object is
760 constructed) */
761void
762start_protect ()
763{
f30432d7
MS
764 if (! doing_eh (0))
765 return;
766
767 emit_label (push_eh_entry (&ehstack));
8d2733ca
MS
768}
769
770/* call this to end a block of unwind protection. the finalization tree is
771 the finalization which needs to be run in order to cleanly unwind through
772 this level of protection. (ie: call this when a scope is exited)*/
773void
774end_protect (finalization)
775 tree finalization;
776{
b7484fbe 777 struct ehEntry *entry;
8d08fdba 778
8d2733ca
MS
779 if (! doing_eh (0))
780 return;
8d08fdba 781
b7484fbe
MS
782 entry = pop_eh_entry (&ehstack);
783
8d2733ca 784 emit_label (entry->end_label);
f30432d7
MS
785 /* Put in something that takes up space, as otherwise the end
786 address for the EH region could have the exact same address as
787 the outer region, causing us to miss the fact that resuming
788 exception handling with this PC value would be inside the outer
789 region. */
790 emit_insn (gen_nop ());
8d08fdba 791
8d2733ca
MS
792 entry->finalization = finalization;
793
794 enqueue_eh_entry (&ehqueue, entry);
795}
8d08fdba 796
8d2733ca
MS
797/* call this on start of a try block. */
798void
799expand_start_try_stmts ()
800{
f30432d7
MS
801 if (! doing_eh (1))
802 return;
803
804 start_protect ();
8d2733ca 805}
8d08fdba 806
8d2733ca
MS
807void
808expand_end_try_stmts ()
809{
810 end_protect (integer_zero_node);
8d08fdba
MS
811}
812
8d08fdba 813
8d2733ca 814/* call this to start processing of all the catch blocks. */
8d08fdba 815void
8d2733ca 816expand_start_all_catch ()
8d08fdba 817{
8d2733ca 818 struct ehEntry *entry;
72b7eeff 819 tree label;
8d2733ca
MS
820
821 if (! doing_eh (1))
822 return;
823
824 emit_line_note (input_filename, lineno);
72b7eeff 825 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
f30432d7
MS
826
827 /* The label for the exception handling block we will save. This is
828 Lresume, in the documention. */
72b7eeff 829 expand_label (label);
a3b49ccd 830
f30432d7
MS
831 /* Put in something that takes up space, as otherwise the end
832 address for the EH region could have the exact same address as
833 the outer region, causing us to miss the fact that resuming
834 exception handling with this PC value would be inside the outer
835 region. */
a3b49ccd
MS
836 emit_insn (gen_nop ());
837
72b7eeff 838 push_label_entry (&caught_return_label_stack, NULL_RTX, label);
f30432d7
MS
839
840 /* Start a new sequence for all the catch blocks. We will add this
841 to the gloabl sequence catch_clauses, when we have completed all
842 the handlers in this handler-seq. */
843 start_sequence ();
8d2733ca
MS
844
845 while (1)
8d08fdba 846 {
8d2733ca
MS
847 entry = dequeue_eh_entry (&ehqueue);
848 emit_label (entry->exception_handler_label);
849
850 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
851
852 /* When we get down to the matching entry, stop. */
853 if (entry->finalization == integer_zero_node)
854 break;
855
f30432d7
MS
856 /* The below can be optimized away, and we could just fall into the
857 next EH handler, if we are certain they are nested. */
858 /* Code to throw out to outer context, if we fall off end of the
859 handler. */
860 expand_internal_throw (gen_rtx (LABEL_REF,
861 Pmode,
862 entry->end_label));
8d2733ca
MS
863 free (entry);
864 }
8d2733ca 865}
8d08fdba 866
8d2733ca
MS
867/* call this to end processing of all the catch blocks. */
868void
869expand_end_all_catch ()
870{
f30432d7 871 rtx new_catch_clause;
8d08fdba 872
8d2733ca
MS
873 if (! doing_eh (1))
874 return;
8d08fdba 875
6060a796 876 /* Code to throw out to outer context, if we fall off end of catch
f30432d7
MS
877 handlers. This is rethrow (Lresume, same id, same obj); in the
878 documentation. */
879 expand_internal_throw (gen_rtx (LABEL_REF,
880 Pmode,
72b7eeff 881 DECL_RTL (top_label_entry (&caught_return_label_stack))));
f30432d7
MS
882
883 /* Now we have the complete catch sequence. */
884 new_catch_clause = get_insns ();
885 end_sequence ();
886
8d2733ca
MS
887 /* this level of catch blocks is done, so set up the successful catch jump
888 label for the next layer of catch blocks. */
889 pop_label_entry (&caught_return_label_stack);
8d08fdba 890
f30432d7
MS
891 /* Add the new sequence of catchs to the main one for this
892 function. */
893 push_to_sequence (catch_clauses);
894 emit_insns (new_catch_clause);
895 catch_clauses = get_insns ();
896 end_sequence ();
8d2733ca 897
a3b49ccd 898 /* Here we fall through into the continuation code. */
8d08fdba
MS
899}
900
f30432d7
MS
901/* Build a type value for use at runtime for a type that is matched
902 against by the exception handling system. */
903static tree
904build_eh_type_type (type)
905 tree type;
8d08fdba 906{
f30432d7
MS
907 char *typestring;
908 tree exp;
8d2733ca 909
f30432d7
MS
910 if (type == error_mark_node)
911 return error_mark_node;
8d2733ca 912
f30432d7
MS
913 /* peel back references, so they match. */
914 if (TREE_CODE (type) == REFERENCE_TYPE)
915 type = TREE_TYPE (type);
8d08fdba 916
f30432d7
MS
917 /* Peel off cv qualifiers. */
918 type = TYPE_MAIN_VARIANT (type);
8d2733ca 919
f30432d7 920 if (flag_rtti)
8d08fdba 921 {
f30432d7 922 return build1 (ADDR_EXPR, ptr_type_node, get_typeid (type));
8d08fdba 923 }
f30432d7
MS
924
925 typestring = build_overload_name (type, 1, 1);
926 exp = combine_strings (build_string (strlen (typestring)+1, typestring));
927 return build1 (ADDR_EXPR, ptr_type_node, exp);
8d08fdba 928}
8d08fdba 929
faae18ab
MS
930/* Build a type value for use at runtime for a exp that is thrown or
931 matched against by the exception handling system. */
932static tree
933build_eh_type (exp)
934 tree exp;
935{
faae18ab
MS
936 if (flag_rtti)
937 {
938 exp = build_typeid (exp);
939 return build1 (ADDR_EXPR, ptr_type_node, exp);
940 }
f30432d7 941 return build_eh_type_type (TREE_TYPE (exp));
faae18ab
MS
942}
943
72b7eeff 944/* This routine creates the cleanup for the exception handling object. */
5566b478 945static void
72b7eeff
MS
946push_eh_cleanup ()
947{
948 /* All cleanups must last longer than normal. */
949 int yes = suspend_momentary ();
950
951 /* Arrange to do a dynamically scoped cleanup upon exit from this region. */
952 tree cleanup = build_function_call (saved_cleanup, NULL_TREE);
953 cp_expand_decl_cleanup (NULL_TREE, cleanup);
954
955 resume_momentary (yes);
956}
957
958
8d2733ca
MS
959/* call this to start a catch block. Typename is the typename, and identifier
960 is the variable to place the object in or NULL if the variable doesn't
961 matter. If typename is NULL, that means its a "catch (...)" or catch
962 everything. In that case we don't need to do any type checking.
963 (ie: it ends up as the "else" clause rather than an "else if" clause) */
8d08fdba 964void
a4443a08
MS
965expand_start_catch_block (declspecs, declarator)
966 tree declspecs, declarator;
8d08fdba 967{
8d2733ca 968 rtx false_label_rtx;
a3b49ccd 969 rtx protect_label_rtx;
faae18ab 970 tree decl = NULL_TREE;
a3b49ccd 971 tree init;
8d2733ca
MS
972
973 if (! doing_eh (1))
974 return;
975
a3b49ccd
MS
976 /* Create a binding level for the parm. */
977 expand_start_bindings (0);
978
f675499c 979 false_label_rtx = gen_label_rtx ();
f30432d7
MS
980 /* This is saved for the exception table. */
981 push_rtl_perm ();
a3b49ccd
MS
982 protect_label_rtx = gen_label_rtx ();
983 pop_rtl_from_perm ();
72b7eeff
MS
984 push_label_entry (&false_label_stack, false_label_rtx, NULL_TREE);
985 push_label_entry (&false_label_stack, protect_label_rtx, NULL_TREE);
a3b49ccd 986
faae18ab 987 if (declspecs)
8d08fdba 988 {
faae18ab 989 tree exp;
8d2733ca 990 rtx call_rtx, return_value_rtx;
faae18ab
MS
991 tree init_type;
992
f30432d7
MS
993 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1,
994 NULL_TREE, NULL_TREE);
faae18ab
MS
995
996 if (decl == NULL_TREE)
997 {
998 error ("invalid catch parameter");
999 return;
1000 }
1001
be99da77
MS
1002 /* Make sure we mark the catch param as used, otherwise we'll get
1003 a warning about an unused ((anonymous)). */
1004 TREE_USED (decl) = 1;
1005
faae18ab
MS
1006 /* Figure out the type that the initializer is. */
1007 init_type = TREE_TYPE (decl);
f30432d7
MS
1008 if (TREE_CODE (init_type) != REFERENCE_TYPE
1009 && TREE_CODE (init_type) != POINTER_TYPE)
faae18ab
MS
1010 init_type = build_reference_type (init_type);
1011
f30432d7 1012 exp = saved_throw_value;
faae18ab 1013 exp = tree_cons (NULL_TREE,
f30432d7 1014 build_eh_type_type (TREE_TYPE (decl)),
faae18ab 1015 tree_cons (NULL_TREE,
f30432d7 1016 saved_throw_type,
faae18ab
MS
1017 tree_cons (NULL_TREE, exp, NULL_TREE)));
1018 exp = build_function_call (CatchMatch, exp);
1019 call_rtx = expand_call (exp, NULL_RTX, 0);
e1cd6e56 1020 assemble_external (TREE_OPERAND (CatchMatch, 0));
8d2733ca 1021
faae18ab 1022 return_value_rtx = hard_function_value (ptr_type_node, exp);
8d2733ca
MS
1023
1024 /* did the throw type match function return TRUE? */
faae18ab 1025 emit_cmp_insn (return_value_rtx, const0_rtx, EQ, NULL_RTX,
8d2733ca
MS
1026 GET_MODE (return_value_rtx), 0, 0);
1027
1028 /* if it returned FALSE, jump over the catch block, else fall into it */
faae18ab
MS
1029 emit_jump_insn (gen_beq (false_label_rtx));
1030
72b7eeff
MS
1031 push_eh_cleanup ();
1032
faae18ab
MS
1033 init = convert_from_reference (save_expr (make_tree (init_type, call_rtx)));
1034
1035 /* Do we need the below two lines? */
b3417a04 1036 /* Let `cp_finish_decl' know that this initializer is ok. */
faae18ab
MS
1037 DECL_INITIAL (decl) = init;
1038 decl = pushdecl (decl);
b3417a04 1039 cp_finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba
MS
1040 }
1041 else
1042 {
72b7eeff
MS
1043 push_eh_cleanup ();
1044
8d2733ca 1045 /* Fall into the catch all section. */
8d08fdba 1046 }
a3b49ccd
MS
1047
1048 /* This is the starting of something to protect. */
1049 emit_label (protect_label_rtx);
1050
8d2733ca 1051 emit_line_note (input_filename, lineno);
8d08fdba
MS
1052}
1053
8d08fdba 1054
f30432d7
MS
1055/* this is called from expand_exception_blocks and
1056 expand_end_catch_block to expand the toplevel finalizations for a
1057 function. We return the first label emitted, if any, otherwise
1058 return NULL_RTX. */
1059static rtx
1060expand_leftover_cleanups ()
1061{
1062 struct ehEntry *entry;
1063 rtx first_label = NULL_RTX;
1064
1065 while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
1066 {
1067 if (! first_label)
1068 first_label = entry->exception_handler_label;
1069 emit_label (entry->exception_handler_label);
1070
1071 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
1072
1073 /* The below can be optimized away, and we could just fall into the
1074 next EH handler, if we are certain they are nested. */
1075 /* Code to throw out to outer context, if we fall off end of the
1076 handler. */
1077 expand_internal_throw (gen_rtx (LABEL_REF,
1078 Pmode,
1079 entry->end_label));
1080
1081 /* leftover try block, opps. */
1082 if (entry->finalization == integer_zero_node)
1083 abort ();
1084
1085 free (entry);
1086 }
1087
1088 return first_label;
1089}
1090
8d2733ca
MS
1091/* Call this to end a catch block. Its responsible for emitting the
1092 code to handle jumping back to the correct place, and for emitting
1093 the label to jump to if this catch block didn't match. */
1094void expand_end_catch_block ()
8d08fdba 1095{
f30432d7
MS
1096 rtx start_protect_label_rtx;
1097 rtx end_protect_label_rtx;
1098 tree decls;
1099 struct ehEntry entry;
a3b49ccd 1100
f30432d7
MS
1101 if (! doing_eh (1))
1102 return;
8d2733ca 1103
f30432d7
MS
1104 /* fall to outside the try statement when done executing handler and
1105 we fall off end of handler. This is jump Lresume in the
1106 documentation. */
72b7eeff 1107 expand_goto (top_label_entry (&caught_return_label_stack));
a3b49ccd 1108
f30432d7
MS
1109 /* We end the rethrow protection region as soon as we hit a label. */
1110 end_protect_label_rtx = expand_leftover_cleanups ();
a3b49ccd 1111
f30432d7
MS
1112 /* Code to throw out to outer context, if we get a throw from within
1113 our catch handler. */
1114 /* These are saved for the exception table. */
1115 push_rtl_perm ();
1116 entry.exception_handler_label = gen_label_rtx ();
1117 pop_rtl_from_perm ();
1118 /* This label is Lhandler in the documentation. */
1119 emit_label (entry.exception_handler_label);
1120 expand_internal_throw (gen_rtx (LABEL_REF,
1121 Pmode,
72b7eeff 1122 DECL_RTL (top_label_entry (&caught_return_label_stack))));
f30432d7
MS
1123
1124 /* No associated finalization. */
1125 entry.finalization = NULL_TREE;
1126 entry.context = current_function_decl;
1127
1128 if (end_protect_label_rtx == NULL_RTX)
1129 end_protect_label_rtx = entry.exception_handler_label;
1130
1131 /* Because we are emitted out of line, we have to protect this. */
1132 /* label for the start of the protection region. */
1133 start_protect_label_rtx = pop_label_entry (&false_label_stack);
1134
1135 /* Cleanup the EH parameter. */
1136 decls = getdecls ();
1137 expand_end_bindings (decls, decls != NULL_TREE, 0);
a3b49ccd 1138
f30432d7
MS
1139 /* label we emit to jump to if this catch block didn't match. */
1140 /* This the closing } in the `if (eq) {' of the documentation. */
1141 emit_label (pop_label_entry (&false_label_stack));
a3b49ccd 1142
f30432d7
MS
1143 /* Because we are reordered out of line, we have to protect this. */
1144 entry.start_label = start_protect_label_rtx;
1145 entry.end_label = end_protect_label_rtx;
a3b49ccd 1146
f30432d7
MS
1147 LABEL_PRESERVE_P (entry.start_label) = 1;
1148 LABEL_PRESERVE_P (entry.end_label) = 1;
1149 LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
8d08fdba 1150
f30432d7
MS
1151 /* These set up a call to throw the caught exception into the outer
1152 context. */
1153 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
8d2733ca 1154}
8d08fdba 1155
db5ae43f
MS
1156/* unwind the stack. */
1157static void
f30432d7
MS
1158do_unwind (inner_throw_label)
1159 rtx inner_throw_label;
db5ae43f 1160{
be99da77
MS
1161#if defined (SPARC_STACK_ALIGN) /* was sparc */
1162 /* This doesn't work for the flat model sparc, I bet. */
db5ae43f
MS
1163 tree fcall;
1164 tree params;
1165 rtx return_val_rtx;
f30432d7 1166 rtx temp;
db5ae43f
MS
1167
1168 /* call to __builtin_return_address () */
f30432d7 1169 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
db5ae43f 1170 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 1171 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
ddd5a7c1 1172 /* In the return, the new pc is pc+8, as the value coming in is
db5ae43f 1173 really the address of the call insn, not the next insn. */
f30432d7
MS
1174 temp = gen_reg_rtx (Pmode);
1175 emit_move_insn (temp, inner_throw_label);
1176 emit_move_insn (return_val_rtx, plus_constant (temp, -8));
db5ae43f
MS
1177 easy_expand_asm ("ret");
1178 easy_expand_asm ("restore");
1179 emit_barrier ();
1180#endif
be99da77 1181#if defined (ARM_FRAME_RTX) /* was __arm */
f30432d7
MS
1182 if (flag_omit_frame_pointer)
1183 sorry ("this implementation of exception handling requires a frame pointer");
db5ae43f 1184
f30432d7
MS
1185 emit_move_insn (stack_pointer_rtx,
1186 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -8)));
1187 emit_move_insn (hard_frame_pointer_rtx,
1188 gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -12)));
db5ae43f 1189#endif
be99da77 1190#if defined (TARGET_88000) /* was m88k */
db5ae43f
MS
1191 rtx temp_frame = frame_pointer_rtx;
1192
1193 temp_frame = memory_address (Pmode, temp_frame);
1194 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
1195
1196 /* hopefully this will successfully pop the frame! */
1197 emit_move_insn (frame_pointer_rtx, temp_frame);
1198 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1199 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
1200 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1201 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
1202
1203#if 0
1204 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1205 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
1206
1207 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
1208
1209 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1210 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
1211#endif
1212#endif
be99da77 1213#if ! defined (TARGET_88000) && ! defined (ARM_FRAME_RTX) && ! defined (SPARC_STACK_ALIGN)
f30432d7
MS
1214 tree fcall;
1215 tree params;
1216 rtx return_val_rtx;
e1cd6e56 1217
be99da77
MS
1218#if 0
1219 /* I would like to do this here, but the move below doesn't seem to work. */
f30432d7
MS
1220 /* call to __builtin_return_address () */
1221 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
1222 fcall = build_function_call (BuiltinReturnAddress, params);
1223 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
be99da77 1224
f30432d7
MS
1225 emit_move_insn (return_val_rtx, inner_throw_label);
1226 /* So, for now, just pass throw label to stack unwinder. */
1227#endif
1228 params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
1229 inner_throw_label), NULL_TREE);
1230
1231 do_function_call (Unwind, params, NULL_TREE);
1232 assemble_external (TREE_OPERAND (Unwind, 0));
1233 emit_barrier ();
e1cd6e56 1234#endif
db5ae43f 1235}
8d08fdba 1236
f30432d7 1237
be99da77
MS
1238/* Given the return address, compute the new pc to throw. This has to
1239 work for the current frame of the current function, and the one
1240 above it in the case of throw. */
5566b478 1241static rtx
be99da77
MS
1242eh_outer_context (addr)
1243 rtx addr;
1244{
1245#if defined (ARM_FRAME_RTX) /* was __arm */
1246 /* On the ARM, '__builtin_return_address', must have 4
1247 subtracted from it. */
1248 emit_insn (gen_add2_insn (addr, GEN_INT (-4)));
1249
1250 /* If we are generating code for an ARM2/ARM3 machine or for an ARM6
1251 in 26 bit mode, the condition codes must be masked out of the
1252 return value, or else they will confuse BuiltinReturnAddress.
1253 This does not apply to ARM6 and later processors when running in
1254 32 bit mode. */
1255 if (!TARGET_6)
1256 emit_insn (gen_rtx (SET, Pmode,
1257 addr,
1258 gen_rtx (AND, Pmode,
1259 addr, GEN_INT (0x03fffffc))));
1260#else
1261#if ! defined (SPARC_STACK_ALIGN) /* was sparc */
1262#if defined (TARGET_SNAKE)
1263 /* On HPPA, the low order two bits hold the priviledge level, so we
1264 must get rid of them. */
1265 emit_insn (gen_rtx (SET, Pmode,
1266 addr,
1267 gen_rtx (AND, Pmode,
1268 addr, GEN_INT (0xfffffffc))));
1269#endif
1270
1271 /* On the SPARC, __builtin_return_address is already -8 or -12, no
1272 need to subtract any more from it. */
1273 addr = plus_constant (addr, -1);
1274#endif
1275#endif
1276
1277 return addr;
1278}
1279
e1cd6e56 1280/* is called from expand_exception_blocks () to generate the code in a function
ddd5a7c1 1281 to "throw" if anything in the function needs to perform a throw.
8d08fdba 1282
ddd5a7c1 1283 expands "throw" as the following pseudo code:
8d2733ca
MS
1284
1285 throw:
1286 eh = find_first_exception_match (saved_pc);
1287 if (!eh) goto gotta_rethrow_it;
1288 goto eh;
1289
1290 gotta_rethrow_it:
1291 saved_pc = __builtin_return_address (0);
1292 pop_to_previous_level ();
1293 goto throw;
1294
1295 */
f30432d7 1296void
8d2733ca
MS
1297expand_builtin_throw ()
1298{
1299 tree fcall;
1300 tree params;
1301 rtx return_val_rtx;
f30432d7
MS
1302 rtx gotta_rethrow_it;
1303 rtx gotta_call_terminate;
f30432d7
MS
1304 rtx top_of_loop;
1305 rtx unwind_first;
1306 tree t;
1307
1308 if (! doing_eh (0))
1309 return;
1310
1311 if (! throw_used)
1312 return;
8d2733ca 1313
f30432d7
MS
1314 params = void_list_node;
1315 t = build_parse_node (CALL_EXPR, get_identifier ("__throw"), params, NULL_TREE);
1316 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1317 void_list_node),
1318 t, NULL_TREE, NULL_TREE, 0);
1319 store_parm_decls ();
1320 pushlevel (0);
1321 clear_last_expr ();
1322 push_momentary ();
1323 expand_start_bindings (0);
1324
1325 gotta_rethrow_it = gen_label_rtx ();
1326 gotta_call_terminate = gen_label_rtx ();
f30432d7
MS
1327 top_of_loop = gen_label_rtx ();
1328 unwind_first = gen_label_rtx ();
1329
1330 emit_jump (unwind_first);
1331
1332 emit_label (top_of_loop);
8d2733ca
MS
1333
1334 /* search for an exception handler for the saved_pc */
1335 return_val_rtx = do_function_call (FirstExceptionMatch,
f30432d7 1336 tree_cons (NULL_TREE, saved_pc, NULL_TREE),
8d2733ca 1337 ptr_type_node);
e1cd6e56 1338 assemble_external (TREE_OPERAND (FirstExceptionMatch, 0));
8d2733ca
MS
1339
1340 /* did we find one? */
1341 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
1342 GET_MODE (return_val_rtx), 0, 0);
1343
1344 /* if not, jump to gotta_rethrow_it */
1345 emit_jump_insn (gen_beq (gotta_rethrow_it));
1346
1347 /* we found it, so jump to it */
1348 emit_indirect_jump (return_val_rtx);
1349
1350 /* code to deal with unwinding and looking for it again */
1351 emit_label (gotta_rethrow_it);
1352
1353 /* call to __builtin_return_address () */
be99da77
MS
1354#if defined (ARM_FRAME_RTX) /* was __arm */
1355 /* This should be moved into arm.h:RETURN_ADDR_RTX */
1356 /* This replaces a 'call' to __builtin_return_address */
e1cd6e56 1357 return_val_rtx = gen_reg_rtx (Pmode);
f30432d7 1358 emit_move_insn (return_val_rtx, gen_rtx (MEM, Pmode, plus_constant (hard_frame_pointer_rtx, -4)));
e1cd6e56 1359#else
f30432d7 1360 params = tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
8d2733ca 1361 fcall = build_function_call (BuiltinReturnAddress, params);
f30432d7 1362 return_val_rtx = expand_expr (fcall, NULL_RTX, Pmode, 0);
e1cd6e56 1363#endif
8d2733ca
MS
1364
1365 /* did __builtin_return_address () return a valid address? */
1366 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
1367 GET_MODE (return_val_rtx), 0, 0);
1368
1369 emit_jump_insn (gen_beq (gotta_call_terminate));
1370
be99da77 1371 return_val_rtx = eh_outer_context (return_val_rtx);
e1cd6e56 1372
be99da77
MS
1373 /* Yes it did. */
1374 emit_move_insn (DECL_RTL (saved_pc), return_val_rtx);
f30432d7
MS
1375
1376 do_unwind (gen_rtx (LABEL_REF, Pmode, top_of_loop));
1377 emit_jump (top_of_loop);
8d2733ca
MS
1378
1379 /* no it didn't --> therefore we need to call terminate */
1380 emit_label (gotta_call_terminate);
1381 do_function_call (Terminate, NULL_TREE, NULL_TREE);
e1cd6e56 1382 assemble_external (TREE_OPERAND (Terminate, 0));
f30432d7
MS
1383
1384 {
1385 rtx ret_val, return_val_rtx;
1386 emit_label (unwind_first);
1387 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
1388 0, hard_frame_pointer_rtx);
1389
1390 /* Set it up so that we continue inside, at the top of the loop. */
1391 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, top_of_loop));
21451173
MS
1392#ifdef RETURN_ADDR_OFFSET
1393 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
f30432d7
MS
1394 if (return_val_rtx != ret_val)
1395 emit_move_insn (ret_val, return_val_rtx);
1396#endif
1397
1398 /* Fall into epilogue to unwind prologue. */
1399 }
1400
1401 expand_end_bindings (getdecls(), 1, 0);
1402 poplevel (1, 0, 0);
1403 pop_momentary ();
1404
1405 finish_function (lineno, 0, 0);
8d08fdba 1406}
8d2733ca
MS
1407
1408
f30432d7
MS
1409void
1410expand_start_eh_spec ()
1411{
1412 start_protect ();
1413}
1414
5566b478 1415static void
f30432d7
MS
1416expand_end_eh_spec (raises)
1417 tree raises;
1418{
1419 tree expr, second_try;
1420 rtx check = gen_label_rtx ();
1421 rtx cont;
1422 rtx ret = gen_reg_rtx (Pmode);
1423 rtx flag = gen_reg_rtx (TYPE_MODE (integer_type_node));
1424 rtx end = gen_label_rtx ();
1425
1426 expr = make_node (RTL_EXPR);
1427 TREE_TYPE (expr) = void_type_node;
1428 RTL_EXPR_RTL (expr) = const0_rtx;
1429 TREE_SIDE_EFFECTS (expr) = 1;
1430 start_sequence_for_rtl_expr (expr);
1431 cont = gen_label_rtx ();
1432 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
1433 emit_jump (check);
1434 emit_label (cont);
1435 jumpif (make_tree (integer_type_node, flag), end);
1436 do_function_call (Terminate, NULL_TREE, NULL_TREE);
1437 assemble_external (TREE_OPERAND (Terminate, 0));
1438 emit_barrier ();
1439 RTL_EXPR_SEQUENCE (expr) = get_insns ();
1440 end_sequence ();
1441
1442 second_try = expr;
1443
1444 expr = make_node (RTL_EXPR);
1445 TREE_TYPE (expr) = void_type_node;
1446 RTL_EXPR_RTL (expr) = const0_rtx;
1447 TREE_SIDE_EFFECTS (expr) = 1;
1448 start_sequence_for_rtl_expr (expr);
1449
1450 cont = gen_label_rtx ();
1451 emit_move_insn (ret, gen_rtx (LABEL_REF, Pmode, cont));
1452 emit_jump (check);
1453 emit_label (cont);
1454 jumpif (make_tree (integer_type_node, flag), end);
1455 start_protect ();
1456 do_function_call (Unexpected, NULL_TREE, NULL_TREE);
1457 assemble_external (TREE_OPERAND (Unexpected, 0));
1458 emit_barrier ();
1459 end_protect (second_try);
1460
1461 emit_label (check);
1462 emit_move_insn (flag, const1_rtx);
1463 cont = gen_label_rtx ();
1464 while (raises)
1465 {
1466 tree exp;
1467 tree match_type = TREE_VALUE (raises);
1468
1469 if (match_type)
1470 {
1471 /* check TREE_VALUE (raises) here */
1472 exp = saved_throw_value;
1473 exp = tree_cons (NULL_TREE,
1474 build_eh_type_type (match_type),
1475 tree_cons (NULL_TREE,
1476 saved_throw_type,
1477 tree_cons (NULL_TREE, exp, NULL_TREE)));
1478 exp = build_function_call (CatchMatch, exp);
1479 assemble_external (TREE_OPERAND (CatchMatch, 0));
1480
1481 jumpif (exp, cont);
1482 }
1483
1484 raises = TREE_CHAIN (raises);
1485 }
1486 emit_move_insn (flag, const0_rtx);
1487 emit_label (cont);
1488 emit_indirect_jump (ret);
1489 emit_label (end);
1490
1491 RTL_EXPR_SEQUENCE (expr) = get_insns ();
1492 end_sequence ();
1493
1494 end_protect (expr);
1495}
1496
8d2733ca
MS
1497/* This is called to expand all the toplevel exception handling
1498 finalization for a function. It should only be called once per
1499 function. */
8d08fdba 1500void
8d2733ca 1501expand_exception_blocks ()
8d08fdba 1502{
21451173 1503 rtx funcend;
f30432d7
MS
1504 rtx insns;
1505
1506 start_sequence ();
8d2733ca
MS
1507
1508 funcend = gen_label_rtx ();
1509 emit_jump (funcend);
1510 /* expand_null_return (); */
1511
f30432d7
MS
1512 start_sequence ();
1513
1514 /* Add all the catch clauses here. */
1515 emit_insns (catch_clauses);
1516 catch_clauses = NULL_RTX;
8d2733ca
MS
1517
1518 expand_leftover_cleanups ();
1519
f30432d7
MS
1520 insns = get_insns ();
1521 end_sequence ();
1522
1523 /* Do this after we expand leftover cleanups, so that the end_protect
1524 that expand_end_eh_spec does will match the right start_protect,
1525 and make sure it comes out before the terminate protected region. */
1526 if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
1527 {
1528 expand_end_eh_spec (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)));
1529 push_to_sequence (insns);
1530
1531 /* Now expand any new ones. */
1532 expand_leftover_cleanups ();
1533
1534 insns = get_insns ();
1535 end_sequence ();
1536 }
1537
1538 if (insns)
1539 {
1540 struct ehEntry entry;
1541
1542 /* These are saved for the exception table. */
1543 push_rtl_perm ();
1544 entry.start_label = gen_label_rtx ();
1545 entry.end_label = gen_label_rtx ();
1546 entry.exception_handler_label = gen_label_rtx ();
1547 entry.finalization = TerminateFunctionCall;
1548 entry.context = current_function_decl;
1549 assemble_external (TREE_OPERAND (Terminate, 0));
1550 pop_rtl_from_perm ();
1551
1552 LABEL_PRESERVE_P (entry.start_label) = 1;
1553 LABEL_PRESERVE_P (entry.end_label) = 1;
1554 LABEL_PRESERVE_P (entry.exception_handler_label) = 1;
1555
1556 emit_label (entry.start_label);
1557 emit_insns (insns);
1558
1559 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
1560
1561 emit_label (entry.exception_handler_label);
1562 expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
1563 emit_label (entry.end_label);
1564 emit_barrier ();
1565 }
1566
8d2733ca 1567 {
f30432d7
MS
1568 /* Mark the end of the stack unwinder. */
1569 rtx unwind_insns;
1570 start_sequence ();
1571 end_eh_unwinder (funcend);
1572 expand_leftover_cleanups ();
1573 unwind_insns = get_insns ();
1574 end_sequence ();
1575 if (unwind_insns)
8d2733ca 1576 {
f30432d7
MS
1577 insns = unwind_insns;
1578 emit_insns (insns);
8d2733ca
MS
1579 }
1580 }
f30432d7 1581
8d2733ca 1582 emit_label (funcend);
f30432d7
MS
1583
1584 /* Only if we had previous insns do we want to emit the jump around
1585 them. If there weren't any, then insns will remain NULL_RTX. */
1586 if (insns)
1587 insns = get_insns ();
1588 end_sequence ();
1589
1590 emit_insns (insns);
8d08fdba
MS
1591}
1592
72b7eeff
MS
1593tree
1594start_anon_func ()
1595{
1596 static int counter = 0;
1597 char name[32];
1598 tree params;
1599 tree t;
1600
1601 push_cp_function_context (NULL_TREE);
1602 push_to_top_level ();
1603
1604 /* No need to mangle this. */
1605 push_lang_context (lang_name_c);
1606
1607 params = void_list_node;
1608 /* tcf stands for throw clean funciton. */
1609 sprintf (name, "__tcf_%d", counter++);
1610 t = build_parse_node (CALL_EXPR, get_identifier (name), params, NULL_TREE);
1611 start_function (decl_tree_cons (NULL_TREE, get_identifier ("static"),
1612 void_list_node),
1613 t, NULL_TREE, NULL_TREE, 0);
1614 store_parm_decls ();
1615 pushlevel (0);
1616 clear_last_expr ();
1617 push_momentary ();
1618 expand_start_bindings (0);
1619 emit_line_note (input_filename, lineno);
1620
1621 pop_lang_context ();
1622
1623 return current_function_decl;
1624}
1625
1626void
1627end_anon_func ()
1628{
1629 expand_end_bindings (getdecls(), 1, 0);
1630 poplevel (1, 0, 0);
1631 pop_momentary ();
1632
1633 finish_function (lineno, 0, 0);
1634
1635 pop_from_top_level ();
1636 pop_cp_function_context (NULL_TREE);
1637}
8d2733ca
MS
1638
1639/* call this to expand a throw statement. This follows the following
1640 algorithm:
1641
1642 1. Allocate space to save the current PC onto the stack.
1643 2. Generate and emit a label and save its address into the
e1cd6e56 1644 newly allocated stack space since we can't save the pc directly.
8d2733ca
MS
1645 3. If this is the first call to throw in this function:
1646 generate a label for the throw block
1647 4. jump to the throw block label. */
8d08fdba 1648void
8d2733ca
MS
1649expand_throw (exp)
1650 tree exp;
8d08fdba 1651{
8d2733ca 1652 rtx label;
8d08fdba 1653
8d2733ca
MS
1654 if (! doing_eh (1))
1655 return;
8d08fdba 1656
a3b49ccd
MS
1657 /* This is the label that represents where in the code we were, when
1658 we got an exception. This needs to be updated when we rethrow an
1659 exception, so that the matching routine knows to search out. */
8d2733ca
MS
1660 label = gen_label_rtx ();
1661 emit_label (label);
8d2733ca
MS
1662
1663 if (exp)
1664 {
faae18ab 1665 tree throw_type;
72b7eeff 1666 tree cleanup = empty_fndecl, e;
faae18ab 1667
a3b49ccd 1668 /* throw expression */
8d2733ca 1669 /* First, decay it. */
f30432d7 1670 exp = decay_conversion (exp);
a3b49ccd 1671
f30432d7
MS
1672 if (TREE_CODE (TREE_TYPE (exp)) == POINTER_TYPE)
1673 {
1674 throw_type = build_eh_type (exp);
1675 exp = build_reinterpret_cast (ptr_type_node, exp);
1676 }
1677 else
1678 {
72b7eeff
MS
1679 rtx cleanup_insns;
1680 tree object;
f30432d7
MS
1681 /* Make a copy of the thrown object. WP 15.1.5 */
1682 exp = build_new (NULL_TREE, TREE_TYPE (exp),
1683 build_tree_list (NULL_TREE, exp),
1684 0);
faae18ab 1685
f30432d7
MS
1686 if (exp == error_mark_node)
1687 error (" in thrown expression");
faae18ab 1688
72b7eeff
MS
1689 object = build_indirect_ref (exp, NULL_PTR);
1690 throw_type = build_eh_type (object);
1691
1692 start_sequence ();
1693 object = build_reinterpret_cast (TREE_TYPE (exp), saved_throw_value);
1694 object = build_indirect_ref (object, NULL_PTR);
1695 cleanup = maybe_build_cleanup (object);
1696 if (cleanup)
1697 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
1698 cleanup_insns = get_insns ();
1699 end_sequence ();
1700
1701 if (cleanup && cleanup_insns)
1702 {
1703 cleanup = start_anon_func ();
1704
1705 expand_expr (maybe_build_cleanup (object), const0_rtx, VOIDmode, 0);
1706
1707 end_anon_func ();
1708
1709 mark_addressable (cleanup);
1710 }
1711 else
1712 {
1713 cleanup = empty_fndecl;
1714 }
f30432d7 1715 }
faae18ab 1716
be99da77
MS
1717 if (cleanup == empty_fndecl)
1718 assemble_external (empty_fndecl);
1719
f30432d7
MS
1720 e = build_modify_expr (saved_throw_type, NOP_EXPR, throw_type);
1721 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff 1722
f30432d7
MS
1723 e = build_modify_expr (saved_throw_value, NOP_EXPR, exp);
1724 e = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (e), e);
1725 expand_expr (e, const0_rtx, VOIDmode, 0);
72b7eeff
MS
1726
1727 cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
1728 cleanup = build_modify_expr (saved_cleanup, NOP_EXPR, cleanup);
1729 expand_expr (cleanup, const0_rtx, VOIDmode, 0);
8d2733ca
MS
1730 }
1731 else
a3b49ccd
MS
1732 {
1733 /* rethrow current exception */
8ccc31eb 1734 /* This part is easy, as we don't have to do anything else. */
a3b49ccd 1735 }
8d2733ca 1736
f30432d7 1737 expand_internal_throw (gen_rtx (LABEL_REF, Pmode, label));
8d08fdba
MS
1738}
1739
b7484fbe
MS
1740void
1741end_protect_partials () {
1742 while (protect_list)
1743 {
1744 end_protect (TREE_VALUE (protect_list));
1745 protect_list = TREE_CHAIN (protect_list);
1746 }
1747}
1748
1749int
1750might_have_exceptions_p ()
1751{
b7484fbe
MS
1752 if (eh_table_output_queue.head)
1753 return 1;
b7484fbe
MS
1754 return 0;
1755}
f376e137
MS
1756
1757/* Output the exception table.
1758 Return the number of handlers. */
b7484fbe
MS
1759void
1760emit_exception_table ()
8d08fdba 1761{
f376e137 1762 int count = 0;
8d2733ca
MS
1763 extern FILE *asm_out_file;
1764 struct ehEntry *entry;
8d08fdba 1765
8d2733ca 1766 if (! doing_eh (0))
b7484fbe
MS
1767 return;
1768
1769 exception_section ();
1770
1771 /* Beginning marker for table. */
f30432d7
MS
1772 assemble_align (GET_MODE_ALIGNMENT (Pmode));
1773 assemble_label ("__EXCEPTION_TABLE__");
b7484fbe
MS
1774 output_exception_table_entry (asm_out_file,
1775 const0_rtx, const0_rtx, const0_rtx);
8d2733ca 1776
f376e137
MS
1777 while (entry = dequeue_eh_entry (&eh_table_output_queue))
1778 {
8ccc31eb
MS
1779 tree context = entry->context;
1780
1781 if (context && ! TREE_ASM_WRITTEN (context))
1782 continue;
1783
f376e137 1784 count++;
8d2733ca 1785 output_exception_table_entry (asm_out_file,
f376e137
MS
1786 entry->start_label, entry->end_label,
1787 entry->exception_handler_label);
8d2733ca
MS
1788 }
1789
b7484fbe 1790 /* Ending marker for table. */
f30432d7 1791 assemble_label ("__EXCEPTION_END__");
b7484fbe
MS
1792 output_exception_table_entry (asm_out_file,
1793 constm1_rtx, constm1_rtx, constm1_rtx);
f376e137 1794}
8d2733ca 1795
f376e137
MS
1796void
1797register_exception_table ()
1798{
f376e137
MS
1799 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
1800 VOIDmode, 1,
81613e43 1801 gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
f376e137 1802 Pmode);
f376e137 1803}
8d2733ca
MS
1804
1805/* Build a throw expression. */
1806tree
1807build_throw (e)
1808 tree e;
1809{
db5ae43f
MS
1810 if (e != error_mark_node)
1811 {
1812 e = build1 (THROW_EXPR, void_type_node, e);
1813 TREE_SIDE_EFFECTS (e) = 1;
faae18ab 1814 TREE_USED (e) = 1;
db5ae43f 1815 }
8d2733ca 1816 return e;
8d08fdba 1817}
f30432d7 1818
5566b478 1819void
f30432d7
MS
1820start_eh_unwinder ()
1821{
1822 start_protect ();
1823}
1824
5566b478 1825static void
f30432d7
MS
1826end_eh_unwinder (end)
1827 rtx end;
1828{
1829 tree expr;
1830 rtx return_val_rtx, ret_val, label;
1831
1832 if (! doing_eh (0))
1833 return;
1834
1835 expr = make_node (RTL_EXPR);
1836 TREE_TYPE (expr) = void_type_node;
1837 RTL_EXPR_RTL (expr) = const0_rtx;
1838 TREE_SIDE_EFFECTS (expr) = 1;
1839 start_sequence_for_rtl_expr (expr);
1840
1841 ret_val = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
1842 0, hard_frame_pointer_rtx);
1843 return_val_rtx = copy_to_reg (ret_val);
be99da77
MS
1844
1845 return_val_rtx = eh_outer_context (return_val_rtx);
1846
f30432d7
MS
1847 emit_move_insn (DECL_RTL (saved_pc), return_val_rtx);
1848
1849#ifdef JUMP_TO_THROW
1850 emit_move_insn (ret_val, gen_rtx (SYMBOL_REF, Pmode, "__throw"));
1851#else
1852 label = gen_label_rtx ();
1853 emit_move_insn (ret_val, gen_rtx (LABEL_REF, Pmode, label));
1854#endif
1855
21451173
MS
1856#ifdef RETURN_ADDR_OFFSET
1857 return_val_rtx = plus_constant (ret_val, -RETURN_ADDR_OFFSET);
f30432d7
MS
1858 if (return_val_rtx != ret_val)
1859 emit_move_insn (ret_val, return_val_rtx);
1860#endif
1861
1862 emit_jump (end);
1863
1864#ifndef JUMP_TO_THROW
1865 emit_label (label);
1866 do_function_call (Throw, NULL_TREE, NULL_TREE);
1867#endif
1868
1869 RTL_EXPR_SEQUENCE (expr) = get_insns ();
1870 end_sequence ();
1871 end_protect (expr);
1872}
This page took 0.365543 seconds and 5 git commands to generate.