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