diff options
author | Andrew MacLeod <amacleod@cygnus.com> | 1998-12-08 14:04:03 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 1998-12-08 14:04:03 +0000 |
commit | e6cfb550ab17484da95c0a3e94773fa42dccd27c (patch) | |
tree | 7f21607b0446aa635cee54fb52e2f750bc2be0d5 /gcc/flow.c | |
parent | 2bfdc2d4e73144131b2e2de7ccfc1183f63175ac (diff) | |
download | gcc-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.c | 58 |
1 files changed, 56 insertions, 2 deletions
@@ -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; |