diff options
author | Andrew MacLeod <amacleod@cygnus.com> | 1998-05-28 07:32:33 +0000 |
---|---|---|
committer | Andrew Macleod <amacleod@gcc.gnu.org> | 1998-05-28 07:32:33 +0000 |
commit | 9f8e62437fbd291bf0f947608a97b910b8f60f37 (patch) | |
tree | 1ae90a1f7e7acf9282967693b1700bd18248222e /gcc | |
parent | d05a5492a531fbee813b2f365fa68127ff445af3 (diff) | |
download | gcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.zip gcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.tar.gz gcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.tar.bz2 |
Flow now removes exception regions when their handlers are all removed.
From-SVN: r20115
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/except.c | 28 | ||||
-rw-r--r-- | gcc/except.h | 7 | ||||
-rw-r--r-- | gcc/flow.c | 44 |
4 files changed, 65 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index c306911..1bb223c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +Thu May 28 10:22:22 EDT 1998 Andrew MacLeod <amacleod@cygnus.com> + + * except.h (remove_handler): Add new prototype. + * except.c (remove_handler): New function to remove handlers + from an exception region. + * flow.c (find_basic_blocks_1): Remove handlers from regions when + handler label is deleted; remove exception regions with no handlers. + Thu May 28 09:36:39 1998 Michael Meissner <meissner@cygnus.com> * except.h (rtx): Define rtx type correctly if needed. diff --git a/gcc/except.c b/gcc/except.c index a2cee20..5881e22 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -754,6 +754,34 @@ add_new_handler (region, newhandler) } } +/* Remove a handler label. The handler label is being deleted, so all + regions which reference this handler should have it removed from their + list of possible handlers. Any region which has the final handler + removed can be deleted. */ + +void remove_handler (removing_label) + rtx removing_label; +{ + struct handler_info *handler, *last; + int x; + for (x = 0 ; x < current_func_eh_entry; ++x) + { + last = NULL; + handler = function_eh_regions[x].handlers; + for ( ; handler; last = handler, handler = handler->next) + if (handler->handler_label == removing_label) + { + if (last) + { + last->next = handler->next; + handler = last; + } + else + function_eh_regions[x].handlers = handler->next; + } + } +} + /* Create a new handler structure initialized with the handler label and typeinfo fields passed in. */ diff --git a/gcc/except.h b/gcc/except.h index b96399e..d2523cb 100644 --- a/gcc/except.h +++ b/gcc/except.h @@ -191,6 +191,13 @@ int new_eh_region_entry PROTO((int)); void add_new_handler PROTO((int, struct handler_info *)); +/* Remove a handler label. The handler label is being deleted, so all + regions which reference this handler should have it removed from their + list of possible handlers. Any region which has the final handler + removed can be deleted. */ + +void remove_handler PROTO((rtx)); + /* Create a new handler structure initialized with the handler label and typeinfo fields passed in. */ @@ -404,6 +404,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p) enum rtx_code prev_code, code; int depth, pass; int in_libcall_block = 0; + int deleted_handler = 0; pass = 1; active_eh_region = (int *) alloca ((max_uid_for_flow + 1) * sizeof (int)); @@ -770,28 +771,9 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p) XEXP (x, 1) = NULL_RTX; XEXP (x, 0) = NULL_RTX; - /* Now we have to find the EH_BEG and EH_END notes - associated with this label and remove them. */ - -#if 0 -/* Handlers and labels no longer needs to have the same values. - If there are no references, scan_region will remove any region - labels which are of no use. */ - for (x = get_insns (); x; x = NEXT_INSN (x)) - { - if (GET_CODE (x) == NOTE - && ((NOTE_LINE_NUMBER (x) - == NOTE_INSN_EH_REGION_BEG) - || (NOTE_LINE_NUMBER (x) - == NOTE_INSN_EH_REGION_END)) - && (NOTE_BLOCK_NUMBER (x) - == CODE_LABEL_NUMBER (insn))) - { - NOTE_LINE_NUMBER (x) = NOTE_INSN_DELETED; - NOTE_SOURCE_FILE (x) = 0; - } - } -#endif + /* Remove the handler from all regions */ + remove_handler (insn); + deleted_handler = 1; break; } prev = &XEXP (x, 1); @@ -861,6 +843,24 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p) } } } + /* If we deleted an exception handler, we may have EH region + begin/end blocks to remove as well. */ + if (deleted_handler) + for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) + if (GET_CODE (insn) == NOTE) + { + if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG) || + (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) + { + NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED; + NOTE_SOURCE_FILE (insn) = 0; + } + } + } /* There are pathological cases where one function calling hundreds of nested inline functions can generate lots and lots of unreachable |