]> gcc.gnu.org Git - gcc.git/blame - gcc/cp/except.c
(ASM_OUTPUT_SECTION_NAME): Renamed from ASM_OUTPUT_SECTION.
[gcc.git] / gcc / cp / except.c
CommitLineData
8d08fdba 1/* Handle exceptional things in C++.
8d2733ca
MS
2 Copyright (C) 1989, 1992, 1993, 1994 Free Software Foundation, Inc.
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
21the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
22
23
24/* High-level class interface. */
25
26#include "config.h"
27#include "tree.h"
28#include "rtl.h"
29#include "cp-tree.h"
30#include "flags.h"
8d2733ca
MS
31#include "obstack.h"
32#include "expr.h"
8d08fdba 33
a3b49ccd
MS
34extern void (*interim_eh_hook) PROTO((tree));
35
8d2733ca
MS
36/* holds the fndecl for __builtin_return_address () */
37tree builtin_return_address_fndecl;
8d08fdba 38
8d2733ca 39/* Define at your own risk! */
a4443a08 40#ifndef CROSS_COMPILE
8d2733ca
MS
41#ifdef sun
42#ifdef sparc
43#define TRY_NEW_EH
44#endif
45#endif
6060a796 46#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
db5ae43f
MS
47#define TRY_NEW_EH
48#endif
a4443a08 49#endif
8d08fdba 50
8d2733ca 51#ifndef TRY_NEW_EH
8d08fdba 52
8d2733ca
MS
53static void
54sorry_no_eh ()
55{
56 static int warned = 0;
57 if (! warned)
58 {
59 sorry ("exception handling not supported");
60 warned = 1;
61 }
62}
8d08fdba 63
8d2733ca
MS
64void
65expand_exception_blocks ()
66{
67}
8d08fdba 68
8d2733ca
MS
69void
70start_protect ()
71{
72}
8d08fdba 73
8d2733ca
MS
74void
75end_protect (finalization)
76 tree finalization;
77{
78}
8d08fdba 79
8d2733ca
MS
80void
81expand_start_try_stmts ()
82{
83 sorry_no_eh ();
84}
8d08fdba 85
8d2733ca
MS
86void
87expand_end_try_stmts ()
88{
89}
8d08fdba 90
8d2733ca
MS
91void
92expand_start_all_catch ()
93{
94}
8d08fdba 95
8d2733ca
MS
96void
97expand_end_all_catch ()
98{
99}
8d08fdba 100
8d2733ca 101void
a4443a08
MS
102expand_start_catch_block (declspecs, declarator)
103 tree declspecs, declarator;
8d2733ca
MS
104{
105}
8d08fdba 106
8d2733ca
MS
107void
108expand_end_catch_block ()
109{
110}
8d08fdba 111
8d2733ca
MS
112void
113init_exception_processing ()
8d08fdba 114{
8d2733ca 115}
8d08fdba 116
8d2733ca
MS
117void
118expand_throw (exp)
119 tree exp;
120{
121 sorry_no_eh ();
122}
8d08fdba 123
8d08fdba 124#else
8d08fdba 125
8d2733ca
MS
126static int
127doing_eh (do_warn)
128 int do_warn;
8d08fdba 129{
8d2733ca 130 if (! flag_handle_exceptions)
8d08fdba 131 {
8d2733ca
MS
132 static int warned = 0;
133 if (! warned && do_warn)
8d08fdba 134 {
8d2733ca
MS
135 error ("exception handling disabled, use -fhandle-exceptions to enable.");
136 warned = 1;
8d08fdba 137 }
8d2733ca 138 return 0;
8d08fdba 139 }
8d2733ca 140 return 1;
8d08fdba
MS
141}
142
8d08fdba 143
8d2733ca
MS
144/*
145NO GNEWS IS GOOD GNEWS WITH GARRY GNUS: This version is much closer
146to supporting exception handling as per Stroustrup's 2nd edition.
147It is a complete rewrite of all the EH stuff that was here before
148 Shortcomings:
149 1. The type of the throw and catch must still match
150 exactly (no support yet for matching base classes)
151 2. Throw specifications of functions still doesnt't work.
152 Cool Things:
153 1. Destructors are called properly :-)
154 2. No overhead for the non-exception thrown case.
155 3. Fixing shortcomings 1 and 2 is simple.
156 -Tad Hunt (tad@mail.csh.rit.edu)
157
158*/
159
160/* A couple of backend routines from m88k.c */
161
162/* used to cache a call to __builtin_return_address () */
163static tree BuiltinReturnAddress;
164
165
166
167
168
169#include <stdio.h>
170
171/* XXX - Tad: for EH */
172/* output an exception table entry */
173
174static void
175output_exception_table_entry (file, start_label, end_label, eh_label)
176 FILE *file;
177 rtx start_label, end_label, eh_label;
8d08fdba 178{
8d2733ca 179 char label[100];
8d08fdba 180
f376e137
MS
181 assemble_integer (start_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
182 assemble_integer (end_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
183 assemble_integer (eh_label, BITS_PER_WORD/BITS_PER_UNIT, 1);
8d2733ca
MS
184 putc ('\n', file); /* blank line */
185}
186
187static void
188easy_expand_asm (str)
189 char *str;
190{
191 expand_asm (build_string (strlen (str)+1, str));
8d08fdba
MS
192}
193
8d08fdba 194
8d2733ca
MS
195#if 0
196/* This is the startup, and finish stuff per exception table. */
8d08fdba 197
8d2733ca
MS
198/* XXX - Tad: exception handling section */
199#ifndef EXCEPT_SECTION_ASM_OP
200#define EXCEPT_SECTION_ASM_OP "section\t.gcc_except_table,\"a\",@progbits"
201#endif
8d08fdba 202
8d2733ca
MS
203#ifdef EXCEPT_SECTION_ASM_OP
204typedef struct {
205 void *start_protect;
206 void *end_protect;
207 void *exception_handler;
208 } exception_table;
209#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 210
8d2733ca 211#ifdef EXCEPT_SECTION_ASM_OP
8d08fdba 212
8d2733ca
MS
213 /* on machines which support it, the exception table lives in another section,
214 but it needs a label so we can reference it... This sets up that
215 label! */
216asm (EXCEPT_SECTION_ASM_OP);
217exception_table __EXCEPTION_TABLE__[1] = { (void*)0, (void*)0, (void*)0 };
218asm (TEXT_SECTION_ASM_OP);
8d08fdba 219
8d2733ca 220#endif /* EXCEPT_SECTION_ASM_OP */
8d08fdba 221
8d2733ca
MS
222#ifdef EXCEPT_SECTION_ASM_OP
223
224 /* we need to know where the end of the exception table is... so this
225 is how we do it! */
226
227asm (EXCEPT_SECTION_ASM_OP);
228exception_table __EXCEPTION_END__[1] = { (void*)-1, (void*)-1, (void*)-1 };
229asm (TEXT_SECTION_ASM_OP);
230
231#endif /* EXCEPT_SECTION_ASM_OP */
232
233#endif
8d08fdba
MS
234
235void
8d2733ca 236exception_section ()
8d08fdba 237{
8d2733ca
MS
238#ifdef ASM_OUTPUT_SECTION_NAME
239 named_section (".gcc_except_table");
240#else
241 text_section ();
8d08fdba 242#endif
8d08fdba
MS
243}
244
8d2733ca
MS
245
246
247
248/* from: my-cp-except.c */
249
250/* VI: ":set ts=4" */
251#if 0
252#include <stdio.h> */
253#include "config.h"
254#include "tree.h"
255#include "rtl.h"
256#include "cp-tree.h"
257#endif
258#include "decl.h"
259#if 0
260#include "flags.h"
261#endif
262#include "insn-flags.h"
263#include "obstack.h"
264#if 0
265#include "expr.h"
266#endif
267
268/* ======================================================================
269 Briefly the algorithm works like this:
270
271 When a constructor or start of a try block is encountered,
272 push_eh_entry (&eh_stack) is called. Push_eh_entry () creates a
273 new entry in the unwind protection stack and returns a label to
274 output to start the protection for that block.
275
276 When a destructor or end try block is encountered, pop_eh_entry
277 (&eh_stack) is called. Pop_eh_entry () returns the ehEntry it
278 created when push_eh_entry () was called. The ehEntry structure
279 contains three things at this point. The start protect label,
280 the end protect label, and the exception handler label. The end
281 protect label should be output before the call to the destructor
282 (if any). If it was a destructor, then its parse tree is stored
283 in the finalization variable in the ehEntry structure. Otherwise
284 the finalization variable is set to NULL to reflect the fact that
285 is the the end of a try block. Next, this modified ehEntry node
286 is enqueued in the finalizations queue by calling
287 enqueue_eh_entry (&queue,entry).
288
289 +---------------------------------------------------------------+
290 |XXX: Will need modification to deal with partially |
291 | constructed arrays of objects |
292 | |
293 | Basically, this consists of keeping track of how many |
294 | of the objects have been constructed already (this |
295 | should be in a register though, so that shouldn't be a |
296 | problem. |
297 +---------------------------------------------------------------+
298
299 When a catch block is encountered, there is a lot of work to be
300 done.
301
302 Since we don't want to generate the catch block inline with the
303 regular flow of the function, we need to have some way of doing
304 so. Luckily, we have a couple of routines "get_last_insn ()" and
305 "set_last_insn ()" provided. When the start of a catch block is
306 encountered, we save a pointer to the last insn generated. After
307 the catch block is generated, we save a pointer to the first
308 catch block insn and the last catch block insn with the routines
309 "NEXT_INSN ()" and "get_last_insn ()". We then set the last insn
310 to be the last insn generated before the catch block, and set the
311 NEXT_INSN (last_insn) to zero.
312
313 Since catch blocks might be nested inside other catch blocks, and
314 we munge the chain of generated insns after the catch block is
315 generated, we need to store the pointers to the last insn
316 generated in a stack, so that when the end of a catch block is
317 encountered, the last insn before the current catch block can be
318 popped and set to be the last insn, and the first and last insns
319 of the catch block just generated can be enqueue'd for output at
320 a later time.
321
322 Next we must insure that when the catch block is executed, all
323 finalizations for the matching try block have been completed. If
324 any of those finalizations throw an exception, we must call
325 terminate according to the ARM (section r.15.6.1). What this
326 means is that we need to dequeue and emit finalizations for each
327 entry in the ehQueue until we get to an entry with a NULL
328 finalization field. For any of the finalization entries, if it
329 is not a call to terminate (), we must protect it by giving it
330 another start label, end label, and exception handler label,
331 setting its finalization tree to be a call to terminate (), and
332 enqueue'ing this new ehEntry to be output at an outer level.
333 Finally, after all that is done, we can get around to outputting
334 the catch block which basically wraps all the "catch (...) {...}"
335 statements in a big if/then/else construct that matches the
336 correct block to call.
337
338 ===================================================================== */
339
340extern rtx emit_insn PROTO((rtx));
341extern rtx gen_nop PROTO(());
8d2733ca
MS
342
343/* local globals for function calls
344 ====================================================================== */
345
346/* used to cache "terminate ()", "unexpected ()", "set_terminate ()", and
347 "set_unexpected ()" after default_conversion. (lib-except.c) */
348static tree Terminate, Unexpected, SetTerminate, SetUnexpected, CatchMatch;
349
350/* used to cache __find_first_exception_table_match ()
351 for throw (lib-except.c) */
352static tree FirstExceptionMatch;
353
354/* used to cache a call to __unwind_function () (lib-except.c) */
355static tree Unwind;
356
357/* holds a ready to emit call to "terminate ()". */
358static tree TerminateFunctionCall;
359
360/* ====================================================================== */
361
362
363
364/* data structures for my various quick and dirty stacks and queues
365 Eventually, most of this should go away, because I think it can be
366 integrated with stuff already built into the compiler. */
367
368/* =================================================================== */
369
370struct labelNode {
371 rtx label;
372 struct labelNode *chain;
373 };
374
375
376/* this is the most important structure here. Basically this is how I store
377 an exception table entry internally. */
378struct ehEntry {
379 rtx start_label;
380 rtx end_label;
381 rtx exception_handler_label;
382
383 tree finalization;
384 };
385
386struct ehNode {
387 struct ehEntry *entry;
388 struct ehNode *chain;
389 };
390
391struct ehStack {
392 struct ehNode *top;
393 };
394
395struct ehQueue {
396 struct ehNode *head;
397 struct ehNode *tail;
398 };
399
400struct exceptNode {
401 rtx catchstart;
402 rtx catchend;
403
404 struct exceptNode *chain;
405 };
406
407struct exceptStack {
408 struct exceptNode *top;
409 };
410/* ========================================================================= */
411
412
413
414/* local globals - these local globals are for storing data necessary for
415 generating the exception table and code in the correct order.
416
417 ========================================================================= */
418
a3b49ccd 419/* Holds the pc for doing "throw" */
8d2733ca 420rtx saved_pc;
a3b49ccd 421/* Holds the type of the thing being thrown. */
8d2733ca 422rtx saved_throw_type;
a3b49ccd
MS
423/* Holds the value being thrown. */
424rtx saved_throw_value;
8d2733ca
MS
425
426rtx throw_label;
427
428static struct ehStack ehstack;
429static struct ehQueue ehqueue;
430static struct ehQueue eh_table_output_queue;
431static struct exceptStack exceptstack;
432static struct labelNode *false_label_stack = NULL;
433static struct labelNode *caught_return_label_stack = NULL;
434/* ========================================================================= */
435
436/* function prototypes */
437static struct ehEntry *pop_eh_entry PROTO((struct ehStack *stack));
438static void enqueue_eh_entry PROTO((struct ehQueue *queue, struct ehEntry *entry));
439static void push_except_stmts PROTO((struct exceptStack *exceptstack,
440 rtx catchstart, rtx catchend));
441static int pop_except_stmts PROTO((struct exceptStack *exceptstack,
442 rtx *catchstart, rtx *catchend));
443static rtx push_eh_entry PROTO((struct ehStack *stack));
444static struct ehEntry *dequeue_eh_entry PROTO((struct ehQueue *queue));
445static void new_eh_queue PROTO((struct ehQueue *queue));
446static void new_eh_stack PROTO((struct ehStack *stack));
447static void new_except_stack PROTO((struct exceptStack *queue));
448static void push_last_insn PROTO(());
449static rtx pop_last_insn PROTO(());
450static void push_label_entry PROTO((struct labelNode **labelstack, rtx label));
451static rtx pop_label_entry PROTO((struct labelNode **labelstack));
452static rtx top_label_entry PROTO((struct labelNode **labelstack));
453static struct ehEntry *copy_eh_entry PROTO((struct ehEntry *entry));
454
455
456
457/* All my cheesy stack/queue/misc data structure handling routines
458
459 ========================================================================= */
460
461static void
462push_label_entry (labelstack, label)
463 struct labelNode **labelstack;
464 rtx label;
8d08fdba 465{
8d2733ca
MS
466 struct labelNode *newnode=(struct labelNode*)xmalloc (sizeof (struct labelNode));
467
468 newnode->label = label;
469 newnode->chain = *labelstack;
470 *labelstack = newnode;
8d08fdba 471}
8d08fdba 472
8d2733ca
MS
473static rtx
474pop_label_entry (labelstack)
475 struct labelNode **labelstack;
8d08fdba 476{
8d2733ca
MS
477 rtx label;
478 struct labelNode *tempnode;
8d08fdba 479
8d2733ca 480 if (! *labelstack) return NULL_RTX;
8d08fdba 481
8d2733ca
MS
482 tempnode = *labelstack;
483 label = tempnode->label;
484 *labelstack = (*labelstack)->chain;
485 free (tempnode);
8d08fdba 486
8d2733ca
MS
487 return label;
488}
8d08fdba 489
8d2733ca
MS
490static rtx
491top_label_entry (labelstack)
492 struct labelNode **labelstack;
493{
494 if (! *labelstack) return NULL_RTX;
8d08fdba 495
8d2733ca 496 return (*labelstack)->label;
8d08fdba
MS
497}
498
8d2733ca
MS
499static void
500push_except_stmts (exceptstack, catchstart, catchend)
501 struct exceptStack *exceptstack;
502 rtx catchstart, catchend;
8d08fdba 503{
8d2733ca
MS
504 struct exceptNode *newnode = (struct exceptNode*)
505 xmalloc (sizeof (struct exceptNode));
8d08fdba 506
8d2733ca
MS
507 newnode->catchstart = catchstart;
508 newnode->catchend = catchend;
509 newnode->chain = exceptstack->top;
8d08fdba 510
8d2733ca
MS
511 exceptstack->top = newnode;
512}
8d08fdba 513
8d2733ca
MS
514static int
515pop_except_stmts (exceptstack, catchstart, catchend)
516 struct exceptStack *exceptstack;
517 rtx *catchstart, *catchend;
518{
519 struct exceptNode *tempnode;
8d08fdba 520
8d2733ca
MS
521 if (!exceptstack->top) {
522 *catchstart = *catchend = NULL_RTX;
523 return 0;
524 }
8d08fdba 525
8d2733ca
MS
526 tempnode = exceptstack->top;
527 exceptstack->top = exceptstack->top->chain;
528
529 *catchstart = tempnode->catchstart;
530 *catchend = tempnode->catchend;
531 free (tempnode);
8d08fdba 532
8d2733ca 533 return 1;
8d08fdba
MS
534}
535
8d2733ca
MS
536/* Push to permanent obstack for rtl generation.
537 One level only! */
538static struct obstack *saved_rtl_obstack;
8d08fdba 539void
8d2733ca 540push_rtl_perm ()
8d08fdba 541{
8d2733ca
MS
542 extern struct obstack permanent_obstack;
543 extern struct obstack *rtl_obstack;
544
545 saved_rtl_obstack = rtl_obstack;
546 rtl_obstack = &permanent_obstack;
547}
8d08fdba 548
8d2733ca
MS
549/* Pop back to normal rtl handling. */
550static void
551pop_rtl_from_perm ()
552{
553 extern struct obstack permanent_obstack;
554 extern struct obstack *rtl_obstack;
555
556 rtl_obstack = saved_rtl_obstack;
557}
8d08fdba 558
8d2733ca
MS
559static rtx
560push_eh_entry (stack)
561 struct ehStack *stack;
562{
563 struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
564 struct ehEntry *entry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
8d08fdba 565
8d2733ca
MS
566 if (stack == NULL) {
567 free (node);
568 free (entry);
569 return NULL_RTX;
570 }
571
572 /* These are saved for the exception table. */
573 push_rtl_perm ();
574 entry->start_label = gen_label_rtx ();
575 entry->end_label = gen_label_rtx ();
576 entry->exception_handler_label = gen_label_rtx ();
577 pop_rtl_from_perm ();
578
579 entry->finalization = NULL_TREE;
8d08fdba 580
8d2733ca
MS
581 node->entry = entry;
582 node->chain = stack->top;
583 stack->top = node;
584
585 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
586
587 return entry->start_label;
8d08fdba
MS
588}
589
8d2733ca
MS
590static struct ehEntry *
591pop_eh_entry (stack)
592 struct ehStack *stack;
8d08fdba 593{
8d2733ca
MS
594 struct ehNode *tempnode;
595 struct ehEntry *tempentry;
596
597 if (stack && (tempnode = stack->top)) {
598 tempentry = tempnode->entry;
599 stack->top = stack->top->chain;
600 free (tempnode);
601
602 return tempentry;
603 }
604
605 return NULL;
8d08fdba
MS
606}
607
8d2733ca
MS
608static struct ehEntry *
609copy_eh_entry (entry)
610 struct ehEntry *entry;
8d08fdba 611{
8d2733ca 612 struct ehEntry *newentry;
8d08fdba 613
8d2733ca
MS
614 newentry = (struct ehEntry*)xmalloc (sizeof (struct ehEntry));
615 memcpy ((void*)newentry, (void*)entry, sizeof (struct ehEntry));
8d08fdba 616
8d2733ca
MS
617 return newentry;
618}
8d08fdba 619
8d2733ca
MS
620static void
621enqueue_eh_entry (queue, entry)
622 struct ehQueue *queue;
623 struct ehEntry *entry;
624{
625 struct ehNode *node = (struct ehNode*)xmalloc (sizeof (struct ehNode));
8d08fdba 626
8d2733ca
MS
627 node->entry = entry;
628 node->chain = NULL;
8d08fdba 629
8d2733ca 630 if (queue->head == NULL)
8d08fdba 631 {
8d2733ca 632 queue->head = node;
8d08fdba 633 }
8d2733ca 634 else
8d08fdba 635 {
8d2733ca 636 queue->tail->chain = node;
8d08fdba 637 }
8d2733ca 638 queue->tail = node;
8d08fdba
MS
639}
640
8d2733ca
MS
641static struct ehEntry *
642dequeue_eh_entry (queue)
643 struct ehQueue *queue;
644{
645 struct ehNode *tempnode;
646 struct ehEntry *tempentry;
647
648 if (queue->head == NULL)
649 return NULL;
650
651 tempnode = queue->head;
652 queue->head = queue->head->chain;
653
654 tempentry = tempnode->entry;
655 free (tempnode);
656
657 return tempentry;
658}
659
660static void
661new_eh_queue (queue)
662 struct ehQueue *queue;
663{
664 queue->head = queue->tail = NULL;
665}
666
667static void
668new_eh_stack (stack)
669 struct ehStack *stack;
670{
671 stack->top = NULL;
672}
673
674static void
675new_except_stack (stack)
676 struct exceptStack *stack;
677{
678 stack->top = NULL;
679}
680/* ========================================================================= */
681
a3b49ccd
MS
682void
683lang_interim_eh (finalization)
684 tree finalization;
685{
686 if (finalization)
687 end_protect (finalization);
688 else
689 start_protect ();
690}
8d2733ca
MS
691
692/* sets up all the global eh stuff that needs to be initialized at the
693 start of compilation.
694
695 This includes:
696 - Setting up all the function call trees
697 - Initializing the ehqueue
698 - Initializing the eh_table_output_queue
699 - Initializing the ehstack
700 - Initializing the exceptstack
701*/
8d08fdba 702
8d08fdba 703void
8d2733ca 704init_exception_processing ()
8d08fdba 705{
8d2733ca
MS
706 extern tree define_function ();
707 tree unexpected_fndecl, terminate_fndecl;
708 tree set_unexpected_fndecl, set_terminate_fndecl;
709 tree catch_match_fndecl;
710 tree find_first_exception_match_fndecl;
711 tree unwind_fndecl;
712 tree temp, PFV;
8d08fdba 713
a3b49ccd
MS
714 interim_eh_hook = lang_interim_eh;
715
8d2733ca
MS
716 /* void (*)() */
717 PFV = build_pointer_type (build_function_type (void_type_node, void_list_node));
8d08fdba 718
8d2733ca
MS
719 /* arg list for the build_function_type call for set_terminate () and
720 set_unexpected () */
721 temp = tree_cons (NULL_TREE, PFV, void_list_node);
8d08fdba 722
8d2733ca
MS
723 push_lang_context (lang_name_c);
724
725 set_terminate_fndecl =
726 define_function ("set_terminate",
727 build_function_type (PFV, temp),
728 NOT_BUILT_IN,
729 pushdecl,
730 0);
731 set_unexpected_fndecl =
732 define_function ("set_unexpected",
733 build_function_type (PFV, temp),
734 NOT_BUILT_IN,
735 pushdecl,
736 0);
737
738 unexpected_fndecl =
739 define_function ("unexpected",
740 build_function_type (void_type_node, void_list_node),
741 NOT_BUILT_IN,
742 pushdecl,
743 0);
744 terminate_fndecl =
745 define_function ("terminate",
746 build_function_type (void_type_node, void_list_node),
747 NOT_BUILT_IN,
748 pushdecl,
749 0);
750 catch_match_fndecl =
751 define_function ("__throw_type_match",
752 build_function_type (integer_type_node,
a4443a08 753 tree_cons (NULL_TREE, string_type_node, tree_cons (NULL_TREE, ptr_type_node, void_list_node))),
8d2733ca
MS
754 NOT_BUILT_IN,
755 pushdecl,
756 0);
757 find_first_exception_match_fndecl =
758 define_function ("__find_first_exception_table_match",
759 build_function_type (ptr_type_node,
760 tree_cons (NULL_TREE, ptr_type_node,
761 void_list_node)),
762 NOT_BUILT_IN,
763 pushdecl,
764 0);
765 unwind_fndecl =
766 define_function ("__unwind_function",
767 build_function_type (void_type_node,
768 tree_cons (NULL_TREE, ptr_type_node, void_list_node)),
769 NOT_BUILT_IN,
770 pushdecl,
771 0);
772
773 Unexpected = default_conversion (unexpected_fndecl);
774 Terminate = default_conversion (terminate_fndecl);
775 SetTerminate = default_conversion (set_terminate_fndecl);
776 SetUnexpected = default_conversion (set_unexpected_fndecl);
777 CatchMatch = default_conversion (catch_match_fndecl);
778 FirstExceptionMatch = default_conversion (find_first_exception_match_fndecl);
779 Unwind = default_conversion (unwind_fndecl);
780 BuiltinReturnAddress = default_conversion (builtin_return_address_fndecl);
781
782 TerminateFunctionCall = build_function_call (Terminate, NULL_TREE);
783
784 pop_lang_context ();
785 throw_label = gen_label_rtx ();
db5ae43f 786#ifdef sparc
8d2733ca
MS
787 saved_pc = gen_rtx (REG, Pmode, 16);
788 saved_throw_type = gen_rtx (REG, Pmode, 17);
a3b49ccd 789 saved_throw_value = gen_rtx (REG, Pmode, 18);
db5ae43f
MS
790#endif
791#ifdef __i386
792 saved_pc = gen_rtx (REG, Pmode, 3);
793 saved_throw_type = gen_rtx (REG, Pmode, 4);
794 saved_throw_value = gen_rtx (REG, Pmode, 5);
795#endif
796#ifdef __rs6000
797 saved_pc = gen_rtx (REG, Pmode, 12);
798 saved_throw_type = gen_rtx (REG, Pmode, 13);
799 saved_throw_value = gen_rtx (REG, Pmode, 14);
800#endif
801#ifdef __hppa
802 saved_pc = gen_rtx (REG, Pmode, 5);
803 saved_throw_type = gen_rtx (REG, Pmode, 6);
804 saved_throw_value = gen_rtx (REG, Pmode, 7);
6060a796
MS
805#endif
806#ifdef __mc68000
807 saved_pc = gen_rtx (REG, Pmode, 10);
808 saved_throw_type = gen_rtx (REG, Pmode, 11);
809 saved_throw_value = gen_rtx (REG, Pmode, 12);
810#endif
811#ifdef __mips
812 saved_pc = gen_rtx (REG, Pmode, 16);
813 saved_throw_type = gen_rtx (REG, Pmode, 17);
814 saved_throw_value = gen_rtx (REG, Pmode, 18);
db5ae43f 815#endif
8d2733ca
MS
816 new_eh_queue (&ehqueue);
817 new_eh_queue (&eh_table_output_queue);
818 new_eh_stack (&ehstack);
819 new_except_stack (&exceptstack);
820}
821
822/* call this to begin a block of unwind protection (ie: when an object is
823 constructed) */
824void
825start_protect ()
826{
827 if (doing_eh (0))
8d08fdba 828 {
8d2733ca 829 emit_label (push_eh_entry (&ehstack));
8d08fdba 830 }
8d2733ca
MS
831}
832
833/* call this to end a block of unwind protection. the finalization tree is
834 the finalization which needs to be run in order to cleanly unwind through
835 this level of protection. (ie: call this when a scope is exited)*/
836void
837end_protect (finalization)
838 tree finalization;
839{
840 struct ehEntry *entry = pop_eh_entry (&ehstack);
8d08fdba 841
8d2733ca
MS
842 if (! doing_eh (0))
843 return;
8d08fdba 844
8d2733ca 845 emit_label (entry->end_label);
8d08fdba 846
8d2733ca
MS
847 entry->finalization = finalization;
848
849 enqueue_eh_entry (&ehqueue, entry);
850}
8d08fdba 851
8d2733ca
MS
852/* call this on start of a try block. */
853void
854expand_start_try_stmts ()
855{
856 if (doing_eh (1))
8d08fdba 857 {
8d2733ca 858 start_protect ();
8d08fdba 859 }
8d2733ca 860}
8d08fdba 861
8d2733ca
MS
862void
863expand_end_try_stmts ()
864{
865 end_protect (integer_zero_node);
8d08fdba
MS
866}
867
8d2733ca
MS
868struct insn_save_node {
869 rtx last;
870 struct insn_save_node *chain;
871 };
8d08fdba 872
8d2733ca
MS
873static struct insn_save_node *InsnSave = NULL;
874
875
876/* Used to keep track of where the catch blocks start. */
877static void
878push_last_insn ()
8d08fdba 879{
8d2733ca
MS
880 struct insn_save_node *newnode = (struct insn_save_node*)
881 xmalloc (sizeof (struct insn_save_node));
8d08fdba 882
8d2733ca
MS
883 newnode->last = get_last_insn ();
884 newnode->chain = InsnSave;
885 InsnSave = newnode;
8d08fdba
MS
886}
887
8d2733ca
MS
888/* Use to keep track of where the catch blocks start. */
889static rtx
890pop_last_insn ()
891{
892 struct insn_save_node *tempnode;
893 rtx temprtx;
894
895 if (!InsnSave) return NULL_RTX;
896
897 tempnode = InsnSave;
898 temprtx = tempnode->last;
899 InsnSave = InsnSave->chain;
900
901 free (tempnode);
902
903 return temprtx;
904}
8d08fdba 905
8d2733ca 906/* call this to start processing of all the catch blocks. */
8d08fdba 907void
8d2733ca 908expand_start_all_catch ()
8d08fdba 909{
8d2733ca
MS
910 struct ehEntry *entry;
911 rtx label;
912
913 if (! doing_eh (1))
914 return;
915
916 emit_line_note (input_filename, lineno);
917 label = gen_label_rtx ();
918 /* The label for the exception handling block we will save. */
919 emit_label (label);
a3b49ccd 920
8d2733ca
MS
921 push_label_entry (&caught_return_label_stack, label);
922
923 /* Remember where we started. */
924 push_last_insn ();
925
a3b49ccd
MS
926 emit_insn (gen_nop ());
927
8d2733ca
MS
928 /* Will this help us not stomp on it? */
929 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
a3b49ccd 930 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
8d2733ca
MS
931
932 while (1)
8d08fdba 933 {
8d2733ca
MS
934 entry = dequeue_eh_entry (&ehqueue);
935 emit_label (entry->exception_handler_label);
936
937 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
938
939 /* When we get down to the matching entry, stop. */
940 if (entry->finalization == integer_zero_node)
941 break;
942
943 free (entry);
944 }
945
946 /* This goes when the below moves out of our way. */
8d08fdba 947#if 1
8d2733ca
MS
948 label = gen_label_rtx ();
949 emit_jump (label);
8d08fdba 950#endif
8d2733ca
MS
951
952 /* All this should be out of line, and saved back in the exception handler
953 block area. */
954#if 1
955 entry->start_label = entry->exception_handler_label;
956 /* These are saved for the exception table. */
957 push_rtl_perm ();
958 entry->end_label = gen_label_rtx ();
959 entry->exception_handler_label = gen_label_rtx ();
960 entry->finalization = TerminateFunctionCall;
961 pop_rtl_from_perm ();
962 emit_label (entry->end_label);
963
8d2733ca
MS
964 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (entry));
965
966 /* After running the finalization, continue on out to the next
967 cleanup, if we have nothing better to do. */
968 emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry->end_label));
969 /* Will this help us not stomp on it? */
970 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
a3b49ccd 971 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
8d2733ca
MS
972 emit_jump (throw_label);
973 emit_label (entry->exception_handler_label);
974 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
975 emit_barrier ();
8d08fdba 976#endif
8d2733ca
MS
977 emit_label (label);
978}
8d08fdba 979
8d2733ca
MS
980/* call this to end processing of all the catch blocks. */
981void
982expand_end_all_catch ()
983{
984 rtx catchstart, catchend, last;
985 rtx label;
8d08fdba 986
8d2733ca
MS
987 if (! doing_eh (1))
988 return;
8d08fdba 989
6060a796
MS
990 /* Code to throw out to outer context, if we fall off end of catch
991 handlers. */
992 emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
993 Pmode,
994 top_label_entry (&caught_return_label_stack)));
995 emit_jump (throw_label);
996
8d2733ca
MS
997 /* Find the start of the catch block. */
998 last = pop_last_insn ();
999 catchstart = NEXT_INSN (last);
1000 catchend = get_last_insn ();
8d08fdba 1001
8d2733ca
MS
1002 NEXT_INSN (last) = 0;
1003 set_last_insn (last);
8d08fdba 1004
8d2733ca
MS
1005 /* this level of catch blocks is done, so set up the successful catch jump
1006 label for the next layer of catch blocks. */
1007 pop_label_entry (&caught_return_label_stack);
8d08fdba 1008
8d2733ca
MS
1009 push_except_stmts (&exceptstack, catchstart, catchend);
1010
a3b49ccd 1011 /* Here we fall through into the continuation code. */
8d08fdba
MS
1012}
1013
8d2733ca
MS
1014
1015/* this is called from expand_exception_blocks () to expand the toplevel
1016 finalizations for a function. */
1017void
1018expand_leftover_cleanups ()
8d08fdba 1019{
8d2733ca
MS
1020 struct ehEntry *entry;
1021 rtx first_label = NULL_RTX;
8d08fdba 1022
8d2733ca
MS
1023 if (! doing_eh (0))
1024 return;
1025
1026 /* Will this help us not stomp on it? */
1027 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
a3b49ccd 1028 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
8d2733ca
MS
1029
1030 while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
8d08fdba 1031 {
8d2733ca
MS
1032 if (! first_label)
1033 first_label = entry->exception_handler_label;
1034 emit_label (entry->exception_handler_label);
1035
1036 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
8d08fdba 1037
8d2733ca
MS
1038 /* leftover try block, opps. */
1039 if (entry->finalization == integer_zero_node)
1040 abort ();
1041
1042 free (entry);
1043 }
1044 if (first_label)
8d08fdba 1045 {
8d2733ca
MS
1046 rtx label;
1047 struct ehEntry entry;
1048 /* These are saved for the exception table. */
1049 push_rtl_perm ();
1050 label = gen_label_rtx ();
1051 entry.start_label = first_label;
1052 entry.end_label = label;
1053 entry.exception_handler_label = gen_label_rtx ();
1054 entry.finalization = TerminateFunctionCall;
1055 pop_rtl_from_perm ();
1056 emit_label (label);
1057
1058 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
1059
1060 /* After running the finalization, continue on out to the next
1061 cleanup, if we have nothing better to do. */
1062 emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, entry.end_label));
1063 /* Will this help us not stomp on it? */
1064 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_type));
a3b49ccd 1065 emit_insn (gen_rtx (USE, VOIDmode, saved_throw_value));
8d2733ca
MS
1066 emit_jump (throw_label);
1067 emit_label (entry.exception_handler_label);
1068 expand_expr (entry.finalization, const0_rtx, VOIDmode, 0);
1069 emit_barrier ();
8d08fdba 1070 }
8d08fdba 1071}
8d08fdba 1072
8d2733ca
MS
1073/* call this to start a catch block. Typename is the typename, and identifier
1074 is the variable to place the object in or NULL if the variable doesn't
1075 matter. If typename is NULL, that means its a "catch (...)" or catch
1076 everything. In that case we don't need to do any type checking.
1077 (ie: it ends up as the "else" clause rather than an "else if" clause) */
8d08fdba 1078void
a4443a08
MS
1079expand_start_catch_block (declspecs, declarator)
1080 tree declspecs, declarator;
8d08fdba 1081{
8d2733ca 1082 rtx false_label_rtx;
a3b49ccd 1083 rtx protect_label_rtx;
8d2733ca 1084 tree type;
a4443a08 1085 tree decl;
a3b49ccd 1086 tree init;
8d2733ca
MS
1087
1088 if (! doing_eh (1))
1089 return;
1090
a3b49ccd
MS
1091 /* Create a binding level for the parm. */
1092 expand_start_bindings (0);
1093
a4443a08
MS
1094 if (declspecs)
1095 {
a3b49ccd 1096 tree init_type;
db5ae43f 1097 decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);
a3b49ccd
MS
1098
1099 /* Figure out the type that the initializer is. */
1100 init_type = TREE_TYPE (decl);
1101 if (TREE_CODE (init_type) != REFERENCE_TYPE)
1102 init_type = build_reference_type (init_type);
1103
1104 init = convert_from_reference (save_expr (make_tree (init_type, saved_throw_value)));
1105
1106 /* Do we need the below two lines? */
1107 /* Let `finish_decl' know that this initializer is ok. */
1108 DECL_INITIAL (decl) = init;
1109 /* This needs to be preallocated under the try block,
1110 in a union of all catch variables. */
1111 pushdecl (decl);
a4443a08 1112 type = TREE_TYPE (decl);
a3b49ccd
MS
1113
1114 /* peel back references, so they match. */
1115 if (TREE_CODE (type) == REFERENCE_TYPE)
1116 type = TREE_TYPE (type);
a4443a08 1117 }
8d2733ca
MS
1118 else
1119 type = NULL_TREE;
1120
f675499c 1121 /* These are saved for the exception table. */
a3b49ccd 1122 push_rtl_perm ();
f675499c 1123 false_label_rtx = gen_label_rtx ();
a3b49ccd
MS
1124 protect_label_rtx = gen_label_rtx ();
1125 pop_rtl_from_perm ();
f675499c 1126 push_label_entry (&false_label_stack, false_label_rtx);
a3b49ccd
MS
1127 push_label_entry (&false_label_stack, protect_label_rtx);
1128
8d2733ca 1129 if (type)
8d08fdba 1130 {
8d2733ca
MS
1131 tree params;
1132 char *typestring;
1133 rtx call_rtx, return_value_rtx;
1134 tree catch_match_fcall;
1135 tree catchmatch_arg, argval;
1136
1137 typestring = build_overload_name (type, 1, 1);
1138
1139 params = tree_cons (NULL_TREE,
1140 combine_strings (build_string (strlen (typestring)+1, typestring)),
1141 tree_cons (NULL_TREE,
1142 make_tree (ptr_type_node, saved_throw_type),
1143 NULL_TREE));
1144 catch_match_fcall = build_function_call (CatchMatch, params);
1145 call_rtx = expand_call (catch_match_fcall, NULL_RTX, 0);
1146
1147 return_value_rtx =
1148 hard_function_value (integer_type_node, catch_match_fcall);
1149
1150 /* did the throw type match function return TRUE? */
1151 emit_cmp_insn (return_value_rtx, const0_rtx, NE, NULL_RTX,
1152 GET_MODE (return_value_rtx), 0, 0);
1153
1154 /* if it returned FALSE, jump over the catch block, else fall into it */
1155 emit_jump_insn (gen_bne (false_label_rtx));
6060a796 1156 finish_decl (decl, init, NULL_TREE, 0, LOOKUP_ONLYCONVERTING);
8d08fdba
MS
1157 }
1158 else
1159 {
8d2733ca 1160 /* Fall into the catch all section. */
8d08fdba 1161 }
a3b49ccd
MS
1162
1163 /* This is the starting of something to protect. */
1164 emit_label (protect_label_rtx);
1165
8d2733ca 1166 emit_line_note (input_filename, lineno);
8d08fdba
MS
1167}
1168
8d08fdba 1169
8d2733ca
MS
1170/* Call this to end a catch block. Its responsible for emitting the
1171 code to handle jumping back to the correct place, and for emitting
1172 the label to jump to if this catch block didn't match. */
1173void expand_end_catch_block ()
8d08fdba 1174{
8d2733ca 1175 if (doing_eh (1))
8d08fdba 1176 {
a3b49ccd
MS
1177 rtx start_protect_label_rtx;
1178 rtx end_protect_label_rtx;
1179 tree decls;
1180 struct ehEntry entry;
1181
8d2733ca
MS
1182 /* label we jump to if we caught the exception */
1183 emit_jump (top_label_entry (&caught_return_label_stack));
1184
6060a796 1185 /* Code to throw out to outer context, if we get a throw from within
a3b49ccd
MS
1186 our catch handler. */
1187 /* These are saved for the exception table. */
1188 push_rtl_perm ();
1189 entry.exception_handler_label = gen_label_rtx ();
1190 pop_rtl_from_perm ();
1191 emit_label (entry.exception_handler_label);
1192 emit_move_insn (saved_pc, gen_rtx (LABEL_REF,
1193 Pmode,
1194 top_label_entry (&caught_return_label_stack)));
1195 emit_jump (throw_label);
1196 /* No associated finalization. */
1197 entry.finalization = NULL_TREE;
1198
1199 /* Because we are reordered out of line, we have to protect this. */
1200 /* label for the start of the protection region. */
1201 start_protect_label_rtx = pop_label_entry (&false_label_stack);
1202
1203 /* Cleanup the EH paramater. */
1204 expand_end_bindings (decls = getdecls (), decls != NULL_TREE, 0);
1205
8d2733ca 1206 /* label we emit to jump to if this catch block didn't match. */
a3b49ccd
MS
1207 emit_label (end_protect_label_rtx = pop_label_entry (&false_label_stack));
1208
1209 /* Because we are reordered out of line, we have to protect this. */
1210 entry.start_label = start_protect_label_rtx;
1211 entry.end_label = end_protect_label_rtx;
1212
1213 /* These set up a call to throw the caught exception into the outer
1214 context. */
1215 enqueue_eh_entry (&eh_table_output_queue, copy_eh_entry (&entry));
8d08fdba 1216 }
8d2733ca 1217}
8d08fdba 1218
8d2733ca
MS
1219/* cheesyness to save some typing. returns the return value rtx */
1220rtx
1221do_function_call (func, params, return_type)
1222 tree func, params, return_type;
1223{
1224 tree func_call;
1225 func_call = build_function_call (func, params);
1226 expand_call (func_call, NULL_RTX, 0);
1227 if (return_type != NULL_TREE)
1228 return hard_function_value (return_type, func_call);
1229 return NULL_RTX;
1230}
8d08fdba 1231
db5ae43f
MS
1232/* unwind the stack. */
1233static void
1234do_unwind (throw_label)
1235 rtx throw_label;
1236{
1237#ifdef sparc
1238 extern FILE *asm_out_file;
1239 tree fcall;
1240 tree params;
1241 rtx return_val_rtx;
1242
1243 /* call to __builtin_return_address () */
1244 params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
1245 fcall = build_function_call (BuiltinReturnAddress, params);
1246 return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
1247 /* In the return, the new pc is pc+8, as the value comming in is
1248 really the address of the call insn, not the next insn. */
1249 emit_move_insn (return_val_rtx, plus_constant(gen_rtx (LABEL_REF,
1250 Pmode,
1251 throw_label), -8));
1252 /* We use three values, PC, type, and value */
1253 easy_expand_asm ("st %l0,[%fp]");
1254 easy_expand_asm ("st %l1,[%fp+4]");
1255 easy_expand_asm ("st %l2,[%fp+8]");
1256 easy_expand_asm ("ret");
1257 easy_expand_asm ("restore");
1258 emit_barrier ();
1259#endif
6060a796 1260#if defined(__i386) || defined(__rs6000) || defined(__hppa) || defined(__mc68000) || defined (__mips)
db5ae43f
MS
1261 extern FILE *asm_out_file;
1262 tree fcall;
1263 tree params;
1264 rtx return_val_rtx;
1265
1266 /* call to __builtin_return_address () */
1267 params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
1268 fcall = build_function_call (BuiltinReturnAddress, params);
1269 return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
1270#if 0
1271 /* I would like to do this here, but doesn't seem to work. */
1272 emit_move_insn (return_val_rtx, gen_rtx (LABEL_REF,
1273 Pmode,
1274 throw_label));
1275 /* So, for now, just pass throw label to stack unwinder. */
1276#endif
1277 /* We use three values, PC, type, and value */
1278 params = tree_cons (NULL_TREE, make_tree (ptr_type_node,
1279 gen_rtx (LABEL_REF, Pmode, throw_label)), NULL_TREE);
1280
1281 do_function_call (Unwind, params, NULL_TREE);
1282 emit_barrier ();
1283#endif
1284#if m88k
1285 rtx temp_frame = frame_pointer_rtx;
1286
1287 temp_frame = memory_address (Pmode, temp_frame);
1288 temp_frame = copy_to_reg (gen_rtx (MEM, Pmode, temp_frame));
1289
1290 /* hopefully this will successfully pop the frame! */
1291 emit_move_insn (frame_pointer_rtx, temp_frame);
1292 emit_move_insn (stack_pointer_rtx, frame_pointer_rtx);
1293 emit_move_insn (arg_pointer_rtx, frame_pointer_rtx);
1294 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1295 (HOST_WIDE_INT)m88k_debugger_offset (stack_pointer_rtx, 0))));
1296
1297#if 0
1298 emit_insn (gen_add2_insn (arg_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1299 -(HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
1300
1301 emit_move_insn (stack_pointer_rtx, arg_pointer_rtx);
1302
1303 emit_insn (gen_add2_insn (stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode,
1304 (HOST_WIDE_INT)m88k_debugger_offset (arg_pointer_rtx, 0))));
1305#endif
1306#endif
1307}
8d08fdba 1308
8d2733ca
MS
1309/* is called from expand_excpetion_blocks () to generate the code in a function
1310 to "throw" if anything in the function needs to preform a throw.
8d08fdba 1311
8d2733ca
MS
1312 expands "throw" as the following psuedo code:
1313
1314 throw:
1315 eh = find_first_exception_match (saved_pc);
1316 if (!eh) goto gotta_rethrow_it;
1317 goto eh;
1318
1319 gotta_rethrow_it:
1320 saved_pc = __builtin_return_address (0);
1321 pop_to_previous_level ();
1322 goto throw;
1323
1324 */
1325static void
1326expand_builtin_throw ()
1327{
1328 tree fcall;
1329 tree params;
1330 rtx return_val_rtx;
1331 rtx gotta_rethrow_it = gen_label_rtx ();
1332 rtx gotta_call_terminate = gen_label_rtx ();
1333 rtx unwind_and_throw = gen_label_rtx ();
1334 rtx goto_unwind_and_throw = gen_label_rtx ();
1335
1336 emit_label (throw_label);
1337
1338 /* search for an exception handler for the saved_pc */
1339 return_val_rtx = do_function_call (FirstExceptionMatch,
1340 tree_cons (NULL_TREE, make_tree (ptr_type_node, saved_pc), NULL_TREE),
1341 ptr_type_node);
1342
1343 /* did we find one? */
1344 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
1345 GET_MODE (return_val_rtx), 0, 0);
1346
1347 /* if not, jump to gotta_rethrow_it */
1348 emit_jump_insn (gen_beq (gotta_rethrow_it));
1349
1350 /* we found it, so jump to it */
1351 emit_indirect_jump (return_val_rtx);
1352
1353 /* code to deal with unwinding and looking for it again */
1354 emit_label (gotta_rethrow_it);
1355
1356 /* call to __builtin_return_address () */
1357 params=tree_cons (NULL_TREE, integer_zero_node, NULL_TREE);
1358 fcall = build_function_call (BuiltinReturnAddress, params);
1359 return_val_rtx = expand_expr (fcall, NULL_RTX, SImode, 0);
1360
1361 /* did __builtin_return_address () return a valid address? */
1362 emit_cmp_insn (return_val_rtx, const0_rtx, EQ, NULL_RTX,
1363 GET_MODE (return_val_rtx), 0, 0);
1364
1365 emit_jump_insn (gen_beq (gotta_call_terminate));
1366
db5ae43f
MS
1367#ifndef sparc
1368 /* On the SPARC, __builtin_return_address is already -8, no need to
1369 subtract any more from it. */
1370 emit_insn (gen_add2_insn (return_val_rtx, GEN_INT (-1)));
1371#endif
1372
8d2733ca
MS
1373 /* yes it did */
1374 emit_move_insn (saved_pc, return_val_rtx);
1375 do_unwind (throw_label);
1376 emit_jump (throw_label);
1377
1378 /* no it didn't --> therefore we need to call terminate */
1379 emit_label (gotta_call_terminate);
1380 do_function_call (Terminate, NULL_TREE, NULL_TREE);
8d08fdba 1381}
8d2733ca
MS
1382
1383
1384/* This is called to expand all the toplevel exception handling
1385 finalization for a function. It should only be called once per
1386 function. */
8d08fdba 1387void
8d2733ca 1388expand_exception_blocks ()
8d08fdba 1389{
8d2733ca
MS
1390 rtx catchstart, catchend;
1391 rtx last;
1392 static rtx funcend;
1393
1394 funcend = gen_label_rtx ();
1395 emit_jump (funcend);
1396 /* expand_null_return (); */
1397
1398 while (pop_except_stmts (&exceptstack, &catchstart, &catchend)) {
1399 last = get_last_insn ();
1400 NEXT_INSN (last) = catchstart;
1401 PREV_INSN (catchstart) = last;
1402 NEXT_INSN (catchend) = 0;
1403 set_last_insn (catchend);
1404 }
1405
1406 expand_leftover_cleanups ();
1407
1408 {
1409 static int have_done = 0;
1410 if (! have_done && TREE_PUBLIC (current_function_decl)
db5ae43f
MS
1411 && DECL_INTERFACE_KNOWN (current_function_decl)
1412 && ! DECL_EXTERNAL (current_function_decl))
8d2733ca
MS
1413 {
1414 have_done = 1;
1415 expand_builtin_throw ();
1416 }
1417 }
1418 emit_label (funcend);
8d08fdba
MS
1419}
1420
8d2733ca
MS
1421
1422/* call this to expand a throw statement. This follows the following
1423 algorithm:
1424
1425 1. Allocate space to save the current PC onto the stack.
1426 2. Generate and emit a label and save its address into the
1427 newly allocate stack space since we can't save the pc directly.
1428 3. If this is the first call to throw in this function:
1429 generate a label for the throw block
1430 4. jump to the throw block label. */
8d08fdba 1431void
8d2733ca
MS
1432expand_throw (exp)
1433 tree exp;
8d08fdba 1434{
8d2733ca
MS
1435 rtx label;
1436 tree type;
8d08fdba 1437
8d2733ca
MS
1438 if (! doing_eh (1))
1439 return;
8d08fdba 1440
a3b49ccd
MS
1441 /* This is the label that represents where in the code we were, when
1442 we got an exception. This needs to be updated when we rethrow an
1443 exception, so that the matching routine knows to search out. */
8d2733ca
MS
1444 label = gen_label_rtx ();
1445 emit_label (label);
1446 emit_move_insn (saved_pc, gen_rtx (LABEL_REF, Pmode, label));
1447
1448 if (exp)
1449 {
a3b49ccd 1450 /* throw expression */
8d2733ca
MS
1451 /* First, decay it. */
1452 exp = default_conversion (exp);
1453 type = TREE_TYPE (exp);
a3b49ccd
MS
1454
1455 {
1456 char *typestring = build_overload_name (type, 1, 1);
1457 tree throw_type = build1 (ADDR_EXPR, ptr_type_node, combine_strings (build_string (strlen (typestring)+1, typestring)));
1458 rtx throw_type_rtx = expand_expr (throw_type, NULL_RTX, VOIDmode, 0);
1459 rtx throw_value_rtx;
1460
1461 emit_move_insn (saved_throw_type, throw_type_rtx);
db5ae43f 1462 exp = convert_to_reference (build_reference_type (build_type_variant (TREE_TYPE (exp), 1, 0)), exp, CONV_STATIC, LOOKUP_COMPLAIN, error_mark_node);
6060a796
MS
1463
1464 /* Make a copy of the thrown object. WP 15.1.5 */
1465 exp = build_new (NULL_TREE, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (exp))), exp, 0);
1466
a3b49ccd
MS
1467 if (exp == error_mark_node)
1468 error (" in thrown expression");
6060a796 1469 throw_value_rtx = expand_expr (exp, NULL_RTX, VOIDmode, 0);
a3b49ccd
MS
1470 emit_move_insn (saved_throw_value, throw_value_rtx);
1471 }
8d2733ca
MS
1472 }
1473 else
a3b49ccd
MS
1474 {
1475 /* rethrow current exception */
1476 /* This part is easy, as we dont' have to do anything else. */
1477 }
8d2733ca
MS
1478
1479 emit_jump (throw_label);
8d08fdba
MS
1480}
1481
f376e137
MS
1482/* end of: my-cp-except.c */
1483#endif
8d2733ca 1484
f376e137
MS
1485
1486/* Output the exception table.
1487 Return the number of handlers. */
1488int
8d2733ca 1489build_exception_table ()
8d08fdba 1490{
f376e137
MS
1491 int count = 0;
1492#ifdef TRY_NEW_EH
8d2733ca
MS
1493 extern FILE *asm_out_file;
1494 struct ehEntry *entry;
f376e137 1495 tree eh_node_decl;
8d08fdba 1496
8d2733ca 1497 if (! doing_eh (0))
f376e137 1498 return 0;
8d2733ca 1499
f376e137
MS
1500 while (entry = dequeue_eh_entry (&eh_table_output_queue))
1501 {
1502 if (count == 0)
1503 {
1504 exception_section ();
1505
1506 /* Beginning marker for table. */
1507 ASM_OUTPUT_ALIGN (asm_out_file, 2);
1508 ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_TABLE__");
db5ae43f
MS
1509 output_exception_table_entry (asm_out_file,
1510 const0_rtx, const0_rtx, const0_rtx);
f376e137
MS
1511 }
1512 count++;
8d2733ca 1513 output_exception_table_entry (asm_out_file,
f376e137
MS
1514 entry->start_label, entry->end_label,
1515 entry->exception_handler_label);
8d2733ca
MS
1516 }
1517
f376e137
MS
1518 if (count)
1519 {
1520 /* Ending marker for table. */
1521 ASM_OUTPUT_LABEL (asm_out_file, "__EXCEPTION_END__");
db5ae43f
MS
1522 output_exception_table_entry (asm_out_file,
1523 constm1_rtx, constm1_rtx, constm1_rtx);
f376e137 1524 }
8d2733ca 1525
f376e137
MS
1526#endif /* TRY_NEW_EH */
1527 return count;
1528}
8d2733ca 1529
f376e137
MS
1530void
1531register_exception_table ()
1532{
1533#ifdef TRY_NEW_EH
1534 emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__register_exceptions"), 0,
1535 VOIDmode, 1,
81613e43 1536 gen_rtx (SYMBOL_REF, Pmode, "__EXCEPTION_TABLE__"),
f376e137
MS
1537 Pmode);
1538#endif /* TRY_NEW_EH */
1539}
8d2733ca
MS
1540
1541/* Build a throw expression. */
1542tree
1543build_throw (e)
1544 tree e;
1545{
db5ae43f
MS
1546 if (e != error_mark_node)
1547 {
1548 e = build1 (THROW_EXPR, void_type_node, e);
1549 TREE_SIDE_EFFECTS (e) = 1;
1550 }
8d2733ca 1551 return e;
8d08fdba 1552}
This page took 0.24618 seconds and 5 git commands to generate.