mirror of
https://github.com/RPCSX/llvm.git
synced 2025-04-12 13:03:14 +00:00
[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
This commit is contained in:
parent
5a39c0c83b
commit
0f16f3c826
@ -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<Instruction>(U);
|
||||
if (UserI->isEHPad())
|
||||
calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
|
||||
if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI))
|
||||
if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest())
|
||||
calculateCXXStateNumbers(FuncInfo, UserI, CatchLow);
|
||||
if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(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<Instruction>(U);
|
||||
if (UserI->isEHPad()) {
|
||||
calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
|
||||
}
|
||||
if (auto *InnerCatchSwitch = dyn_cast<CatchSwitchInst>(UserI))
|
||||
if (InnerCatchSwitch->getUnwindDest() == CatchSwitch->getUnwindDest())
|
||||
calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
|
||||
if (auto *InnerCleanupPad = dyn_cast<CleanupPadInst>(UserI))
|
||||
if (getCleanupRetUnwindDest(InnerCleanupPad) ==
|
||||
CatchSwitch->getUnwindDest())
|
||||
calculateSEHStateNumbers(FuncInfo, UserI, ParentState);
|
||||
}
|
||||
} else {
|
||||
auto *CleanupPad = cast<CleanupPadInst>(FirstNonPHI);
|
||||
|
@ -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(...)
|
||||
|
Loading…
x
Reference in New Issue
Block a user