diff options
author | Jakub Jelinek <jakub@redhat.com> | 2002-01-14 22:06:26 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2002-01-14 22:06:26 +0100 |
commit | 655dd289ba24fa9f80a07c36431937e6f649a490 (patch) | |
tree | ec54cec524d78b39ae5d7136e8cd28a953bc4958 /gcc/except.c | |
parent | e6a5e4628761239be448d4dfd14eed42bc37383c (diff) | |
download | gcc-655dd289ba24fa9f80a07c36431937e6f649a490.tar.gz |
except.c (remove_unreachable_regions): New.
* except.c (remove_unreachable_regions): New.
(free_eh_status): Clear exception_handler_labels.
(convert_from_eh_region_ranges): Call remove_unreachable_regions.
(find_exception_handler_labels): Don't add the same label more than
once.
(remove_exception_handler_label): Don't die if
find_exception_handler_labels hasn't been called for the current
function yet.
From-SVN: r48845
Diffstat (limited to 'gcc/except.c')
-rw-r--r-- | gcc/except.c | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/gcc/except.c b/gcc/except.c index 6da82f77534..2ce69f2c05d 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -263,6 +263,7 @@ static rtx get_exception_filter PARAMS ((struct function *)); static void collect_eh_region_array PARAMS ((void)); static void resolve_fixup_regions PARAMS ((void)); static void remove_fixup_regions PARAMS ((void)); +static void remove_unreachable_regions PARAMS ((rtx)); static void convert_from_eh_region_ranges_1 PARAMS ((rtx *, int *, int)); static struct eh_region *duplicate_eh_region_1 PARAMS ((struct eh_region *, @@ -632,6 +633,7 @@ free_eh_status (f) free (eh); f->eh = NULL; + exception_handler_labels = NULL; } @@ -1212,6 +1214,69 @@ remove_fixup_regions () } } +/* Remove all regions whose labels are not reachable from insns. */ + +static void +remove_unreachable_regions (insns) + rtx insns; +{ + int i, *uid_region_num; + bool *reachable; + struct eh_region *r; + rtx insn; + + uid_region_num = xcalloc (get_max_uid (), sizeof(int)); + reachable = xcalloc (cfun->eh->last_region_number + 1, sizeof(bool)); + + for (i = cfun->eh->last_region_number; i > 0; --i) + { + r = cfun->eh->region_array[i]; + if (!r || r->region_number != i) + continue; + + if (r->resume) + { + if (uid_region_num[INSN_UID (r->resume)]) + abort (); + uid_region_num[INSN_UID (r->resume)] = i; + } + if (r->label) + { + if (uid_region_num[INSN_UID (r->label)]) + abort (); + uid_region_num[INSN_UID (r->label)] = i; + } + if (r->type == ERT_TRY && r->u.try.continue_label) + { + if (uid_region_num[INSN_UID (r->u.try.continue_label)]) + abort (); + uid_region_num[INSN_UID (r->u.try.continue_label)] = i; + } + } + + for (insn = insns; insn; insn = NEXT_INSN (insn)) + reachable[uid_region_num[INSN_UID (insn)]] = true; + + for (i = cfun->eh->last_region_number; i > 0; --i) + { + r = cfun->eh->region_array[i]; + if (r && r->region_number == i && !reachable[i]) + { + /* Don't remove ERT_THROW regions if their outer region + is reachable. */ + if (r->type == ERT_THROW + && r->outer + && reachable[r->outer->region_number]) + continue; + + remove_eh_handler (r); + } + } + + free (reachable); + free (uid_region_num); +} + /* Turn NOTE_INSN_EH_REGION notes into REG_EH_REGION notes for each can_throw instruction in the region. */ @@ -1314,6 +1379,7 @@ convert_from_eh_region_ranges () free (stack); remove_fixup_regions (); + remove_unreachable_regions (insns); } void @@ -1332,7 +1398,7 @@ find_exception_handler_labels () struct eh_region *region = cfun->eh->region_array[i]; rtx lab; - if (! region) + if (! region || region->region_number != i) continue; if (cfun->eh->built_landing_pads) lab = region->landing_pad; @@ -2427,6 +2493,11 @@ remove_exception_handler_label (label) { rtx *pl, l; + /* If exception_handler_labels was not built yet, + there is nothing to do. */ + if (exception_handler_labels == NULL) + return; + for (pl = &exception_handler_labels, l = *pl; XEXP (l, 0) != label; pl = &XEXP (l, 1), l = *pl) |