From 0f16f3c826def2829befdbff764ef3d8ada3032c Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Wed, 23 Dec 2015 03:59:04 +0000 Subject: [PATCH] [WinEH] Don't visit the same catchswitch twice We visited the same catchswitch twice because it was both the child of another funclet and the predecessor of a cleanuppad. Instead, change the numbering algorithm to only recurse if the unwind destination of the inner funclet agrees with the unwind destination of the catchswitch. This fixes PR25926. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@256317 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/WinEHPrepare.cpp | 22 ++++++--- test/CodeGen/WinEH/wineh-statenumbering.ll | 55 ++++++++++++++++++++++ 2 files changed, 70 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index 3b076b65e69..dc9f78f006a 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -165,8 +165,7 @@ static void calculateStateNumbersForInvokes(const Function *Fn, continue; auto &BBColors = BlockColors[&BB]; - assert(BBColors.size() == 1 && - "multi-color BB not removed by preparation"); + assert(BBColors.size() == 1 && "multi-color BB not removed by preparation"); BasicBlock *FuncletEntryBB = BBColors.front(); BasicBlock *FuncletUnwindDest; @@ -249,8 +248,13 @@ static void calculateCXXStateNumbers(WinEHFuncInfo &FuncInfo, FuncInfo.FuncletBaseStateMap[CatchPad] = CatchLow; for (const User *U : CatchPad->users()) { const auto *UserI = cast(U); - if (UserI->isEHPad()) - calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); + if (auto *InnerCatchSwitch = dyn_cast(UserI)) + if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) + calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); + if (auto *InnerCleanupPad = dyn_cast(UserI)) + if (getCleanupRetUnwindDest(InnerCleanupPad) == + CatchSwitch->getUnwindDest()) + calculateCXXStateNumbers(FuncInfo, UserI, CatchLow); } } int CatchHigh = FuncInfo.getLastStateNumber(); @@ -347,9 +351,13 @@ static void calculateSEHStateNumbers(WinEHFuncInfo &FuncInfo, // outside the __try. for (const User *U : CatchPad->users()) { const auto *UserI = cast(U); - if (UserI->isEHPad()) { - calculateSEHStateNumbers(FuncInfo, UserI, ParentState); - } + if (auto *InnerCatchSwitch = dyn_cast(UserI)) + if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest()) + calculateSEHStateNumbers(FuncInfo, UserI, ParentState); + if (auto *InnerCleanupPad = dyn_cast(UserI)) + if (getCleanupRetUnwindDest(InnerCleanupPad) == + CatchSwitch->getUnwindDest()) + calculateSEHStateNumbers(FuncInfo, UserI, ParentState); } } else { auto *CleanupPad = cast(FirstNonPHI); diff --git a/test/CodeGen/WinEH/wineh-statenumbering.ll b/test/CodeGen/WinEH/wineh-statenumbering.ll index b7ec843aa39..dab7fde61a6 100644 --- a/test/CodeGen/WinEH/wineh-statenumbering.ll +++ b/test/CodeGen/WinEH/wineh-statenumbering.ll @@ -79,8 +79,63 @@ define i32 @nopads() #0 personality i32 (...)* @__CxxFrameHandler3 { ; CHECK-NEXT: ret i32 0 ; CHECK-NOT: __ehhandler$nopads +; CHECK-LABEL: define void @PR25926() +define void @PR25926() personality i32 (...)* @__CxxFrameHandler3 { +entry: + ; CHECK: entry: + ; CHECK: store i32 -1 + ; CHECK: store i32 0 + ; CHECK: invoke void @_CxxThrowException( + invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) + to label %unreachable unwind label %catch.dispatch + +catch.dispatch: ; preds = %entry + %0 = catchswitch within none [label %catch] unwind to caller + +catch: ; preds = %catch.dispatch + %1 = catchpad within %0 [i8* null, i32 64, i8* null] + ; CHECK: catch: + ; CHECK: store i32 3 + ; CHECK: invoke void @_CxxThrowException( + invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) [ "funclet"(token %1) ] + to label %unreachable1 unwind label %catch.dispatch1 + +catch.dispatch1: ; preds = %catch + %2 = catchswitch within %1 [label %catch2] unwind label %ehcleanup + +catch2: ; preds = %catch.dispatch1 + %3 = catchpad within %2 [i8* null, i32 64, i8* null] + catchret from %3 to label %try.cont + +try.cont: ; preds = %catch2 + ; CHECK: try.cont: + ; CHECK: store i32 1 + ; CHECK: call void @dtor() + call void @dtor() #3 [ "funclet"(token %1) ] + catchret from %1 to label %try.cont4 + +try.cont4: ; preds = %try.cont + ret void + +ehcleanup: ; preds = %catch.dispatch1 + %4 = cleanuppad within %1 [] + ; CHECK: ehcleanup: + ; CHECK: store i32 -1 + ; CHECK: call void @dtor() + call void @dtor() #3 [ "funclet"(token %4) ] + cleanupret from %4 unwind to caller + +unreachable: ; preds = %entry + unreachable + +unreachable1: ; preds = %catch + unreachable +} + declare void @g(i32) #0 +declare void @dtor() + declare x86_stdcallcc void @_CxxThrowException(i8*, %eh.ThrowInfo*) declare i32 @__CxxFrameHandler3(...) -- 2.34.1