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