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