aboutsummaryrefslogtreecommitdiff
path: root/gcc/flow.c
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@cygnus.com>1998-12-08 14:04:03 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>1998-12-08 14:04:03 +0000
commite6cfb550ab17484da95c0a3e94773fa42dccd27c (patch)
tree7f21607b0446aa635cee54fb52e2f750bc2be0d5 /gcc/flow.c
parent2bfdc2d4e73144131b2e2de7ccfc1183f63175ac (diff)
downloadgcc-e6cfb550ab17484da95c0a3e94773fa42dccd27c.zip
gcc-e6cfb550ab17484da95c0a3e94773fa42dccd27c.tar.gz
gcc-e6cfb550ab17484da95c0a3e94773fa42dccd27c.tar.bz2
See ChangeLog..
Tue Dec 8 15:32:56 EST 1998 Andrew MacLeod <amacleod@cygnus.com> See ChangeLog.. These are the files that were changed: * eh-common.h (struct eh_context): Add table_index for rethrows. * rtl.h (enum reg_note): Add REG_EH_REGION and REG_EH_RETHROW reg notes. * rtl.c (reg_note_name): Add strings for new reg_note enums. * expr.h (rethrow_libfunc): New library decl. * optabs.c (rethrow_libfunc): Initialize. * except.h (struct eh_entry): Add new field 'rethrow_label'. * except.c (create_rethrow_ref): New function to create a single * flow.c (make_edges): Add different edges for rethrow calls, * integrate.c (save_for_inline_eh_labelmap): New callback routine to * libgcc2.c (find_exception_handler): Generalize to enable it to * cp/except.c * cp/exception.cc From-SVN: r24194
Diffstat (limited to 'gcc/flow.c')
-rw-r--r--gcc/flow.c58
1 files changed, 56 insertions, 2 deletions
diff --git a/gcc/flow.c b/gcc/flow.c
index cc76a9c..6a4a448 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -721,6 +721,7 @@ make_edges (i)
int i;
{
rtx insn, x;
+ rtx pending_eh_region = NULL_RTX;
/* See if control drops into the next block. */
if (i + 1 < n_basic_blocks)
@@ -801,6 +802,40 @@ make_edges (i)
}
}
+ /* If this is a call with an EH_RETHROW note, then we
+ know its a rethrow call, and we know exactly where
+ this call can end up going. */
+ else if (GET_CODE (insn) == CALL_INSN
+ && (note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX)))
+ {
+ int region = XINT (XEXP (note, 0), 0);
+ /* if nested region is not 0, we know for sure it has been
+ processed. If it is zero, we dont know whether its an
+ outer region, or hasn't been seen yet, so defer it */
+ if (nested_eh_region[region] != 0)
+ {
+ /* start with the first region OUTSIDE the one specified
+ in the rethrow parameter. (since a rethrow behaves
+ as if a handler in the region didn't handle the
+ exception, so the handlers for the next outer region
+ are going to get a shot at it.*/
+ for ( region = nested_eh_region[region]; region;
+ region = nested_eh_region[region])
+ {
+ handler_info *ptr = get_first_handler (region);
+ for ( ; ptr ; ptr = ptr->next)
+ add_edge_to_label (i, ptr->handler_label);
+ }
+ }
+ else
+ {
+ /* Push this region onto a list, and after we've done the
+ whole procedure, we'll process everything on the list */
+ pending_eh_region = gen_rtx_EXPR_LIST (VOIDmode, insn,
+ pending_eh_region);
+ }
+ }
+
/* If this is a CALL_INSN, then mark it as reaching the active EH
handler for this CALL_INSN. If we're handling asynchronous
exceptions mark every insn as reaching the active EH handler.
@@ -837,6 +872,24 @@ make_edges (i)
}
}
}
+
+ while (pending_eh_region != NULL_RTX)
+ {
+ rtx insn = XEXP (pending_eh_region, 0);
+ rtx note = find_reg_note (insn, REG_EH_RETHROW, NULL_RTX);
+ int region = XINT (XEXP (note, 0), 0);
+ /* start with the first region OUTSIDE the one specified
+ in the rethrow parameter */
+ for ( region = nested_eh_region[region]; region;
+ region = nested_eh_region[region])
+ {
+ handler_info *ptr = get_first_handler (region);
+ for ( ; ptr ; ptr = ptr->next)
+ add_edge_to_label (BLOCK_NUM (insn), ptr->handler_label);
+ }
+ pending_eh_region = XEXP (pending_eh_region, 1);
+ }
+
/* We know something about the structure of the function __throw in
libgcc2.c. It is the only function that ever contains eh_stub labels.
It modifies its return address so that the last block returns to one of
@@ -918,8 +971,9 @@ delete_unreachable_blocks ()
NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
{
int num = CODE_LABEL_NUMBER (insn);
- /* A NULL handler indicates a region is no longer needed */
- if (get_first_handler (num) == NULL)
+ /* A NULL handler indicates a region is no longer needed,
+ unless its the target of a rethrow. */
+ if (get_first_handler (num) == NULL && !rethrow_used (num))
{
NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
NOTE_SOURCE_FILE (insn) = 0;