Use target specific, language specific object files feature to allow build
[official-gcc.git] / gcc / except.c
blob5364b2503283f753e9f393ac376cdf41c8c6d269
1 /* Implements exception handling.
2 Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
3 1999, 2000 Free Software Foundation, Inc.
4 Contributed by Mike Stump <mrs@cygnus.com>.
6 This file is part of GNU CC.
8 GNU CC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 GNU CC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU CC; see the file COPYING. If not, write to
20 the Free Software Foundation, 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
24 /* An exception is an event that can be signaled from within a
25 function. This event can then be "caught" or "trapped" by the
26 callers of this function. This potentially allows program flow to
27 be transferred to any arbitrary code associated with a function call
28 several levels up the stack.
30 The intended use for this mechanism is for signaling "exceptional
31 events" in an out-of-band fashion, hence its name. The C++ language
32 (and many other OO-styled or functional languages) practically
33 requires such a mechanism, as otherwise it becomes very difficult
34 or even impossible to signal failure conditions in complex
35 situations. The traditional C++ example is when an error occurs in
36 the process of constructing an object; without such a mechanism, it
37 is impossible to signal that the error occurs without adding global
38 state variables and error checks around every object construction.
40 The act of causing this event to occur is referred to as "throwing
41 an exception". (Alternate terms include "raising an exception" or
42 "signaling an exception".) The term "throw" is used because control
43 is returned to the callers of the function that is signaling the
44 exception, and thus there is the concept of "throwing" the
45 exception up the call stack.
47 There are two major codegen options for exception handling. The
48 flag -fsjlj-exceptions can be used to select the setjmp/longjmp
49 approach, which is the default. -fno-sjlj-exceptions can be used to
50 get the PC range table approach. While this is a compile time
51 flag, an entire application must be compiled with the same codegen
52 option. The first is a PC range table approach, the second is a
53 setjmp/longjmp based scheme. We will first discuss the PC range
54 table approach, after that, we will discuss the setjmp/longjmp
55 based approach.
57 It is appropriate to speak of the "context of a throw". This
58 context refers to the address where the exception is thrown from,
59 and is used to determine which exception region will handle the
60 exception.
62 Regions of code within a function can be marked such that if it
63 contains the context of a throw, control will be passed to a
64 designated "exception handler". These areas are known as "exception
65 regions". Exception regions cannot overlap, but they can be nested
66 to any arbitrary depth. Also, exception regions cannot cross
67 function boundaries.
69 Exception handlers can either be specified by the user (which we
70 will call a "user-defined handler") or generated by the compiler
71 (which we will designate as a "cleanup"). Cleanups are used to
72 perform tasks such as destruction of objects allocated on the
73 stack.
75 In the current implementation, cleanups are handled by allocating an
76 exception region for the area that the cleanup is designated for,
77 and the handler for the region performs the cleanup and then
78 rethrows the exception to the outer exception region. From the
79 standpoint of the current implementation, there is little
80 distinction made between a cleanup and a user-defined handler, and
81 the phrase "exception handler" can be used to refer to either one
82 equally well. (The section "Future Directions" below discusses how
83 this will change).
85 Each object file that is compiled with exception handling contains
86 a static array of exception handlers named __EXCEPTION_TABLE__.
87 Each entry contains the starting and ending addresses of the
88 exception region, and the address of the handler designated for
89 that region.
91 If the target does not use the DWARF 2 frame unwind information, at
92 program startup each object file invokes a function named
93 __register_exceptions with the address of its local
94 __EXCEPTION_TABLE__. __register_exceptions is defined in libgcc2.c, and
95 is responsible for recording all of the exception regions into one list
96 (which is kept in a static variable named exception_table_list).
98 On targets that support crtstuff.c, the unwind information
99 is stored in a section named .eh_frame and the information for the
100 entire shared object or program is registered with a call to
101 __register_frame_info. On other targets, the information for each
102 translation unit is registered from the file generated by collect2.
103 __register_frame_info is defined in frame.c, and is responsible for
104 recording all of the unwind regions into one list (which is kept in a
105 static variable named unwind_table_list).
107 The function __throw is actually responsible for doing the
108 throw. On machines that have unwind info support, __throw is generated
109 by code in libgcc2.c, otherwise __throw is generated on a
110 per-object-file basis for each source file compiled with
111 -fexceptions by the C++ frontend. Before __throw is invoked,
112 the current context of the throw needs to be placed in the global
113 variable __eh_pc.
115 __throw attempts to find the appropriate exception handler for the
116 PC value stored in __eh_pc by calling __find_first_exception_table_match
117 (which is defined in libgcc2.c). If __find_first_exception_table_match
118 finds a relevant handler, __throw transfers control directly to it.
120 If a handler for the context being thrown from can't be found, __throw
121 walks (see Walking the stack below) the stack up the dynamic call chain to
122 continue searching for an appropriate exception handler based upon the
123 caller of the function it last sought a exception handler for. It stops
124 then either an exception handler is found, or when the top of the
125 call chain is reached.
127 If no handler is found, an external library function named
128 __terminate is called. If a handler is found, then we restart
129 our search for a handler at the end of the call chain, and repeat
130 the search process, but instead of just walking up the call chain,
131 we unwind the call chain as we walk up it.
133 Internal implementation details:
135 To associate a user-defined handler with a block of statements, the
136 function expand_start_try_stmts is used to mark the start of the
137 block of statements with which the handler is to be associated
138 (which is known as a "try block"). All statements that appear
139 afterwards will be associated with the try block.
141 A call to expand_start_all_catch marks the end of the try block,
142 and also marks the start of the "catch block" (the user-defined
143 handler) associated with the try block.
145 This user-defined handler will be invoked for *every* exception
146 thrown with the context of the try block. It is up to the handler
147 to decide whether or not it wishes to handle any given exception,
148 as there is currently no mechanism in this implementation for doing
149 this. (There are plans for conditionally processing an exception
150 based on its "type", which will provide a language-independent
151 mechanism).
153 If the handler chooses not to process the exception (perhaps by
154 looking at an "exception type" or some other additional data
155 supplied with the exception), it can fall through to the end of the
156 handler. expand_end_all_catch and expand_leftover_cleanups
157 add additional code to the end of each handler to take care of
158 rethrowing to the outer exception handler.
160 The handler also has the option to continue with "normal flow of
161 code", or in other words to resume executing at the statement
162 immediately after the end of the exception region. The variable
163 caught_return_label_stack contains a stack of labels, and jumping
164 to the topmost entry's label via expand_goto will resume normal
165 flow to the statement immediately after the end of the exception
166 region. If the handler falls through to the end, the exception will
167 be rethrown to the outer exception region.
169 The instructions for the catch block are kept as a separate
170 sequence, and will be emitted at the end of the function along with
171 the handlers specified via expand_eh_region_end. The end of the
172 catch block is marked with expand_end_all_catch.
174 Any data associated with the exception must currently be handled by
175 some external mechanism maintained in the frontend. For example,
176 the C++ exception mechanism passes an arbitrary value along with
177 the exception, and this is handled in the C++ frontend by using a
178 global variable to hold the value. (This will be changing in the
179 future.)
181 The mechanism in C++ for handling data associated with the
182 exception is clearly not thread-safe. For a thread-based
183 environment, another mechanism must be used (possibly using a
184 per-thread allocation mechanism if the size of the area that needs
185 to be allocated isn't known at compile time.)
187 Internally-generated exception regions (cleanups) are marked by
188 calling expand_eh_region_start to mark the start of the region,
189 and expand_eh_region_end (handler) is used to both designate the
190 end of the region and to associate a specified handler/cleanup with
191 the region. The rtl code in HANDLER will be invoked whenever an
192 exception occurs in the region between the calls to
193 expand_eh_region_start and expand_eh_region_end. After HANDLER is
194 executed, additional code is emitted to handle rethrowing the
195 exception to the outer exception handler. The code for HANDLER will
196 be emitted at the end of the function.
198 TARGET_EXPRs can also be used to designate exception regions. A
199 TARGET_EXPR gives an unwind-protect style interface commonly used
200 in functional languages such as LISP. The associated expression is
201 evaluated, and whether or not it (or any of the functions that it
202 calls) throws an exception, the protect expression is always
203 invoked. This implementation takes care of the details of
204 associating an exception table entry with the expression and
205 generating the necessary code (it actually emits the protect
206 expression twice, once for normal flow and once for the exception
207 case). As for the other handlers, the code for the exception case
208 will be emitted at the end of the function.
210 Cleanups can also be specified by using add_partial_entry (handler)
211 and end_protect_partials. add_partial_entry creates the start of
212 a new exception region; HANDLER will be invoked if an exception is
213 thrown with the context of the region between the calls to
214 add_partial_entry and end_protect_partials. end_protect_partials is
215 used to mark the end of these regions. add_partial_entry can be
216 called as many times as needed before calling end_protect_partials.
217 However, end_protect_partials should only be invoked once for each
218 group of calls to add_partial_entry as the entries are queued
219 and all of the outstanding entries are processed simultaneously
220 when end_protect_partials is invoked. Similarly to the other
221 handlers, the code for HANDLER will be emitted at the end of the
222 function.
224 The generated RTL for an exception region includes
225 NOTE_INSN_EH_REGION_BEG and NOTE_INSN_EH_REGION_END notes that mark
226 the start and end of the exception region. A unique label is also
227 generated at the start of the exception region, which is available
228 by looking at the ehstack variable. The topmost entry corresponds
229 to the current region.
231 In the current implementation, an exception can only be thrown from
232 a function call (since the mechanism used to actually throw an
233 exception involves calling __throw). If an exception region is
234 created but no function calls occur within that region, the region
235 can be safely optimized away (along with its exception handlers)
236 since no exceptions can ever be caught in that region. This
237 optimization is performed unless -fasynchronous-exceptions is
238 given. If the user wishes to throw from a signal handler, or other
239 asynchronous place, -fasynchronous-exceptions should be used when
240 compiling for maximally correct code, at the cost of additional
241 exception regions. Using -fasynchronous-exceptions only produces
242 code that is reasonably safe in such situations, but a correct
243 program cannot rely upon this working. It can be used in failsafe
244 code, where trying to continue on, and proceeding with potentially
245 incorrect results is better than halting the program.
248 Walking the stack:
250 The stack is walked by starting with a pointer to the current
251 frame, and finding the pointer to the callers frame. The unwind info
252 tells __throw how to find it.
254 Unwinding the stack:
256 When we use the term unwinding the stack, we mean undoing the
257 effects of the function prologue in a controlled fashion so that we
258 still have the flow of control. Otherwise, we could just return
259 (jump to the normal end of function epilogue).
261 This is done in __throw in libgcc2.c when we know that a handler exists
262 in a frame higher up the call stack than its immediate caller.
264 To unwind, we find the unwind data associated with the frame, if any.
265 If we don't find any, we call the library routine __terminate. If we do
266 find it, we use the information to copy the saved register values from
267 that frame into the register save area in the frame for __throw, return
268 into a stub which updates the stack pointer, and jump to the handler.
269 The normal function epilogue for __throw handles restoring the saved
270 values into registers.
272 When unwinding, we use this method if we know it will
273 work (if DWARF2_UNWIND_INFO is defined). Otherwise, we know that
274 an inline unwinder will have been emitted for any function that
275 __unwind_function cannot unwind. The inline unwinder appears as a
276 normal exception handler for the entire function, for any function
277 that we know cannot be unwound by __unwind_function. We inform the
278 compiler of whether a function can be unwound with
279 __unwind_function by having DOESNT_NEED_UNWINDER evaluate to true
280 when the unwinder isn't needed. __unwind_function is used as an
281 action of last resort. If no other method can be used for
282 unwinding, __unwind_function is used. If it cannot unwind, it
283 should call __terminate.
285 By default, if the target-specific backend doesn't supply a definition
286 for __unwind_function and doesn't support DWARF2_UNWIND_INFO, inlined
287 unwinders will be used instead. The main tradeoff here is in text space
288 utilization. Obviously, if inline unwinders have to be generated
289 repeatedly, this uses much more space than if a single routine is used.
291 However, it is simply not possible on some platforms to write a
292 generalized routine for doing stack unwinding without having some
293 form of additional data associated with each function. The current
294 implementation can encode this data in the form of additional
295 machine instructions or as static data in tabular form. The later
296 is called the unwind data.
298 The backend macro DOESNT_NEED_UNWINDER is used to conditionalize whether
299 or not per-function unwinders are needed. If DOESNT_NEED_UNWINDER is
300 defined and has a non-zero value, a per-function unwinder is not emitted
301 for the current function. If the static unwind data is supported, then
302 a per-function unwinder is not emitted.
304 On some platforms it is possible that neither __unwind_function
305 nor inlined unwinders are available. For these platforms it is not
306 possible to throw through a function call, and abort will be
307 invoked instead of performing the throw.
309 The reason the unwind data may be needed is that on some platforms
310 the order and types of data stored on the stack can vary depending
311 on the type of function, its arguments and returned values, and the
312 compilation options used (optimization versus non-optimization,
313 -fomit-frame-pointer, processor variations, etc).
315 Unfortunately, this also means that throwing through functions that
316 aren't compiled with exception handling support will still not be
317 possible on some platforms. This problem is currently being
318 investigated, but no solutions have been found that do not imply
319 some unacceptable performance penalties.
321 Future directions:
323 Currently __throw makes no differentiation between cleanups and
324 user-defined exception regions. While this makes the implementation
325 simple, it also implies that it is impossible to determine if a
326 user-defined exception handler exists for a given exception without
327 completely unwinding the stack in the process. This is undesirable
328 from the standpoint of debugging, as ideally it would be possible
329 to trap unhandled exceptions in the debugger before the process of
330 unwinding has even started.
332 This problem can be solved by marking user-defined handlers in a
333 special way (probably by adding additional bits to exception_table_list).
334 A two-pass scheme could then be used by __throw to iterate
335 through the table. The first pass would search for a relevant
336 user-defined handler for the current context of the throw, and if
337 one is found, the second pass would then invoke all needed cleanups
338 before jumping to the user-defined handler.
340 Many languages (including C++ and Ada) make execution of a
341 user-defined handler conditional on the "type" of the exception
342 thrown. (The type of the exception is actually the type of the data
343 that is thrown with the exception.) It will thus be necessary for
344 __throw to be able to determine if a given user-defined
345 exception handler will actually be executed, given the type of
346 exception.
348 One scheme is to add additional information to exception_table_list
349 as to the types of exceptions accepted by each handler. __throw
350 can do the type comparisons and then determine if the handler is
351 actually going to be executed.
353 There is currently no significant level of debugging support
354 available, other than to place a breakpoint on __throw. While
355 this is sufficient in most cases, it would be helpful to be able to
356 know where a given exception was going to be thrown to before it is
357 actually thrown, and to be able to choose between stopping before
358 every exception region (including cleanups), or just user-defined
359 exception regions. This should be possible to do in the two-pass
360 scheme by adding additional labels to __throw for appropriate
361 breakpoints, and additional debugger commands could be added to
362 query various state variables to determine what actions are to be
363 performed next.
365 Another major problem that is being worked on is the issue with stack
366 unwinding on various platforms. Currently the only platforms that have
367 support for the generation of a generic unwinder are the SPARC and MIPS.
368 All other ports require per-function unwinders, which produce large
369 amounts of code bloat.
371 For setjmp/longjmp based exception handling, some of the details
372 are as above, but there are some additional details. This section
373 discusses the details.
375 We don't use NOTE_INSN_EH_REGION_{BEG,END} pairs. We don't
376 optimize EH regions yet. We don't have to worry about machine
377 specific issues with unwinding the stack, as we rely upon longjmp
378 for all the machine specific details. There is no variable context
379 of a throw, just the one implied by the dynamic handler stack
380 pointed to by the dynamic handler chain. There is no exception
381 table, and no calls to __register_exceptions. __sjthrow is used
382 instead of __throw, and it works by using the dynamic handler
383 chain, and longjmp. -fasynchronous-exceptions has no effect, as
384 the elimination of trivial exception regions is not yet performed.
386 A frontend can set protect_cleanup_actions_with_terminate when all
387 the cleanup actions should be protected with an EH region that
388 calls terminate when an unhandled exception is throw. C++ does
389 this, Ada does not. */
392 #include "config.h"
393 #include "defaults.h"
394 #include "eh-common.h"
395 #include "system.h"
396 #include "rtl.h"
397 #include "tree.h"
398 #include "flags.h"
399 #include "except.h"
400 #include "function.h"
401 #include "insn-flags.h"
402 #include "expr.h"
403 #include "insn-codes.h"
404 #include "regs.h"
405 #include "hard-reg-set.h"
406 #include "insn-config.h"
407 #include "recog.h"
408 #include "output.h"
409 #include "toplev.h"
410 #include "intl.h"
411 #include "obstack.h"
412 #include "ggc.h"
413 #include "tm_p.h"
415 /* One to use setjmp/longjmp method of generating code for exception
416 handling. */
418 int exceptions_via_longjmp = 2;
420 /* One to enable asynchronous exception support. */
422 int asynchronous_exceptions = 0;
424 /* One to protect cleanup actions with a handler that calls
425 __terminate, zero otherwise. */
427 int protect_cleanup_actions_with_terminate;
429 /* A list of labels used for exception handlers. Created by
430 find_exception_handler_labels for the optimization passes. */
432 rtx exception_handler_labels;
434 /* Keeps track of the label used as the context of a throw to rethrow an
435 exception to the outer exception region. */
437 struct label_node *outer_context_label_stack = NULL;
439 /* Pseudos used to hold exception return data in the interim between
440 __builtin_eh_return and the end of the function. */
442 static rtx eh_return_context;
443 static rtx eh_return_stack_adjust;
444 static rtx eh_return_handler;
446 /* This is used for targets which can call rethrow with an offset instead
447 of an address. This is subtracted from the rethrow label we are
448 interested in. */
450 static rtx first_rethrow_symbol = NULL_RTX;
451 static rtx final_rethrow = NULL_RTX;
452 static rtx last_rethrow_symbol = NULL_RTX;
455 /* Prototypes for local functions. */
457 static void push_eh_entry PARAMS ((struct eh_stack *));
458 static struct eh_entry * pop_eh_entry PARAMS ((struct eh_stack *));
459 static void enqueue_eh_entry PARAMS ((struct eh_queue *, struct eh_entry *));
460 static struct eh_entry * dequeue_eh_entry PARAMS ((struct eh_queue *));
461 static rtx call_get_eh_context PARAMS ((void));
462 static void start_dynamic_cleanup PARAMS ((tree, tree));
463 static void start_dynamic_handler PARAMS ((void));
464 static void expand_rethrow PARAMS ((rtx));
465 static void output_exception_table_entry PARAMS ((FILE *, int));
466 static rtx scan_region PARAMS ((rtx, int, int *));
467 static void eh_regs PARAMS ((rtx *, rtx *, rtx *, int));
468 static void set_insn_eh_region PARAMS ((rtx *, int));
469 #ifdef DONT_USE_BUILTIN_SETJMP
470 static void jumpif_rtx PARAMS ((rtx, rtx));
471 #endif
472 static void find_exception_handler_labels_1 PARAMS ((rtx));
473 static void mark_eh_node PARAMS ((struct eh_node *));
474 static void mark_eh_stack PARAMS ((struct eh_stack *));
475 static void mark_eh_queue PARAMS ((struct eh_queue *));
476 static void mark_tree_label_node PARAMS ((struct label_node *));
477 static void mark_func_eh_entry PARAMS ((void *));
478 static rtx create_rethrow_ref PARAMS ((int));
479 static void push_entry PARAMS ((struct eh_stack *, struct eh_entry*));
480 static void receive_exception_label PARAMS ((rtx));
481 static int new_eh_region_entry PARAMS ((int, rtx));
482 static int find_func_region PARAMS ((int));
483 static int find_func_region_from_symbol PARAMS ((rtx));
484 static void clear_function_eh_region PARAMS ((void));
485 static void process_nestinfo PARAMS ((int, eh_nesting_info *, int *));
486 rtx expand_builtin_return_addr PARAMS ((enum built_in_function, int, rtx));
487 static void emit_cleanup_handler PARAMS ((struct eh_entry *));
488 static int eh_region_from_symbol PARAMS ((rtx));
491 /* Various support routines to manipulate the various data structures
492 used by the exception handling code. */
494 extern struct obstack permanent_obstack;
496 /* Generate a SYMBOL_REF for rethrow to use */
498 static rtx
499 create_rethrow_ref (region_num)
500 int region_num;
502 rtx def;
503 const char *ptr;
504 char buf[60];
506 ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", region_num);
507 ptr = ggc_strdup (buf);
508 def = gen_rtx_SYMBOL_REF (Pmode, ptr);
509 SYMBOL_REF_NEED_ADJUST (def) = 1;
511 return def;
514 /* Push a label entry onto the given STACK. */
516 void
517 push_label_entry (stack, rlabel, tlabel)
518 struct label_node **stack;
519 rtx rlabel;
520 tree tlabel;
522 struct label_node *newnode
523 = (struct label_node *) xmalloc (sizeof (struct label_node));
525 if (rlabel)
526 newnode->u.rlabel = rlabel;
527 else
528 newnode->u.tlabel = tlabel;
529 newnode->chain = *stack;
530 *stack = newnode;
533 /* Pop a label entry from the given STACK. */
536 pop_label_entry (stack)
537 struct label_node **stack;
539 rtx label;
540 struct label_node *tempnode;
542 if (! *stack)
543 return NULL_RTX;
545 tempnode = *stack;
546 label = tempnode->u.rlabel;
547 *stack = (*stack)->chain;
548 free (tempnode);
550 return label;
553 /* Return the top element of the given STACK. */
555 tree
556 top_label_entry (stack)
557 struct label_node **stack;
559 if (! *stack)
560 return NULL_TREE;
562 return (*stack)->u.tlabel;
565 /* Get an exception label. */
568 gen_exception_label ()
570 rtx lab;
571 lab = gen_label_rtx ();
572 return lab;
575 /* Push a new eh_node entry onto STACK. */
577 static void
578 push_eh_entry (stack)
579 struct eh_stack *stack;
581 struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
582 struct eh_entry *entry = (struct eh_entry *) xmalloc (sizeof (struct eh_entry));
584 rtx rlab = gen_exception_label ();
585 entry->finalization = NULL_TREE;
586 entry->label_used = 0;
587 entry->exception_handler_label = rlab;
588 entry->false_label = NULL_RTX;
589 if (! flag_new_exceptions)
590 entry->outer_context = gen_label_rtx ();
591 else
592 entry->outer_context = create_rethrow_ref (CODE_LABEL_NUMBER (rlab));
593 entry->rethrow_label = entry->outer_context;
594 entry->goto_entry_p = 0;
596 node->entry = entry;
597 node->chain = stack->top;
598 stack->top = node;
601 /* Push an existing entry onto a stack. */
603 static void
604 push_entry (stack, entry)
605 struct eh_stack *stack;
606 struct eh_entry *entry;
608 struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
609 node->entry = entry;
610 node->chain = stack->top;
611 stack->top = node;
614 /* Pop an entry from the given STACK. */
616 static struct eh_entry *
617 pop_eh_entry (stack)
618 struct eh_stack *stack;
620 struct eh_node *tempnode;
621 struct eh_entry *tempentry;
623 tempnode = stack->top;
624 tempentry = tempnode->entry;
625 stack->top = stack->top->chain;
626 free (tempnode);
628 return tempentry;
631 /* Enqueue an ENTRY onto the given QUEUE. */
633 static void
634 enqueue_eh_entry (queue, entry)
635 struct eh_queue *queue;
636 struct eh_entry *entry;
638 struct eh_node *node = (struct eh_node *) xmalloc (sizeof (struct eh_node));
640 node->entry = entry;
641 node->chain = NULL;
643 if (queue->head == NULL)
644 queue->head = node;
645 else
646 queue->tail->chain = node;
647 queue->tail = node;
650 /* Dequeue an entry from the given QUEUE. */
652 static struct eh_entry *
653 dequeue_eh_entry (queue)
654 struct eh_queue *queue;
656 struct eh_node *tempnode;
657 struct eh_entry *tempentry;
659 if (queue->head == NULL)
660 return NULL;
662 tempnode = queue->head;
663 queue->head = queue->head->chain;
665 tempentry = tempnode->entry;
666 free (tempnode);
668 return tempentry;
671 static void
672 receive_exception_label (handler_label)
673 rtx handler_label;
675 emit_label (handler_label);
677 #ifdef HAVE_exception_receiver
678 if (! exceptions_via_longjmp)
679 if (HAVE_exception_receiver)
680 emit_insn (gen_exception_receiver ());
681 #endif
683 #ifdef HAVE_nonlocal_goto_receiver
684 if (! exceptions_via_longjmp)
685 if (HAVE_nonlocal_goto_receiver)
686 emit_insn (gen_nonlocal_goto_receiver ());
687 #endif
691 struct func_eh_entry
693 int range_number; /* EH region number from EH NOTE insn's. */
694 rtx rethrow_label; /* Label for rethrow. */
695 int rethrow_ref; /* Is rethrow_label referenced? */
696 int emitted; /* 1 if this entry has been emitted in assembly file. */
697 struct handler_info *handlers;
701 /* table of function eh regions */
702 static struct func_eh_entry *function_eh_regions = NULL;
703 static int num_func_eh_entries = 0;
704 static int current_func_eh_entry = 0;
706 #define SIZE_FUNC_EH(X) (sizeof (struct func_eh_entry) * X)
708 /* Add a new eh_entry for this function. The number returned is an
709 number which uniquely identifies this exception range. */
711 static int
712 new_eh_region_entry (note_eh_region, rethrow)
713 int note_eh_region;
714 rtx rethrow;
716 if (current_func_eh_entry == num_func_eh_entries)
718 if (num_func_eh_entries == 0)
720 function_eh_regions =
721 (struct func_eh_entry *) xmalloc (SIZE_FUNC_EH (50));
722 num_func_eh_entries = 50;
724 else
726 num_func_eh_entries = num_func_eh_entries * 3 / 2;
727 function_eh_regions = (struct func_eh_entry *)
728 xrealloc (function_eh_regions, SIZE_FUNC_EH (num_func_eh_entries));
731 function_eh_regions[current_func_eh_entry].range_number = note_eh_region;
732 if (rethrow == NULL_RTX)
733 function_eh_regions[current_func_eh_entry].rethrow_label =
734 create_rethrow_ref (note_eh_region);
735 else
736 function_eh_regions[current_func_eh_entry].rethrow_label = rethrow;
737 function_eh_regions[current_func_eh_entry].handlers = NULL;
738 function_eh_regions[current_func_eh_entry].emitted = 0;
740 return current_func_eh_entry++;
743 /* Add new handler information to an exception range. The first parameter
744 specifies the range number (returned from new_eh_entry()). The second
745 parameter specifies the handler. By default the handler is inserted at
746 the end of the list. A handler list may contain only ONE NULL_TREE
747 typeinfo entry. Regardless where it is positioned, a NULL_TREE entry
748 is always output as the LAST handler in the exception table for a region. */
750 void
751 add_new_handler (region, newhandler)
752 int region;
753 struct handler_info *newhandler;
755 struct handler_info *last;
757 /* If find_func_region returns -1, callers might attempt to pass us
758 this region number. If that happens, something has gone wrong;
759 -1 is never a valid region. */
760 if (region == -1)
761 abort ();
763 newhandler->next = NULL;
764 last = function_eh_regions[region].handlers;
765 if (last == NULL)
766 function_eh_regions[region].handlers = newhandler;
767 else
769 for ( ; ; last = last->next)
771 if (last->type_info == CATCH_ALL_TYPE)
772 pedwarn ("additional handler after ...");
773 if (last->next == NULL)
774 break;
776 last->next = newhandler;
780 /* Remove a handler label. The handler label is being deleted, so all
781 regions which reference this handler should have it removed from their
782 list of possible handlers. Any region which has the final handler
783 removed can be deleted. */
785 void remove_handler (removing_label)
786 rtx removing_label;
788 struct handler_info *handler, *last;
789 int x;
790 for (x = 0 ; x < current_func_eh_entry; ++x)
792 last = NULL;
793 handler = function_eh_regions[x].handlers;
794 for ( ; handler; last = handler, handler = handler->next)
795 if (handler->handler_label == removing_label)
797 if (last)
799 last->next = handler->next;
800 handler = last;
802 else
803 function_eh_regions[x].handlers = handler->next;
808 /* This function will return a malloc'd pointer to an array of
809 void pointer representing the runtime match values that
810 currently exist in all regions. */
812 int
813 find_all_handler_type_matches (array)
814 void ***array;
816 struct handler_info *handler, *last;
817 int x,y;
818 void *val;
819 void **ptr;
820 int max_ptr;
821 int n_ptr = 0;
823 *array = NULL;
825 if (!doing_eh (0) || ! flag_new_exceptions)
826 return 0;
828 max_ptr = 100;
829 ptr = (void **) xmalloc (max_ptr * sizeof (void *));
831 for (x = 0 ; x < current_func_eh_entry; x++)
833 last = NULL;
834 handler = function_eh_regions[x].handlers;
835 for ( ; handler; last = handler, handler = handler->next)
837 val = handler->type_info;
838 if (val != NULL && val != CATCH_ALL_TYPE)
840 /* See if this match value has already been found. */
841 for (y = 0; y < n_ptr; y++)
842 if (ptr[y] == val)
843 break;
845 /* If we break early, we already found this value. */
846 if (y < n_ptr)
847 continue;
849 /* Do we need to allocate more space? */
850 if (n_ptr >= max_ptr)
852 max_ptr += max_ptr / 2;
853 ptr = (void **) xrealloc (ptr, max_ptr * sizeof (void *));
855 ptr[n_ptr] = val;
856 n_ptr++;
861 if (n_ptr == 0)
863 free (ptr);
864 ptr = NULL;
866 *array = ptr;
867 return n_ptr;
870 /* Create a new handler structure initialized with the handler label and
871 typeinfo fields passed in. */
873 struct handler_info *
874 get_new_handler (handler, typeinfo)
875 rtx handler;
876 void *typeinfo;
878 struct handler_info* ptr;
879 ptr = (struct handler_info *) xmalloc (sizeof (struct handler_info));
880 ptr->handler_label = handler;
881 ptr->handler_number = CODE_LABEL_NUMBER (handler);
882 ptr->type_info = typeinfo;
883 ptr->next = NULL;
885 return ptr;
890 /* Find the index in function_eh_regions associated with a NOTE region. If
891 the region cannot be found, a -1 is returned. */
893 static int
894 find_func_region (insn_region)
895 int insn_region;
897 int x;
898 for (x = 0; x < current_func_eh_entry; x++)
899 if (function_eh_regions[x].range_number == insn_region)
900 return x;
902 return -1;
905 /* Get a pointer to the first handler in an exception region's list. */
907 struct handler_info *
908 get_first_handler (region)
909 int region;
911 int r = find_func_region (region);
912 if (r == -1)
913 abort ();
914 return function_eh_regions[r].handlers;
917 /* Clean out the function_eh_region table and free all memory */
919 static void
920 clear_function_eh_region ()
922 int x;
923 struct handler_info *ptr, *next;
924 for (x = 0; x < current_func_eh_entry; x++)
925 for (ptr = function_eh_regions[x].handlers; ptr != NULL; ptr = next)
927 next = ptr->next;
928 free (ptr);
930 if (function_eh_regions)
931 free (function_eh_regions);
932 num_func_eh_entries = 0;
933 current_func_eh_entry = 0;
936 /* Make a duplicate of an exception region by copying all the handlers
937 for an exception region. Return the new handler index. The final
938 parameter is a routine which maps old labels to new ones. */
940 int
941 duplicate_eh_handlers (old_note_eh_region, new_note_eh_region, map)
942 int old_note_eh_region, new_note_eh_region;
943 rtx (*map) PARAMS ((rtx));
945 struct handler_info *ptr, *new_ptr;
946 int new_region, region;
948 region = find_func_region (old_note_eh_region);
949 if (region == -1)
950 fatal ("Cannot duplicate non-existant exception region.");
952 /* duplicate_eh_handlers may have been called during a symbol remap. */
953 new_region = find_func_region (new_note_eh_region);
954 if (new_region != -1)
955 return (new_region);
957 new_region = new_eh_region_entry (new_note_eh_region, NULL_RTX);
959 ptr = function_eh_regions[region].handlers;
961 for ( ; ptr; ptr = ptr->next)
963 new_ptr = get_new_handler (map (ptr->handler_label), ptr->type_info);
964 add_new_handler (new_region, new_ptr);
967 return new_region;
971 /* Given a rethrow symbol, find the EH region number this is for. */
973 static int
974 eh_region_from_symbol (sym)
975 rtx sym;
977 int x;
978 if (sym == last_rethrow_symbol)
979 return 1;
980 for (x = 0; x < current_func_eh_entry; x++)
981 if (function_eh_regions[x].rethrow_label == sym)
982 return function_eh_regions[x].range_number;
983 return -1;
986 /* Like find_func_region, but using the rethrow symbol for the region
987 rather than the region number itself. */
989 static int
990 find_func_region_from_symbol (sym)
991 rtx sym;
993 return find_func_region (eh_region_from_symbol (sym));
996 /* When inlining/unrolling, we have to map the symbols passed to
997 __rethrow as well. This performs the remap. If a symbol isn't foiund,
998 the original one is returned. This is not an efficient routine,
999 so don't call it on everything!! */
1001 rtx
1002 rethrow_symbol_map (sym, map)
1003 rtx sym;
1004 rtx (*map) PARAMS ((rtx));
1006 int x, y;
1008 if (! flag_new_exceptions)
1009 return sym;
1011 for (x = 0; x < current_func_eh_entry; x++)
1012 if (function_eh_regions[x].rethrow_label == sym)
1014 /* We've found the original region, now lets determine which region
1015 this now maps to. */
1016 rtx l1 = function_eh_regions[x].handlers->handler_label;
1017 rtx l2 = map (l1);
1018 y = CODE_LABEL_NUMBER (l2); /* This is the new region number */
1019 x = find_func_region (y); /* Get the new permanent region */
1020 if (x == -1) /* Hmm, Doesn't exist yet */
1022 x = duplicate_eh_handlers (CODE_LABEL_NUMBER (l1), y, map);
1023 /* Since we're mapping it, it must be used. */
1024 function_eh_regions[x].rethrow_ref = 1;
1026 return function_eh_regions[x].rethrow_label;
1028 return sym;
1031 /* Returns nonzero if the rethrow label for REGION is referenced
1032 somewhere (i.e. we rethrow out of REGION or some other region
1033 masquerading as REGION). */
1035 int
1036 rethrow_used (region)
1037 int region;
1039 if (flag_new_exceptions)
1041 int ret = function_eh_regions[find_func_region (region)].rethrow_ref;
1042 return ret;
1044 return 0;
1048 /* Routine to see if exception handling is turned on.
1049 DO_WARN is non-zero if we want to inform the user that exception
1050 handling is turned off.
1052 This is used to ensure that -fexceptions has been specified if the
1053 compiler tries to use any exception-specific functions. */
1056 doing_eh (do_warn)
1057 int do_warn;
1059 if (! flag_exceptions)
1061 static int warned = 0;
1062 if (! warned && do_warn)
1064 error ("exception handling disabled, use -fexceptions to enable");
1065 warned = 1;
1067 return 0;
1069 return 1;
1072 /* Given a return address in ADDR, determine the address we should use
1073 to find the corresponding EH region. */
1076 eh_outer_context (addr)
1077 rtx addr;
1079 /* First mask out any unwanted bits. */
1080 #ifdef MASK_RETURN_ADDR
1081 expand_and (addr, MASK_RETURN_ADDR, addr);
1082 #endif
1084 /* Then adjust to find the real return address. */
1085 #if defined (RETURN_ADDR_OFFSET)
1086 addr = plus_constant (addr, RETURN_ADDR_OFFSET);
1087 #endif
1089 return addr;
1092 /* Start a new exception region for a region of code that has a
1093 cleanup action and push the HANDLER for the region onto
1094 protect_list. All of the regions created with add_partial_entry
1095 will be ended when end_protect_partials is invoked. */
1097 void
1098 add_partial_entry (handler)
1099 tree handler;
1101 expand_eh_region_start ();
1103 /* Because this is a cleanup action, we may have to protect the handler
1104 with __terminate. */
1105 handler = protect_with_terminate (handler);
1107 /* For backwards compatibility, we allow callers to omit calls to
1108 begin_protect_partials for the outermost region. So, we must
1109 explicitly do so here. */
1110 if (!protect_list)
1111 begin_protect_partials ();
1113 /* Add this entry to the front of the list. */
1114 TREE_VALUE (protect_list)
1115 = tree_cons (NULL_TREE, handler, TREE_VALUE (protect_list));
1118 /* Emit code to get EH context to current function. */
1120 static rtx
1121 call_get_eh_context ()
1123 static tree fn;
1124 tree expr;
1126 if (fn == NULL_TREE)
1128 tree fntype;
1129 fn = get_identifier ("__get_eh_context");
1130 fntype = build_pointer_type (build_pointer_type
1131 (build_pointer_type (void_type_node)));
1132 fntype = build_function_type (fntype, NULL_TREE);
1133 fn = build_decl (FUNCTION_DECL, fn, fntype);
1134 DECL_EXTERNAL (fn) = 1;
1135 TREE_PUBLIC (fn) = 1;
1136 DECL_ARTIFICIAL (fn) = 1;
1137 TREE_READONLY (fn) = 1;
1138 make_decl_rtl (fn, NULL_PTR, 1);
1139 assemble_external (fn);
1141 ggc_add_tree_root (&fn, 1);
1144 expr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (fn)), fn);
1145 expr = build (CALL_EXPR, TREE_TYPE (TREE_TYPE (fn)),
1146 expr, NULL_TREE, NULL_TREE);
1147 TREE_SIDE_EFFECTS (expr) = 1;
1149 return copy_to_reg (expand_expr (expr, NULL_RTX, VOIDmode, 0));
1152 /* Get a reference to the EH context.
1153 We will only generate a register for the current function EH context here,
1154 and emit a USE insn to mark that this is a EH context register.
1156 Later, emit_eh_context will emit needed call to __get_eh_context
1157 in libgcc2, and copy the value to the register we have generated. */
1160 get_eh_context ()
1162 if (current_function_ehc == 0)
1164 rtx insn;
1166 current_function_ehc = gen_reg_rtx (Pmode);
1168 insn = gen_rtx_USE (GET_MODE (current_function_ehc),
1169 current_function_ehc);
1170 insn = emit_insn_before (insn, get_first_nonparm_insn ());
1172 REG_NOTES (insn)
1173 = gen_rtx_EXPR_LIST (REG_EH_CONTEXT, current_function_ehc,
1174 REG_NOTES (insn));
1176 return current_function_ehc;
1179 /* Get a reference to the dynamic handler chain. It points to the
1180 pointer to the next element in the dynamic handler chain. It ends
1181 when there are no more elements in the dynamic handler chain, when
1182 the value is &top_elt from libgcc2.c. Immediately after the
1183 pointer, is an area suitable for setjmp/longjmp when
1184 DONT_USE_BUILTIN_SETJMP is defined, and an area suitable for
1185 __builtin_setjmp/__builtin_longjmp when DONT_USE_BUILTIN_SETJMP
1186 isn't defined. */
1189 get_dynamic_handler_chain ()
1191 rtx ehc, dhc, result;
1193 ehc = get_eh_context ();
1195 /* This is the offset of dynamic_handler_chain in the eh_context struct
1196 declared in eh-common.h. If its location is change, change this offset */
1197 dhc = plus_constant (ehc, POINTER_SIZE / BITS_PER_UNIT);
1199 result = copy_to_reg (dhc);
1201 /* We don't want a copy of the dcc, but rather, the single dcc. */
1202 return gen_rtx_MEM (Pmode, result);
1205 /* Get a reference to the dynamic cleanup chain. It points to the
1206 pointer to the next element in the dynamic cleanup chain.
1207 Immediately after the pointer, are two Pmode variables, one for a
1208 pointer to a function that performs the cleanup action, and the
1209 second, the argument to pass to that function. */
1212 get_dynamic_cleanup_chain ()
1214 rtx dhc, dcc, result;
1216 dhc = get_dynamic_handler_chain ();
1217 dcc = plus_constant (dhc, POINTER_SIZE / BITS_PER_UNIT);
1219 result = copy_to_reg (dcc);
1221 /* We don't want a copy of the dcc, but rather, the single dcc. */
1222 return gen_rtx_MEM (Pmode, result);
1225 #ifdef DONT_USE_BUILTIN_SETJMP
1226 /* Generate code to evaluate X and jump to LABEL if the value is nonzero.
1227 LABEL is an rtx of code CODE_LABEL, in this function. */
1229 static void
1230 jumpif_rtx (x, label)
1231 rtx x;
1232 rtx label;
1234 jumpif (make_tree (type_for_mode (GET_MODE (x), 0), x), label);
1236 #endif
1238 /* Start a dynamic cleanup on the EH runtime dynamic cleanup stack.
1239 We just need to create an element for the cleanup list, and push it
1240 into the chain.
1242 A dynamic cleanup is a cleanup action implied by the presence of an
1243 element on the EH runtime dynamic cleanup stack that is to be
1244 performed when an exception is thrown. The cleanup action is
1245 performed by __sjthrow when an exception is thrown. Only certain
1246 actions can be optimized into dynamic cleanup actions. For the
1247 restrictions on what actions can be performed using this routine,
1248 see expand_eh_region_start_tree. */
1250 static void
1251 start_dynamic_cleanup (func, arg)
1252 tree func;
1253 tree arg;
1255 rtx dcc;
1256 rtx new_func, new_arg;
1257 rtx x, buf;
1258 int size;
1260 /* We allocate enough room for a pointer to the function, and
1261 one argument. */
1262 size = 2;
1264 /* XXX, FIXME: The stack space allocated this way is too long lived,
1265 but there is no allocation routine that allocates at the level of
1266 the last binding contour. */
1267 buf = assign_stack_local (BLKmode,
1268 GET_MODE_SIZE (Pmode)*(size+1),
1271 buf = change_address (buf, Pmode, NULL_RTX);
1273 /* Store dcc into the first word of the newly allocated buffer. */
1275 dcc = get_dynamic_cleanup_chain ();
1276 emit_move_insn (buf, dcc);
1278 /* Store func and arg into the cleanup list element. */
1280 new_func = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
1281 GET_MODE_SIZE (Pmode)));
1282 new_arg = gen_rtx_MEM (Pmode, plus_constant (XEXP (buf, 0),
1283 GET_MODE_SIZE (Pmode)*2));
1284 x = expand_expr (func, new_func, Pmode, 0);
1285 if (x != new_func)
1286 emit_move_insn (new_func, x);
1288 x = expand_expr (arg, new_arg, Pmode, 0);
1289 if (x != new_arg)
1290 emit_move_insn (new_arg, x);
1292 /* Update the cleanup chain. */
1294 x = force_operand (XEXP (buf, 0), dcc);
1295 if (x != dcc)
1296 emit_move_insn (dcc, x);
1299 /* Emit RTL to start a dynamic handler on the EH runtime dynamic
1300 handler stack. This should only be used by expand_eh_region_start
1301 or expand_eh_region_start_tree. */
1303 static void
1304 start_dynamic_handler ()
1306 rtx dhc, dcc;
1307 rtx x, arg, buf;
1308 int size;
1310 #ifndef DONT_USE_BUILTIN_SETJMP
1311 /* The number of Pmode words for the setjmp buffer, when using the
1312 builtin setjmp/longjmp, see expand_builtin, case BUILT_IN_LONGJMP. */
1313 /* We use 2 words here before calling expand_builtin_setjmp.
1314 expand_builtin_setjmp uses 2 words, and then calls emit_stack_save.
1315 emit_stack_save needs space of size STACK_SAVEAREA_MODE (SAVE_NONLOCAL).
1316 Subtract one, because the assign_stack_local call below adds 1. */
1317 size = (2 + 2 + (GET_MODE_SIZE (STACK_SAVEAREA_MODE (SAVE_NONLOCAL))
1318 / GET_MODE_SIZE (Pmode))
1319 - 1);
1320 #else
1321 #ifdef JMP_BUF_SIZE
1322 size = JMP_BUF_SIZE;
1323 #else
1324 /* Should be large enough for most systems, if it is not,
1325 JMP_BUF_SIZE should be defined with the proper value. It will
1326 also tend to be larger than necessary for most systems, a more
1327 optimal port will define JMP_BUF_SIZE. */
1328 size = FIRST_PSEUDO_REGISTER+2;
1329 #endif
1330 #endif
1331 /* XXX, FIXME: The stack space allocated this way is too long lived,
1332 but there is no allocation routine that allocates at the level of
1333 the last binding contour. */
1334 arg = assign_stack_local (BLKmode,
1335 GET_MODE_SIZE (Pmode)*(size+1),
1338 arg = change_address (arg, Pmode, NULL_RTX);
1340 /* Store dhc into the first word of the newly allocated buffer. */
1342 dhc = get_dynamic_handler_chain ();
1343 dcc = gen_rtx_MEM (Pmode, plus_constant (XEXP (arg, 0),
1344 GET_MODE_SIZE (Pmode)));
1345 emit_move_insn (arg, dhc);
1347 /* Zero out the start of the cleanup chain. */
1348 emit_move_insn (dcc, const0_rtx);
1350 /* The jmpbuf starts two words into the area allocated. */
1351 buf = plus_constant (XEXP (arg, 0), GET_MODE_SIZE (Pmode)*2);
1353 #ifdef DONT_USE_BUILTIN_SETJMP
1354 x = emit_library_call_value (setjmp_libfunc, NULL_RTX, LCT_CONST,
1355 TYPE_MODE (integer_type_node), 1,
1356 buf, Pmode);
1357 /* If we come back here for a catch, transfer control to the handler. */
1358 jumpif_rtx (x, ehstack.top->entry->exception_handler_label);
1359 #else
1361 /* A label to continue execution for the no exception case. */
1362 rtx noex = gen_label_rtx();
1363 x = expand_builtin_setjmp (buf, NULL_RTX, noex,
1364 ehstack.top->entry->exception_handler_label);
1365 emit_label (noex);
1367 #endif
1369 /* We are committed to this, so update the handler chain. */
1371 emit_move_insn (dhc, force_operand (XEXP (arg, 0), NULL_RTX));
1374 /* Start an exception handling region for the given cleanup action.
1375 All instructions emitted after this point are considered to be part
1376 of the region until expand_eh_region_end is invoked. CLEANUP is
1377 the cleanup action to perform. The return value is true if the
1378 exception region was optimized away. If that case,
1379 expand_eh_region_end does not need to be called for this cleanup,
1380 nor should it be.
1382 This routine notices one particular common case in C++ code
1383 generation, and optimizes it so as to not need the exception
1384 region. It works by creating a dynamic cleanup action, instead of
1385 a using an exception region. */
1388 expand_eh_region_start_tree (decl, cleanup)
1389 tree decl;
1390 tree cleanup;
1392 /* This is the old code. */
1393 if (! doing_eh (0))
1394 return 0;
1396 /* The optimization only applies to actions protected with
1397 terminate, and only applies if we are using the setjmp/longjmp
1398 codegen method. */
1399 if (exceptions_via_longjmp
1400 && protect_cleanup_actions_with_terminate)
1402 tree func, arg;
1403 tree args;
1405 /* Ignore any UNSAVE_EXPR. */
1406 if (TREE_CODE (cleanup) == UNSAVE_EXPR)
1407 cleanup = TREE_OPERAND (cleanup, 0);
1409 /* Further, it only applies if the action is a call, if there
1410 are 2 arguments, and if the second argument is 2. */
1412 if (TREE_CODE (cleanup) == CALL_EXPR
1413 && (args = TREE_OPERAND (cleanup, 1))
1414 && (func = TREE_OPERAND (cleanup, 0))
1415 && (arg = TREE_VALUE (args))
1416 && (args = TREE_CHAIN (args))
1418 /* is the second argument 2? */
1419 && TREE_CODE (TREE_VALUE (args)) == INTEGER_CST
1420 && compare_tree_int (TREE_VALUE (args), 2) == 0
1422 /* Make sure there are no other arguments. */
1423 && TREE_CHAIN (args) == NULL_TREE)
1425 /* Arrange for returns and gotos to pop the entry we make on the
1426 dynamic cleanup stack. */
1427 expand_dcc_cleanup (decl);
1428 start_dynamic_cleanup (func, arg);
1429 return 1;
1433 expand_eh_region_start_for_decl (decl);
1434 ehstack.top->entry->finalization = cleanup;
1436 return 0;
1439 /* Just like expand_eh_region_start, except if a cleanup action is
1440 entered on the cleanup chain, the TREE_PURPOSE of the element put
1441 on the chain is DECL. DECL should be the associated VAR_DECL, if
1442 any, otherwise it should be NULL_TREE. */
1444 void
1445 expand_eh_region_start_for_decl (decl)
1446 tree decl;
1448 rtx note;
1450 /* This is the old code. */
1451 if (! doing_eh (0))
1452 return;
1454 /* We need a new block to record the start and end of the
1455 dynamic handler chain. We also want to prevent jumping into
1456 a try block. */
1457 expand_start_bindings (2);
1459 /* But we don't need or want a new temporary level. */
1460 pop_temp_slots ();
1462 /* Mark this block as created by expand_eh_region_start. This
1463 is so that we can pop the block with expand_end_bindings
1464 automatically. */
1465 mark_block_as_eh_region ();
1467 if (exceptions_via_longjmp)
1469 /* Arrange for returns and gotos to pop the entry we make on the
1470 dynamic handler stack. */
1471 expand_dhc_cleanup (decl);
1474 push_eh_entry (&ehstack);
1475 note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_BEG);
1476 NOTE_EH_HANDLER (note)
1477 = CODE_LABEL_NUMBER (ehstack.top->entry->exception_handler_label);
1478 if (exceptions_via_longjmp)
1479 start_dynamic_handler ();
1482 /* Start an exception handling region. All instructions emitted after
1483 this point are considered to be part of the region until
1484 expand_eh_region_end is invoked. */
1486 void
1487 expand_eh_region_start ()
1489 expand_eh_region_start_for_decl (NULL_TREE);
1492 /* End an exception handling region. The information about the region
1493 is found on the top of ehstack.
1495 HANDLER is either the cleanup for the exception region, or if we're
1496 marking the end of a try block, HANDLER is integer_zero_node.
1498 HANDLER will be transformed to rtl when expand_leftover_cleanups
1499 is invoked. */
1501 void
1502 expand_eh_region_end (handler)
1503 tree handler;
1505 struct eh_entry *entry;
1506 struct eh_node *node;
1507 rtx note;
1508 int ret, r;
1510 if (! doing_eh (0))
1511 return;
1513 entry = pop_eh_entry (&ehstack);
1515 note = emit_note (NULL_PTR, NOTE_INSN_EH_REGION_END);
1516 ret = NOTE_EH_HANDLER (note)
1517 = CODE_LABEL_NUMBER (entry->exception_handler_label);
1518 if (exceptions_via_longjmp == 0 && ! flag_new_exceptions
1519 /* We share outer_context between regions; only emit it once. */
1520 && INSN_UID (entry->outer_context) == 0)
1522 rtx label;
1524 label = gen_label_rtx ();
1525 emit_jump (label);
1527 /* Emit a label marking the end of this exception region that
1528 is used for rethrowing into the outer context. */
1529 emit_label (entry->outer_context);
1530 expand_internal_throw ();
1532 emit_label (label);
1535 entry->finalization = handler;
1537 /* create region entry in final exception table */
1538 r = new_eh_region_entry (NOTE_EH_HANDLER (note), entry->rethrow_label);
1540 enqueue_eh_entry (ehqueue, entry);
1542 /* If we have already started ending the bindings, don't recurse. */
1543 if (is_eh_region ())
1545 /* Because we don't need or want a new temporary level and
1546 because we didn't create one in expand_eh_region_start,
1547 create a fake one now to avoid removing one in
1548 expand_end_bindings. */
1549 push_temp_slots ();
1551 mark_block_as_not_eh_region ();
1553 expand_end_bindings (NULL_TREE, 0, 0);
1556 /* Go through the goto handlers in the queue, emitting their
1557 handlers if we now have enough information to do so. */
1558 for (node = ehqueue->head; node; node = node->chain)
1559 if (node->entry->goto_entry_p
1560 && node->entry->outer_context == entry->rethrow_label)
1561 emit_cleanup_handler (node->entry);
1563 /* We can't emit handlers for goto entries until their scopes are
1564 complete because we don't know where they need to rethrow to,
1565 yet. */
1566 if (entry->finalization != integer_zero_node
1567 && (!entry->goto_entry_p
1568 || find_func_region_from_symbol (entry->outer_context) != -1))
1569 emit_cleanup_handler (entry);
1572 /* End the EH region for a goto fixup. We only need them in the region-based
1573 EH scheme. */
1575 void
1576 expand_fixup_region_start ()
1578 if (! doing_eh (0) || exceptions_via_longjmp)
1579 return;
1581 expand_eh_region_start ();
1582 /* Mark this entry as the entry for a goto. */
1583 ehstack.top->entry->goto_entry_p = 1;
1586 /* End the EH region for a goto fixup. CLEANUP is the cleanup we just
1587 expanded; to avoid running it twice if it throws, we look through the
1588 ehqueue for a matching region and rethrow from its outer_context. */
1590 void
1591 expand_fixup_region_end (cleanup)
1592 tree cleanup;
1594 struct eh_node *node;
1595 int dont_issue;
1597 if (! doing_eh (0) || exceptions_via_longjmp)
1598 return;
1600 for (node = ehstack.top; node && node->entry->finalization != cleanup; )
1601 node = node->chain;
1602 if (node == 0)
1603 for (node = ehqueue->head; node && node->entry->finalization != cleanup; )
1604 node = node->chain;
1605 if (node == 0)
1606 abort ();
1608 /* If the outer context label has not been issued yet, we don't want
1609 to issue it as a part of this region, unless this is the
1610 correct region for the outer context. If we did, then the label for
1611 the outer context will be WITHIN the begin/end labels,
1612 and we could get an infinte loop when it tried to rethrow, or just
1613 generally incorrect execution following a throw. */
1615 if (flag_new_exceptions)
1616 dont_issue = 0;
1617 else
1618 dont_issue = ((INSN_UID (node->entry->outer_context) == 0)
1619 && (ehstack.top->entry != node->entry));
1621 ehstack.top->entry->outer_context = node->entry->outer_context;
1623 /* Since we are rethrowing to the OUTER region, we know we don't need
1624 a jump around sequence for this region, so we'll pretend the outer
1625 context label has been issued by setting INSN_UID to 1, then clearing
1626 it again afterwards. */
1628 if (dont_issue)
1629 INSN_UID (node->entry->outer_context) = 1;
1631 /* Just rethrow. size_zero_node is just a NOP. */
1632 expand_eh_region_end (size_zero_node);
1634 if (dont_issue)
1635 INSN_UID (node->entry->outer_context) = 0;
1638 /* If we are using the setjmp/longjmp EH codegen method, we emit a
1639 call to __sjthrow. Otherwise, we emit a call to __throw. */
1641 void
1642 emit_throw ()
1644 if (exceptions_via_longjmp)
1646 emit_library_call (sjthrow_libfunc, 0, VOIDmode, 0);
1648 else
1650 #ifdef JUMP_TO_THROW
1651 emit_indirect_jump (throw_libfunc);
1652 #else
1653 emit_library_call (throw_libfunc, 0, VOIDmode, 0);
1654 #endif
1656 emit_barrier ();
1659 /* Throw the current exception. If appropriate, this is done by jumping
1660 to the next handler. */
1662 void
1663 expand_internal_throw ()
1665 emit_throw ();
1668 /* Called from expand_exception_blocks and expand_end_catch_block to
1669 emit any pending handlers/cleanups queued from expand_eh_region_end. */
1671 void
1672 expand_leftover_cleanups ()
1674 struct eh_entry *entry;
1676 for (entry = dequeue_eh_entry (ehqueue);
1677 entry;
1678 entry = dequeue_eh_entry (ehqueue))
1680 /* A leftover try block. Shouldn't be one here. */
1681 if (entry->finalization == integer_zero_node)
1682 abort ();
1684 free (entry);
1688 /* Called at the start of a block of try statements. */
1689 void
1690 expand_start_try_stmts ()
1692 if (! doing_eh (1))
1693 return;
1695 expand_eh_region_start ();
1698 /* Called to begin a catch clause. The parameter is the object which
1699 will be passed to the runtime type check routine. */
1700 void
1701 start_catch_handler (rtime)
1702 tree rtime;
1704 rtx handler_label;
1705 int insn_region_num;
1706 int eh_region_entry;
1708 if (! doing_eh (1))
1709 return;
1711 handler_label = catchstack.top->entry->exception_handler_label;
1712 insn_region_num = CODE_LABEL_NUMBER (handler_label);
1713 eh_region_entry = find_func_region (insn_region_num);
1715 /* If we've already issued this label, pick a new one */
1716 if (catchstack.top->entry->label_used)
1717 handler_label = gen_exception_label ();
1718 else
1719 catchstack.top->entry->label_used = 1;
1721 receive_exception_label (handler_label);
1723 add_new_handler (eh_region_entry, get_new_handler (handler_label, rtime));
1725 if (flag_new_exceptions && ! exceptions_via_longjmp)
1726 return;
1728 /* Under the old mechanism, as well as setjmp/longjmp, we need to
1729 issue code to compare 'rtime' to the value in eh_info, via the
1730 matching function in eh_info. If its is false, we branch around
1731 the handler we are about to issue. */
1733 if (rtime != NULL_TREE && rtime != CATCH_ALL_TYPE)
1735 rtx call_rtx, rtime_address;
1737 if (catchstack.top->entry->false_label != NULL_RTX)
1739 error ("Never issued previous false_label");
1740 abort ();
1742 catchstack.top->entry->false_label = gen_exception_label ();
1744 rtime_address = expand_expr (rtime, NULL_RTX, Pmode, EXPAND_INITIALIZER);
1745 #ifdef POINTERS_EXTEND_UNSIGNED
1746 rtime_address = convert_memory_address (Pmode, rtime_address);
1747 #endif
1748 rtime_address = force_reg (Pmode, rtime_address);
1750 /* Now issue the call, and branch around handler if needed */
1751 call_rtx = emit_library_call_value (eh_rtime_match_libfunc, NULL_RTX,
1752 LCT_NORMAL,
1753 TYPE_MODE (integer_type_node),
1754 1, rtime_address, Pmode);
1756 /* Did the function return true? */
1757 emit_cmp_and_jump_insns (call_rtx, const0_rtx, EQ, NULL_RTX,
1758 GET_MODE (call_rtx), 0, 0,
1759 catchstack.top->entry->false_label);
1763 /* Called to end a catch clause. If we aren't using the new exception
1764 model tabel mechanism, we need to issue the branch-around label
1765 for the end of the catch block. */
1767 void
1768 end_catch_handler ()
1770 if (! doing_eh (1))
1771 return;
1773 if (flag_new_exceptions && ! exceptions_via_longjmp)
1775 emit_barrier ();
1776 return;
1779 /* A NULL label implies the catch clause was a catch all or cleanup */
1780 if (catchstack.top->entry->false_label == NULL_RTX)
1781 return;
1783 emit_label (catchstack.top->entry->false_label);
1784 catchstack.top->entry->false_label = NULL_RTX;
1787 /* Save away the current ehqueue. */
1789 void
1790 push_ehqueue ()
1792 struct eh_queue *q;
1793 q = (struct eh_queue *) xcalloc (1, sizeof (struct eh_queue));
1794 q->next = ehqueue;
1795 ehqueue = q;
1798 /* Restore a previously pushed ehqueue. */
1800 void
1801 pop_ehqueue ()
1803 struct eh_queue *q;
1804 expand_leftover_cleanups ();
1805 q = ehqueue->next;
1806 free (ehqueue);
1807 ehqueue = q;
1810 /* Emit the handler specified by ENTRY. */
1812 static void
1813 emit_cleanup_handler (entry)
1814 struct eh_entry *entry;
1816 rtx prev;
1817 rtx handler_insns;
1819 /* Since the cleanup could itself contain try-catch blocks, we
1820 squirrel away the current queue and replace it when we are done
1821 with this function. */
1822 push_ehqueue ();
1824 /* Put these handler instructions in a sequence. */
1825 do_pending_stack_adjust ();
1826 start_sequence ();
1828 /* Emit the label for the cleanup handler for this region, and
1829 expand the code for the handler.
1831 Note that a catch region is handled as a side-effect here; for a
1832 try block, entry->finalization will contain integer_zero_node, so
1833 no code will be generated in the expand_expr call below. But, the
1834 label for the handler will still be emitted, so any code emitted
1835 after this point will end up being the handler. */
1837 receive_exception_label (entry->exception_handler_label);
1839 /* register a handler for this cleanup region */
1840 add_new_handler (find_func_region (CODE_LABEL_NUMBER (entry->exception_handler_label)),
1841 get_new_handler (entry->exception_handler_label, NULL));
1843 /* And now generate the insns for the cleanup handler. */
1844 expand_expr (entry->finalization, const0_rtx, VOIDmode, 0);
1846 prev = get_last_insn ();
1847 if (prev == NULL || GET_CODE (prev) != BARRIER)
1848 /* Code to throw out to outer context when we fall off end of the
1849 handler. We can't do this here for catch blocks, so it's done
1850 in expand_end_all_catch instead. */
1851 expand_rethrow (entry->outer_context);
1853 /* Finish this sequence. */
1854 do_pending_stack_adjust ();
1855 handler_insns = get_insns ();
1856 end_sequence ();
1858 /* And add it to the CATCH_CLAUSES. */
1859 push_to_full_sequence (catch_clauses, catch_clauses_last);
1860 emit_insns (handler_insns);
1861 end_full_sequence (&catch_clauses, &catch_clauses_last);
1863 /* Now we've left the handler. */
1864 pop_ehqueue ();
1867 /* Generate RTL for the start of a group of catch clauses.
1869 It is responsible for starting a new instruction sequence for the
1870 instructions in the catch block, and expanding the handlers for the
1871 internally-generated exception regions nested within the try block
1872 corresponding to this catch block. */
1874 void
1875 expand_start_all_catch ()
1877 struct eh_entry *entry;
1878 tree label;
1879 rtx outer_context;
1881 if (! doing_eh (1))
1882 return;
1884 outer_context = ehstack.top->entry->outer_context;
1886 /* End the try block. */
1887 expand_eh_region_end (integer_zero_node);
1889 emit_line_note (input_filename, lineno);
1890 label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
1892 /* The label for the exception handling block that we will save.
1893 This is Lresume in the documentation. */
1894 expand_label (label);
1896 /* Push the label that points to where normal flow is resumed onto
1897 the top of the label stack. */
1898 push_label_entry (&caught_return_label_stack, NULL_RTX, label);
1900 /* Start a new sequence for all the catch blocks. We will add this
1901 to the global sequence catch_clauses when we have completed all
1902 the handlers in this handler-seq. */
1903 start_sequence ();
1905 /* Throw away entries in the queue that we won't need anymore. We
1906 need entries for regions that have ended but to which there might
1907 still be gotos pending. */
1908 for (entry = dequeue_eh_entry (ehqueue);
1909 entry->finalization != integer_zero_node;
1910 entry = dequeue_eh_entry (ehqueue))
1911 free (entry);
1913 /* At this point, all the cleanups are done, and the ehqueue now has
1914 the current exception region at its head. We dequeue it, and put it
1915 on the catch stack. */
1916 push_entry (&catchstack, entry);
1918 /* If we are not doing setjmp/longjmp EH, because we are reordered
1919 out of line, we arrange to rethrow in the outer context. We need to
1920 do this because we are not physically within the region, if any, that
1921 logically contains this catch block. */
1922 if (! exceptions_via_longjmp)
1924 expand_eh_region_start ();
1925 ehstack.top->entry->outer_context = outer_context;
1930 /* Finish up the catch block. At this point all the insns for the
1931 catch clauses have already been generated, so we only have to add
1932 them to the catch_clauses list. We also want to make sure that if
1933 we fall off the end of the catch clauses that we rethrow to the
1934 outer EH region. */
1936 void
1937 expand_end_all_catch ()
1939 rtx new_catch_clause;
1940 struct eh_entry *entry;
1942 if (! doing_eh (1))
1943 return;
1945 /* Dequeue the current catch clause region. */
1946 entry = pop_eh_entry (&catchstack);
1947 free (entry);
1949 if (! exceptions_via_longjmp)
1951 rtx outer_context = ehstack.top->entry->outer_context;
1953 /* Finish the rethrow region. size_zero_node is just a NOP. */
1954 expand_eh_region_end (size_zero_node);
1955 /* New exceptions handling models will never have a fall through
1956 of a catch clause */
1957 if (!flag_new_exceptions)
1958 expand_rethrow (outer_context);
1960 else
1961 expand_rethrow (NULL_RTX);
1963 /* Code to throw out to outer context, if we fall off end of catch
1964 handlers. This is rethrow (Lresume, same id, same obj) in the
1965 documentation. We use Lresume because we know that it will throw
1966 to the correct context.
1968 In other words, if the catch handler doesn't exit or return, we
1969 do a "throw" (using the address of Lresume as the point being
1970 thrown from) so that the outer EH region can then try to process
1971 the exception. */
1973 /* Now we have the complete catch sequence. */
1974 new_catch_clause = get_insns ();
1975 end_sequence ();
1977 /* This level of catch blocks is done, so set up the successful
1978 catch jump label for the next layer of catch blocks. */
1979 pop_label_entry (&caught_return_label_stack);
1980 pop_label_entry (&outer_context_label_stack);
1982 /* Add the new sequence of catches to the main one for this function. */
1983 push_to_full_sequence (catch_clauses, catch_clauses_last);
1984 emit_insns (new_catch_clause);
1985 end_full_sequence (&catch_clauses, &catch_clauses_last);
1987 /* Here we fall through into the continuation code. */
1990 /* Rethrow from the outer context LABEL. */
1992 static void
1993 expand_rethrow (label)
1994 rtx label;
1996 if (exceptions_via_longjmp)
1997 emit_throw ();
1998 else
1999 if (flag_new_exceptions)
2001 rtx insn;
2002 int region;
2003 if (label == NULL_RTX)
2004 label = last_rethrow_symbol;
2005 emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
2006 region = find_func_region (eh_region_from_symbol (label));
2007 /* If the region is -1, it doesn't exist yet. We shouldn't be
2008 trying to rethrow there yet. */
2009 if (region == -1)
2010 abort ();
2011 function_eh_regions[region].rethrow_ref = 1;
2013 /* Search backwards for the actual call insn. */
2014 insn = get_last_insn ();
2015 while (GET_CODE (insn) != CALL_INSN)
2016 insn = PREV_INSN (insn);
2017 delete_insns_since (insn);
2019 /* Mark the label/symbol on the call. */
2020 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, label,
2021 REG_NOTES (insn));
2022 emit_barrier ();
2024 else
2025 emit_jump (label);
2028 /* Begin a region that will contain entries created with
2029 add_partial_entry. */
2031 void
2032 begin_protect_partials ()
2034 /* Push room for a new list. */
2035 protect_list = tree_cons (NULL_TREE, NULL_TREE, protect_list);
2038 /* End all the pending exception regions on protect_list. The handlers
2039 will be emitted when expand_leftover_cleanups is invoked. */
2041 void
2042 end_protect_partials ()
2044 tree t;
2046 /* For backwards compatibility, we allow callers to omit the call to
2047 begin_protect_partials for the outermost region. So,
2048 PROTECT_LIST may be NULL. */
2049 if (!protect_list)
2050 return;
2052 /* End all the exception regions. */
2053 for (t = TREE_VALUE (protect_list); t; t = TREE_CHAIN (t))
2054 expand_eh_region_end (TREE_VALUE (t));
2056 /* Pop the topmost entry. */
2057 protect_list = TREE_CHAIN (protect_list);
2061 /* Arrange for __terminate to be called if there is an unhandled throw
2062 from within E. */
2064 tree
2065 protect_with_terminate (e)
2066 tree e;
2068 /* We only need to do this when using setjmp/longjmp EH and the
2069 language requires it, as otherwise we protect all of the handlers
2070 at once, if we need to. */
2071 if (exceptions_via_longjmp && protect_cleanup_actions_with_terminate)
2073 tree handler, result;
2075 handler = make_node (RTL_EXPR);
2076 TREE_TYPE (handler) = void_type_node;
2077 RTL_EXPR_RTL (handler) = const0_rtx;
2078 TREE_SIDE_EFFECTS (handler) = 1;
2079 start_sequence_for_rtl_expr (handler);
2081 emit_library_call (terminate_libfunc, 0, VOIDmode, 0);
2082 emit_barrier ();
2084 RTL_EXPR_SEQUENCE (handler) = get_insns ();
2085 end_sequence ();
2087 result = build (TRY_CATCH_EXPR, TREE_TYPE (e), e, handler);
2088 TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (e);
2089 TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (e);
2090 TREE_READONLY (result) = TREE_READONLY (e);
2092 e = result;
2095 return e;
2098 /* The exception table that we build that is used for looking up and
2099 dispatching exceptions, the current number of entries, and its
2100 maximum size before we have to extend it.
2102 The number in eh_table is the code label number of the exception
2103 handler for the region. This is added by add_eh_table_entry and
2104 used by output_exception_table_entry. */
2106 static int *eh_table = NULL;
2107 static int eh_table_size = 0;
2108 static int eh_table_max_size = 0;
2110 /* Note the need for an exception table entry for region N. If we
2111 don't need to output an explicit exception table, avoid all of the
2112 extra work.
2114 Called from final_scan_insn when a NOTE_INSN_EH_REGION_BEG is seen.
2115 (Or NOTE_INSN_EH_REGION_END sometimes)
2116 N is the NOTE_EH_HANDLER of the note, which comes from the code
2117 label number of the exception handler for the region. */
2119 void
2120 add_eh_table_entry (n)
2121 int n;
2123 #ifndef OMIT_EH_TABLE
2124 if (eh_table_size >= eh_table_max_size)
2126 if (eh_table)
2128 eh_table_max_size += eh_table_max_size>>1;
2130 if (eh_table_max_size < 0)
2131 abort ();
2133 eh_table = (int *) xrealloc (eh_table,
2134 eh_table_max_size * sizeof (int));
2136 else
2138 eh_table_max_size = 252;
2139 eh_table = (int *) xmalloc (eh_table_max_size * sizeof (int));
2142 eh_table[eh_table_size++] = n;
2144 if (flag_new_exceptions)
2146 /* We will output the exception table late in the compilation. That
2147 references type_info objects which should have already been output
2148 by that time. We explicitly mark those objects as being
2149 referenced now so we know to emit them. */
2150 struct handler_info *handler = get_first_handler (n);
2152 for (; handler; handler = handler->next)
2153 if (handler->type_info && handler->type_info != CATCH_ALL_TYPE)
2155 tree tinfo = (tree)handler->type_info;
2157 tinfo = TREE_OPERAND (tinfo, 0);
2158 TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (tinfo)) = 1;
2161 #endif
2164 /* Return a non-zero value if we need to output an exception table.
2166 On some platforms, we don't have to output a table explicitly.
2167 This routine doesn't mean we don't have one. */
2170 exception_table_p ()
2172 if (eh_table)
2173 return 1;
2175 return 0;
2178 /* Output the entry of the exception table corresponding to the
2179 exception region numbered N to file FILE.
2181 N is the code label number corresponding to the handler of the
2182 region. */
2184 static void
2185 output_exception_table_entry (file, n)
2186 FILE *file;
2187 int n;
2189 char buf[256];
2190 rtx sym;
2191 struct handler_info *handler = get_first_handler (n);
2192 int index = find_func_region (n);
2193 rtx rethrow;
2195 /* Form and emit the rethrow label, if needed */
2196 if (flag_new_exceptions
2197 && (handler || function_eh_regions[index].rethrow_ref))
2198 rethrow = function_eh_regions[index].rethrow_label;
2199 else
2200 rethrow = NULL_RTX;
2202 if (function_eh_regions[index].emitted)
2203 return;
2204 function_eh_regions[index].emitted = 1;
2206 for ( ; handler != NULL || rethrow != NULL_RTX; handler = handler->next)
2208 /* rethrow label should indicate the LAST entry for a region */
2209 if (rethrow != NULL_RTX && (handler == NULL || handler->next == NULL))
2211 ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", n);
2212 assemble_eh_label(buf);
2213 rethrow = NULL_RTX;
2216 ASM_GENERATE_INTERNAL_LABEL (buf, "LEHB", n);
2217 sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2218 assemble_eh_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2220 ASM_GENERATE_INTERNAL_LABEL (buf, "LEHE", n);
2221 sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2222 assemble_eh_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2224 if (handler == NULL)
2225 assemble_eh_integer (GEN_INT (0), POINTER_SIZE / BITS_PER_UNIT, 1);
2226 else
2228 ASM_GENERATE_INTERNAL_LABEL (buf, "L", handler->handler_number);
2229 sym = gen_rtx_SYMBOL_REF (Pmode, buf);
2230 assemble_eh_integer (sym, POINTER_SIZE / BITS_PER_UNIT, 1);
2233 if (flag_new_exceptions)
2235 if (handler == NULL || handler->type_info == NULL)
2236 assemble_eh_integer (const0_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2237 else
2238 if (handler->type_info == CATCH_ALL_TYPE)
2239 assemble_eh_integer (GEN_INT (CATCH_ALL_TYPE),
2240 POINTER_SIZE / BITS_PER_UNIT, 1);
2241 else
2242 output_constant ((tree)(handler->type_info),
2243 POINTER_SIZE / BITS_PER_UNIT);
2245 putc ('\n', file); /* blank line */
2246 /* We only output the first label under the old scheme */
2247 if (! flag_new_exceptions || handler == NULL)
2248 break;
2252 /* Output the exception table if we have and need one. */
2254 static short language_code = 0;
2255 static short version_code = 0;
2257 /* This routine will set the language code for exceptions. */
2258 void
2259 set_exception_lang_code (code)
2260 int code;
2262 language_code = code;
2265 /* This routine will set the language version code for exceptions. */
2266 void
2267 set_exception_version_code (code)
2268 int code;
2270 version_code = code;
2273 /* Free the EH table structures. */
2274 void
2275 free_exception_table ()
2277 if (eh_table)
2278 free (eh_table);
2279 clear_function_eh_region ();
2282 /* Output the common content of an exception table. */
2283 void
2284 output_exception_table_data ()
2286 int i;
2287 char buf[256];
2288 extern FILE *asm_out_file;
2290 if (flag_new_exceptions)
2292 assemble_eh_integer (GEN_INT (NEW_EH_RUNTIME),
2293 POINTER_SIZE / BITS_PER_UNIT, 1);
2294 assemble_eh_integer (GEN_INT (language_code), 2 , 1);
2295 assemble_eh_integer (GEN_INT (version_code), 2 , 1);
2297 /* Add enough padding to make sure table aligns on a pointer boundry. */
2298 i = GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT - 4;
2299 for ( ; i < 0; i = i + GET_MODE_ALIGNMENT (ptr_mode) / BITS_PER_UNIT)
2301 if (i != 0)
2302 assemble_eh_integer (const0_rtx, i , 1);
2304 /* Generate the label for offset calculations on rethrows. */
2305 ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", 0);
2306 assemble_eh_label(buf);
2309 for (i = 0; i < eh_table_size; ++i)
2310 output_exception_table_entry (asm_out_file, eh_table[i]);
2314 /* Output an exception table for the entire compilation unit. */
2315 void
2316 output_exception_table ()
2318 char buf[256];
2319 extern FILE *asm_out_file;
2321 if (! doing_eh (0) || ! eh_table)
2322 return;
2324 exception_section ();
2326 /* Beginning marker for table. */
2327 assemble_eh_align (GET_MODE_ALIGNMENT (ptr_mode));
2328 assemble_eh_label ("__EXCEPTION_TABLE__");
2330 output_exception_table_data ();
2332 /* Ending marker for table. */
2333 /* Generate the label for end of table. */
2334 ASM_GENERATE_INTERNAL_LABEL (buf, "LRTH", CODE_LABEL_NUMBER (final_rethrow));
2335 assemble_eh_label(buf);
2336 assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2338 /* For binary compatibility, the old __throw checked the second
2339 position for a -1, so we should output at least 2 -1's */
2340 if (! flag_new_exceptions)
2341 assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2343 putc ('\n', asm_out_file); /* blank line */
2346 /* Used by the ia64 unwind format to output data for an individual
2347 function. */
2348 void
2349 output_function_exception_table ()
2351 extern FILE *asm_out_file;
2353 if (! doing_eh (0) || ! eh_table)
2354 return;
2356 #ifdef HANDLER_SECTION
2357 HANDLER_SECTION;
2358 #endif
2360 output_exception_table_data ();
2362 /* Ending marker for table. */
2363 assemble_eh_integer (constm1_rtx, POINTER_SIZE / BITS_PER_UNIT, 1);
2365 putc ('\n', asm_out_file); /* blank line */
2369 /* Emit code to get EH context.
2371 We have to scan thru the code to find possible EH context registers.
2372 Inlined functions may use it too, and thus we'll have to be able
2373 to change them too.
2375 This is done only if using exceptions_via_longjmp. */
2377 void
2378 emit_eh_context ()
2380 rtx insn;
2381 rtx ehc = 0;
2383 if (! doing_eh (0))
2384 return;
2386 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2387 if (GET_CODE (insn) == INSN
2388 && GET_CODE (PATTERN (insn)) == USE)
2390 rtx reg = find_reg_note (insn, REG_EH_CONTEXT, 0);
2391 if (reg)
2393 rtx insns;
2395 start_sequence ();
2397 /* If this is the first use insn, emit the call here. This
2398 will always be at the top of our function, because if
2399 expand_inline_function notices a REG_EH_CONTEXT note, it
2400 adds a use insn to this function as well. */
2401 if (ehc == 0)
2402 ehc = call_get_eh_context ();
2404 emit_move_insn (XEXP (reg, 0), ehc);
2405 insns = get_insns ();
2406 end_sequence ();
2408 emit_insns_before (insns, insn);
2413 /* Scan the insn chain F and build a list of handler labels. The
2414 resulting list is placed in the global variable exception_handler_labels. */
2416 static void
2417 find_exception_handler_labels_1 (f)
2418 rtx f;
2420 rtx insn;
2422 /* For each start of a region, add its label to the list. */
2424 for (insn = f; insn; insn = NEXT_INSN (insn))
2426 struct handler_info* ptr;
2427 if (GET_CODE (insn) == NOTE
2428 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2430 ptr = get_first_handler (NOTE_EH_HANDLER (insn));
2431 for ( ; ptr; ptr = ptr->next)
2433 /* make sure label isn't in the list already */
2434 rtx x;
2435 for (x = exception_handler_labels; x; x = XEXP (x, 1))
2436 if (XEXP (x, 0) == ptr->handler_label)
2437 break;
2438 if (! x)
2439 exception_handler_labels = gen_rtx_EXPR_LIST (VOIDmode,
2440 ptr->handler_label, exception_handler_labels);
2443 else if (GET_CODE (insn) == CALL_INSN
2444 && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER)
2446 find_exception_handler_labels_1 (XEXP (PATTERN (insn), 0));
2447 find_exception_handler_labels_1 (XEXP (PATTERN (insn), 1));
2448 find_exception_handler_labels_1 (XEXP (PATTERN (insn), 2));
2453 /* Scan the current insns and build a list of handler labels. The
2454 resulting list is placed in the global variable exception_handler_labels.
2456 It is called after the last exception handling region is added to
2457 the current function (when the rtl is almost all built for the
2458 current function) and before the jump optimization pass. */
2459 void
2460 find_exception_handler_labels ()
2462 exception_handler_labels = NULL_RTX;
2464 /* If we aren't doing exception handling, there isn't much to check. */
2465 if (! doing_eh (0))
2466 return;
2468 find_exception_handler_labels_1 (get_insns ());
2471 /* Return a value of 1 if the parameter label number is an exception handler
2472 label. Return 0 otherwise. */
2475 is_exception_handler_label (lab)
2476 int lab;
2478 rtx x;
2479 for (x = exception_handler_labels ; x ; x = XEXP (x, 1))
2480 if (lab == CODE_LABEL_NUMBER (XEXP (x, 0)))
2481 return 1;
2482 return 0;
2485 /* Perform sanity checking on the exception_handler_labels list.
2487 Can be called after find_exception_handler_labels is called to
2488 build the list of exception handlers for the current function and
2489 before we finish processing the current function. */
2491 void
2492 check_exception_handler_labels ()
2494 rtx insn, insn2;
2496 /* If we aren't doing exception handling, there isn't much to check. */
2497 if (! doing_eh (0))
2498 return;
2500 /* Make sure there is no more than 1 copy of a label */
2501 for (insn = exception_handler_labels; insn; insn = XEXP (insn, 1))
2503 int count = 0;
2504 for (insn2 = exception_handler_labels; insn2; insn2 = XEXP (insn2, 1))
2505 if (XEXP (insn, 0) == XEXP (insn2, 0))
2506 count++;
2507 if (count != 1)
2508 warning ("Counted %d copies of EH region %d in list.\n", count,
2509 CODE_LABEL_NUMBER (insn));
2514 /* Mark the children of NODE for GC. */
2516 static void
2517 mark_eh_node (node)
2518 struct eh_node *node;
2520 while (node)
2522 if (node->entry)
2524 ggc_mark_rtx (node->entry->outer_context);
2525 ggc_mark_rtx (node->entry->exception_handler_label);
2526 ggc_mark_tree (node->entry->finalization);
2527 ggc_mark_rtx (node->entry->false_label);
2528 ggc_mark_rtx (node->entry->rethrow_label);
2530 node = node ->chain;
2534 /* Mark S for GC. */
2536 static void
2537 mark_eh_stack (s)
2538 struct eh_stack *s;
2540 if (s)
2541 mark_eh_node (s->top);
2544 /* Mark Q for GC. */
2546 static void
2547 mark_eh_queue (q)
2548 struct eh_queue *q;
2550 while (q)
2552 mark_eh_node (q->head);
2553 q = q->next;
2557 /* Mark NODE for GC. A label_node contains a union containing either
2558 a tree or an rtx. This label_node will contain a tree. */
2560 static void
2561 mark_tree_label_node (node)
2562 struct label_node *node;
2564 while (node)
2566 ggc_mark_tree (node->u.tlabel);
2567 node = node->chain;
2571 /* Mark EH for GC. */
2573 void
2574 mark_eh_status (eh)
2575 struct eh_status *eh;
2577 if (eh == 0)
2578 return;
2580 mark_eh_stack (&eh->x_ehstack);
2581 mark_eh_stack (&eh->x_catchstack);
2582 mark_eh_queue (eh->x_ehqueue);
2583 ggc_mark_rtx (eh->x_catch_clauses);
2585 if (lang_mark_false_label_stack)
2586 (*lang_mark_false_label_stack) (eh->x_false_label_stack);
2587 mark_tree_label_node (eh->x_caught_return_label_stack);
2589 ggc_mark_tree (eh->x_protect_list);
2590 ggc_mark_rtx (eh->ehc);
2591 ggc_mark_rtx (eh->x_eh_return_stub_label);
2594 /* Mark ARG (which is really a struct func_eh_entry**) for GC. */
2596 static void
2597 mark_func_eh_entry (arg)
2598 void *arg;
2600 struct func_eh_entry *fee;
2601 struct handler_info *h;
2602 int i;
2604 fee = *((struct func_eh_entry **) arg);
2606 for (i = 0; i < current_func_eh_entry; ++i)
2608 ggc_mark_rtx (fee->rethrow_label);
2609 for (h = fee->handlers; h; h = h->next)
2611 ggc_mark_rtx (h->handler_label);
2612 if (h->type_info != CATCH_ALL_TYPE)
2613 ggc_mark_tree ((tree) h->type_info);
2616 /* Skip to the next entry in the array. */
2617 ++fee;
2621 /* This group of functions initializes the exception handling data
2622 structures at the start of the compilation, initializes the data
2623 structures at the start of a function, and saves and restores the
2624 exception handling data structures for the start/end of a nested
2625 function. */
2627 /* Toplevel initialization for EH things. */
2629 void
2630 init_eh ()
2632 first_rethrow_symbol = create_rethrow_ref (0);
2633 final_rethrow = gen_exception_label ();
2634 last_rethrow_symbol = create_rethrow_ref (CODE_LABEL_NUMBER (final_rethrow));
2636 ggc_add_rtx_root (&exception_handler_labels, 1);
2637 ggc_add_rtx_root (&eh_return_context, 1);
2638 ggc_add_rtx_root (&eh_return_stack_adjust, 1);
2639 ggc_add_rtx_root (&eh_return_handler, 1);
2640 ggc_add_rtx_root (&first_rethrow_symbol, 1);
2641 ggc_add_rtx_root (&final_rethrow, 1);
2642 ggc_add_rtx_root (&last_rethrow_symbol, 1);
2643 ggc_add_root (&function_eh_regions, 1, sizeof (function_eh_regions),
2644 mark_func_eh_entry);
2647 /* Initialize the per-function EH information. */
2649 void
2650 init_eh_for_function ()
2652 cfun->eh = (struct eh_status *) xcalloc (1, sizeof (struct eh_status));
2653 ehqueue = (struct eh_queue *) xcalloc (1, sizeof (struct eh_queue));
2654 eh_return_context = NULL_RTX;
2655 eh_return_stack_adjust = NULL_RTX;
2656 eh_return_handler = NULL_RTX;
2659 void
2660 free_eh_status (f)
2661 struct function *f;
2663 free (f->eh->x_ehqueue);
2664 free (f->eh);
2665 f->eh = NULL;
2668 /* This section is for the exception handling specific optimization
2669 pass. */
2671 /* Determine if the given INSN can throw an exception. */
2674 can_throw (insn)
2675 rtx insn;
2677 if (GET_CODE (insn) == INSN
2678 && GET_CODE (PATTERN (insn)) == SEQUENCE)
2679 insn = XVECEXP (PATTERN (insn), 0, 0);
2681 /* Calls can always potentially throw exceptions, unless they have
2682 a REG_EH_REGION note with a value of 0 or less. */
2683 if (GET_CODE (insn) == CALL_INSN)
2685 rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
2686 if (!note || INTVAL (XEXP (note, 0)) > 0)
2687 return 1;
2690 if (asynchronous_exceptions)
2692 /* If we wanted asynchronous exceptions, then everything but NOTEs
2693 and CODE_LABELs could throw. */
2694 if (GET_CODE (insn) != NOTE && GET_CODE (insn) != CODE_LABEL)
2695 return 1;
2698 return 0;
2701 /* Return nonzero if nothing in this function can throw. */
2704 nothrow_function_p ()
2706 rtx insn;
2708 if (! flag_exceptions)
2709 return 1;
2711 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2712 if (can_throw (insn))
2713 return 0;
2714 for (insn = current_function_epilogue_delay_list; insn;
2715 insn = XEXP (insn, 1))
2716 if (can_throw (insn))
2717 return 0;
2719 return 1;
2722 /* Scan a exception region looking for the matching end and then
2723 remove it if possible. INSN is the start of the region, N is the
2724 region number, and DELETE_OUTER is to note if anything in this
2725 region can throw.
2727 Regions are removed if they cannot possibly catch an exception.
2728 This is determined by invoking can_throw on each insn within the
2729 region; if can_throw returns true for any of the instructions, the
2730 region can catch an exception, since there is an insn within the
2731 region that is capable of throwing an exception.
2733 Returns the NOTE_INSN_EH_REGION_END corresponding to this region, or
2734 calls abort if it can't find one.
2736 Can abort if INSN is not a NOTE_INSN_EH_REGION_BEGIN, or if N doesn't
2737 correspond to the region number, or if DELETE_OUTER is NULL. */
2739 static rtx
2740 scan_region (insn, n, delete_outer)
2741 rtx insn;
2742 int n;
2743 int *delete_outer;
2745 rtx start = insn;
2747 /* Assume we can delete the region. */
2748 int delete = 1;
2750 /* Can't delete something which is rethrown from. */
2751 if (rethrow_used (n))
2752 delete = 0;
2754 if (insn == NULL_RTX
2755 || GET_CODE (insn) != NOTE
2756 || NOTE_LINE_NUMBER (insn) != NOTE_INSN_EH_REGION_BEG
2757 || NOTE_EH_HANDLER (insn) != n
2758 || delete_outer == NULL)
2759 abort ();
2761 insn = NEXT_INSN (insn);
2763 /* Look for the matching end. */
2764 while (! (GET_CODE (insn) == NOTE
2765 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
2767 /* If anything can throw, we can't remove the region. */
2768 if (delete && can_throw (insn))
2770 delete = 0;
2773 /* Watch out for and handle nested regions. */
2774 if (GET_CODE (insn) == NOTE
2775 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2777 insn = scan_region (insn, NOTE_EH_HANDLER (insn), &delete);
2780 insn = NEXT_INSN (insn);
2783 /* The _BEG/_END NOTEs must match and nest. */
2784 if (NOTE_EH_HANDLER (insn) != n)
2785 abort ();
2787 /* If anything in this exception region can throw, we can throw. */
2788 if (! delete)
2789 *delete_outer = 0;
2790 else
2792 /* Delete the start and end of the region. */
2793 delete_insn (start);
2794 delete_insn (insn);
2796 /* We no longer removed labels here, since flow will now remove any
2797 handler which cannot be called any more. */
2799 #if 0
2800 /* Only do this part if we have built the exception handler
2801 labels. */
2802 if (exception_handler_labels)
2804 rtx x, *prev = &exception_handler_labels;
2806 /* Find it in the list of handlers. */
2807 for (x = exception_handler_labels; x; x = XEXP (x, 1))
2809 rtx label = XEXP (x, 0);
2810 if (CODE_LABEL_NUMBER (label) == n)
2812 /* If we are the last reference to the handler,
2813 delete it. */
2814 if (--LABEL_NUSES (label) == 0)
2815 delete_insn (label);
2817 if (optimize)
2819 /* Remove it from the list of exception handler
2820 labels, if we are optimizing. If we are not, then
2821 leave it in the list, as we are not really going to
2822 remove the region. */
2823 *prev = XEXP (x, 1);
2824 XEXP (x, 1) = 0;
2825 XEXP (x, 0) = 0;
2828 break;
2830 prev = &XEXP (x, 1);
2833 #endif
2835 return insn;
2838 /* Perform various interesting optimizations for exception handling
2839 code.
2841 We look for empty exception regions and make them go (away). The
2842 jump optimization code will remove the handler if nothing else uses
2843 it. */
2845 void
2846 exception_optimize ()
2848 rtx insn;
2849 int n;
2851 /* Remove empty regions. */
2852 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2854 if (GET_CODE (insn) == NOTE
2855 && NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2857 /* Since scan_region will return the NOTE_INSN_EH_REGION_END
2858 insn, we will indirectly skip through all the insns
2859 inbetween. We are also guaranteed that the value of insn
2860 returned will be valid, as otherwise scan_region won't
2861 return. */
2862 insn = scan_region (insn, NOTE_EH_HANDLER (insn), &n);
2867 /* This function determines whether the rethrow labels for any of the
2868 exception regions in the current function are used or not, and set
2869 the reference flag according. */
2871 void
2872 update_rethrow_references ()
2874 rtx insn;
2875 int x, region;
2876 int *saw_region, *saw_rethrow;
2878 if (!flag_new_exceptions)
2879 return;
2881 saw_region = (int *) xcalloc (current_func_eh_entry, sizeof (int));
2882 saw_rethrow = (int *) xcalloc (current_func_eh_entry, sizeof (int));
2884 /* Determine what regions exist, and whether there are any rethrows
2885 from those regions or not. */
2886 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2887 if (GET_CODE (insn) == CALL_INSN)
2889 rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
2890 if (note)
2892 region = eh_region_from_symbol (XEXP (note, 0));
2893 region = find_func_region (region);
2894 saw_rethrow[region] = 1;
2897 else
2898 if (GET_CODE (insn) == NOTE)
2900 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
2902 region = find_func_region (NOTE_EH_HANDLER (insn));
2903 saw_region[region] = 1;
2907 /* For any regions we did see, set the referenced flag. */
2908 for (x = 0; x < current_func_eh_entry; x++)
2909 if (saw_region[x])
2910 function_eh_regions[x].rethrow_ref = saw_rethrow[x];
2912 /* Clean up. */
2913 free (saw_region);
2914 free (saw_rethrow);
2917 /* Various hooks for the DWARF 2 __throw routine. */
2919 /* Do any necessary initialization to access arbitrary stack frames.
2920 On the SPARC, this means flushing the register windows. */
2922 void
2923 expand_builtin_unwind_init ()
2925 /* Set this so all the registers get saved in our frame; we need to be
2926 able to copy the saved values for any registers from frames we unwind. */
2927 current_function_has_nonlocal_label = 1;
2929 #ifdef SETUP_FRAME_ADDRESSES
2930 SETUP_FRAME_ADDRESSES ();
2931 #endif
2934 /* Given a value extracted from the return address register or stack slot,
2935 return the actual address encoded in that value. */
2938 expand_builtin_extract_return_addr (addr_tree)
2939 tree addr_tree;
2941 rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
2942 return eh_outer_context (addr);
2945 /* Given an actual address in addr_tree, do any necessary encoding
2946 and return the value to be stored in the return address register or
2947 stack slot so the epilogue will return to that address. */
2950 expand_builtin_frob_return_addr (addr_tree)
2951 tree addr_tree;
2953 rtx addr = expand_expr (addr_tree, NULL_RTX, Pmode, 0);
2954 #ifdef RETURN_ADDR_OFFSET
2955 addr = plus_constant (addr, -RETURN_ADDR_OFFSET);
2956 #endif
2957 return addr;
2960 /* Choose three registers for communication between the main body of
2961 __throw and the epilogue (or eh stub) and the exception handler.
2962 We must do this with hard registers because the epilogue itself
2963 will be generated after reload, at which point we may not reference
2964 pseudos at all.
2966 The first passes the exception context to the handler. For this
2967 we use the return value register for a void*.
2969 The second holds the stack pointer value to be restored. For this
2970 we use the static chain register if it exists, is different from
2971 the previous, and is call-clobbered; otherwise some arbitrary
2972 call-clobbered register.
2974 The third holds the address of the handler itself. Here we use
2975 some arbitrary call-clobbered register. */
2977 static void
2978 eh_regs (pcontext, psp, pra, outgoing)
2979 rtx *pcontext, *psp, *pra;
2980 int outgoing ATTRIBUTE_UNUSED;
2982 rtx rcontext, rsp, rra;
2983 unsigned int i;
2985 #ifdef FUNCTION_OUTGOING_VALUE
2986 if (outgoing)
2987 rcontext = FUNCTION_OUTGOING_VALUE (build_pointer_type (void_type_node),
2988 current_function_decl);
2989 else
2990 #endif
2991 rcontext = FUNCTION_VALUE (build_pointer_type (void_type_node),
2992 current_function_decl);
2994 #ifdef STATIC_CHAIN_REGNUM
2995 if (outgoing)
2996 rsp = static_chain_incoming_rtx;
2997 else
2998 rsp = static_chain_rtx;
2999 if (REGNO (rsp) == REGNO (rcontext)
3000 || ! call_used_regs [REGNO (rsp)])
3001 #endif /* STATIC_CHAIN_REGNUM */
3002 rsp = NULL_RTX;
3004 if (rsp == NULL_RTX)
3006 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
3007 if (call_used_regs[i] && ! fixed_regs[i] && i != REGNO (rcontext))
3008 break;
3009 if (i == FIRST_PSEUDO_REGISTER)
3010 abort();
3012 rsp = gen_rtx_REG (Pmode, i);
3015 for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
3016 if (call_used_regs[i] && ! fixed_regs[i]
3017 && i != REGNO (rcontext) && i != REGNO (rsp))
3018 break;
3019 if (i == FIRST_PSEUDO_REGISTER)
3020 abort();
3022 rra = gen_rtx_REG (Pmode, i);
3024 *pcontext = rcontext;
3025 *psp = rsp;
3026 *pra = rra;
3029 /* Retrieve the register which contains the pointer to the eh_context
3030 structure set the __throw. */
3032 #if 0
3033 rtx
3034 get_reg_for_handler ()
3036 rtx reg1;
3037 reg1 = FUNCTION_VALUE (build_pointer_type (void_type_node),
3038 current_function_decl);
3039 return reg1;
3041 #endif
3043 /* Set up the epilogue with the magic bits we'll need to return to the
3044 exception handler. */
3046 void
3047 expand_builtin_eh_return (context, stack, handler)
3048 tree context, stack, handler;
3050 if (eh_return_context)
3051 error("Duplicate call to __builtin_eh_return");
3053 eh_return_context
3054 = copy_to_reg (expand_expr (context, NULL_RTX, VOIDmode, 0));
3055 eh_return_stack_adjust
3056 = copy_to_reg (expand_expr (stack, NULL_RTX, VOIDmode, 0));
3057 eh_return_handler
3058 = copy_to_reg (expand_expr (handler, NULL_RTX, VOIDmode, 0));
3061 void
3062 expand_eh_return ()
3064 rtx reg1, reg2, reg3;
3065 rtx stub_start, after_stub;
3066 rtx ra, tmp;
3068 if (!eh_return_context)
3069 return;
3071 current_function_cannot_inline = N_("function uses __builtin_eh_return");
3073 eh_regs (&reg1, &reg2, &reg3, 1);
3074 #ifdef POINTERS_EXTEND_UNSIGNED
3075 eh_return_context = convert_memory_address (Pmode, eh_return_context);
3076 eh_return_stack_adjust =
3077 convert_memory_address (Pmode, eh_return_stack_adjust);
3078 eh_return_handler = convert_memory_address (Pmode, eh_return_handler);
3079 #endif
3080 emit_move_insn (reg1, eh_return_context);
3081 emit_move_insn (reg2, eh_return_stack_adjust);
3082 emit_move_insn (reg3, eh_return_handler);
3084 /* Talk directly to the target's epilogue code when possible. */
3086 #ifdef HAVE_eh_epilogue
3087 if (HAVE_eh_epilogue)
3089 emit_insn (gen_eh_epilogue (reg1, reg2, reg3));
3090 return;
3092 #endif
3094 /* Otherwise, use the same stub technique we had before. */
3096 eh_return_stub_label = stub_start = gen_label_rtx ();
3097 after_stub = gen_label_rtx ();
3099 /* Set the return address to the stub label. */
3101 ra = expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS,
3102 0, hard_frame_pointer_rtx);
3103 if (GET_CODE (ra) == REG && REGNO (ra) >= FIRST_PSEUDO_REGISTER)
3104 abort();
3106 tmp = memory_address (Pmode, gen_rtx_LABEL_REF (Pmode, stub_start));
3107 #ifdef RETURN_ADDR_OFFSET
3108 tmp = plus_constant (tmp, -RETURN_ADDR_OFFSET);
3109 #endif
3110 tmp = force_operand (tmp, ra);
3111 if (tmp != ra)
3112 emit_move_insn (ra, tmp);
3114 /* Indicate that the registers are in fact used. */
3115 emit_insn (gen_rtx_USE (VOIDmode, reg1));
3116 emit_insn (gen_rtx_USE (VOIDmode, reg2));
3117 emit_insn (gen_rtx_USE (VOIDmode, reg3));
3118 if (GET_CODE (ra) == REG)
3119 emit_insn (gen_rtx_USE (VOIDmode, ra));
3121 /* Generate the stub. */
3123 emit_jump (after_stub);
3124 emit_label (stub_start);
3126 eh_regs (&reg1, &reg2, &reg3, 0);
3127 adjust_stack (reg2);
3128 emit_indirect_jump (reg3);
3130 emit_label (after_stub);
3134 /* This contains the code required to verify whether arbitrary instructions
3135 are in the same exception region. */
3137 static int *insn_eh_region = (int *)0;
3138 static int maximum_uid;
3140 static void
3141 set_insn_eh_region (first, region_num)
3142 rtx *first;
3143 int region_num;
3145 rtx insn;
3146 int rnum;
3148 for (insn = *first; insn; insn = NEXT_INSN (insn))
3150 if ((GET_CODE (insn) == NOTE)
3151 && (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG))
3153 rnum = NOTE_EH_HANDLER (insn);
3154 insn_eh_region[INSN_UID (insn)] = rnum;
3155 insn = NEXT_INSN (insn);
3156 set_insn_eh_region (&insn, rnum);
3157 /* Upon return, insn points to the EH_REGION_END of nested region */
3158 continue;
3160 insn_eh_region[INSN_UID (insn)] = region_num;
3161 if ((GET_CODE (insn) == NOTE) &&
3162 (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END))
3163 break;
3165 *first = insn;
3168 /* Free the insn table, an make sure it cannot be used again. */
3170 void
3171 free_insn_eh_region ()
3173 if (!doing_eh (0))
3174 return;
3176 if (insn_eh_region)
3178 free (insn_eh_region);
3179 insn_eh_region = (int *)0;
3183 /* Initialize the table. max_uid must be calculated and handed into
3184 this routine. If it is unavailable, passing a value of 0 will
3185 cause this routine to calculate it as well. */
3187 void
3188 init_insn_eh_region (first, max_uid)
3189 rtx first;
3190 int max_uid;
3192 rtx insn;
3194 if (!doing_eh (0))
3195 return;
3197 if (insn_eh_region)
3198 free_insn_eh_region();
3200 if (max_uid == 0)
3201 for (insn = first; insn; insn = NEXT_INSN (insn))
3202 if (INSN_UID (insn) > max_uid) /* find largest UID */
3203 max_uid = INSN_UID (insn);
3205 maximum_uid = max_uid;
3206 insn_eh_region = (int *) xmalloc ((max_uid + 1) * sizeof (int));
3207 insn = first;
3208 set_insn_eh_region (&insn, 0);
3212 /* Check whether 2 instructions are within the same region. */
3214 int
3215 in_same_eh_region (insn1, insn2)
3216 rtx insn1, insn2;
3218 int ret, uid1, uid2;
3220 /* If no exceptions, instructions are always in same region. */
3221 if (!doing_eh (0))
3222 return 1;
3224 /* If the table isn't allocated, assume the worst. */
3225 if (!insn_eh_region)
3226 return 0;
3228 uid1 = INSN_UID (insn1);
3229 uid2 = INSN_UID (insn2);
3231 /* if instructions have been allocated beyond the end, either
3232 the table is out of date, or this is a late addition, or
3233 something... Assume the worst. */
3234 if (uid1 > maximum_uid || uid2 > maximum_uid)
3235 return 0;
3237 ret = (insn_eh_region[uid1] == insn_eh_region[uid2]);
3238 return ret;
3242 /* This function will initialize the handler list for a specified block.
3243 It may recursively call itself if the outer block hasn't been processed
3244 yet. At some point in the future we can trim out handlers which we
3245 know cannot be called. (ie, if a block has an INT type handler,
3246 control will never be passed to an outer INT type handler). */
3248 static void
3249 process_nestinfo (block, info, nested_eh_region)
3250 int block;
3251 eh_nesting_info *info;
3252 int *nested_eh_region;
3254 handler_info *ptr, *last_ptr = NULL;
3255 int x, y, count = 0;
3256 int extra = 0;
3257 handler_info **extra_handlers = 0;
3258 int index = info->region_index[block];
3260 /* If we've already processed this block, simply return. */
3261 if (info->num_handlers[index] > 0)
3262 return;
3264 for (ptr = get_first_handler (block); ptr; last_ptr = ptr, ptr = ptr->next)
3265 count++;
3267 /* pick up any information from the next outer region. It will already
3268 contain a summary of itself and all outer regions to it. */
3270 if (nested_eh_region [block] != 0)
3272 int nested_index = info->region_index[nested_eh_region[block]];
3273 process_nestinfo (nested_eh_region[block], info, nested_eh_region);
3274 extra = info->num_handlers[nested_index];
3275 extra_handlers = info->handlers[nested_index];
3276 info->outer_index[index] = nested_index;
3279 /* If the last handler is either a CATCH_ALL or a cleanup, then we
3280 won't use the outer ones since we know control will not go past the
3281 catch-all or cleanup. */
3283 if (last_ptr != NULL && (last_ptr->type_info == NULL
3284 || last_ptr->type_info == CATCH_ALL_TYPE))
3285 extra = 0;
3287 info->num_handlers[index] = count + extra;
3288 info->handlers[index] = (handler_info **) xmalloc ((count + extra)
3289 * sizeof (handler_info **));
3291 /* First put all our handlers into the list. */
3292 ptr = get_first_handler (block);
3293 for (x = 0; x < count; x++)
3295 info->handlers[index][x] = ptr;
3296 ptr = ptr->next;
3299 /* Now add all the outer region handlers, if they aren't they same as
3300 one of the types in the current block. We won't worry about
3301 derived types yet, we'll just look for the exact type. */
3302 for (y =0, x = 0; x < extra ; x++)
3304 int i, ok;
3305 ok = 1;
3306 /* Check to see if we have a type duplication. */
3307 for (i = 0; i < count; i++)
3308 if (info->handlers[index][i]->type_info == extra_handlers[x]->type_info)
3310 ok = 0;
3311 /* Record one less handler. */
3312 (info->num_handlers[index])--;
3313 break;
3315 if (ok)
3317 info->handlers[index][y + count] = extra_handlers[x];
3318 y++;
3323 /* This function will allocate and initialize an eh_nesting_info structure.
3324 It returns a pointer to the completed data structure. If there are
3325 no exception regions, a NULL value is returned. */
3327 eh_nesting_info *
3328 init_eh_nesting_info ()
3330 int *nested_eh_region;
3331 int region_count = 0;
3332 rtx eh_note = NULL_RTX;
3333 eh_nesting_info *info;
3334 rtx insn;
3335 int x;
3337 if (! flag_exceptions)
3338 return 0;
3340 info = (eh_nesting_info *) xmalloc (sizeof (eh_nesting_info));
3341 info->region_index = (int *) xcalloc ((max_label_num () + 1), sizeof (int));
3342 nested_eh_region = (int *) xcalloc (max_label_num () + 1, sizeof (int));
3344 /* Create the nested_eh_region list. If indexed with a block number, it
3345 returns the block number of the next outermost region, if any.
3346 We can count the number of regions and initialize the region_index
3347 vector at the same time. */
3348 for (insn = get_insns(); insn; insn = NEXT_INSN (insn))
3350 if (GET_CODE (insn) == NOTE)
3352 if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
3354 int block = NOTE_EH_HANDLER (insn);
3355 region_count++;
3356 info->region_index[block] = region_count;
3357 if (eh_note)
3358 nested_eh_region [block] =
3359 NOTE_EH_HANDLER (XEXP (eh_note, 0));
3360 else
3361 nested_eh_region [block] = 0;
3362 eh_note = gen_rtx_EXPR_LIST (VOIDmode, insn, eh_note);
3364 else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
3365 eh_note = XEXP (eh_note, 1);
3369 /* If there are no regions, wrap it up now. */
3370 if (region_count == 0)
3372 free (info->region_index);
3373 free (info);
3374 free (nested_eh_region);
3375 return NULL;
3378 region_count++;
3379 info->handlers = (handler_info ***) xcalloc (region_count,
3380 sizeof (handler_info ***));
3381 info->num_handlers = (int *) xcalloc (region_count, sizeof (int));
3382 info->outer_index = (int *) xcalloc (region_count, sizeof (int));
3384 /* Now initialize the handler lists for all exception blocks. */
3385 for (x = 0; x <= max_label_num (); x++)
3387 if (info->region_index[x] != 0)
3388 process_nestinfo (x, info, nested_eh_region);
3390 info->region_count = region_count;
3392 /* Clean up. */
3393 free (nested_eh_region);
3395 return info;
3399 /* This function is used to retreive the vector of handlers which
3400 can be reached by a given insn in a given exception region.
3401 BLOCK is the exception block the insn is in.
3402 INFO is the eh_nesting_info structure.
3403 INSN is the (optional) insn within the block. If insn is not NULL_RTX,
3404 it may contain reg notes which modify its throwing behavior, and
3405 these will be obeyed. If NULL_RTX is passed, then we simply return the
3406 handlers for block.
3407 HANDLERS is the address of a pointer to a vector of handler_info pointers.
3408 Upon return, this will have the handlers which can be reached by block.
3409 This function returns the number of elements in the handlers vector. */
3411 int
3412 reachable_handlers (block, info, insn, handlers)
3413 int block;
3414 eh_nesting_info *info;
3415 rtx insn ;
3416 handler_info ***handlers;
3418 int index = 0;
3419 *handlers = NULL;
3421 if (info == NULL)
3422 return 0;
3423 if (block > 0)
3424 index = info->region_index[block];
3426 if (insn && GET_CODE (insn) == CALL_INSN)
3428 /* RETHROWs specify a region number from which we are going to rethrow.
3429 This means we won't pass control to handlers in the specified
3430 region, but rather any region OUTSIDE the specified region.
3431 We accomplish this by setting block to the outer_index of the
3432 specified region. */
3433 rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
3434 if (note)
3436 index = eh_region_from_symbol (XEXP (note, 0));
3437 index = info->region_index[index];
3438 if (index)
3439 index = info->outer_index[index];
3441 else
3443 /* If there is no rethrow, we look for a REG_EH_REGION, and
3444 we'll throw from that block. A value of 0 or less
3445 indicates that this insn cannot throw. */
3446 note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3447 if (note)
3449 int b = INTVAL (XEXP (note, 0));
3450 if (b <= 0)
3451 index = 0;
3452 else
3453 index = info->region_index[b];
3457 /* If we reach this point, and index is 0, there is no throw. */
3458 if (index == 0)
3459 return 0;
3461 *handlers = info->handlers[index];
3462 return info->num_handlers[index];
3466 /* This function will free all memory associated with the eh_nesting info. */
3468 void
3469 free_eh_nesting_info (info)
3470 eh_nesting_info *info;
3472 int x;
3473 if (info != NULL)
3475 if (info->region_index)
3476 free (info->region_index);
3477 if (info->num_handlers)
3478 free (info->num_handlers);
3479 if (info->outer_index)
3480 free (info->outer_index);
3481 if (info->handlers)
3483 for (x = 0; x < info->region_count; x++)
3484 if (info->handlers[x])
3485 free (info->handlers[x]);
3486 free (info->handlers);
3488 free (info);