diff options
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/except.c | 52 | ||||
-rw-r--r-- | gcc/stmt.c | 7 |
3 files changed, 66 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8f9f324..2af7dc1 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +Wed Dec 3 12:01:56 1997 Jason Merrill <jason@yorick.cygnus.com> + + * except.c (expand_fixup_region_end): New fn. + (expand_fixup_region_start): Likewise. + (expand_eh_region_start_tree): Store cleanup into finalization here. + * stmt.c (expand_cleanups): Use them to protect fixups. + Wed Dec 3 11:41:13 1997 Gavin Koch <gavin@cygnus.com> * mips/mips.md (muldi3_r4000): Broaden the output template diff --git a/gcc/except.c b/gcc/except.c index 0b5ceec..a493375 100644 --- a/gcc/except.c +++ b/gcc/except.c @@ -1013,6 +1013,7 @@ expand_eh_region_start_tree (decl, cleanup) } expand_eh_region_start_for_decl (decl); + ehstack.top->entry->finalization = cleanup; return 0; } @@ -1138,6 +1139,57 @@ expand_eh_region_end (handler) } } +/* End the EH region for a goto fixup. We only need them in the region-based + EH scheme. */ + +void +expand_fixup_region_start () +{ + if (! doing_eh (0) || exceptions_via_longjmp) + return; + + expand_eh_region_start (); +} + +/* End the EH region for a goto fixup. CLEANUP is the cleanup we just + expanded; to avoid running it twice if it throws, we look through the + ehqueue for a matching region and rethrow from its outer_context. */ + +void +expand_fixup_region_end (cleanup) + tree cleanup; +{ + tree t; + struct eh_node *node; + int yes; + + if (! doing_eh (0) || exceptions_via_longjmp) + return; + + for (node = ehstack.top; node && node->entry->finalization != cleanup; ) + node = node->chain; + if (node == 0) + for (node = ehqueue.head; node && node->entry->finalization != cleanup; ) + node = node->chain; + if (node == 0) + abort (); + + yes = suspend_momentary (); + + t = build (RTL_EXPR, void_type_node, NULL_RTX, const0_rtx); + TREE_SIDE_EFFECTS (t) = 1; + do_pending_stack_adjust (); + start_sequence_for_rtl_expr (t); + expand_internal_throw (node->entry->outer_context); + do_pending_stack_adjust (); + RTL_EXPR_SEQUENCE (t) = get_insns (); + end_sequence (); + + resume_momentary (yes); + + expand_eh_region_end (t); +} + /* If we are using the setjmp/longjmp EH codegen method, we emit a call to __sjthrow. @@ -4229,7 +4229,14 @@ expand_cleanups (list, dont_do, in_fixup, reachable) the target. Though the cleanups are expanded multiple times, the control paths are non-overlapping so the cleanups will not be executed twice. */ + + /* We may need to protect fixups with rethrow regions. */ + int protect = (in_fixup && ! TREE_ADDRESSABLE (tail)); + if (protect) + expand_fixup_region_start (); expand_expr (TREE_VALUE (tail), const0_rtx, VOIDmode, 0); + if (protect) + expand_fixup_region_end (TREE_VALUE (tail)); free_temp_slots (); } } |