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