OSDN Git Service

* Makefile.in (tree.o): Depend on ggc.h.
[pf3gnuchains/gcc-fork.git] / gcc / except.c
1 /* Implements exception handling.
2    Copyright (C) 1989, 1992-1999 Free Software Foundation, Inc.
3    Contributed by Mike Stump <mrs@cygnus.com>.
4
5 This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22
23 /* An exception is an event that can be signaled from within a
24    function. This event can then be "caught" or "trapped" by the
25    callers of this function. This potentially allows program flow to
26    be transferred to any arbitrary code associated with a function call
27    several levels up the stack.
28
29    The intended use for this mechanism is for signaling "exceptional
30    events" in an out-of-band fashion, hence its name. The C++ language
31    (and many other OO-styled or functional languages) practically
32    requires such a mechanism, as otherwise it becomes very difficult
33    or even impossible to signal failure conditions in complex
34    situations.  The traditional C++ example is when an error occurs in
35    the process of constructing an object; without such a mechanism, it
36    is impossible to signal that the error occurs without adding global
37    state variables and error checks around every object construction.
38
39    The act of causing this event to occur is referred to as "throwing
40    an exception". (Alternate terms include "raising an exception" or
41    "signaling an exception".) The term "throw" is used because control
42    is returned to the callers of the function that is signaling the
43    exception, and thus there is the concept of "throwing" the
44    exception up the call stack.
45
46    There are two major codegen options for exception handling.  The
47    flag -fsjlj-exceptions can be used to select the setjmp/longjmp
48    approach, which is the default.  -fno-sjlj-exceptions can be used to
49    get the PC range table approach.  While this is a compile time
50    flag, an entire application must be compiled with the same codegen
51    option.  The first is a PC range table approach, the second is a
52    setjmp/longjmp based scheme.  We will first discuss the PC range
53    table approach, after that, we will discuss the setjmp/longjmp
54    based approach.
55
56    It is appropriate to speak of the "context of a throw". This
57    context refers to the address where the exception is thrown from,
58    and is used to determine which exception region will handle the
59    exception.
60
61    Regions of code within a function can be marked such that if it
62    contains the context of a throw, control will be passed to a
63    designated "exception handler". These areas are known as "exception
64    regions".  Exception regions cannot overlap, but they can be nested
65    to any arbitrary depth. Also, exception regions cannot cross
66    function boundaries.
67
68    Exception handlers can either be specified by the user (which we
69    will call a "user-defined handler") or generated by the compiler
70    (which we will designate as a "cleanup"). Cleanups are used to
71    perform tasks such as destruction of objects allocated on the
72    stack.
73
74    In the current implementation, cleanups are handled by allocating an
75    exception region for the area that the cleanup is designated for,
76    and the handler for the region performs the cleanup and then
77    rethrows the exception to the outer exception region. From the
78    standpoint of the current implementation, there is little
79    distinction made between a cleanup and a user-defined handler, and
80    the phrase "exception handler" can be used to refer to either one
81    equally well. (The section "Future Directions" below discusses how
82    this will change).
83
84    Each object file that is compiled with exception handling contains
85    a static array of exception handlers named __EXCEPTION_TABLE__.
86    Each entry contains the starting and ending addresses of the
87    exception region, and the address of the handler designated for
88    that region.
89
90    If the target does not use the DWARF 2 frame unwind information, at
91    program startup each object file invokes a function named
92    __register_exceptions with the address of its local
93    __EXCEPTION_TABLE__. __register_exceptions is defined in libgcc2.c, and
94    is responsible for recording all of the exception regions into one list
95    (which is kept in a static variable named exception_table_list).
96
97    On targets that support crtstuff.c, the unwind information
98    is stored in a section named .eh_frame and the information for the
99    entire shared object or program is registered with a call to
100    __register_frame_info.  On other targets, the information for each
101    translation unit is registered from the file generated by collect2.
102    __register_frame_info is defined in frame.c, and is responsible for
103    recording all of the unwind regions into one list (which is kept in a
104    static variable named unwind_table_list).
105
106    The function __throw is actually responsible for doing the
107    throw. On machines that have unwind info support, __throw is generated
108    by code in libgcc2.c, otherwise __throw is generated on a
109    per-object-file basis for each source file compiled with
110    -fexceptions by the C++ frontend.  Before __throw is invoked,
111    the current context of the throw needs to be placed in the global
112    variable __eh_pc.
113
114    __throw attempts to find the appropriate exception handler for the 
115    PC value stored in __eh_pc by calling __find_first_exception_table_match
116    (which is defined in libgcc2.c). If __find_first_exception_table_match
117    finds a relevant handler, __throw transfers control directly to it.
118
119    If a handler for the context being thrown from can't be found, __throw
120    walks (see Walking the stack below) the stack up the dynamic call chain to
121    continue searching for an appropriate exception handler based upon the
122    caller of the function it last sought a exception handler for.  It stops
123    then either an exception handler is found, or when the top of the
124    call chain is reached.
125
126    If no handler is found, an external library function named
127    __terminate is called.  If a handler is found, then we restart
128    our search for a handler at the end of the call chain, and repeat
129    the search process, but instead of just walking up the call chain,
130    we unwind the call chain as we walk up it.
131
132    Internal implementation details:
133
134    To associate a user-defined handler with a block of statements, the
135    function expand_start_try_stmts is used to mark the start of the
136    block of statements with which the handler is to be associated
137    (which is known as a "try block"). All statements that appear
138    afterwards will be associated with the try block.
139
140    A call to expand_start_all_catch marks the end of the try block,
141    and also marks the start of the "catch block" (the user-defined
142    handler) associated with the try block.
143
144    This user-defined handler will be invoked for *every* exception
145    thrown with the context of the try block. It is up to the handler
146    to decide whether or not it wishes to handle any given exception,
147    as there is currently no mechanism in this implementation for doing
148    this. (There are plans for conditionally processing an exception
149    based on its "type", which will provide a language-independent
150    mechanism).
151
152    If the handler chooses not to process the exception (perhaps by
153    looking at an "exception type" or some other additional data
154    supplied with the exception), it can fall through to the end of the
155    handler. expand_end_all_catch and expand_leftover_cleanups
156    add additional code to the end of each handler to take care of
157    rethrowing to the outer exception handler.
158
159    The handler also has the option to continue with "normal flow of
160    code", or in other words to resume executing at the statement
161    immediately after the end of the exception region. The variable
162    caught_return_label_stack contains a stack of labels, and jumping
163    to the topmost entry's label via expand_goto will resume normal
164    flow to the statement immediately after the end of the exception
165    region. If the handler falls through to the end, the exception will
166    be rethrown to the outer exception region.
167
168    The instructions for the catch block are kept as a separate
169    sequence, and will be emitted at the end of the function along with
170    the handlers specified via expand_eh_region_end. The end of the
171    catch block is marked with expand_end_all_catch.
172
173    Any data associated with the exception must currently be handled by
174    some external mechanism maintained in the frontend.  For example,
175    the C++ exception mechanism passes an arbitrary value along with
176    the exception, and this is handled in the C++ frontend by using a
177    global variable to hold the value. (This will be changing in the
178    future.)
179
180    The mechanism in C++ for handling data associated with the
181    exception is clearly not thread-safe. For a thread-based
182    environment, another mechanism must be used (possibly using a
183    per-thread allocation mechanism if the size of the area that needs
184    to be allocated isn't known at compile time.)
185
186    Internally-generated exception regions (cleanups) are marked by
187    calling expand_eh_region_start to mark the start of the region,
188    and expand_eh_region_end (handler) is used to both designate the
189    end of the region and to associate a specified handler/cleanup with
190    the region. The rtl code in HANDLER will be invoked whenever an
191    exception occurs in the region between the calls to
192    expand_eh_region_start and expand_eh_region_end. After HANDLER is
193    executed, additional code is emitted to handle rethrowing the
194    exception to the outer exception handler. The code for HANDLER will
195    be emitted at the end of the function.
196
197    TARGET_EXPRs can also be used to designate exception regions. A
198    TARGET_EXPR gives an unwind-protect style interface commonly used
199    in functional languages such as LISP. The associated expression is
200    evaluated, and whether or not it (or any of the functions that it
201    calls) throws an exception, the protect expression is always
202    invoked. This implementation takes care of the details of
203    associating an exception table entry with the expression and
204    generating the necessary code (it actually emits the protect
205    expression twice, once for normal flow and once for the exception
206    case). As for the other handlers, the code for the exception case
207    will be emitted at the end of the function.
208
209    Cleanups can also be specified by using add_partial_entry (handler)
210    and end_protect_partials. add_partial_entry creates the start of
211    a new exception region; HANDLER will be invoked if an exception is
212    thrown with the context of the region between the calls to
213    add_partial_entry and end_protect_partials. end_protect_partials is
214    used to mark the end of these regions. add_partial_entry can be
215    called as many times as needed before calling end_protect_partials.
216    However, end_protect_partials should only be invoked once for each
217    group of calls to add_partial_entry as the entries are queued
218    and all of the outstanding entries are processed simultaneously
219    when end_protect_partials is invoked. Similarly to the other
220    handlers, the code for HANDLER will be emitted at the end of the
221    function.
222
223    The generated RTL for an exception region includes
224    NOTE_INSN_EH_REGION_BEG and NOTE_INSN_EH_REGION_END notes that mark
225    the start and end of the exception region. A unique label is also
226    generated at the start of the exception region, which is available
227    by looking at the ehstack variable. The topmost entry corresponds
228    to the current region.
229
230    In the current implementation, an exception can only be thrown from
231    a function call (since the mechanism used to actually throw an
232    exception involves calling __throw).  If an exception region is
233    created but no function calls occur within that region, the region
234    can be safely optimized away (along with its exception handlers)
235    since no exceptions can ever be caught in that region.  This
236    optimization is performed unless -fasynchronous-exceptions is
237    given.  If the user wishes to throw from a signal handler, or other
238    asynchronous place, -fasynchronous-exceptions should be used when
239    compiling for maximally correct code, at the cost of additional
240    exception regions.  Using -fasynchronous-exceptions only produces
241    code that is reasonably safe in such situations, but a correct
242    program cannot rely upon this working.  It can be used in failsafe
243    code, where trying to continue on, and proceeding with potentially
244    incorrect results is better than halting the program.
245
246
247    Walking the stack:
248
249    The stack is walked by starting with a pointer to the current
250    frame, and finding the pointer to the callers frame.  The unwind info
251    tells __throw how to find it.
252
253    Unwinding the stack:
254
255    When we use the term unwinding the stack, we mean undoing the
256    effects of the function prologue in a controlled fashion so that we
257    still have the flow of control.  Otherwise, we could just return
258    (jump to the normal end of function epilogue).
259
260    This is done in __throw in libgcc2.c when we know that a handler exists
261    in a frame higher up the call stack than its immediate caller.
262
263    To unwind, we find the unwind data associated with the frame, if any.
264    If we don't find any, we call the library routine __terminate.  If we do
265    find it, we use the information to copy the saved register values from
266    that frame into the register save area in the frame for __throw, return
267    into a stub which updates the stack pointer, and jump to the handler.
268    The normal function epilogue for __throw handles restoring the saved
269    values into registers.
270
271    When unwinding, we use this method if we know it will
272    work (if DWARF2_UNWIND_INFO is defined).  Otherwise, we know that
273    an inline unwinder will have been emitted for any function that
274    __unwind_function cannot unwind.  The inline unwinder appears as a
275    normal exception handler for the entire function, for any function
276    that we know cannot be unwound by __unwind_function.  We inform the
277    compiler of whether a function can be unwound with
278    __unwind_function by having DOESNT_NEED_UNWINDER evaluate to true
279    when the unwinder isn't needed.  __unwind_function is used as an
280    action of last resort.  If no other method can be used for
281    unwinding, __unwind_function is used.  If it cannot unwind, it
282    should call __terminate.
283
284    By default, if the target-specific backend doesn't supply a definition
285    for __unwind_function and doesn't support DWARF2_UNWIND_INFO, inlined
286    unwinders will be used instead. The main tradeoff here is in text space
287    utilization.  Obviously, if inline unwinders have to be generated
288    repeatedly, this uses much more space than if a single routine is used.
289
290    However, it is simply not possible on some platforms to write a
291    generalized routine for doing stack unwinding without having some
292    form of additional data associated with each function.  The current
293    implementation can encode this data in the form of additional
294    machine instructions or as static data in tabular form.  The later
295    is called the unwind data.
296
297    The backend macro DOESNT_NEED_UNWINDER is used to conditionalize whether
298    or not per-function unwinders are needed. If DOESNT_NEED_UNWINDER is
299    defined and has a non-zero value, a per-function unwinder is not emitted
300    for the current function.  If the static unwind data is supported, then
301    a per-function unwinder is not emitted.
302
303    On some platforms it is possible that neither __unwind_function
304    nor inlined unwinders are available. For these platforms it is not
305    possible to throw through a function call, and abort will be
306    invoked instead of performing the throw. 
307
308    The reason the unwind data may be needed is that on some platforms
309    the order and types of data stored on the stack can vary depending
310    on the type of function, its arguments and returned values, and the
311    compilation options used (optimization versus non-optimization,
312    -fomit-frame-pointer, processor variations, etc).
313
314    Unfortunately, this also means that throwing through functions that
315    aren't compiled with exception handling support will still not be
316    possible on some platforms. This problem is currently being
317    investigated, but no solutions have been found that do not imply
318    some unacceptable performance penalties.
319
320    Future directions:
321
322    Currently __throw makes no differentiation between cleanups and
323    user-defined exception regions. While this makes the implementation
324    simple, it also implies that it is impossible to determine if a
325    user-defined exception handler exists for a given exception without
326    completely unwinding the stack in the process. This is undesirable
327    from the standpoint of debugging, as ideally it would be possible
328    to trap unhandled exceptions in the debugger before the process of
329    unwinding has even started.
330
331    This problem can be solved by marking user-defined handlers in a
332    special way (probably by adding additional bits to exception_table_list).
333    A two-pass scheme could then be used by __throw to iterate
334    through the table. The first pass would search for a relevant
335    user-defined handler for the current context of the throw, and if
336    one is found, the second pass would then invoke all needed cleanups
337    before jumping to the user-defined handler.
338
339    Many languages (including C++ and Ada) make execution of a
340    user-defined handler conditional on the "type" of the exception
341    thrown. (The type of the exception is actually the type of the data
342    that is thrown with the exception.) It will thus be necessary for
343    __throw to be able to determine if a given user-defined
344    exception handler will actually be executed, given the type of
345    exception.
346
347    One scheme is to add additional information to exception_table_list
348    as to the types of exceptions accepted by each handler. __throw
349    can do the type comparisons and then determine if the handler is
350    actually going to be executed.
351
352    There is currently no significant level of debugging support
353    available, other than to place a breakpoint on __throw. While
354    this is sufficient in most cases, it would be helpful to be able to
355    know where a given exception was going to be thrown to before it is
356    actually thrown, and to be able to choose between stopping before
357    every exception region (including cleanups), or just user-defined
358    exception regions. This should be possible to do in the two-pass
359    scheme by adding additional labels to __throw for appropriate
360    breakpoints, and additional debugger commands could be added to
361    query various state variables to determine what actions are to be
362    performed next.
363
364    Another major problem that is being worked on is the issue with stack
365    unwinding on various platforms. Currently the only platforms that have
366    support for the generation of a generic unwinder are the SPARC and MIPS.
367    All other ports require per-function unwinders, which produce large
368    amounts of code bloat.
369
370    For setjmp/longjmp based exception handling, some of the details
371    are as above, but there are some additional details.  This section
372    discusses the details.
373
374    We don't use NOTE_INSN_EH_REGION_{BEG,END} pairs.  We don't
375    optimize EH regions yet.  We don't have to worry about machine
376    specific issues with unwinding the stack, as we rely upon longjmp
377    for all the machine specific details.  There is no variable context
378    of a throw, just the one implied by the dynamic handler stack
379    pointed to by the dynamic handler chain.  There is no exception
380    table, and no calls to __register_exceptions.  __sjthrow is used
381    instead of __throw, and it works by using the dynamic handler
382    chain, and longjmp.  -fasynchronous-exceptions has no effect, as
383    the elimination of trivial exception regions is not yet performed.
384
385    A frontend can set protect_cleanup_actions_with_terminate when all
386    the cleanup actions should be protected with an EH region that
387    calls terminate when an unhandled exception is throw.  C++ does
388    this, Ada does not.  */
389
390
391 #include "config.h"
392 #include "defaults.h"
393 #include "eh-common.h"
394 #include "system.h"
395 #include "rtl.h"
396 #include "tree.h"
397 #include "flags.h"
398 #include "except.h"
399 #include "function.h"
400 #include "insn-flags.h"
401 #include "expr.h"
402 #include "insn-codes.h"
403 #include "regs.h"
404 #include "hard-reg-set.h"
405 #include "insn-config.h"
406 #include "recog.h"
407 #include "output.h"
408 #include "toplev.h"
409 #include "intl.h"
410 #include "obstack.h"
411 #include "ggc.h"
412
413 /* One to use setjmp/longjmp method of generating code for exception
414    handling.  */
415
416 int exceptions_via_longjmp = 2;
417
418 /* One to enable asynchronous exception support.  */
419
420 int asynchronous_exceptions = 0;
421
422 /* One to protect cleanup actions with a handler that calls
423    __terminate, zero otherwise.  */
424
425 int protect_cleanup_actions_with_terminate;
426
427 /* A list of labels used for exception handlers.  Created by
428    find_exception_handler_labels for the optimization passes.  */
429
430 rtx exception_handler_labels;
431
432 /* Keeps track of the label used as the context of a throw to rethrow an
433    exception to the outer exception region.  */
434
435 struct label_node *outer_context_label_stack = NULL;
436
437 /* Pseudos used to hold exception return data in the interim between
438    __builtin_eh_return and the end of the function.  */
439
440 static rtx eh_return_context;
441 static rtx eh_return_stack_adjust;
442 static rtx eh_return_handler;
443
444 /* This is used for targets which can call rethrow with an offset instead
445    of an address. This is subtracted from the rethrow label we are
446    interested in. */
447
448 static rtx first_rethrow_symbol = NULL_RTX;
449 static rtx final_rethrow = NULL_RTX;
450 static rtx last_rethrow_symbol = NULL_RTX;
451
452
453 /* Prototypes for local functions.  */
454
455 static void push_eh_entry       PROTO((struct eh_stack *));
456 static struct eh_entry * pop_eh_entry           PROTO((struct eh_stack *));
457 static void enqueue_eh_entry    PROTO((struct eh_queue *, struct eh_entry *));
458 static struct eh_entry * dequeue_eh_entry       PROTO((struct eh_queue *));
459 static rtx call_get_eh_context  PROTO((void));
460 static void start_dynamic_cleanup               PROTO((tree, tree));
461 static void start_dynamic_handler               PROTO((void));
462 static void expand_rethrow      PROTO((rtx));
463 static void output_exception_table_entry        PROTO((FILE *, int));
464 static int can_throw            PROTO((rtx));
465 static rtx scan_region          PROTO((rtx, int, int *));
466 static void eh_regs             PROTO((rtx *, rtx *, rtx *, int));
467 static void set_insn_eh_region  PROTO((rtx *, int));
468 #ifdef DONT_USE_BUILTIN_SETJMP
469 static void jumpif_rtx          PROTO((rtx, rtx));
470 #endif
471 static void mark_eh_node        PROTO((struct eh_node *));
472 static void mark_eh_stack       PROTO((struct eh_stack *));
473 static void mark_eh_queue       PROTO((struct eh_queue *));
474 static void mark_tree_label_node PROTO ((struct label_node *));
475
476 rtx expand_builtin_return_addr  PROTO((enum built_in_function, int, rtx));
477 \f
478 /* Various support routines to manipulate the various data structures
479    used by the exception handling code.  */
480
481 extern struct obstack permanent_obstack;
482
483 /* Generate a SYMBOL_REF for rethrow to use */
484 static rtx
485 create_rethrow_ref (region_num)
486      int region_num;
487 {
488   rtx def;
489   char *ptr;
490   char buf[60];
491
492   push_obstacks_nochange ();
493   end_temporary_allocation ();
494
495   ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", region_num);
496   ptr = (char *) obstack_copy0 (&permanent_obstack, buf, strlen (buf));
497   def = gen_rtx_SYMBOL_REF (Pmode, ptr);
498   SYMBOL_REF_NEED_ADJUST (def) = 1;
499
500   pop_obstacks ();
501   return def;
502 }
503
504 /* Push a label entry onto the given STACK.  */
505
506 void
507 push_label_entry (stack, rlabel, tlabel)
508      struct label_node **stack;
509      rtx rlabel;
510      tree tlabel;
511 {
512   struct label_node *newnode
513     = (struct label_node *) xmalloc (sizeof (struct label_node));
514
515   if (rlabel)
516     newnode->u.rlabel = rlabel;
517   else
518     newnode->u.tlabel = tlabel;
519   newnode->chain = *stack;
520   *stack = newnode;
521 }
522
523 /* Pop a label entry from the given STACK.  */
524
525 rtx
526 pop_label_entry (stack)
527      struct label_node **stack;
528 {
529   rtx label;
530   struct label_node *tempnode;
531
532   if (! *stack)
533     return NULL_RTX;
534
535   tempnode = *stack;
536   label = tempnode->u.rlabel;
537   *stack = (*stack)->chain;
538   free (tempnode);
539
540   return label;
541 }
542
543 /* Return the top element of the given STACK.  */
544
545 tree
546 top_label_entry (stack)
547      struct label_node **stack;
548 {
549   if (! *stack)
550     return NULL_TREE;
551
552   return (*stack)->u.tlabel;
553 }
554
555 /* get an exception label. These must be on the permanent obstack */
556
557 rtx
558 gen_exception_label ()
559 {
560   rtx lab;
561   lab = gen_label_rtx ();
562   return lab;
563 }
564
565 /* Push a new eh_node entry onto STACK.  */
566
567 static void
568 push_eh_entry (stack)
569      struct eh_stack *stack;
570 {
571   struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
572   struct eh_entry *entry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
573
574   rtx rlab = gen_exception_label ();
575   entry->finalization = NULL_TREE;
576   entry->label_used = 0;
577   entry->exception_handler_label = rlab;
578   entry->false_label = NULL_RTX;
579   if (! flag_new_exceptions)
580     entry->outer_context = gen_label_rtx ();
581   else
582     entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab));
583   entry->rethrow_label = entry->outer_context;
584
585   node->entry = entry;
586   node->chain = stack->top;
587   stack->top = node;
588 }
589
590 /* push an existing entry onto a stack. */
591 static void
592 push_entry (stack, entry)
593      struct eh_stack *stack;
594      struct eh_entry *entry;
595 {
596   struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
597   node->entry = entry;
598   node->chain = stack->top;
599   stack->top = node;
600 }
601
602 /* Pop an entry from the given STACK.  */
603
604 static struct eh_entry *
605 pop_eh_entry (stack)
606      struct eh_stack *stack;
607 {
608   struct eh_node *tempnode;
609   struct eh_entry *tempentry;
610   
611   tempnode = stack->top;
612   tempentry = tempnode->entry;
613   stack->top = stack->top->chain;
614   free (tempnode);
615
616   return tempentry;
617 }
618
619 /* Enqueue an ENTRY onto the given QUEUE.  */
620
621 static void
622 enqueue_eh_entry (queue, entry)
623      struct eh_queue *queue;
624      struct eh_entry *entry;
625 {
626   struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
627
628   node->entry = entry;
629   node->chain = NULL;
630
631   if (queue->head == NULL)
632     {
633       queue->head = node;
634     }
635   else
636     {
637       queue->tail->chain = node;
638     }
639   queue->tail = node;
640 }
641
642 /* Dequeue an entry from the given QUEUE.  */
643
644 static struct eh_entry *
645 dequeue_eh_entry (queue)
646      struct eh_queue *queue;
647 {
648   struct eh_node *tempnode;
649   struct eh_entry *tempentry;
650
651   if (queue->head == NULL)
652     return NULL;
653
654   tempnode = queue->head;
655   queue->head = queue->head->chain;
656
657   tempentry = tempnode->entry;
658   free (tempnode);
659
660   return tempentry;
661 }
662
663 static void
664 receive_exception_label (handler_label)
665      rtx handler_label;
666 {
667   emit_label (handler_label);
668   
669 #ifdef HAVE_exception_receiver
670   if (! exceptions_via_longjmp)
671     if (HAVE_exception_receiver)
672       emit_insn (gen_exception_receiver ());
673 #endif
674
675 #ifdef HAVE_nonlocal_goto_receiver
676   if (! exceptions_via_longjmp)
677     if (HAVE_nonlocal_goto_receiver)
678       emit_insn (gen_nonlocal_goto_receiver ());
679 #endif
680 }
681
682
683 struct func_eh_entry 
684 {
685   int range_number;   /* EH region number from EH NOTE insn's.  */
686   rtx rethrow_label;  /* Label for rethrow.  */
687   int rethrow_ref;    /* Is rethrow referenced?  */
688   struct handler_info *handlers;
689 };
690
691
692 /* table of function eh regions */
693 static struct func_eh_entry *function_eh_regions = NULL;
694 static int num_func_eh_entries = 0;
695 static int current_func_eh_entry = 0;
696
697 #define SIZE_FUNC_EH(X)   (sizeof (struct func_eh_entry) * X)
698
699 /* Add a new eh_entry for this function, and base it off of the information
700    in the EH_ENTRY parameter. A NULL parameter is invalid. 
701    OUTER_CONTEXT is a label which is used for rethrowing. The number
702    returned is an number which uniquely identifies this exception range. */
703
704 static int 
705 new_eh_region_entry (note_eh_region, rethrow) 
706      int note_eh_region;
707      rtx rethrow;
708 {
709   if (current_func_eh_entry == num_func_eh_entries) 
710     {
711       if (num_func_eh_entries == 0)
712         {
713           function_eh_regions = 
714                         (struct func_eh_entry *) malloc (SIZE_FUNC_EH (50));
715           num_func_eh_entries = 50;
716         }
717       else
718         {
719           num_func_eh_entries  = num_func_eh_entries * 3 / 2;
720           function_eh_regions = (struct func_eh_entry *) 
721             realloc (function_eh_regions, SIZE_FUNC_EH (num_func_eh_entries));
722         }
723     }
724   function_eh_regions[current_func_eh_entry].range_number = note_eh_region;
725   if (rethrow == NULL_RTX)
726     function_eh_regions[current_func_eh_entry].rethrow_label = 
727                                           create_rethrow_ref (note_eh_region);
728   else
729     function_eh_regions[current_func_eh_entry].rethrow_label = rethrow;
730   function_eh_regions[current_func_eh_entry].handlers = NULL;
731
732   return current_func_eh_entry++;
733 }
734
735 /* Add new handler information to an exception range. The  first parameter
736    specifies the range number (returned from new_eh_entry()). The second
737    parameter specifies the handler.  By default the handler is inserted at
738    the end of the list. A handler list may contain only ONE NULL_TREE
739    typeinfo entry. Regardless where it is positioned, a NULL_TREE entry
740    is always output as the LAST handler in the exception table for a region. */
741
742 void 
743 add_new_handler (region, newhandler)
744      int region;
745      struct handler_info *newhandler;
746 {
747   struct handler_info *last;
748
749   newhandler->next = NULL;
750   last = function_eh_regions[region].handlers;
751   if (last == NULL)
752     function_eh_regions[region].handlers = newhandler;
753   else 
754     {
755       for ( ; ; last = last->next)
756         {
757           if (last->type_info == CATCH_ALL_TYPE)
758             pedwarn ("additional handler after ...");
759           if (last->next == NULL)
760             break;
761         }
762       last->next = newhandler;
763     }
764 }
765
766 /* Remove a handler label. The handler label is being deleted, so all
767    regions which reference this handler should have it removed from their
768    list of possible handlers. Any region which has the final handler
769    removed can be deleted. */
770
771 void remove_handler (removing_label)
772      rtx removing_label;
773 {
774   struct handler_info *handler, *last;
775   int x;
776   for (x = 0 ; x < current_func_eh_entry; ++x)
777     {
778       last = NULL;
779       handler = function_eh_regions[x].handlers;
780       for ( ; handler; last = handler, handler = handler->next)
781         if (handler->handler_label == removing_label)
782           {
783             if (last)
784               {
785                 last->next = handler->next;
786                 handler = last;
787               }
788             else
789               function_eh_regions[x].handlers = handler->next;
790           }
791     }
792 }
793
794 /* This function will return a malloc'd pointer to an array of 
795    void pointer representing the runtime match values that 
796    currently exist in all regions. */
797
798 int 
799 find_all_handler_type_matches (array)
800   void ***array;
801 {
802   struct handler_info *handler, *last;
803   int x,y;
804   void *val;
805   void **ptr;
806   int max_ptr;
807   int n_ptr = 0;
808
809   *array = NULL;
810
811   if (!doing_eh (0) || ! flag_new_exceptions)
812     return 0;
813
814   max_ptr = 100;
815   ptr = (void **)malloc (max_ptr * sizeof (void *));
816
817   if (ptr == NULL)
818     return 0;
819
820   for (x = 0 ; x < current_func_eh_entry; x++)
821     {
822       last = NULL;
823       handler = function_eh_regions[x].handlers;
824       for ( ; handler; last = handler, handler = handler->next)
825         {
826           val = handler->type_info;
827           if (val != NULL && val != CATCH_ALL_TYPE)
828             {
829               /* See if this match value has already been found. */
830               for (y = 0; y < n_ptr; y++)
831                 if (ptr[y] == val)
832                   break;
833
834               /* If we break early, we already found this value. */
835               if (y < n_ptr)
836                 continue;
837
838               /* Do we need to allocate more space? */
839               if (n_ptr >= max_ptr) 
840                 {
841                   max_ptr += max_ptr / 2;
842                   ptr = (void **)realloc (ptr, max_ptr * sizeof (void *));
843                   if (ptr == NULL)
844                     return 0;
845                 }
846               ptr[n_ptr] = val;
847               n_ptr++;
848             }
849         }
850     }
851   *array = ptr;
852   return n_ptr;
853 }
854
855 /* Create a new handler structure initialized with the handler label and
856    typeinfo fields passed in. */
857
858 struct handler_info *
859 get_new_handler (handler, typeinfo)
860      rtx handler;
861      void *typeinfo;
862 {
863   struct handler_info* ptr;
864   ptr = (struct handler_info *) malloc (sizeof (struct handler_info));
865   ptr->handler_label = handler;
866   ptr->handler_number = CODE_LABEL_NUMBER (handler);
867   ptr->type_info = typeinfo;
868   ptr->next = NULL;
869
870   return ptr;
871 }
872
873
874
875 /* Find the index in function_eh_regions associated with a NOTE region. If
876    the region cannot be found, a -1 is returned. This should never happen! */
877
878 int 
879 find_func_region (insn_region)
880      int insn_region;
881 {
882   int x;
883   for (x = 0; x < current_func_eh_entry; x++)
884     if (function_eh_regions[x].range_number == insn_region)
885       return x;
886
887   return -1;
888 }
889
890 /* Get a pointer to the first handler in an exception region's list. */
891
892 struct handler_info *
893 get_first_handler (region)
894      int region;
895 {
896   return function_eh_regions[find_func_region (region)].handlers;
897 }
898
899 /* Clean out the function_eh_region table and free all memory */
900
901 static void
902 clear_function_eh_region ()
903 {
904   int x;
905   struct handler_info *ptr, *next;
906   for (x = 0; x < current_func_eh_entry; x++)
907     for (ptr = function_eh_regions[x].handlers; ptr != NULL; ptr = next)
908       {
909         next = ptr->next;
910         free (ptr);
911       }
912   free (function_eh_regions);
913   num_func_eh_entries  = 0;
914   current_func_eh_entry = 0;
915 }
916
917 /* Make a duplicate of an exception region by copying all the handlers
918    for an exception region. Return the new handler index. The final
919    parameter is a routine which maps old labels to new ones. */
920
921 int 
922 duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map)
923      int old_note_eh_region, new_note_eh_region;
924      rtx (*map) PARAMS ((rtx));
925 {
926   struct handler_info *ptr, *new_ptr;
927   int new_region, region;
928
929   region = find_func_region (old_note_eh_region);
930   if (region == -1)
931     fatal ("Cannot duplicate non-existant exception region.");
932
933   /* duplicate_eh_handlers may have been called during a symbol remap. */
934   new_region = find_func_region (new_note_eh_region);
935   if (new_region != -1)
936     return (new_region);
937
938   new_region = new_eh_region_entry (new_note_eh_region, NULL_RTX);
939
940   ptr = function_eh_regions[region].handlers;
941
942   for ( ; ptr; ptr = ptr->next) 
943     {
944       new_ptr = get_new_handler (map (ptr->handler_label), ptr->type_info);
945       add_new_handler (new_region, new_ptr);
946     }
947
948   return new_region;
949 }
950
951
952 /* Given a rethrow symbol, find the EH region number this is for. */
953 int 
954 eh_region_from_symbol (sym)
955      rtx sym;
956 {
957   int x;
958   if (sym == last_rethrow_symbol)
959     return 1;
960   for (x = 0; x < current_func_eh_entry; x++)
961     if (function_eh_regions[x].rethrow_label == sym)
962       return function_eh_regions[x].range_number;
963   return -1;
964 }
965
966
967 /* When inlining/unrolling, we have to map the symbols passed to
968    __rethrow as well. This performs the remap. If a symbol isn't foiund,
969    the original one is returned. This is not an efficient routine,
970    so don't call it on everything!! */
971 rtx 
972 rethrow_symbol_map (sym, map)
973      rtx sym;
974      rtx (*map) PARAMS ((rtx));
975 {
976   int x, y;
977   for (x = 0; x < current_func_eh_entry; x++)
978     if (function_eh_regions[x].rethrow_label == sym)
979       {
980         /* We've found the original region, now lets determine which region
981            this now maps to. */
982         rtx l1 = function_eh_regions[x].handlers->handler_label;
983         rtx l2 = map (l1);
984         y = CODE_LABEL_NUMBER (l2); /* This is the new region number */
985         x = find_func_region (y);  /* Get the new permanent region */
986         if (x == -1)  /* Hmm, Doesn't exist yet */
987           {
988             x = duplicate_eh_handlers (CODE_LABEL_NUMBER (l1), y, map);
989             /* Since we're mapping it, it must be used. */
990             function_eh_regions[x].rethrow_ref = 1;
991           }
992         return function_eh_regions[x].rethrow_label;
993       }
994   return sym;
995 }
996
997 int 
998 rethrow_used (region)
999      int region;
1000 {
1001   if (flag_new_exceptions)
1002     {
1003       int ret = function_eh_regions[find_func_region (region)].rethrow_ref;
1004       return ret;
1005     }
1006   return 0;
1007 }
1008
1009 \f
1010 /* Routine to see if exception handling is turned on.
1011    DO_WARN is non-zero if we want to inform the user that exception
1012    handling is turned off. 
1013
1014    This is used to ensure that -fexceptions has been specified if the
1015    compiler tries to use any exception-specific functions.  */
1016
1017 int
1018 doing_eh (do_warn)
1019      int do_warn;
1020 {
1021   if (! flag_exceptions)
1022     {
1023       static int warned = 0;
1024       if (! warned && do_warn)
1025         {
1026           error ("exception handling disabled, use -fexceptions to enable");
1027           warned = 1;
1028         }
1029       return 0;
1030     }
1031   return 1;
1032 }
1033
1034 /* Given a return address in ADDR, determine the address we should use
1035    to find the corresponding EH region.  */
1036
1037 rtx
1038 eh_outer_context (addr)
1039      rtx addr;
1040 {
1041   /* First mask out any unwanted bits.  */
1042 #ifdef MASK_RETURN_ADDR
1043   expand_and (addr, MASK_RETURN_ADDR, addr);
1044 #endif
1045
1046   /* Then adjust to find the real return address.  */
1047 #if defined (RETURN_ADDR_OFFSET)
1048   addr = plus_constant (addr, RETURN_ADDR_OFFSET);
1049 #endif
1050
1051   return addr;
1052 }
1053
1054 /* Start a new exception region for a region of code that has a
1055    cleanup action and push the HANDLER for the region onto
1056    protect_list. All of the regions created with add_partial_entry
1057    will be ended when end_protect_partials is invoked.  */
1058
1059 void
1060 add_partial_entry (handler)
1061      tree handler;
1062 {
1063   expand_eh_region_start ();
1064
1065   /* Make sure the entry is on the correct obstack.  */
1066   push_obstacks_nochange ();
1067   resume_temporary_allocation ();
1068
1069   /* Because this is a cleanup action, we may have to protect the handler
1070      with __terminate.  */
1071   handler = protect_with_terminate (handler);
1072
1073   protect_list = tree_cons (NULL_TREE, handler, protect_list);
1074   pop_obstacks ();
1075 }
1076
1077 /* Emit code to get EH context to current function.  */
1078
1079 static rtx
1080 call_get_eh_context ()
1081 {
1082   static tree fn;
1083   tree expr;
1084
1085   if (fn == NULL_TREE)
1086     {
1087       tree fntype;
1088       fn = get_identifier ("__get_eh_context");
1089       push_obstacks_nochange ();
1090       end_temporary_allocation ();
1091       fntype = build_pointer_type (build_pointer_type
1092                                    (build_pointer_type (void_type_node)));
1093       fntype = build_function_type (fntype, NULL_TREE);
1094       fn = build_decl (FUNCTION_DECL, fn, fntype);
1095       DECL_EXTERNAL (fn) = 1;
1096       TREE_PUBLIC (fn) = 1;
1097       DECL_ARTIFICIAL (fn) = 1;
1098       TREE_READONLY (fn) = 1;
1099       make_decl_rtl (fn, NULL_PTR, 1);
1100       assemble_external (fn);
1101       pop_obstacks ();
1102     }
1103
1104   expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
1105   expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1106                 expr, NULL_TREE, NULL_TREE);
1107   TREE_SIDE_EFFECTS (expr) = 1;
1108
1109   return copy_to_reg (expand_expr (expr, NULL_RTX, VOIDmode, 0));
1110 }
1111
1112 /* Get a reference to the EH context.
1113    We will only generate a register for the current function EH context here,
1114    and emit a USE insn to mark that this is a EH context register.
1115
1116    Later, emit_eh_context will emit needed call to __get_eh_context
1117    in libgcc2, and copy the value to the register we have generated. */
1118
1119 rtx
1120 get_eh_context ()
1121 {
1122   if (current_function_ehc == 0)
1123     {
1124       rtx insn;
1125
1126       current_function_ehc = gen_reg_rtx (Pmode);
1127       
1128       insn = gen_rtx_USE (GET_MODE (current_function_ehc),
1129                           current_function_ehc);
1130       insn = emit_insn_before (insn, get_first_nonparm_insn ());
1131
1132       REG_NOTES (insn)
1133         = gen_rtx_EXPR_LIST (REG_EH_CONTEXT, current_function_ehc,
1134                              REG_NOTES (insn));
1135     }
1136   return current_function_ehc;
1137 }
1138      
1139 /* Get a reference to the dynamic handler chain.  It points to the
1140    pointer to the next element in the dynamic handler chain.  It ends
1141    when there are no more elements in the dynamic handler chain, when
1142    the value is &top_elt from libgcc2.c.  Immediately after the
1143    pointer, is an area suitable for setjmp/longjmp when
1144    DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
1145    __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
1146    isn't defined. */
1147
1148 rtx
1149 get_dynamic_handler_chain ()
1150 {
1151   rtx ehc, dhc, result;
1152
1153   ehc = get_eh_context ();
1154
1155   /* This is the offset of dynamic_handler_chain in the eh_context struct
1156      declared in eh-common.h. If its location is change, change this offset */
1157   dhc = plus_constant (ehc, POINTER_SIZE / BITS_PER_UNIT);
1158
1159   result = copy_to_reg (dhc);
1160
1161   /* We don't want a copy of the dcc, but rather, the single dcc.  */
1162   return gen_rtx_MEM (Pmode, result);
1163 }
1164
1165 /* Get a reference to the dynamic cleanup chain.  It points to the
1166    pointer to the next element in the dynamic cleanup chain.
1167    Immediately after the pointer, are two Pmode variables, one for a
1168    pointer to a function that performs the cleanup action, and the
1169    second, the argument to pass to that function.  */
1170
1171 rtx
1172 get_dynamic_cleanup_chain ()
1173 {
1174   rtx dhc, dcc, result;
1175
1176   dhc = get_dynamic_handler_chain ();
1177   dcc = plus_constant (dhc, POINTER_SIZE / BITS_PER_UNIT);
1178
1179   result = copy_to_reg (dcc);
1180
1181   /* We don't want a copy of the dcc, but rather, the single dcc.  */
1182   return gen_rtx_MEM (Pmode, result);
1183 }
1184
1185 #ifdef DONT_USE_BUILTIN_SETJMP
1186 /* Generate code to evaluate X and jump to LABEL if the value is nonzero.
1187    LABEL is an rtx of code CODE_LABEL, in this function.  */
1188
1189 static void
1190 jumpif_rtx (x, label)
1191      rtx x;
1192      rtx label;
1193 {
1194   jumpif (make_tree (type_for_mode (GET_MODE (x), 0), x), label);
1195 }
1196 #endif
1197
1198 /* Start a dynamic cleanup on the EH runtime dynamic cleanup stack.
1199    We just need to create an element for the cleanup list, and push it
1200    into the chain.
1201
1202    A dynamic cleanup is a cleanup action implied by the presence of an
1203    element on the EH runtime dynamic cleanup stack that is to be
1204    performed when an exception is thrown.  The cleanup action is
1205    performed by __sjthrow when an exception is thrown.  Only certain
1206    actions can be optimized into dynamic cleanup actions.  For the
1207    restrictions on what actions can be performed using this routine,
1208    see expand_eh_region_start_tree.  */
1209
1210 static void
1211 start_dynamic_cleanup (func, arg)
1212      tree func;
1213      tree arg;
1214 {
1215   rtx dcc;
1216   rtx new_func, new_arg;
1217   rtx x, buf;
1218   int size;
1219
1220   /* We allocate enough room for a pointer to the function, and
1221      one argument.  */
1222   size = 2;
1223
1224   /* XXX, FIXME: The stack space allocated this way is too long lived,
1225      but there is no allocation routine that allocates at the level of
1226      the last binding contour.  */
1227   buf = assign_stack_local (BLKmode,
1228                             GET_MODE_SIZE (Pmode)*(size+1),
1229                             0);
1230
1231   buf = change_address (buf, Pmode, NULL_RTX);
1232
1233   /* Store dcc into the first word of the newly allocated buffer.  */
1234
1235   dcc = get_dynamic_cleanup_chain ();
1236   emit_move_insn (buf, dcc);
1237
1238   /* Store func and arg into the cleanup list element.  */
1239
1240   new_func = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
1241                                                 GET_MODE_SIZE (Pmode)));
1242   new_arg = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
1243                                                GET_MODE_SIZE (Pmode)*2));
1244   x = expand_expr (func, new_func, Pmode, 0);
1245   if (x != new_func)
1246     emit_move_insn (new_func, x);
1247
1248   x = expand_expr (arg, new_arg, Pmode, 0);
1249   if (x != new_arg)
1250     emit_move_insn (new_arg, x);
1251
1252   /* Update the cleanup chain.  */
1253
1254   x = force_operand (XEXP (buf, 0), dcc);
1255   if (x != dcc)
1256     emit_move_insn (dcc, x);
1257 }
1258
1259 /* Emit RTL to start a dynamic handler on the EH runtime dynamic
1260    handler stack.  This should only be used by expand_eh_region_start
1261    or expand_eh_region_start_tree.  */
1262
1263 static void
1264 start_dynamic_handler ()
1265 {
1266   rtx dhc, dcc;
1267   rtx x, arg, buf;
1268   int size;
1269
1270 #ifndef DONT_USE_BUILTIN_SETJMP
1271   /* The number of Pmode words for the setjmp buffer, when using the
1272      builtin setjmp/longjmp, see expand_builtin, case
1273      BUILT_IN_LONGJMP.  */
1274   size = 5;
1275 #else
1276 #ifdef JMP_BUF_SIZE
1277   size = JMP_BUF_SIZE;
1278 #else
1279   /* Should be large enough for most systems, if it is not,
1280      JMP_BUF_SIZE should be defined with the proper value.  It will
1281      also tend to be larger than necessary for most systems, a more
1282      optimal port will define JMP_BUF_SIZE.  */
1283   size = FIRST_PSEUDO_REGISTER+2;
1284 #endif
1285 #endif
1286   /* XXX, FIXME: The stack space allocated this way is too long lived,
1287      but there is no allocation routine that allocates at the level of
1288      the last binding contour.  */
1289   arg = assign_stack_local (BLKmode,
1290                             GET_MODE_SIZE (Pmode)*(size+1),
1291                             0);
1292
1293   arg = change_address (arg, Pmode, NULL_RTX);
1294
1295   /* Store dhc into the first word of the newly allocated buffer.  */
1296
1297   dhc = get_dynamic_handler_chain ();
1298   dcc = gen_rtx_MEM (Pmode, plus_constant (XEXP (arg, 0),
1299                                            GET_MODE_SIZE (Pmode)));
1300   emit_move_insn (arg, dhc);
1301
1302   /* Zero out the start of the cleanup chain.  */
1303   emit_move_insn (dcc, const0_rtx);
1304
1305   /* The jmpbuf starts two words into the area allocated.  */
1306   buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
1307
1308 #ifdef DONT_USE_BUILTIN_SETJMP
1309   x = emit_library_call_value (setjmp_libfunc, NULL_RTX, 1, SImode, 1,
1310                                buf, Pmode);
1311   /* If we come back here for a catch, transfer control to the handler.  */
1312   jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
1313 #else
1314   {
1315     /* A label to continue execution for the no exception case.  */
1316     rtx noex = gen_label_rtx();
1317     x = expand_builtin_setjmp (buf, NULL_RTX, noex,
1318                                ehstack.top->entry->exception_handler_label);
1319     emit_label (noex);
1320   }
1321 #endif
1322
1323   /* We are committed to this, so update the handler chain.  */
1324
1325   emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
1326 }
1327
1328 /* Start an exception handling region for the given cleanup action.
1329    All instructions emitted after this point are considered to be part
1330    of the region until expand_eh_region_end is invoked.  CLEANUP is
1331    the cleanup action to perform.  The return value is true if the
1332    exception region was optimized away.  If that case,
1333    expand_eh_region_end does not need to be called for this cleanup,
1334    nor should it be.
1335
1336    This routine notices one particular common case in C++ code
1337    generation, and optimizes it so as to not need the exception
1338    region.  It works by creating a dynamic cleanup action, instead of
1339    a using an exception region.  */
1340
1341 int
1342 expand_eh_region_start_tree (decl, cleanup)
1343      tree decl;
1344      tree cleanup;
1345 {
1346   /* This is the old code.  */
1347   if (! doing_eh (0))
1348     return 0;
1349
1350   /* The optimization only applies to actions protected with
1351      terminate, and only applies if we are using the setjmp/longjmp
1352      codegen method.  */
1353   if (exceptions_via_longjmp
1354       && protect_cleanup_actions_with_terminate)
1355     {
1356       tree func, arg;
1357       tree args;
1358
1359       /* Ignore any UNSAVE_EXPR.  */
1360       if (TREE_CODE (cleanup) == UNSAVE_EXPR)
1361         cleanup = TREE_OPERAND (cleanup, 0);
1362       
1363       /* Further, it only applies if the action is a call, if there
1364          are 2 arguments, and if the second argument is 2.  */
1365
1366       if (TREE_CODE (cleanup) == CALL_EXPR
1367           && (args = TREE_OPERAND (cleanup, 1))
1368           && (func = TREE_OPERAND (cleanup, 0))
1369           && (arg = TREE_VALUE (args))
1370           && (args = TREE_CHAIN (args))
1371
1372           /* is the second argument 2?  */
1373           && TREE_CODE (TREE_VALUE (args)) == INTEGER_CST
1374           && TREE_INT_CST_LOW (TREE_VALUE (args)) == 2
1375           && TREE_INT_CST_HIGH (TREE_VALUE (args)) == 0
1376
1377           /* Make sure there are no other arguments.  */
1378           && TREE_CHAIN (args) == NULL_TREE)
1379         {
1380           /* Arrange for returns and gotos to pop the entry we make on the
1381              dynamic cleanup stack.  */
1382           expand_dcc_cleanup (decl);
1383           start_dynamic_cleanup (func, arg);
1384           return 1;
1385         }
1386     }
1387
1388   expand_eh_region_start_for_decl (decl);
1389   ehstack.top->entry->finalization = cleanup;
1390
1391   return 0;
1392 }
1393
1394 /* Just like expand_eh_region_start, except if a cleanup action is
1395    entered on the cleanup chain, the TREE_PURPOSE of the element put
1396    on the chain is DECL.  DECL should be the associated VAR_DECL, if
1397    any, otherwise it should be NULL_TREE.  */
1398
1399 void
1400 expand_eh_region_start_for_decl (decl)
1401      tree decl;
1402 {
1403   rtx note;
1404
1405   /* This is the old code.  */
1406   if (! doing_eh (0))
1407     return;
1408
1409   /* We need a new block to record the start and end of the
1410      dynamic handler chain.  We also want to prevent jumping into
1411      a try block.  */
1412   expand_start_bindings (0);
1413
1414   /* But we don't need or want a new temporary level.  */
1415   pop_temp_slots ();
1416
1417   /* Mark this block as created by expand_eh_region_start.  This
1418      is so that we can pop the block with expand_end_bindings
1419      automatically.  */
1420   mark_block_as_eh_region ();
1421
1422   if (exceptions_via_longjmp)
1423     {
1424       /* Arrange for returns and gotos to pop the entry we make on the
1425          dynamic handler stack.  */
1426       expand_dhc_cleanup (decl);
1427     }
1428
1429   push_eh_entry (&ehstack);
1430   note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_BEG);
1431   NOTE_BLOCK_NUMBER (note)
1432     = CODE_LABEL_NUMBER (ehstack.top->entry->exception_handler_label);
1433   if (exceptions_via_longjmp)
1434     start_dynamic_handler ();
1435 }
1436
1437 /* Start an exception handling region.  All instructions emitted after
1438    this point are considered to be part of the region until
1439    expand_eh_region_end is invoked.  */
1440
1441 void
1442 expand_eh_region_start ()
1443 {
1444   expand_eh_region_start_for_decl (NULL_TREE);
1445 }
1446
1447 /* End an exception handling region.  The information about the region
1448    is found on the top of ehstack.
1449
1450    HANDLER is either the cleanup for the exception region, or if we're
1451    marking the end of a try block, HANDLER is integer_zero_node.
1452
1453    HANDLER will be transformed to rtl when expand_leftover_cleanups
1454    is invoked.  */
1455
1456 void
1457 expand_eh_region_end (handler)
1458      tree handler;
1459 {
1460   struct eh_entry *entry;
1461   rtx note;
1462   int ret, r;
1463
1464   if (! doing_eh (0))
1465     return;
1466
1467   entry = pop_eh_entry (&ehstack);
1468
1469   note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_END);
1470   ret = NOTE_BLOCK_NUMBER (note)
1471     = CODE_LABEL_NUMBER (entry->exception_handler_label);
1472   if (exceptions_via_longjmp == 0 && ! flag_new_exceptions
1473       /* We share outer_context between regions; only emit it once.  */
1474       && INSN_UID (entry->outer_context) == 0)
1475     {
1476       rtx label;
1477
1478       label = gen_label_rtx ();
1479       emit_jump (label);
1480
1481       /* Emit a label marking the end of this exception region that
1482          is used for rethrowing into the outer context.  */
1483       emit_label (entry->outer_context);
1484       expand_internal_throw ();
1485
1486       emit_label (label);
1487     }
1488
1489   entry->finalization = handler;
1490
1491   /* create region entry in final exception table */
1492   r = new_eh_region_entry (NOTE_BLOCK_NUMBER (note), entry->rethrow_label);
1493
1494   enqueue_eh_entry (&ehqueue, entry);
1495
1496   /* If we have already started ending the bindings, don't recurse.  */
1497   if (is_eh_region ())
1498     {
1499       /* Because we don't need or want a new temporary level and
1500          because we didn't create one in expand_eh_region_start,
1501          create a fake one now to avoid removing one in
1502          expand_end_bindings.  */
1503       push_temp_slots ();
1504
1505       mark_block_as_not_eh_region ();
1506
1507       expand_end_bindings (NULL_TREE, 0, 0);
1508     }
1509 }
1510
1511 /* End the EH region for a goto fixup.  We only need them in the region-based
1512    EH scheme.  */
1513
1514 void
1515 expand_fixup_region_start ()
1516 {
1517   if (! doing_eh (0) || exceptions_via_longjmp)
1518     return;
1519
1520   expand_eh_region_start ();
1521 }
1522
1523 /* End the EH region for a goto fixup.  CLEANUP is the cleanup we just
1524    expanded; to avoid running it twice if it throws, we look through the
1525    ehqueue for a matching region and rethrow from its outer_context.  */
1526
1527 void
1528 expand_fixup_region_end (cleanup)
1529      tree cleanup;
1530 {
1531   struct eh_node *node;
1532   int dont_issue;
1533
1534   if (! doing_eh (0) || exceptions_via_longjmp)
1535     return;
1536
1537   for (node = ehstack.top; node && node->entry->finalization != cleanup; )
1538     node = node->chain;
1539   if (node == 0)
1540     for (node = ehqueue.head; node && node->entry->finalization != cleanup; )
1541       node = node->chain;
1542   if (node == 0)
1543     abort ();
1544
1545   /* If the outer context label has not been issued yet, we don't want
1546      to issue it as a part of this region, unless this is the
1547      correct region for the outer context. If we did, then the label for
1548      the outer context will be WITHIN the begin/end labels, 
1549      and we could get an infinte loop when it tried to rethrow, or just
1550      generally incorrect execution following a throw. */
1551
1552   if (flag_new_exceptions)
1553     dont_issue = 0;
1554   else
1555     dont_issue = ((INSN_UID (node->entry->outer_context) == 0) 
1556                   && (ehstack.top->entry != node->entry));
1557
1558   ehstack.top->entry->outer_context = node->entry->outer_context;
1559
1560   /* Since we are rethrowing to the OUTER region, we know we don't need
1561      a jump around sequence for this region, so we'll pretend the outer 
1562      context label has been issued by setting INSN_UID to 1, then clearing
1563      it again afterwards. */
1564
1565   if (dont_issue)
1566     INSN_UID (node->entry->outer_context) = 1;
1567
1568   /* Just rethrow.  size_zero_node is just a NOP.  */
1569   expand_eh_region_end (size_zero_node);
1570
1571   if (dont_issue)
1572     INSN_UID (node->entry->outer_context) = 0;
1573 }
1574
1575 /* If we are using the setjmp/longjmp EH codegen method, we emit a
1576    call to __sjthrow.
1577
1578    Otherwise, we emit a call to __throw and note that we threw
1579    something, so we know we need to generate the necessary code for
1580    __throw.
1581
1582    Before invoking throw, the __eh_pc variable must have been set up
1583    to contain the PC being thrown from. This address is used by
1584    __throw to determine which exception region (if any) is
1585    responsible for handling the exception.  */
1586
1587 void
1588 emit_throw ()
1589 {
1590   if (exceptions_via_longjmp)
1591     {
1592       emit_library_call (sjthrow_libfunc, 0, VOIDmode, 0);
1593     }
1594   else
1595     {
1596 #ifdef JUMP_TO_THROW
1597       emit_indirect_jump (throw_libfunc);
1598 #else
1599       emit_library_call (throw_libfunc, 0, VOIDmode, 0);
1600 #endif
1601     }
1602   emit_barrier ();
1603 }
1604
1605 /* Throw the current exception.  If appropriate, this is done by jumping
1606    to the next handler.  */
1607
1608 void
1609 expand_internal_throw ()
1610 {
1611   emit_throw ();
1612 }
1613
1614 /* Called from expand_exception_blocks and expand_end_catch_block to
1615    emit any pending handlers/cleanups queued from expand_eh_region_end.  */
1616
1617 void
1618 expand_leftover_cleanups ()
1619 {
1620   struct eh_entry *entry;
1621
1622   while ((entry = dequeue_eh_entry (&ehqueue)) != 0)
1623     {
1624       rtx prev;
1625
1626       /* A leftover try block. Shouldn't be one here.  */
1627       if (entry->finalization == integer_zero_node)
1628         abort ();
1629
1630       /* Output the label for the start of the exception handler.  */
1631
1632       receive_exception_label (entry->exception_handler_label);
1633
1634       /* register a handler for this cleanup region */
1635       add_new_handler (
1636         find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)), 
1637         get_new_handler (entry->exception_handler_label, NULL));
1638
1639       /* And now generate the insns for the handler.  */
1640       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
1641
1642       prev = get_last_insn ();
1643       if (prev == NULL || GET_CODE (prev) != BARRIER)
1644         /* Emit code to throw to the outer context if we fall off
1645            the end of the handler.  */
1646         expand_rethrow (entry->outer_context);
1647
1648       do_pending_stack_adjust ();
1649       free (entry);
1650     }
1651 }
1652
1653 /* Called at the start of a block of try statements.  */
1654 void
1655 expand_start_try_stmts ()
1656 {
1657   if (! doing_eh (1))
1658     return;
1659
1660   expand_eh_region_start ();
1661 }
1662
1663 /* Called to begin a catch clause. The parameter is the object which
1664    will be passed to the runtime type check routine. */
1665 void 
1666 start_catch_handler (rtime)
1667      tree rtime;
1668 {
1669   rtx handler_label;
1670   int insn_region_num;
1671   int eh_region_entry;
1672
1673   if (! doing_eh (1))
1674     return;
1675
1676   handler_label = catchstack.top->entry->exception_handler_label;
1677   insn_region_num = CODE_LABEL_NUMBER (handler_label);
1678   eh_region_entry = find_func_region (insn_region_num);
1679
1680   /* If we've already issued this label, pick a new one */
1681   if (catchstack.top->entry->label_used)
1682     handler_label = gen_exception_label ();
1683   else
1684     catchstack.top->entry->label_used = 1;
1685
1686   receive_exception_label (handler_label);
1687
1688   add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime));
1689
1690   if (flag_new_exceptions && ! exceptions_via_longjmp)
1691     return;
1692
1693   /* Under the old mechanism, as well as setjmp/longjmp, we need to
1694      issue code to compare 'rtime' to the value in eh_info, via the
1695      matching function in eh_info. If its is false, we branch around
1696      the handler we are about to issue. */
1697
1698   if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE)
1699     {
1700       rtx call_rtx, rtime_address;
1701
1702       if (catchstack.top->entry->false_label != NULL_RTX)
1703         {
1704           error ("Never issued previous false_label");
1705           abort ();
1706         }
1707       catchstack.top->entry->false_label = gen_exception_label ();
1708
1709       rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER);
1710 #ifdef POINTERS_EXTEND_UNSIGNED
1711       rtime_address = convert_memory_address (Pmode, rtime_address);
1712 #endif
1713       rtime_address = force_reg (Pmode, rtime_address);
1714
1715       /* Now issue the call, and branch around handler if needed */
1716       call_rtx = emit_library_call_value (eh_rtime_match_libfunc, NULL_RTX, 
1717                                           0, SImode, 1, rtime_address, Pmode);
1718
1719       /* Did the function return true? */
1720       emit_cmp_and_jump_insns (call_rtx, const0_rtx, EQ, NULL_RTX,
1721                                GET_MODE (call_rtx), 0, 0,
1722                                catchstack.top->entry->false_label);
1723     }
1724 }
1725
1726 /* Called to end a catch clause. If we aren't using the new exception
1727    model tabel mechanism, we need to issue the branch-around label
1728    for the end of the catch block. */
1729
1730 void 
1731 end_catch_handler ()
1732 {
1733   if (! doing_eh (1))
1734     return;
1735
1736   if (flag_new_exceptions && ! exceptions_via_longjmp) 
1737     {
1738       emit_barrier ();
1739       return;
1740     }
1741   
1742   /* A NULL label implies the catch clause was a catch all or cleanup */
1743   if (catchstack.top->entry->false_label == NULL_RTX)
1744     return;
1745
1746   emit_label (catchstack.top->entry->false_label);
1747   catchstack.top->entry->false_label = NULL_RTX;
1748 }
1749
1750 /* Generate RTL for the start of a group of catch clauses. 
1751
1752    It is responsible for starting a new instruction sequence for the
1753    instructions in the catch block, and expanding the handlers for the
1754    internally-generated exception regions nested within the try block
1755    corresponding to this catch block.  */
1756
1757 void
1758 expand_start_all_catch ()
1759 {
1760   struct eh_entry *entry;
1761   tree label;
1762   rtx outer_context;
1763
1764   if (! doing_eh (1))
1765     return;
1766
1767   outer_context = ehstack.top->entry->outer_context;
1768
1769   /* End the try block.  */
1770   expand_eh_region_end (integer_zero_node);
1771
1772   emit_line_note (input_filename, lineno);
1773   label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
1774
1775   /* The label for the exception handling block that we will save.
1776      This is Lresume in the documentation.  */
1777   expand_label (label);
1778   
1779   /* Push the label that points to where normal flow is resumed onto
1780      the top of the label stack.  */
1781   push_label_entry (&caught_return_label_stack, NULL_RTX, label);
1782
1783   /* Start a new sequence for all the catch blocks.  We will add this
1784      to the global sequence catch_clauses when we have completed all
1785      the handlers in this handler-seq.  */
1786   start_sequence ();
1787
1788   entry = dequeue_eh_entry (&ehqueue);
1789   for ( ; entry->finalization != integer_zero_node;
1790                                  entry = dequeue_eh_entry (&ehqueue))
1791     {
1792       rtx prev;
1793
1794       /* Emit the label for the cleanup handler for this region, and
1795          expand the code for the handler. 
1796
1797          Note that a catch region is handled as a side-effect here;
1798          for a try block, entry->finalization will contain
1799          integer_zero_node, so no code will be generated in the
1800          expand_expr call below. But, the label for the handler will
1801          still be emitted, so any code emitted after this point will
1802          end up being the handler.  */
1803       
1804       receive_exception_label (entry->exception_handler_label);
1805
1806       /* register a handler for this cleanup region */
1807       add_new_handler (
1808         find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)), 
1809         get_new_handler (entry->exception_handler_label, NULL));
1810
1811       /* And now generate the insns for the cleanup handler.  */
1812       expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
1813
1814       prev = get_last_insn ();
1815       if (prev == NULL || GET_CODE (prev) != BARRIER)
1816         /* Code to throw out to outer context when we fall off end
1817            of the handler. We can't do this here for catch blocks,
1818            so it's done in expand_end_all_catch instead.  */
1819         expand_rethrow (entry->outer_context);
1820
1821       do_pending_stack_adjust ();
1822       free (entry);
1823     }
1824
1825   /* At this point, all the cleanups are done, and the ehqueue now has
1826      the current exception region at its head. We dequeue it, and put it
1827      on the catch stack. */
1828
1829     push_entry (&catchstack, entry);
1830
1831   /* If we are not doing setjmp/longjmp EH, because we are reordered
1832      out of line, we arrange to rethrow in the outer context.  We need to
1833      do this because we are not physically within the region, if any, that
1834      logically contains this catch block.  */
1835   if (! exceptions_via_longjmp)
1836     {
1837       expand_eh_region_start ();
1838       ehstack.top->entry->outer_context = outer_context;
1839     }
1840
1841 }
1842
1843 /* Finish up the catch block.  At this point all the insns for the
1844    catch clauses have already been generated, so we only have to add
1845    them to the catch_clauses list. We also want to make sure that if
1846    we fall off the end of the catch clauses that we rethrow to the
1847    outer EH region.  */
1848
1849 void
1850 expand_end_all_catch ()
1851 {
1852   rtx new_catch_clause;
1853   struct eh_entry *entry;
1854
1855   if (! doing_eh (1))
1856     return;
1857
1858   /* Dequeue the current catch clause region. */
1859   entry = pop_eh_entry (&catchstack);
1860   free (entry);
1861
1862   if (! exceptions_via_longjmp)
1863     {
1864       rtx outer_context = ehstack.top->entry->outer_context;
1865
1866       /* Finish the rethrow region.  size_zero_node is just a NOP.  */
1867       expand_eh_region_end (size_zero_node);
1868       /* New exceptions handling models will never have a fall through
1869          of a catch clause */
1870       if (!flag_new_exceptions)
1871         expand_rethrow (outer_context);
1872     }
1873   else 
1874     expand_rethrow (NULL_RTX);
1875
1876   /* Code to throw out to outer context, if we fall off end of catch
1877      handlers.  This is rethrow (Lresume, same id, same obj) in the
1878      documentation. We use Lresume because we know that it will throw
1879      to the correct context.
1880
1881      In other words, if the catch handler doesn't exit or return, we
1882      do a "throw" (using the address of Lresume as the point being
1883      thrown from) so that the outer EH region can then try to process
1884      the exception.  */
1885
1886   /* Now we have the complete catch sequence.  */
1887   new_catch_clause = get_insns ();
1888   end_sequence ();
1889   
1890   /* This level of catch blocks is done, so set up the successful
1891      catch jump label for the next layer of catch blocks.  */
1892   pop_label_entry (&caught_return_label_stack);
1893   pop_label_entry (&outer_context_label_stack);
1894
1895   /* Add the new sequence of catches to the main one for this function.  */
1896   push_to_sequence (catch_clauses);
1897   emit_insns (new_catch_clause);
1898   catch_clauses = get_insns ();
1899   end_sequence ();
1900   
1901   /* Here we fall through into the continuation code.  */
1902 }
1903
1904 /* Rethrow from the outer context LABEL.  */
1905
1906 static void
1907 expand_rethrow (label)
1908      rtx label;
1909 {
1910   if (exceptions_via_longjmp)
1911     emit_throw ();
1912   else
1913     if (flag_new_exceptions)
1914       {
1915         rtx insn;
1916         int region;
1917         if (label == NULL_RTX)
1918           label = last_rethrow_symbol;
1919         emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
1920         region = find_func_region (eh_region_from_symbol (label));
1921         function_eh_regions[region].rethrow_ref = 1;
1922
1923         /* Search backwards for the actual call insn.  */
1924         insn = get_last_insn ();
1925         while (GET_CODE (insn) != CALL_INSN)
1926           insn = PREV_INSN (insn);
1927         delete_insns_since (insn);
1928
1929         /* Mark the label/symbol on the call. */
1930         REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, label,
1931                                               REG_NOTES (insn));
1932         emit_barrier ();
1933       }
1934     else
1935       emit_jump (label);
1936 }
1937
1938 /* End all the pending exception regions on protect_list. The handlers
1939    will be emitted when expand_leftover_cleanups is invoked.  */
1940
1941 void
1942 end_protect_partials ()
1943 {
1944   while (protect_list)
1945     {
1946       expand_eh_region_end (TREE_VALUE (protect_list));
1947       protect_list = TREE_CHAIN (protect_list);
1948     }
1949 }
1950
1951 /* Arrange for __terminate to be called if there is an unhandled throw
1952    from within E.  */
1953
1954 tree
1955 protect_with_terminate (e)
1956      tree e;
1957 {
1958   /* We only need to do this when using setjmp/longjmp EH and the
1959      language requires it, as otherwise we protect all of the handlers
1960      at once, if we need to.  */
1961   if (exceptions_via_longjmp && protect_cleanup_actions_with_terminate)
1962     {
1963       tree handler, result;
1964
1965       /* All cleanups must be on the function_obstack.  */
1966       push_obstacks_nochange ();
1967       resume_temporary_allocation ();
1968
1969       handler = make_node (RTL_EXPR);
1970       TREE_TYPE (handler) = void_type_node;
1971       RTL_EXPR_RTL (handler) = const0_rtx;
1972       TREE_SIDE_EFFECTS (handler) = 1;
1973       start_sequence_for_rtl_expr (handler);
1974
1975       emit_library_call (terminate_libfunc, 0, VOIDmode, 0);
1976       emit_barrier ();
1977
1978       RTL_EXPR_SEQUENCE (handler) = get_insns ();
1979       end_sequence ();
1980         
1981       result = build (TRY_CATCH_EXPR, TREE_TYPE (e), e, handler);
1982       TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
1983       TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
1984       TREE_READONLY (result) = TREE_READONLY (e);
1985
1986       pop_obstacks ();
1987
1988       e = result;
1989     }
1990
1991   return e;
1992 }
1993 \f
1994 /* The exception table that we build that is used for looking up and
1995    dispatching exceptions, the current number of entries, and its
1996    maximum size before we have to extend it. 
1997
1998    The number in eh_table is the code label number of the exception
1999    handler for the region. This is added by add_eh_table_entry and
2000    used by output_exception_table_entry.  */
2001
2002 static int *eh_table = NULL;
2003 static int eh_table_size = 0;
2004 static int eh_table_max_size = 0;
2005
2006 /* Note the need for an exception table entry for region N.  If we
2007    don't need to output an explicit exception table, avoid all of the
2008    extra work.
2009
2010    Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG is seen.
2011    (Or NOTE_INSN_EH_REGION_END sometimes)
2012    N is the NOTE_BLOCK_NUMBER of the note, which comes from the code
2013    label number of the exception handler for the region.  */
2014
2015 void
2016 add_eh_table_entry (n)
2017      int n;
2018 {
2019 #ifndef OMIT_EH_TABLE
2020   if (eh_table_size >= eh_table_max_size)
2021     {
2022       if (eh_table)
2023         {
2024           eh_table_max_size += eh_table_max_size>>1;
2025
2026           if (eh_table_max_size < 0)
2027             abort ();
2028
2029           eh_table = (int *) xrealloc (eh_table,
2030                                        eh_table_max_size * sizeof (int));
2031         }
2032       else
2033         {
2034           eh_table_max_size = 252;
2035           eh_table = (int *) xmalloc (eh_table_max_size * sizeof (int));
2036         }
2037     }
2038   eh_table[eh_table_size++] = n;
2039 #endif
2040 }
2041
2042 /* Return a non-zero value if we need to output an exception table.
2043
2044    On some platforms, we don't have to output a table explicitly.
2045    This routine doesn't mean we don't have one.  */
2046
2047 int
2048 exception_table_p ()
2049 {
2050   if (eh_table)
2051     return 1;
2052
2053   return 0;
2054 }
2055
2056 /* Output the entry of the exception table corresponding to the
2057    exception region numbered N to file FILE. 
2058
2059    N is the code label number corresponding to the handler of the
2060    region.  */
2061
2062 static void
2063 output_exception_table_entry (file, n)
2064      FILE *file;
2065      int n;
2066 {
2067   char buf[256];
2068   rtx sym;
2069   struct handler_info *handler = get_first_handler (n);
2070   int index = find_func_region (n);
2071   rtx rethrow;
2072   
2073  /* form and emit the rethrow label, if needed  */
2074   rethrow = function_eh_regions[index].rethrow_label;
2075   if (rethrow != NULL_RTX && !flag_new_exceptions)
2076       rethrow = NULL_RTX;
2077   if (rethrow != NULL_RTX && handler == NULL)
2078     if (! function_eh_regions[index].rethrow_ref)
2079       rethrow = NULL_RTX;
2080
2081
2082   for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
2083     {
2084       /* rethrow label should indicate the LAST entry for a region */
2085       if (rethrow != NULL_RTX && (handler == NULL || handler->next == NULL))
2086         {
2087           ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", n);
2088           assemble_label(buf);
2089           rethrow = NULL_RTX;
2090         }
2091
2092       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
2093       sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2094       assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2095
2096       ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", n);
2097       sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2098       assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2099       
2100       if (handler == NULL)
2101         assemble_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
2102       else
2103         {
2104           ASM_GENERATE_INTERNAL_LABEL (buf, "L", handler->handler_number);
2105           sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2106           assemble_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2107         }
2108
2109       if (flag_new_exceptions)
2110         {
2111           if (handler == NULL || handler->type_info == NULL)
2112             assemble_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2113           else
2114             if (handler->type_info == CATCH_ALL_TYPE)
2115               assemble_integer (GEN_INT (CATCH_ALL_TYPE), 
2116                                              POINTER_SIZE / BITS_PER_UNIT, 1);
2117             else
2118               output_constant ((tree)(handler->type_info), 
2119                                                 POINTER_SIZE / BITS_PER_UNIT);
2120         }
2121       putc ('\n', file);                /* blank line */
2122       /* We only output the first label under the old scheme */
2123       if (! flag_new_exceptions || handler == NULL)
2124         break;
2125     }
2126 }
2127
2128 /* Output the exception table if we have and need one.  */
2129
2130 static short language_code = 0;
2131 static short version_code = 0; 
2132
2133 /* This routine will set the language code for exceptions. */
2134 void
2135 set_exception_lang_code (code)
2136      int code;
2137 {
2138   language_code = code;
2139 }
2140
2141 /* This routine will set the language version code for exceptions. */
2142 void
2143 set_exception_version_code (code)
2144      int code;
2145 {
2146   version_code = code;
2147 }
2148
2149
2150 void
2151 output_exception_table ()
2152 {
2153   int i;
2154   char buf[256];
2155   extern FILE *asm_out_file;
2156
2157   if (! doing_eh (0) || ! eh_table)
2158     return;
2159
2160   exception_section ();
2161
2162   /* Beginning marker for table.  */
2163   assemble_align (GET_MODE_ALIGNMENT (ptr_mode));
2164   assemble_label ("__EXCEPTION_TABLE__");
2165
2166   if (flag_new_exceptions)
2167     {
2168       assemble_integer (GEN_INT (NEW_EH_RUNTIME), 
2169                                         POINTER_SIZE / BITS_PER_UNIT, 1);
2170       assemble_integer (GEN_INT (language_code), 2 , 1); 
2171       assemble_integer (GEN_INT (version_code), 2 , 1);
2172
2173       /* Add enough padding to make sure table aligns on a pointer boundry. */
2174       i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4;
2175       for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT)
2176         ;
2177       if (i != 0)
2178         assemble_integer (const0_rtx, i , 1);
2179
2180       /* Generate the label for offset calculations on rethrows */
2181       ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
2182       assemble_label(buf);
2183     }
2184
2185   for (i = 0; i < eh_table_size; ++i)
2186     output_exception_table_entry (asm_out_file, eh_table[i]);
2187
2188   free (eh_table);
2189   clear_function_eh_region ();
2190
2191   /* Ending marker for table.  */
2192   /* Generate the label for end of table. */
2193   ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", CODE_LABEL_NUMBER (final_rethrow));
2194   assemble_label(buf);
2195   assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2196
2197   /* for binary compatability, the old __throw checked the second
2198      position for a -1, so we should output at least 2 -1's */
2199   if (! flag_new_exceptions)
2200     assemble_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2201
2202   putc ('\n', asm_out_file);            /* blank line */
2203 }
2204 \f
2205 /* Emit code to get EH context.
2206    
2207    We have to scan thru the code to find possible EH context registers.
2208    Inlined functions may use it too, and thus we'll have to be able
2209    to change them too.
2210
2211    This is done only if using exceptions_via_longjmp. */
2212
2213 void
2214 emit_eh_context ()
2215 {
2216   rtx insn;
2217   rtx ehc = 0;
2218
2219   if (! doing_eh (0))
2220     return;
2221
2222   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2223     if (GET_CODE (insn) == INSN
2224         && GET_CODE (PATTERN (insn)) == USE)
2225       {
2226         rtx reg = find_reg_note (insn, REG_EH_CONTEXT, 0);
2227         if (reg)
2228           {
2229             rtx insns;
2230             
2231             start_sequence ();
2232
2233             /* If this is the first use insn, emit the call here.  This
2234                will always be at the top of our function, because if
2235                expand_inline_function notices a REG_EH_CONTEXT note, it
2236                adds a use insn to this function as well.  */
2237             if (ehc == 0)
2238               ehc = call_get_eh_context ();
2239
2240             emit_move_insn (XEXP (reg, 0), ehc);
2241             insns = get_insns ();
2242             end_sequence ();
2243
2244             emit_insns_before (insns, insn);
2245
2246             /* At -O0, we must make the context register stay alive so
2247                that the stupid.c register allocator doesn't get confused. */
2248             if (obey_regdecls != 0)
2249               {
2250                 insns = gen_rtx_USE (GET_MODE (XEXP (reg,0)), XEXP (reg,0));
2251                 emit_insn_before (insns, get_last_insn ());
2252               }
2253           }
2254       }
2255 }
2256
2257 /* Scan the current insns and build a list of handler labels. The
2258    resulting list is placed in the global variable exception_handler_labels.
2259
2260    It is called after the last exception handling region is added to
2261    the current function (when the rtl is almost all built for the
2262    current function) and before the jump optimization pass.  */
2263
2264 void
2265 find_exception_handler_labels ()
2266 {
2267   rtx insn;
2268
2269   exception_handler_labels = NULL_RTX;
2270
2271   /* If we aren't doing exception handling, there isn't much to check.  */
2272   if (! doing_eh (0))
2273     return;
2274
2275   /* For each start of a region, add its label to the list.  */
2276
2277   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2278     {
2279       struct handler_info* ptr;
2280       if (GET_CODE (insn) == NOTE
2281           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2282         {
2283           ptr = get_first_handler (NOTE_BLOCK_NUMBER (insn));
2284           for ( ; ptr; ptr = ptr->next) 
2285             {
2286               /* make sure label isn't in the list already */
2287               rtx x;
2288               for (x = exception_handler_labels; x; x = XEXP (x, 1))
2289                 if (XEXP (x, 0) == ptr->handler_label)
2290                   break;
2291               if (! x)
2292                 exception_handler_labels = gen_rtx_EXPR_LIST (VOIDmode,
2293                                ptr->handler_label, exception_handler_labels);
2294             }
2295         }
2296     }
2297 }
2298
2299 /* Return a value of 1 if the parameter label number is an exception handler
2300    label. Return 0 otherwise. */
2301
2302 int
2303 is_exception_handler_label (lab)
2304      int lab;
2305 {
2306   rtx x;
2307   for (x = exception_handler_labels ; x ; x = XEXP (x, 1))
2308     if (lab == CODE_LABEL_NUMBER (XEXP (x, 0)))
2309       return 1;
2310   return 0;
2311 }
2312
2313 /* Perform sanity checking on the exception_handler_labels list.
2314
2315    Can be called after find_exception_handler_labels is called to
2316    build the list of exception handlers for the current function and
2317    before we finish processing the current function.  */
2318
2319 void
2320 check_exception_handler_labels ()
2321 {
2322   rtx insn, insn2;
2323
2324   /* If we aren't doing exception handling, there isn't much to check.  */
2325   if (! doing_eh (0))
2326     return;
2327
2328   /* Make sure there is no more than 1 copy of a label */
2329   for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
2330     {
2331       int count = 0;
2332       for (insn2 = exception_handler_labels; insn2; insn2 = XEXP (insn2, 1))
2333         if (XEXP (insn, 0) == XEXP (insn2, 0))
2334           count++;
2335       if (count != 1)
2336        warning ("Counted %d copies of EH region %d in list.\n", count, 
2337                                         CODE_LABEL_NUMBER (insn));
2338     }
2339
2340 }
2341
2342 /* Mark the children of NODE for GC.  */
2343
2344 static void
2345 mark_eh_node (node)
2346      struct eh_node *node;
2347 {
2348   while (node)
2349     {
2350       if (node->entry)
2351         {
2352           ggc_mark_rtx (node->entry->outer_context);
2353           ggc_mark_rtx (node->entry->exception_handler_label);
2354           ggc_mark_tree (node->entry->finalization);
2355         }
2356       node = node ->chain;
2357     }
2358 }
2359
2360 /* Mark S for GC.  */
2361
2362 static void
2363 mark_eh_stack (s)
2364      struct eh_stack *s;
2365 {
2366   if (s)
2367     mark_eh_node (s->top);
2368 }
2369
2370 /* Mark Q for GC.  */
2371
2372 static void
2373 mark_eh_queue (q)
2374      struct eh_queue *q;
2375 {
2376   if (q)
2377     mark_eh_node (q->head);
2378 }
2379
2380 /* Mark NODE for GC.  A label_node contains a union containing either
2381    a tree or an rtx.  This label_node will contain a tree.  */
2382
2383 static void
2384 mark_tree_label_node (node)
2385      struct label_node *node;
2386 {
2387   while (node)
2388     {
2389       ggc_mark_tree (node->u.tlabel);
2390       node = node->chain;
2391     }
2392 }
2393
2394 /* Mark EH for GC.  */
2395
2396 void
2397 mark_eh_state (eh)
2398      struct eh_status *eh;
2399 {
2400   mark_eh_stack (&eh->x_ehstack);
2401   mark_eh_queue (&eh->x_ehqueue);
2402   ggc_mark_rtx (eh->x_catch_clauses);
2403
2404   lang_mark_false_label_stack (eh->x_false_label_stack);
2405   mark_tree_label_node (eh->x_caught_return_label_stack);
2406
2407   ggc_mark_tree (eh->x_protect_list);
2408   ggc_mark_rtx (eh->ehc);
2409 }
2410
2411 /* This group of functions initializes the exception handling data
2412    structures at the start of the compilation, initializes the data
2413    structures at the start of a function, and saves and restores the
2414    exception handling data structures for the start/end of a nested
2415    function.  */
2416
2417 /* Toplevel initialization for EH things.  */ 
2418
2419 void
2420 init_eh ()
2421 {
2422   first_rethrow_symbol = create_rethrow_ref (0);
2423   final_rethrow = gen_exception_label ();
2424   last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow));
2425 }
2426
2427 /* Initialize the per-function EH information.  */
2428
2429 void
2430 init_eh_for_function ()
2431 {
2432   current_function->eh = (struct eh_status *) xmalloc (sizeof (struct eh_status));
2433
2434   ehstack.top = 0;
2435   catchstack.top = 0;
2436   ehqueue.head = ehqueue.tail = 0;
2437   catch_clauses = NULL_RTX;
2438   false_label_stack = 0;
2439   caught_return_label_stack = 0;
2440   protect_list = NULL_TREE;
2441   current_function_ehc = NULL_RTX;
2442   eh_return_context = NULL_RTX;
2443   eh_return_stack_adjust = NULL_RTX;
2444   eh_return_handler = NULL_RTX;
2445   eh_return_stub_label = NULL_RTX;
2446 }
2447 \f
2448 /* This section is for the exception handling specific optimization
2449    pass.  First are the internal routines, and then the main
2450    optimization pass.  */
2451
2452 /* Determine if the given INSN can throw an exception.  */
2453
2454 static int
2455 can_throw (insn)
2456      rtx insn;
2457 {
2458   /* Calls can always potentially throw exceptions, unless they have
2459      a REG_EH_REGION note with a value of 0 or less.  */
2460   if (GET_CODE (insn) == CALL_INSN)
2461     {
2462       rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2463       if (!note || XINT (XEXP (note, 0), 0) > 0)
2464         return 1;
2465     }
2466
2467   if (asynchronous_exceptions)
2468     {
2469       /* If we wanted asynchronous exceptions, then everything but NOTEs
2470          and CODE_LABELs could throw.  */
2471       if (GET_CODE (insn) != NOTE && GET_CODE (insn) != CODE_LABEL)
2472         return 1;
2473     }
2474
2475   return 0;
2476 }
2477
2478 /* Scan a exception region looking for the matching end and then
2479    remove it if possible. INSN is the start of the region, N is the
2480    region number, and DELETE_OUTER is to note if anything in this
2481    region can throw.
2482
2483    Regions are removed if they cannot possibly catch an exception.
2484    This is determined by invoking can_throw on each insn within the
2485    region; if can_throw returns true for any of the instructions, the
2486    region can catch an exception, since there is an insn within the
2487    region that is capable of throwing an exception.
2488
2489    Returns the NOTE_INSN_EH_REGION_END corresponding to this region, or
2490    calls abort if it can't find one.
2491
2492    Can abort if INSN is not a NOTE_INSN_EH_REGION_BEGIN, or if N doesn't
2493    correspond to the region number, or if DELETE_OUTER is NULL.  */
2494
2495 static rtx
2496 scan_region (insn, n, delete_outer)
2497      rtx insn;
2498      int n;
2499      int *delete_outer;
2500 {
2501   rtx start = insn;
2502
2503   /* Assume we can delete the region.  */
2504   int delete = 1;
2505
2506   /* Can't delete something which is rethrown to. */
2507   if (rethrow_used (n))
2508     delete = 0;
2509
2510   if (insn == NULL_RTX
2511       || GET_CODE (insn) != NOTE
2512       || NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
2513       || NOTE_BLOCK_NUMBER (insn) != n
2514       || delete_outer == NULL)
2515     abort ();
2516
2517   insn = NEXT_INSN (insn);
2518
2519   /* Look for the matching end.  */
2520   while (! (GET_CODE (insn) == NOTE
2521             && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
2522     {
2523       /* If anything can throw, we can't remove the region.  */
2524       if (delete && can_throw (insn))
2525         {
2526           delete = 0;
2527         }
2528
2529       /* Watch out for and handle nested regions.  */
2530       if (GET_CODE (insn) == NOTE
2531           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2532         {
2533           insn = scan_region (insn, NOTE_BLOCK_NUMBER (insn), &delete);
2534         }
2535
2536       insn = NEXT_INSN (insn);
2537     }
2538
2539   /* The _BEG/_END NOTEs must match and nest.  */
2540   if (NOTE_BLOCK_NUMBER (insn) != n)
2541     abort ();
2542
2543   /* If anything in this exception region can throw, we can throw.  */
2544   if (! delete)
2545     *delete_outer = 0;
2546   else
2547     {
2548       /* Delete the start and end of the region.  */
2549       delete_insn (start);
2550       delete_insn (insn);
2551
2552 /* We no longer removed labels here, since flow will now remove any
2553    handler which cannot be called any more. */
2554    
2555 #if 0
2556       /* Only do this part if we have built the exception handler
2557          labels.  */
2558       if (exception_handler_labels)
2559         {
2560           rtx x, *prev = &exception_handler_labels;
2561
2562           /* Find it in the list of handlers.  */
2563           for (x = exception_handler_labels; x; x = XEXP (x, 1))
2564             {
2565               rtx label = XEXP (x, 0);
2566               if (CODE_LABEL_NUMBER (label) == n)
2567                 {
2568                   /* If we are the last reference to the handler,
2569                      delete it.  */
2570                   if (--LABEL_NUSES (label) == 0)
2571                     delete_insn (label);
2572
2573                   if (optimize)
2574                     {
2575                       /* Remove it from the list of exception handler
2576                          labels, if we are optimizing.  If we are not, then
2577                          leave it in the list, as we are not really going to
2578                          remove the region.  */
2579                       *prev = XEXP (x, 1);
2580                       XEXP (x, 1) = 0;
2581                       XEXP (x, 0) = 0;
2582                     }
2583
2584                   break;
2585                 }
2586               prev = &XEXP (x, 1);
2587             }
2588         }
2589 #endif
2590     }
2591   return insn;
2592 }
2593
2594 /* Perform various interesting optimizations for exception handling
2595    code.
2596
2597    We look for empty exception regions and make them go (away). The
2598    jump optimization code will remove the handler if nothing else uses
2599    it.  */
2600
2601 void
2602 exception_optimize ()
2603 {
2604   rtx insn;
2605   int n;
2606
2607   /* Remove empty regions.  */
2608   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2609     {
2610       if (GET_CODE (insn) == NOTE
2611           && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2612         {
2613           /* Since scan_region will return the NOTE_INSN_EH_REGION_END
2614              insn, we will indirectly skip through all the insns
2615              inbetween. We are also guaranteed that the value of insn
2616              returned will be valid, as otherwise scan_region won't
2617              return.  */
2618           insn = scan_region (insn, NOTE_BLOCK_NUMBER (insn), &n);
2619         }
2620     }
2621 }
2622
2623 /* This function determines whether any of the exception regions in the
2624    current function are targets of a rethrow or not, and set the 
2625    reference flag according.  */
2626 void
2627 update_rethrow_references ()
2628 {
2629   rtx insn;
2630   int x, region;
2631   int *saw_region, *saw_rethrow;
2632
2633   if (!flag_new_exceptions)
2634     return;
2635
2636   saw_region = (int *) alloca (current_func_eh_entry * sizeof (int));
2637   saw_rethrow = (int *) alloca (current_func_eh_entry * sizeof (int));
2638   bzero ((char *) saw_region, (current_func_eh_entry * sizeof (int)));
2639   bzero ((char *) saw_rethrow, (current_func_eh_entry * sizeof (int)));
2640
2641   /* Determine what regions exist, and whether there are any rethrows
2642      to those regions or not.  */
2643   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2644     if (GET_CODE (insn) == CALL_INSN)
2645       {
2646         rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
2647         if (note)
2648           {
2649             region = eh_region_from_symbol (XEXP (note, 0));
2650             region = find_func_region  (region);
2651             saw_rethrow[region] = 1;
2652           }
2653       }
2654     else
2655       if (GET_CODE (insn) == NOTE)
2656         {
2657           if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2658             {
2659               region = find_func_region (NOTE_BLOCK_NUMBER (insn));
2660               saw_region[region] = 1;
2661             }
2662         }
2663
2664   /* For any regions we did see, set the referenced flag.  */
2665   for (x = 0; x < current_func_eh_entry; x++)
2666     if (saw_region[x])
2667       function_eh_regions[x].rethrow_ref = saw_rethrow[x];
2668 }
2669 \f
2670 /* Various hooks for the DWARF 2 __throw routine.  */
2671
2672 /* Do any necessary initialization to access arbitrary stack frames.
2673    On the SPARC, this means flushing the register windows.  */
2674
2675 void
2676 expand_builtin_unwind_init ()
2677 {
2678   /* Set this so all the registers get saved in our frame; we need to be
2679      able to copy the saved values for any registers from frames we unwind. */
2680   current_function_has_nonlocal_label = 1;
2681
2682 #ifdef SETUP_FRAME_ADDRESSES
2683   SETUP_FRAME_ADDRESSES ();
2684 #endif
2685 }
2686
2687 /* Given a value extracted from the return address register or stack slot,
2688    return the actual address encoded in that value.  */
2689
2690 rtx
2691 expand_builtin_extract_return_addr (addr_tree)
2692      tree addr_tree;
2693 {
2694   rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
2695   return eh_outer_context (addr);
2696 }
2697
2698 /* Given an actual address in addr_tree, do any necessary encoding
2699    and return the value to be stored in the return address register or
2700    stack slot so the epilogue will return to that address.  */
2701
2702 rtx
2703 expand_builtin_frob_return_addr (addr_tree)
2704      tree addr_tree;
2705 {
2706   rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
2707 #ifdef RETURN_ADDR_OFFSET
2708   addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
2709 #endif
2710   return addr;
2711 }
2712
2713 /* Choose three registers for communication between the main body of
2714    __throw and the epilogue (or eh stub) and the exception handler. 
2715    We must do this with hard registers because the epilogue itself
2716    will be generated after reload, at which point we may not reference
2717    pseudos at all.
2718
2719    The first passes the exception context to the handler.  For this
2720    we use the return value register for a void*.
2721
2722    The second holds the stack pointer value to be restored.  For
2723    this we use the static chain register if it exists and is different
2724    from the previous, otherwise some arbitrary call-clobbered register.
2725
2726    The third holds the address of the handler itself.  Here we use
2727    some arbitrary call-clobbered register.  */
2728
2729 static void
2730 eh_regs (pcontext, psp, pra, outgoing)
2731      rtx *pcontext, *psp, *pra;
2732      int outgoing;
2733 {
2734   rtx rcontext, rsp, rra;
2735   int i;
2736
2737 #ifdef FUNCTION_OUTGOING_VALUE
2738   if (outgoing)
2739     rcontext = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
2740                                         current_function_decl);
2741   else
2742 #endif
2743     rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
2744                                current_function_decl);
2745
2746 #ifdef STATIC_CHAIN_REGNUM
2747   if (outgoing)
2748     rsp = static_chain_incoming_rtx;
2749   else
2750     rsp = static_chain_rtx;
2751   if (REGNO (rsp) == REGNO (rcontext))
2752 #endif /* STATIC_CHAIN_REGNUM */
2753     rsp = NULL_RTX;
2754
2755   if (rsp == NULL_RTX)
2756     {
2757       for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
2758         if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (rcontext))
2759           break;
2760       if (i == FIRST_PSEUDO_REGISTER)
2761         abort();
2762
2763       rsp = gen_rtx_REG (Pmode, i);
2764     }
2765
2766   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
2767     if (call_used_regs[i] && ! fixed_regs[i]
2768         && i != REGNO (rcontext) && i != REGNO (rsp))
2769       break;
2770   if (i == FIRST_PSEUDO_REGISTER)
2771     abort();
2772
2773   rra = gen_rtx_REG (Pmode, i);
2774
2775   *pcontext = rcontext;
2776   *psp = rsp;
2777   *pra = rra;
2778 }
2779
2780 /* Retrieve the register which contains the pointer to the eh_context
2781    structure set the __throw. */
2782
2783 rtx 
2784 get_reg_for_handler ()
2785 {
2786   rtx reg1;
2787   reg1 = FUNCTION_VALUE (build_pointer_type (void_type_node),
2788                            current_function_decl);
2789   return reg1;
2790 }
2791
2792 /* Set up the epilogue with the magic bits we'll need to return to the
2793    exception handler.  */
2794
2795 void
2796 expand_builtin_eh_return (context, stack, handler)
2797     tree context, stack, handler;
2798 {
2799   if (eh_return_context)
2800     error("Duplicate call to __builtin_eh_return");
2801
2802   eh_return_context
2803     = copy_to_reg (expand_expr (context, NULL_RTX, VOIDmode, 0));
2804   eh_return_stack_adjust
2805     = copy_to_reg (expand_expr (stack, NULL_RTX, VOIDmode, 0));
2806   eh_return_handler
2807     = copy_to_reg (expand_expr (handler, NULL_RTX, VOIDmode, 0));
2808 }
2809
2810 void
2811 expand_eh_return ()
2812 {
2813   rtx reg1, reg2, reg3;
2814   rtx stub_start, after_stub;
2815   rtx ra, tmp;
2816
2817   if (!eh_return_context)
2818     return;
2819
2820   current_function_cannot_inline = N_("function uses __builtin_eh_return");
2821
2822   eh_regs (&reg1, &reg2, &reg3, 1);
2823 #ifdef POINTERS_EXTEND_UNSIGNED
2824   eh_return_context = convert_memory_address (Pmode, eh_return_context);
2825   eh_return_stack_adjust = 
2826       convert_memory_address (Pmode, eh_return_stack_adjust);
2827   eh_return_handler = convert_memory_address (Pmode, eh_return_handler);
2828 #endif
2829   emit_move_insn (reg1, eh_return_context);
2830   emit_move_insn (reg2, eh_return_stack_adjust);
2831   emit_move_insn (reg3, eh_return_handler);
2832
2833   /* Talk directly to the target's epilogue code when possible.  */
2834
2835 #ifdef HAVE_eh_epilogue
2836   if (HAVE_eh_epilogue)
2837     {
2838       emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
2839       return;
2840     }
2841 #endif
2842
2843   /* Otherwise, use the same stub technique we had before.  */
2844
2845   eh_return_stub_label = stub_start = gen_label_rtx ();
2846   after_stub = gen_label_rtx ();
2847
2848   /* Set the return address to the stub label.  */
2849
2850   ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
2851                                    0, hard_frame_pointer_rtx);
2852   if (GET_CODE (ra) == REG && REGNO (ra) >= FIRST_PSEUDO_REGISTER)
2853     abort();
2854
2855   tmp = memory_address (Pmode, gen_rtx_LABEL_REF (Pmode, stub_start)); 
2856 #ifdef RETURN_ADDR_OFFSET
2857   tmp = plus_constant (tmp, -RETURN_ADDR_OFFSET);
2858 #endif
2859   tmp = force_operand (tmp, ra);
2860   if (tmp != ra)
2861     emit_move_insn (ra, tmp);
2862
2863   /* Indicate that the registers are in fact used.  */
2864   emit_insn (gen_rtx_USE (VOIDmode, reg1));
2865   emit_insn (gen_rtx_USE (VOIDmode, reg2));
2866   emit_insn (gen_rtx_USE (VOIDmode, reg3));
2867   if (GET_CODE (ra) == REG)
2868     emit_insn (gen_rtx_USE (VOIDmode, ra));
2869
2870   /* Generate the stub.  */
2871
2872   emit_jump (after_stub);
2873   emit_label (stub_start);
2874
2875   eh_regs (&reg1, &reg2, &reg3, 0);
2876   adjust_stack (reg2);
2877   emit_indirect_jump (reg3);
2878
2879   emit_label (after_stub);
2880 }
2881 \f
2882
2883 /* This contains the code required to verify whether arbitrary instructions
2884    are in the same exception region. */
2885
2886 static int *insn_eh_region = (int *)0;
2887 static int maximum_uid;
2888
2889 static void
2890 set_insn_eh_region (first, region_num)
2891      rtx *first;
2892      int region_num;
2893 {
2894   rtx insn;
2895   int rnum;
2896
2897   for (insn = *first; insn; insn = NEXT_INSN (insn))
2898     {
2899       if ((GET_CODE (insn) == NOTE) && 
2900                         (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG))
2901         {
2902           rnum = NOTE_BLOCK_NUMBER (insn);
2903           insn_eh_region[INSN_UID (insn)] =  rnum;
2904           insn = NEXT_INSN (insn);
2905           set_insn_eh_region (&insn, rnum);
2906           /* Upon return, insn points to the EH_REGION_END of nested region */
2907           continue;
2908         }
2909       insn_eh_region[INSN_UID (insn)] = region_num;
2910       if ((GET_CODE (insn) == NOTE) && 
2911             (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
2912         break;
2913     }
2914   *first = insn;
2915 }
2916
2917 /* Free the insn table, an make sure it cannot be used again. */
2918
2919 void 
2920 free_insn_eh_region () 
2921 {
2922   if (!doing_eh (0))
2923     return;
2924
2925   if (insn_eh_region)
2926     {
2927       free (insn_eh_region);
2928       insn_eh_region = (int *)0;
2929     }
2930 }
2931
2932 /* Initialize the table. max_uid must be calculated and handed into 
2933    this routine. If it is unavailable, passing a value of 0 will 
2934    cause this routine to calculate it as well. */
2935
2936 void 
2937 init_insn_eh_region (first, max_uid)
2938      rtx first;
2939      int max_uid;
2940 {
2941   rtx insn;
2942
2943   if (!doing_eh (0))
2944     return;
2945
2946   if (insn_eh_region)
2947     free_insn_eh_region();
2948
2949   if (max_uid == 0) 
2950     for (insn = first; insn; insn = NEXT_INSN (insn))
2951       if (INSN_UID (insn) > max_uid)       /* find largest UID */
2952         max_uid = INSN_UID (insn);
2953
2954   maximum_uid = max_uid;
2955   insn_eh_region = (int *) malloc ((max_uid + 1) * sizeof (int));
2956   insn = first;
2957   set_insn_eh_region (&insn, 0);
2958 }
2959
2960
2961 /* Check whether 2 instructions are within the same region. */
2962
2963 int 
2964 in_same_eh_region (insn1, insn2) 
2965      rtx insn1, insn2;
2966 {
2967   int ret, uid1, uid2;
2968
2969   /* If no exceptions, instructions are always in same region. */
2970   if (!doing_eh (0))
2971     return 1;
2972
2973   /* If the table isn't allocated, assume the worst. */
2974   if (!insn_eh_region)  
2975     return 0;
2976
2977   uid1 = INSN_UID (insn1);
2978   uid2 = INSN_UID (insn2);
2979
2980   /* if instructions have been allocated beyond the end, either
2981      the table is out of date, or this is a late addition, or
2982      something... Assume the worst. */
2983   if (uid1 > maximum_uid || uid2 > maximum_uid)
2984     return 0;
2985
2986   ret = (insn_eh_region[uid1] == insn_eh_region[uid2]);
2987   return ret;
2988 }
2989 \f
2990
2991 /* This function will initialize the handler list for a specified block.
2992    It may recursively call itself if the outer block hasn't been processed
2993    yet.  At some point in the future we can trim out handlers which we
2994    know cannot be called. (ie, if a block has an INT type handler,
2995    control will never be passed to an outer INT type handler).  */
2996 static void 
2997 process_nestinfo (block, info, nested_eh_region)
2998      int block;
2999      eh_nesting_info *info;
3000      int *nested_eh_region;
3001 {
3002   handler_info *ptr, *last_ptr = NULL;
3003   int x, y, count = 0;
3004   int extra = 0;
3005   handler_info **extra_handlers;
3006   int index = info->region_index[block];
3007
3008   /* If we've already processed this block, simply return. */
3009   if (info->num_handlers[index] > 0)
3010     return;
3011
3012   for (ptr = get_first_handler (block); ptr; last_ptr = ptr, ptr = ptr->next)
3013     count++;
3014
3015  /* pick up any information from the next outer region.  It will already
3016     contain a summary of itself and all outer regions to it.  */
3017
3018   if (nested_eh_region [block] != 0) 
3019     {
3020       int nested_index = info->region_index[nested_eh_region[block]];
3021       process_nestinfo (nested_eh_region[block], info, nested_eh_region);
3022       extra = info->num_handlers[nested_index];
3023       extra_handlers = info->handlers[nested_index];
3024       info->outer_index[index] = nested_index;
3025     }
3026
3027   /* If the last handler is either a CATCH_ALL or a cleanup, then we
3028      won't use the outer ones since we know control will not go past the
3029      catch-all or cleanup.  */
3030
3031   if (last_ptr != NULL && (last_ptr->type_info == NULL 
3032                            || last_ptr->type_info == CATCH_ALL_TYPE))
3033     extra = 0;
3034
3035   info->num_handlers[index] = count + extra;
3036   info->handlers[index] = (handler_info **) malloc ((count + extra) 
3037                                                     * sizeof (handler_info **));
3038
3039   /* First put all our handlers into the list.  */
3040   ptr = get_first_handler (block);
3041   for (x = 0; x < count; x++)
3042     {
3043       info->handlers[index][x] = ptr;
3044       ptr = ptr->next;
3045     }
3046
3047   /* Now add all the outer region handlers, if they aren't they same as 
3048      one of the types in the current block.  We won't worry about
3049      derived types yet, we'll just look for the exact type.  */
3050   for (y =0, x = 0; x < extra ; x++)
3051     {
3052       int i, ok;
3053       ok = 1;
3054       /* Check to see if we have a type duplication.  */
3055       for (i = 0; i < count; i++)
3056         if (info->handlers[index][i]->type_info == extra_handlers[x]->type_info)
3057           {
3058             ok = 0;
3059             /* Record one less handler.  */
3060             (info->num_handlers[index])--;
3061             break;
3062           }
3063       if (ok)
3064         {
3065           info->handlers[index][y + count] = extra_handlers[x];
3066           y++;
3067         }
3068     }
3069 }
3070
3071 /* This function will allocate and initialize an eh_nesting_info structure. 
3072    It returns a pointer to the completed data structure.  If there are
3073    no exception regions, a NULL value is returned.  */
3074 eh_nesting_info *
3075 init_eh_nesting_info ()
3076 {
3077   int *nested_eh_region;
3078   int region_count = 0;
3079   rtx eh_note = NULL_RTX;
3080   eh_nesting_info *info;
3081   rtx insn;
3082   int x;
3083
3084   info = (eh_nesting_info *) malloc (sizeof (eh_nesting_info));
3085   info->region_index = (int *) malloc ((max_label_num () + 1) * sizeof (int));
3086   bzero ((char *) info->region_index, (max_label_num () + 1) * sizeof (int));
3087
3088   nested_eh_region = (int *) alloca ((max_label_num () + 1) * sizeof (int));
3089   bzero ((char *) nested_eh_region, (max_label_num () + 1) * sizeof (int));
3090
3091   /* Create the nested_eh_region list.  If indexed with a block number, it 
3092      returns the block number of the next outermost region, if any. 
3093      We can count the number of regions and initialize the region_index
3094      vector at the same time.  */
3095   for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
3096     {
3097       if (GET_CODE (insn) == NOTE)
3098         {
3099           if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
3100             {
3101               int block = NOTE_BLOCK_NUMBER (insn);
3102               region_count++;
3103               info->region_index[block] = region_count;
3104               if (eh_note)
3105                 nested_eh_region [block] =
3106                                      NOTE_BLOCK_NUMBER (XEXP (eh_note, 0));
3107               else
3108                 nested_eh_region [block] = 0;
3109               eh_note = gen_rtx_EXPR_LIST (VOIDmode, insn, eh_note);
3110             }
3111           else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
3112             eh_note = XEXP (eh_note, 1);
3113         }
3114     }
3115   
3116   /* If there are no regions, wrap it up now.  */
3117   if (region_count == 0)
3118     {
3119       free (info->region_index);
3120       free (info);
3121       return NULL;
3122     }
3123
3124   region_count++;
3125   info->handlers = (handler_info ***) malloc (region_count 
3126                                               * sizeof (handler_info ***));
3127   info->num_handlers = (int *) malloc (region_count * sizeof (int));
3128   info->outer_index = (int *) malloc (region_count * sizeof (int));
3129
3130   bzero ((char *) info->handlers, region_count * sizeof (rtx *));
3131   bzero ((char *) info->num_handlers, region_count * sizeof (int));
3132   bzero ((char *) info->outer_index, region_count * sizeof (int));
3133
3134  /* Now initialize the handler lists for all exception blocks.  */
3135   for (x = 0; x <= max_label_num (); x++)
3136     {
3137       if (info->region_index[x] != 0)
3138         process_nestinfo (x, info, nested_eh_region);
3139     }
3140   info->region_count = region_count;
3141   return info;
3142 }
3143
3144
3145 /* This function is used to retreive the vector of handlers which 
3146    can be reached by a given insn in a given exception region.
3147    BLOCK is the exception block the insn is in.
3148    INFO is the eh_nesting_info structure.
3149    INSN is the (optional) insn within the block.  If insn is not NULL_RTX,
3150    it may contain reg notes which modify its throwing behavior, and
3151    these will be obeyed.  If NULL_RTX is passed, then we simply return the
3152    handlers for block.
3153    HANDLERS is the address of a pointer to a vector of handler_info pointers.
3154    Upon return, this will have the handlers which can be reached by block.
3155    This function returns the number of elements in the handlers vector.  */
3156 int 
3157 reachable_handlers (block, info, insn, handlers)
3158      int block;
3159      eh_nesting_info *info;
3160      rtx insn ;
3161      handler_info ***handlers;
3162 {
3163   int index = 0;
3164   *handlers = NULL;
3165
3166   if (info == NULL)
3167     return 0;
3168   if (block > 0)
3169     index = info->region_index[block];
3170
3171   if (insn && GET_CODE (insn) == CALL_INSN)
3172     {
3173       /* RETHROWs specify a region number from which we are going to rethrow.
3174          This means we wont pass control to handlers in the specified
3175          region, but rather any region OUTSIDE the specified region.
3176          We accomplish this by setting block to the outer_index of the
3177          specified region.  */
3178       rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
3179       if (note)
3180         {
3181           index = eh_region_from_symbol (XEXP (note, 0));
3182           index = info->region_index[index];
3183           if (index)
3184             index = info->outer_index[index];
3185         }
3186       else
3187         {
3188           /* If there is no rethrow, we look for a REG_EH_REGION, and
3189              we'll throw from that block.  A value of 0 or less
3190              indicates that this insn cannot throw.  */
3191           note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3192           if (note)
3193             {
3194               int b = XINT (XEXP (note, 0), 0);
3195               if (b <= 0)
3196                 index = 0;
3197               else
3198                 index = info->region_index[b];
3199             }
3200         }
3201     }
3202   /* If we reach this point, and index is 0, there is no throw.  */
3203   if (index == 0)
3204     return 0;
3205   
3206   *handlers = info->handlers[index];
3207   return info->num_handlers[index];
3208 }
3209
3210
3211 /* This function will free all memory associated with the eh_nesting info.  */
3212
3213 void 
3214 free_eh_nesting_info (info)
3215      eh_nesting_info *info;
3216 {
3217   int x;
3218   if (info != NULL)
3219     {
3220       if (info->region_index)
3221         free (info->region_index);
3222       if (info->num_handlers)
3223         free (info->num_handlers);
3224       if (info->outer_index)
3225         free (info->outer_index);
3226       if (info->handlers)
3227         {
3228           for (x = 0; x < info->region_count; x++)
3229             if (info->handlers[x])
3230               free (info->handlers[x]);
3231           free (info->handlers);
3232         }
3233     }
3234 }