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]

[PATCH] Fix cross-jumping EH bug on s390


Hi!

The following testcase is miscompiled on s390 on gcc-3_2-rhl8-branch.
gcc 3.3 changed enough that this problem is not exposed there, but I'd like
to know if the following analysis still holds for the trunk.

bb12:
...
r1 = [.LC18]	REG_EQUIV _Unwind_Resume
call *r1	REG_NORETURN and no REG_EH_REGION note
barrier

bb13:
r2 = r6
r1 = [.LC1]	REG_EQUIV __cxa_call_unexpected
call *r1	REG_NORETURN, REG_EH_REGION 36

_Unwind_Resume has no REG_EH_REGION note, which means it is supposed to
have landing_pad 0 and action 0 in LSDA.
__cxa_call_unexpected's region has no handlers, which means it is not
supposed to be in LSDA table at all (if exception is thrown, it should
terminate).
Both basic blocks don't have any EH_EDGE successor edges, the first because
it has no REG_EH_REGION note, the latter because it has no handlers.

Now, outgoing_edges_match counts successor EH_EDGEs and looks at
REG_EH_REGION notes only if they are some EH_EDGEs, which is not this case.

This means it happily cross-jumps it together, resulting in:
bb12:
...
r1 = [.LC18]	REG_EQUIV _Unwind_Resume
jump lab1
barrier

bb13:
r2 = r6
r1 = [.LC1]	REG_EQUIV __cxa_call_unexpected

bb14:
lab1:
call *r1	REG_NORETURN, REG_EH_REGION 36

This means when _Unwind_Resume throws the exception, terminate is called
instead of continuing in unwinding.

Is this something still relevant to mainline? If yes, ok to commit?

2003-08-01  Jakub Jelinek  <jakub@redhat.com>

	* cfgcleanup.c (outgoing_edges_match): Check REG_EH_REGION notes
	even if nehedges1 is 0.

	* g++.dg/eh/crossjump1.C: New test.

--- gcc/testsuite/g++.dg/eh/crossjump1.C.jj	2003-08-01 10:23:22.000000000 -0400
+++ gcc/testsuite/g++.dg/eh/crossjump1.C	2003-08-01 11:14:35.000000000 -0400
@@ -0,0 +1,31 @@
+// This testcase failed on s390, because cross-jumping merged 2 calls,
+// one with REG_EH_REGION note with no handlers (ie. termination)
+// and one without REG_EH_REGION note.
+// { dg-do run }
+// { dg-options "-O2" }
+
+#include <exception>
+#include <string>
+
+struct E : public std::exception
+{
+  std::string m;
+  E () : m ("test") { }
+  ~E () throw() { }
+};
+
+struct C : public E { };
+
+void foo ()
+{
+  throw C ();
+}
+
+int main ()
+{
+  try
+    {
+      foo ();
+    }
+  catch (...) { }
+}
--- gcc/cfgcleanup.c.jj	2003-03-25 11:42:18.000000000 -0500
+++ gcc/cfgcleanup.c	2003-08-01 10:07:51.000000000 -0400
@@ -1255,15 +1255,17 @@ outgoing_edges_match (mode, bb1, bb2)
 	return false;
     }
 
-  /* In case we do have EH edges, ensure we are in the same region.  */
-  if (nehedges1)
-    {
-      rtx n1 = find_reg_note (bb1->end, REG_EH_REGION, 0);
-      rtx n2 = find_reg_note (bb2->end, REG_EH_REGION, 0);
-
-      if (XEXP (n1, 0) != XEXP (n2, 0))
-	return false;
-    }
+  /* Ensure the same EH region.  */
+  {
+    rtx n1 = find_reg_note (bb1->end, REG_EH_REGION, 0);
+    rtx n2 = find_reg_note (bb2->end, REG_EH_REGION, 0);
+
+    if (!n1 && n2)
+      return false;
+
+    if (n1 && (!n2 || XEXP (n1, 0) != XEXP (n2, 0)))
+      return false;
+  }
 
   /* We don't need to match the rest of edges as above checks should be enought
      to ensure that they are equivalent.  */

	Jakub


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