This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix cross-jumping EH bug on s390
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Richard Henderson <rth at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Fri, 1 Aug 2003 17:29:26 +0200
- Subject: [PATCH] Fix cross-jumping EH bug on s390
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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