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