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