This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

fix eh tests on x86-darwin


Here's a partial patch for the problems I discussed in
<http://gcc.gnu.org/ml/gcc/2006-08/msg00360.html>.

This patch should get everything right when
flag_asynchronous_unwind_tables is not set.  It also adds a minor
optimisation, by not outputting information for calls which can't
throw or which are outside an EH region.

In the case where flag_asynchronous_unwind_tables is set, it improves
the situation by ensuring that at least at a call, all the arguments
for the call are marked; so if no asynchronous exception is actually
thrown, everything will work.

There are still lots of problems, though.  If you replace the two
'FIXME' comments with gcc_assert, you'll find that many tests
in the GCC testsuite that use -fnon-call-exceptions fail.

Importantly, the assert in calls.c does *not* trigger in my
bootstrap and testrun.

I'm running one last bootstrap & testrun and will wait for that and
for a day or so for people to comment before I commit.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/gcc-stackadjust-1.patch===================
2006-08-24  Geoffrey Keating  <geoffk@apple.com>

	* dwarf2out.c (dwarf2out_stack_adjust): For
	synchnonous unwind tables, trust that the argument size
	in the call instruction is correct.  For asynchronous
	unwind tables, ensure that at least the argument size
	in the call instruction is in effect at the call.  Add comments
	pointing out brokenness in this code.
	* calls.c (expand_call): Assert that calls expanded during
	the expansion of a different call are always nothrow.

Index: calls.c
===================================================================
--- calls.c	(revision 116355)
+++ calls.c	(working copy)
@@ -2141,6 +2141,15 @@
 	  || (!ACCUMULATE_OUTGOING_ARGS && args_size.constant)))
     structure_value_addr = copy_to_reg (structure_value_addr);
 
+  /* On targets where ! ACCUMULATE_OUTGOING_ARGS, the DWARF
+     EH machinery can't handle nested calls that might throw.
+     With GIMPLE, the only nested calls are to memcpy(),
+     at least that's what this assert is here to check.  
+     The test intentionally doesn't check for
+     ! ACCUMULATE_OUTGOING_ARGS so that GCC developers on platforms
+     without it will still notice that there's a problem.  */
+  gcc_assert (! currently_expanding_call || (flags & ECF_NOTHROW));
+
   /* Tail calls can make things harder to debug, and we've traditionally
      pushed these optimizations into -O2.  Don't try if we're already
      expanding a call, as that means we're an argument.  Don't try if
Index: dwarf2out.c
===================================================================
--- dwarf2out.c	(revision 116355)
+++ dwarf2out.c	(working copy)
@@ -1086,13 +1086,54 @@
   const char *label;
   int i;
 
+  /* If only calls can throw, use the information in the call instruction.
+     This assumes that a call which is emitted in the middle of emitting
+     a different call won't throw; with GIMPLE, this appears to be the
+     case.  */
+  if (! flag_asynchronous_unwind_tables)
+    {
+      rtx note;
+
+      if (! CALL_P (insn))
+	return;
+
+      /* Maybe this call is outside an EH region or can't throw.  */
+      note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+      if (!note || INTVAL (XEXP (note, 0)) <= 0)
+	return;
+
+      /* Extract the size of the args from the CALL rtx itself.  */
+      insn = PATTERN (insn);
+      if (GET_CODE (insn) == PARALLEL)
+	insn = XVECEXP (insn, 0, 0);
+      if (GET_CODE (insn) == SET)
+	insn = SET_SRC (insn);
+      dwarf2out_args_size ("", INTVAL (XEXP (insn, 1)));
+      return;
+    }
+
   /* Don't handle epilogues at all.  Certainly it would be wrong to do so
      with this function.  Proper support would require all frame-related
      insns to be marked, and to be able to handle saving state around
-     epilogues textually in the middle of the function.  */
+     epilogues textually in the middle of the function.  This can go wrong
+     if a prologue instruction is combined with part of the setup for
+     a call.  */
   if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
     return;
 
+  /* Check that we didn't somehow miss a push of an argument.  */
+  if (CALL_P (insn))
+    {
+      rtx cinsn = PATTERN (insn);
+      if (GET_CODE (cinsn) == PARALLEL)
+	cinsn = XVECEXP (cinsn, 0, 0);
+      if (GET_CODE (cinsn) == SET)
+	cinsn = SET_SRC (cinsn);
+      if (args_size < INTVAL (XEXP (cinsn, 1)))
+	/* FIXME: this code should never be reached.  */
+	args_size = INTVAL (XEXP (cinsn, 1));
+    }
+
   if (BARRIER_P (insn))
     {
       /* When we see a BARRIER, we know to reset args_size to 0.  Usually
@@ -1115,20 +1156,11 @@
 	if (GET_CODE (XVECEXP (PATTERN (insn), 0, i)) == SET)
 	  offset += stack_adjust_offset (XVECEXP (PATTERN (insn), 0, i));
     }
-  else if (GET_CODE (insn) == CALL_INSN)
+  else if (CALL_P (insn))
     offset = 0;
   else
     return;
 
-  /* We handle this separately because we want stack adjustments in a
-     CALL_INSN to be handled.  */;
-  if (GET_CODE (insn) == CALL_INSN)
-    {
-      /* If only calls can throw, adjust args_size only at call sites.  */
-      if (!flag_asynchronous_unwind_tables)
-	dwarf2out_args_size ("", args_size);
-    }
-
   if (offset == 0)
     return;
 
@@ -1141,6 +1173,7 @@
 
   args_size += offset;
   if (args_size < 0)
+    /* FIXME: this code should never be reached.  */
     args_size = 0;
 
   /* If only calls can throw and we have a frame pointer, we'll save
============================================================


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]