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