OSDN Git Service

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