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