OSDN Git Service

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