1 /* Implements exceptiom handling.
2 Copyright (C) 1989, 92-95, 1996 Free Software Foundation, Inc.
3 Contributed by Mike Stump <mrs@cygnus.com>.
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
23 /* This file contains the exception handling code for the compiler.
25 Exception handling is a mechanism by which complex flows of control
26 can be designated. The central concepts are the `exception region',
27 the associated `exception handler' for that region and the concept of
28 throwing an exception, and the context of the throw.
30 Restrictions are, the regions must be non-overlapping, they can be
31 nested, and there can be zero or more per function. For each
32 region, there is one associated handler. Regions only ever
33 surround possible context points of throws. Regions with no such
34 context points can be optimized away, as they are trivial, and it
35 is not possible for the associated handler to ever be used during a
38 Semantics are, when an exception is thrown, control is transferred
39 to a handler, and the code of the exception handler is executed.
40 As control is transferred, the machine state (stack pointer, all
41 callee saved registers and possibly the frame pointer) is restored.
43 The handler that is selected by a throw, is the handler associated
44 with the smallest (most nested) region that contains the context of
45 the throw, if such a region exists. If no region exists, the
46 search for a handler continues in the function that called the
47 function that contains the current context of the throw, with the
48 context of the throw then becoming that point in the code that
49 contains the call instruction.
52 One can add to the basic model the concepts of thrown exception
53 type, and thrown exception value. Semantics are as above, except a
54 further check is done when finding a handler for the thrown
55 exception to see if the given handler can handle the thrown
56 exception based upon the exception object's type and possibly its
57 value. A common optimization is when two regions are identical,
58 the handlers are combined into just one handler so the first check
59 of the resulting handler is for the inner (nested) region's
60 handler, and the second one is for the outer region's handler. To
61 separate these two notions of handlers, we can call the subhandlers
62 `catch blocks', and use the name `handler' to refer to the
63 combination of the two. Currently, this layer of functionality is
64 managed by the various front ends.
67 To mark the start of a exception handling region,
68 expand_eh_region_start () is called. To mark the end, and
69 associate a handler for the region expand_eh_region_end () is used.
70 The front end can use this interface, if useful. The back end
71 creates exception regions with these routines. Another interface
72 the front end can use, is TARGET_EXPR. TARGET_EXPR gives an
73 unwind-protect style interface a la emacs.
76 In this implementation, regions do not span more than one function.
78 In order to help with the task of finding the associated handler for
79 a region, an exception table is built which associates handlers
80 with regions. A 3-tuple, containing a reference to the start, the
81 end and the handler is sufficient for the exception table.
83 In order to help with the task of restoring callee saved registers
84 and performing other associated function exit actions, function
85 `unwinders' can be generated within those function for which a
86 generic function unwinder called __unwind_function () cannot work.
87 Whether the generic __unwind_function can work is machine dependent
88 and possibly function dependent. The macro DOESNT_NEEED_UNWINDER
89 decides if the current function being compiled needs an unwinder or
92 The default is for unwinders to be used, as the default generic
93 function unwinder only calls abort (). The compiler-generated per
94 function function unwinders simply modify the context of thrown
95 exception to be that of the call site, and then arrange for control
96 to be transferred to __throw instead of the function's caller on
97 return, and then return. */
106 #include "function.h"
107 #include "insn-flags.h"
109 #include "insn-codes.h"
111 #include "hard-reg-set.h"
112 #include "insn-config.h"
116 /* List of labels use for exception handlers. Created by
117 find_exception_handler_labels for the optimization passes. */
119 rtx exception_handler_labels
;
121 /* Nonzero means that throw was used. Used for now, because __throw
122 is emitted statically in each file. */
126 /* A stack used for keeping track of the currectly active exception
127 handling region. As exceptions regions are started, an entry
128 describing the region is pushed onto this stack. The current
129 region can be found by looking at the top of the stack, and as we
130 end regions, entries are poped. */
132 struct eh_stack ehstack
;
134 /* A queue used for tracking which exception regions have closed, but
135 whose handlers have not yet been expanded. As we end regions, we
136 enqueue the entry onto this queue. Entries are dequeue from the
137 queue during expand_leftover_cleanups and expand_start_all_catch,
138 and the handlers for regions are expanded in groups in an effort to
139 group all the handlers together in the same region of program space
140 to improve page performance. We should redo things, so that we
141 either take RTL for the handler, or we expand the handler expressed
142 as a tree immediately at region end time. */
144 struct eh_queue ehqueue
;
146 /* Insns for the catch clauses. */
150 /* A list of actions for handlers for regions that are not yet
155 /* Stacks to keep track of various labels. */
157 /* Keeps track of the label to resume to, should one want to resume
158 the normal control flow out of a handler. Also used to rethrow
159 exceptions caught in handlers, as if they were physically emitted
162 struct label_node
*caught_return_label_stack
= NULL
;
164 /* A spare data area for the front end's own use. */
166 struct label_node
*false_label_stack
= NULL
;
168 /* The rtx and the tree for the saved PC value. */
173 rtx expand_builtin_return_addr
PROTO((enum built_in_function
, int, rtx
));
175 /* Various support routines to manipulate the various data structures
176 used by the exception handling code. */
178 /* Push a label entry onto the given STACK. */
181 push_label_entry (stack
, rlabel
, tlabel
)
182 struct label_node
**stack
;
186 struct label_node
*newnode
187 = (struct label_node
*) xmalloc (sizeof (struct label_node
));
190 newnode
->u
.rlabel
= rlabel
;
192 newnode
->u
.tlabel
= tlabel
;
193 newnode
->chain
= *stack
;
197 /* Pop a label entry from the given STACK. */
200 pop_label_entry (stack
)
201 struct label_node
**stack
;
204 struct label_node
*tempnode
;
210 label
= tempnode
->u
.rlabel
;
211 *stack
= (*stack
)->chain
;
217 /* Return the top element of the given STACK. */
220 top_label_entry (stack
)
221 struct label_node
**stack
;
226 return (*stack
)->u
.tlabel
;
231 static struct eh_entry
*
232 copy_eh_entry (entry
)
233 struct eh_entry
*entry
;
235 struct eh_entry
*newentry
;
237 newentry
= (struct eh_entry
*) xmalloc (sizeof (struct eh_entry
));
238 bcopy ((char *) entry
, (char *) newentry
, sizeof (struct eh_entry
));
243 /* Push an entry onto the given STACK. */
246 push_eh_entry (stack
)
247 struct eh_stack
*stack
;
249 struct eh_node
*node
= (struct eh_node
*) xmalloc (sizeof (struct eh_node
));
250 struct eh_entry
*entry
= (struct eh_entry
*) xmalloc (sizeof (struct eh_entry
));
252 entry
->start_label
= gen_label_rtx ();
253 entry
->end_label
= gen_label_rtx ();
254 entry
->exception_handler_label
= gen_label_rtx ();
255 entry
->finalization
= NULL_TREE
;
258 node
->chain
= stack
->top
;
261 return entry
->start_label
;
264 /* Pop an entry from the given STACK. */
266 static struct eh_entry
*
268 struct eh_stack
*stack
;
270 struct eh_node
*tempnode
;
271 struct eh_entry
*tempentry
;
273 tempnode
= stack
->top
;
274 tempentry
= tempnode
->entry
;
275 stack
->top
= stack
->top
->chain
;
281 /* Enqueue an ENTRY onto the given QUEUE. */
284 enqueue_eh_entry (queue
, entry
)
285 struct eh_queue
*queue
;
286 struct eh_entry
*entry
;
288 struct eh_node
*node
= (struct eh_node
*) xmalloc (sizeof (struct eh_node
));
293 if (queue
->head
== NULL
)
299 queue
->tail
->chain
= node
;
304 /* Dequeue an entry from the given QUEUE. */
306 static struct eh_entry
*
307 dequeue_eh_entry (queue
)
308 struct eh_queue
*queue
;
310 struct eh_node
*tempnode
;
311 struct eh_entry
*tempentry
;
313 if (queue
->head
== NULL
)
316 tempnode
= queue
->head
;
317 queue
->head
= queue
->head
->chain
;
319 tempentry
= tempnode
->entry
;
325 /* Routine to see if exception exception handling is turned on.
326 DO_WARN is non-zero if we want to inform the user that exception
327 handling is turned off. */
333 if (! flag_exceptions
)
335 static int warned
= 0;
336 if (! warned
&& do_warn
)
338 error ("exception handling disabled, use -fexceptions to enable");
346 /* Given the return address in ADDR, compute the new pc to throw.
347 This has to work for the current frame of the current function, and
348 the one above it in the case of throw. */
351 eh_outer_context (addr
)
354 /* First mask out any unwanted bits. */
355 #ifdef MASK_RETURN_ADDR
356 emit_insn (gen_rtx (SET
, Pmode
,
359 addr
, MASK_RETURN_ADDR
)));
362 /* Then subtract out enough to get into the prior region. If this
363 is defined, assume we don't need to subtract anything, as it is
364 already within the region. */
365 #if ! defined (RETURN_ADDR_OFFSET)
366 addr
= plus_constant (addr
, -1);
372 /* Output a note marking the start of an exception handling region. */
375 expand_eh_region_start ()
379 /* This is the old code. */
384 /* Maybe do this to prevent jumping in and so on... */
388 note
= emit_note (NULL_PTR
, NOTE_INSN_EH_REGION_BEG
);
389 emit_label (push_eh_entry (&ehstack
));
390 NOTE_BLOCK_NUMBER (note
)
391 = CODE_LABEL_NUMBER (ehstack
.top
->entry
->exception_handler_label
);
394 /* Output a note marking the end of an exception handling region.
395 HANDLER is the the handler for the exception region. */
398 expand_eh_region_end (handler
)
403 struct eh_entry
*entry
;
408 entry
= pop_eh_entry (&ehstack
);
410 note
= emit_note (NULL_PTR
, NOTE_INSN_EH_REGION_END
);
411 NOTE_BLOCK_NUMBER (note
) = CODE_LABEL_NUMBER (entry
->exception_handler_label
);
413 emit_label (entry
->end_label
);
415 /* Put in something that takes up space, as otherwise the end
416 address for the EH region could have the exact same address as
417 the outer region, causing us to miss the fact that resuming
418 exception handling with this PC value would be inside the outer
420 emit_insn (gen_nop ());
422 entry
->finalization
= handler
;
424 enqueue_eh_entry (&ehqueue
, entry
);
428 /* Makebe do this to prevent jumping in and so on... */
433 /* Emit a call to __throw and note that we threw something. */
439 emit_indirect_jump (throw_libfunc
);
441 SYMBOL_REF_USED (throw_libfunc
) = 1;
442 emit_library_call (throw_libfunc
, 0, VOIDmode
, 0);
448 /* An internal throw with an indirect CONTEXT we want to throw from. */
451 expand_internal_throw_indirect (context
)
454 assemble_external (eh_saved_pc
);
455 emit_move_insn (eh_saved_pc_rtx
, context
);
459 /* An internal throw with a direct CONTEXT we want to throw from. The
460 context should be a label. */
463 expand_internal_throw (context
)
466 expand_internal_throw_indirect (gen_rtx (LABEL_REF
, Pmode
, context
));
469 /* Called from expand_exception_blocks and expand_end_catch_block to
470 expand any pending handlers. */
473 expand_leftover_cleanups ()
475 struct eh_entry
*entry
;
477 while ((entry
= dequeue_eh_entry (&ehqueue
)) != 0)
481 emit_label (entry
->exception_handler_label
);
483 expand_expr (entry
->finalization
, const0_rtx
, VOIDmode
, 0);
485 prev
= get_last_insn ();
486 if (! (prev
&& GET_CODE (prev
) == BARRIER
))
488 /* The below can be optimized away, and we could just fall into the
489 next EH handler, if we are certain they are nested. */
490 /* Code to throw out to outer context, if we fall off end of the
492 expand_internal_throw (entry
->end_label
);
495 /* leftover try block, opps. */
496 if (entry
->finalization
== integer_zero_node
)
503 /* Generate RTL for the start of all the catch blocks. Used for
504 arranging for the exception handling code to be placed farther out
505 of line than normal. */
508 expand_start_all_catch ()
510 struct eh_entry
*entry
;
516 emit_line_note (input_filename
, lineno
);
517 label
= build_decl (LABEL_DECL
, NULL_TREE
, NULL_TREE
);
519 /* The label for the exception handling block we will save. This is
520 Lresume, in the documention. */
521 expand_label (label
);
523 /* Put in something that takes up space, as otherwise the end
524 address for the EH region could have the exact same address as
525 the outer region, causing us to miss the fact that resuming
526 exception handling with this PC value would be inside the outer
528 emit_insn (gen_nop ());
530 push_label_entry (&caught_return_label_stack
, NULL_RTX
, label
);
532 /* Start a new sequence for all the catch blocks. We will add this
533 to the gloabl sequence catch_clauses, when we have completed all
534 the handlers in this handler-seq. */
541 entry
= dequeue_eh_entry (&ehqueue
);
542 emit_label (entry
->exception_handler_label
);
544 expand_expr (entry
->finalization
, const0_rtx
, VOIDmode
, 0);
546 /* When we get down to the matching entry, stop. */
547 if (entry
->finalization
== integer_zero_node
)
550 prev
= get_last_insn ();
551 if (! (prev
&& GET_CODE (prev
) == BARRIER
))
553 /* The below can be optimized away, and we could just fall into the
554 next EH handler, if we are certain they are nested. */
555 /* Code to throw out to outer context, if we fall off end of the
557 expand_internal_throw (entry
->end_label
);
564 /* Generate RTL for the end of all the catch blocks. */
567 expand_end_all_catch ()
569 rtx new_catch_clause
;
574 /* Code to throw out to outer context, if we fall off end of catch
575 handlers. This is rethrow (Lresume, same id, same obj); in the
577 expand_internal_throw (DECL_RTL (top_label_entry (&caught_return_label_stack
)));
579 /* Now we have the complete catch sequence. */
580 new_catch_clause
= get_insns ();
583 /* This level of catch blocks is done, so set up the successful
584 catch jump label for the next layer of catch blocks. */
585 pop_label_entry (&caught_return_label_stack
);
587 /* Add the new sequence of catches to the main one for this function. */
588 push_to_sequence (catch_clauses
);
589 emit_insns (new_catch_clause
);
590 catch_clauses
= get_insns ();
593 /* Here we fall through into the continuation code. */
596 /* End all the pending exception regions from protect_list that have
597 been started, but not yet completed. */
600 end_protect_partials ()
604 expand_eh_region_end (TREE_VALUE (protect_list
));
605 protect_list
= TREE_CHAIN (protect_list
);
609 /* The exception table that we build that is used for looking up and
610 dispatching exceptions, it's size, and it's maximum size before we
611 have to extend it. */
612 static int *eh_table
;
613 static int eh_table_size
;
614 static int eh_table_max_size
;
616 /* Note the need for an exception table entry for region N. If we
617 don't need to output an explicit exception table, avoid all the
618 extra work. Called during final_scan_insn time. */
621 add_eh_table_entry (n
)
624 #ifndef OMIT_EH_TABLE
625 if (eh_table_size
>= eh_table_max_size
)
629 eh_table_max_size
+= eh_table_max_size
>>1;
631 if (eh_table_max_size
< 0)
634 if ((eh_table
= (int *) realloc (eh_table
,
635 eh_table_max_size
* sizeof (int)))
637 fatal ("virtual memory exhausted");
641 eh_table_max_size
= 252;
642 eh_table
= (int *) xmalloc (eh_table_max_size
* sizeof (int));
645 eh_table
[eh_table_size
++] = n
;
649 /* Conditional to test to see if we need to output an exception table.
650 Note, on some platforms, we don't have to output a table
651 explicitly. This routine doesn't mean we don't have one. */
662 /* Output an entry N for the exception table to the specified FILE. */
665 output_exception_table_entry (file
, n
)
672 ASM_GENERATE_INTERNAL_LABEL (buf
, "LEHB", n
);
673 sym
= gen_rtx (SYMBOL_REF
, Pmode
, buf
);
674 assemble_integer (sym
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
676 ASM_GENERATE_INTERNAL_LABEL (buf
, "LEHE", n
);
677 sym
= gen_rtx (SYMBOL_REF
, Pmode
, buf
);
678 assemble_integer (sym
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
680 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", n
);
681 sym
= gen_rtx (SYMBOL_REF
, Pmode
, buf
);
682 assemble_integer (sym
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
684 putc ('\n', file
); /* blank line */
687 /* Output the exception table if we have one and need one. */
690 output_exception_table ()
693 extern FILE *asm_out_file
;
698 exception_section ();
700 /* Beginning marker for table. */
701 assemble_align (GET_MODE_ALIGNMENT (ptr_mode
));
702 assemble_label ("__EXCEPTION_TABLE__");
704 assemble_integer (const0_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
705 assemble_integer (const0_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
706 assemble_integer (const0_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
707 putc ('\n', asm_out_file
); /* blank line */
709 for (i
= 0; i
< eh_table_size
; ++i
)
710 output_exception_table_entry (asm_out_file
, eh_table
[i
]);
714 /* Ending marker for table. */
715 assemble_label ("__EXCEPTION_END__");
716 assemble_integer (constm1_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
717 assemble_integer (constm1_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
718 assemble_integer (constm1_rtx
, POINTER_SIZE
/ BITS_PER_UNIT
, 1);
719 putc ('\n', asm_out_file
); /* blank line */
722 /* Generate code to initialize the exception table at program startup
726 register_exception_table ()
728 emit_library_call (gen_rtx (SYMBOL_REF
, Pmode
, "__register_exceptions"), 0,
730 gen_rtx (SYMBOL_REF
, Pmode
, "__EXCEPTION_TABLE__"),
734 /* Emit the RTL for the start of the per function unwinder for the
740 #ifdef DOESNT_NEED_UNWINDER
741 if (DOESNT_NEED_UNWINDER
)
745 expand_eh_region_start ();
748 /* Emit the RTL for the end of the per function unwinder for the
755 rtx return_val_rtx
, ret_val
, label
, end
, insns
;
760 #ifdef DOESNT_NEED_UNWINDER
761 if (DOESNT_NEED_UNWINDER
)
765 assemble_external (eh_saved_pc
);
767 expr
= make_node (RTL_EXPR
);
768 TREE_TYPE (expr
) = void_type_node
;
769 RTL_EXPR_RTL (expr
) = const0_rtx
;
770 TREE_SIDE_EFFECTS (expr
) = 1;
771 start_sequence_for_rtl_expr (expr
);
773 ret_val
= expand_builtin_return_addr (BUILT_IN_RETURN_ADDRESS
,
774 0, hard_frame_pointer_rtx
);
775 return_val_rtx
= copy_to_reg (ret_val
);
777 return_val_rtx
= eh_outer_context (return_val_rtx
);
779 emit_move_insn (eh_saved_pc_rtx
, return_val_rtx
);
782 emit_move_insn (ret_val
, throw_libfunc
);
784 label
= gen_label_rtx ();
785 emit_move_insn (ret_val
, gen_rtx (LABEL_REF
, Pmode
, label
));
788 #ifdef RETURN_ADDR_OFFSET
789 return_val_rtx
= plus_constant (ret_val
, -RETURN_ADDR_OFFSET
);
790 if (return_val_rtx
!= ret_val
)
791 emit_move_insn (ret_val
, return_val_rtx
);
794 end
= gen_label_rtx ();
797 RTL_EXPR_SEQUENCE (expr
) = get_insns ();
799 expand_eh_region_end (expr
);
803 #ifndef JUMP_TO_THROW
808 expand_leftover_cleanups ();
813 /* Emit the RTL for the per function unwinder for the current
814 function, if needed. Called after all the code that needs unwind
815 protection is output. */
823 start_eh_unwinder ();
824 insns
= get_insns ();
828 emit_insns_after (insns
, get_insns ());
833 /* Scan the current insns and build a list of handler labels. Called
834 after the last exception handling region is added to the current
835 function (when the rtl is almost all built for the current
836 function) and before the jump optimization pass. */
839 find_exception_handler_labels ()
842 int max_labelno
= max_label_num ();
843 int min_labelno
= get_first_label_num ();
846 exception_handler_labels
= NULL_RTX
;
848 /* If we aren't doing exception handling, there isn't much to check. */
852 /* First we generate a handy reference to each label. */
854 labels
= (rtx
*) alloca ((max_labelno
- min_labelno
) * sizeof (rtx
));
855 labels
-= min_labelno
;
857 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
859 if (GET_CODE (insn
) == CODE_LABEL
)
860 if (CODE_LABEL_NUMBER (insn
) >= min_labelno
861 && CODE_LABEL_NUMBER (insn
) < max_labelno
)
862 labels
[CODE_LABEL_NUMBER (insn
)] = insn
;
865 /* Then for each start of a region, we add its label to the list. */
866 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
868 if (GET_CODE (insn
) == NOTE
869 && NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_BEG
)
871 rtx label
= NULL_RTX
;
873 if (NOTE_BLOCK_NUMBER (insn
) >= min_labelno
874 && NOTE_BLOCK_NUMBER (insn
) < max_labelno
)
876 label
= labels
[NOTE_BLOCK_NUMBER (insn
)];
879 exception_handler_labels
880 = gen_rtx (EXPR_LIST
, VOIDmode
,
881 label
, exception_handler_labels
);
883 warning ("didn't find handler for EH region %d",
884 NOTE_BLOCK_NUMBER (insn
));
887 warning ("mismatched EH region %d", NOTE_BLOCK_NUMBER (insn
));
892 /* Do some sanity checking on the exception_handler_labels list. Can
893 be called after find_exception_handler_labels is called to build
894 the list of exception handlers for the current function, and before
895 we finish processing the current function. */
898 check_exception_handler_labels ()
902 /* If we aren't doing exception handling, there isn't much to check. */
906 for (handler
= exception_handler_labels
;
908 handler
= XEXP (handler
, 1))
910 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
912 if (GET_CODE (insn
) == CODE_LABEL
)
914 if (CODE_LABEL_NUMBER (insn
)
915 == CODE_LABEL_NUMBER (XEXP (handler
, 0)))
917 if (insn
!= XEXP (handler
, 0))
918 warning ("mismatched handler %d",
919 CODE_LABEL_NUMBER (insn
));
924 if (insn
== NULL_RTX
)
925 warning ("handler not found %d",
926 CODE_LABEL_NUMBER (XEXP (handler
, 0)));
929 /* Now go through, and make sure that for each region we have, that we
930 have the corresponding label. */
931 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
933 if (GET_CODE (insn
) == NOTE
934 && (NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_BEG
||
935 NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_END
))
937 for (handler
= exception_handler_labels
;
939 handler
= XEXP (handler
, 1))
941 if (CODE_LABEL_NUMBER (XEXP (handler
, 0))
942 == NOTE_BLOCK_NUMBER (insn
))
945 if (handler
== NULL_RTX
)
946 warning ("region exists, no handler %d",
947 NOTE_BLOCK_NUMBER (insn
));
952 /* This group of functions initializes the exception handling data
953 structures at the start of the compilation, initializes the data
954 structures at the start of a function, saves and restores the
955 exception handling data structures for the start/end of a nested
958 /* Toplevel initialization for EH things. */
963 tree type
= build_pointer_type (make_node (VOID_TYPE
));
965 eh_saved_pc
= build_decl (VAR_DECL
, get_identifier ("__eh_pc"), type
);
966 DECL_EXTERNAL (eh_saved_pc
) = 1;
967 TREE_PUBLIC (eh_saved_pc
) = 1;
968 make_decl_rtl (eh_saved_pc
, NULL_PTR
, 1);
969 eh_saved_pc_rtx
= DECL_RTL (eh_saved_pc
);
972 /* Initialize various EH things. */
975 init_eh_for_function ()
978 ehqueue
.head
= ehqueue
.tail
= 0;
979 catch_clauses
= NULL_RTX
;
980 false_label_stack
= 0;
981 caught_return_label_stack
= 0;
982 protect_list
= NULL_TREE
;
985 /* Save various EH things for the current function into the save area
992 p
->ehstack
= ehstack
;
993 p
->ehqueue
= ehqueue
;
994 p
->catch_clauses
= catch_clauses
;
995 p
->false_label_stack
= false_label_stack
;
996 p
->caught_return_label_stack
= caught_return_label_stack
;
997 p
->protect_list
= protect_list
;
1002 /* Restore various EH things for the current function from the save
1003 area denoted by P. */
1006 restore_eh_status (p
)
1009 protect_list
= p
->protect_list
;
1010 caught_return_label_stack
= p
->caught_return_label_stack
;
1011 false_label_stack
= p
->false_label_stack
;
1012 catch_clauses
= p
->catch_clauses
;
1013 ehqueue
= p
->ehqueue
;
1014 ehstack
= p
->ehstack
;
1017 /* This section is for the exception handling specific optimization
1018 pass. First are the internal routines, and then the main
1019 optimization pass. */
1021 /* Determine if the given INSN can throw an exception. */
1027 /* The only things that can possibly throw are calls. */
1028 if (GET_CODE (insn
) == CALL_INSN
)
1031 #ifdef ASYNCH_EXCEPTIONS
1032 /* If we wanted asynchronous exceptions, then everything but NOTEs
1033 and CODE_LABELs could throw. */
1034 if (GET_CODE (insn
) != NOTE
&& GET_CODE (insn
) != CODE_LABEL
)
1041 /* Scan a region, looking for a matching end, and decide if the region
1042 can be removed. INSN is the start of the region, N is the region
1043 number, and DELETE_OUTER is to note if anything in this region can
1047 scan_region (insn
, n
, delete_outer
)
1054 /* Assume we can delete the region. */
1057 insn
= NEXT_INSN (insn
);
1059 /* Look for the matching end. */
1060 while (! (GET_CODE (insn
) == NOTE
1061 && NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_END
))
1063 /* If anything can throw, we can't remove the region. */
1064 if (delete && can_throw (insn
))
1069 /* Watch out for and handle nested regions. */
1070 if (GET_CODE (insn
) == NOTE
1071 && NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_BEG
)
1073 insn
= scan_region (insn
, NOTE_BLOCK_NUMBER (insn
), &delete);
1076 insn
= NEXT_INSN (insn
);
1079 /* The _BEG/_END NOTEs must match and nest. */
1080 if (NOTE_BLOCK_NUMBER (insn
) != n
)
1083 /* If anything can throw, we can throw. */
1088 /* Delete the start and end of the region. */
1089 delete_insn (start
);
1092 /* Only do this part if we have built the exception handler
1094 if (exception_handler_labels
)
1096 rtx x
, *prev
= &exception_handler_labels
;
1098 /* Find it in the list of handlers. */
1099 for (x
= exception_handler_labels
; x
; x
= XEXP (x
, 1))
1101 rtx label
= XEXP (x
, 0);
1102 if (CODE_LABEL_NUMBER (label
) == n
)
1104 /* If we are the last reference to the handler,
1106 if (--LABEL_NUSES (label
) == 0)
1107 delete_insn (label
);
1111 /* Remove it from the list of exception handler
1112 labels, if we are optimizing. If we are not, then
1113 leave it in the list, as we are not really going to
1114 remove the region. */
1115 *prev
= XEXP (x
, 1);
1122 prev
= &XEXP (x
, 1);
1129 /* Perform various interesting optimizations for exception handling
1132 We find empty exception regions, and remove them. The jump
1133 optimization code will remove the handler if nothing else uses it. */
1136 exception_optimize ()
1138 rtx insn
, regions
= NULL_RTX
;
1141 /* First remove empty regions. */
1142 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
1144 if (GET_CODE (insn
) == NOTE
1145 && NOTE_LINE_NUMBER (insn
) == NOTE_INSN_EH_REGION_BEG
)
1147 insn
= scan_region (insn
, NOTE_BLOCK_NUMBER (insn
), &n
);