aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@cygnus.com>1998-05-28 07:32:33 +0000
committerAndrew Macleod <amacleod@gcc.gnu.org>1998-05-28 07:32:33 +0000
commit9f8e62437fbd291bf0f947608a97b910b8f60f37 (patch)
tree1ae90a1f7e7acf9282967693b1700bd18248222e
parentd05a5492a531fbee813b2f365fa68127ff445af3 (diff)
downloadgcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.zip
gcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.tar.gz
gcc-9f8e62437fbd291bf0f947608a97b910b8f60f37.tar.bz2
Flow now removes exception regions when their handlers are all removed.
From-SVN: r20115
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/except.c28
-rw-r--r--gcc/except.h7
-rw-r--r--gcc/flow.c44
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. */
diff --git a/gcc/flow.c b/gcc/flow.c
index 4ade02a..8021b4e 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -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