[llvm] r258651 - [WinEH] Don't miscompile cleanups which conditionally unwind to caller

David Majnemer via llvm-commits llvm-commits at lists.llvm.org
Sat Jan 23 15:54:33 PST 2016


Author: majnemer
Date: Sat Jan 23 17:54:33 2016
New Revision: 258651

URL: http://llvm.org/viewvc/llvm-project?rev=258651&view=rev
Log:
[WinEH] Don't miscompile cleanups which conditionally unwind to caller

A cleanup can have paths which unwind or end up in unreachable.
If there is an unreachable path *and* a path which unwinds to caller,
we would mistakenly inject an unwind path to a catchswitch on the
unreachable path.  This results in a verifier assertion firing because
the cleanup unwinds to two different places: to the caller and to the
catchswitch.

This occured because we used getCleanupRetUnwindDest to determine if the
cleanuppad had no cleanuprets.
This is incorrect, getCleanupRetUnwindDest returns null for cleanuprets
which unwind to caller.

Modified:
    llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
    llvm/trunk/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll

Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=258651&r1=258650&r2=258651&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Sat Jan 23 17:54:33 2016
@@ -1072,7 +1072,8 @@ void WinEHPrepare::fixupNoReturnCleanupP
     if (!CleanupPad)
       continue;
     // Skip over any cleanups have unwind targets, they do not need this.
-    if (getCleanupRetUnwindDest(CleanupPad) != nullptr)
+    if (any_of(CleanupPad->users(),
+               [](const User *U) { return isa<CleanupReturnInst>(U); }))
       continue;
     // Walk the blocks within the cleanup which end in 'unreachable'.
     // We will replace the unreachable instruction with a cleanupret;

Modified: llvm/trunk/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll?rev=258651&r1=258650&r2=258651&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll (original)
+++ llvm/trunk/test/CodeGen/WinEH/wineh-cleanuppad-nounwind.ll Sat Jan 23 17:54:33 2016
@@ -65,6 +65,30 @@ exit:
   unreachable
 }
 
+; CHECK-LABEL: @test2(
+define void @test2(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
+entry:
+  invoke void @f()
+          to label %invoke.cont unwind label %ehcleanup
+
+invoke.cont:
+  unreachable
+
+ehcleanup:
+  %cp = cleanuppad within none []
+  br i1 %B, label %ret, label %if.then
+
+if.then:
+  call void @exit(i32 1) [ "funclet"(token %cp) ]
+  unreachable
+
+ret:
+  cleanupret from %cp unwind to caller
+}
+
+; CHECK: call void @exit(i32 1) [ "funclet"(token %cp) ]
+; CHECK-NEXT: unreachable
+
 declare void @f()
 declare void @exit(i32) nounwind noreturn
 




More information about the llvm-commits mailing list