except.c (expand_fixup_region_end): New fn.
authorJason Merrill <jason@yorick.cygnus.com>
Wed, 3 Dec 1997 20:04:31 +0000 (20:04 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 3 Dec 1997 20:04:31 +0000 (15:04 -0500)
* 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.

From-SVN: r16929

gcc/ChangeLog
gcc/except.c
gcc/stmt.c

index 8f9f324..2af7dc1 100644 (file)
@@ -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
index 0b5ceec..a493375 100644 (file)
@@ -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.
 
index d61de3a..ee9139c 100644 (file)
@@ -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 ();
              }
          }