OSDN Git Service

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