diff options
author | Reid Kleckner <rnk@google.com> | 2015-09-09 21:10:03 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2015-09-09 21:10:03 +0000 |
commit | 94b704c4691a8b10eff156277976702475bdfd3e (patch) | |
tree | e1a2622631516e9ea1177e4bc60ef8c45dfcaa7f /llvm/lib/CodeGen | |
parent | 81f3ccb505f8a594703bfc574442bb5c8bb841e3 (diff) | |
download | bcm5719-llvm-94b704c4691a8b10eff156277976702475bdfd3e.tar.gz bcm5719-llvm-94b704c4691a8b10eff156277976702475bdfd3e.zip |
[SEH] Emit 32-bit SEH tables for the new EH IR
The 32-bit tables don't actually contain PC range data, so emitting them
is incredibly simple.
The 64-bit tables, on the other hand, use the same table for state
numbering as well as label ranges. This makes things more difficult, so
it will be implemented later.
llvm-svn: 247192
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 52 | ||||
-rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinException.h | 2 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp | 23 | ||||
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 201 |
5 files changed, 225 insertions, 79 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index aedac5467c6..e706d73dee2 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -161,7 +161,7 @@ void WinException::endFunction(const MachineFunction *MF) { // Emit the tables appropriate to the personality function in use. If we // don't recognize the personality, assume it uses an Itanium-style LSDA. if (Per == EHPersonality::MSVC_Win64SEH) - emitCSpecificHandlerTable(); + emitCSpecificHandlerTable(MF); else if (Per == EHPersonality::MSVC_X86SEH) emitExceptHandlerTable(MF); else if (Per == EHPersonality::MSVC_CXX) @@ -222,9 +222,13 @@ const MCExpr *WinException::create32bitRef(const Value *V) { /// imagerel32 LabelLPad; // Zero means __finally. /// } Entries[NumEntries]; /// }; -void WinException::emitCSpecificHandlerTable() { +void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); + WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction()); + if (!FuncInfo.SEHUnwindMap.empty()) + report_fatal_error("x64 SEH tables not yet implemented"); + // Simplifying assumptions for first implementation: // - Cleanups are not implemented. // - Filters are not implemented. @@ -309,6 +313,15 @@ void WinException::emitCSpecificHandlerTable() { } } +/// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues +/// are used in the old WinEH scheme, and they will be removed eventually. +static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) { + if (Handler.is<MachineBasicBlock *>()) + return Handler.get<MachineBasicBlock *>()->getSymbol(); + else + return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>())); +} + void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { const Function *F = MF->getFunction(); const Function *ParentF = MMI->getWinEHParent(F); @@ -422,9 +435,9 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { int CatchHigh = TBME.CatchHigh; if (CatchHigh == -1) { for (WinEHHandlerType &HT : TBME.HandlerArray) - CatchHigh = std::max( - CatchHigh, - FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]); + CatchHigh = + std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast<Function>( + HT.Handler.get<const Value *>())]); } assert(TBME.TryLow <= TBME.TryHigh); @@ -464,13 +477,12 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext); } - OS.EmitIntValue(HT.Adjectives, 4); // Adjectives - OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type - OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset - if (HT.HandlerMBB) // Handler - OS.EmitValue(create32bitRef(HT.HandlerMBB->getSymbol()), 4); - else - OS.EmitValue(create32bitRef(HT.Handler), 4); + MCSymbol *HandlerSym = getMCSymbolForMBBOrGV(Asm, HT.Handler); + + OS.EmitIntValue(HT.Adjectives, 4); // Adjectives + OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type + OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset + OS.EmitValue(create32bitRef(HandlerSym), 4); // Handler if (shouldEmitPersonality) { if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) { @@ -482,7 +494,8 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { } else { MCSymbol *ParentFrameOffset = Asm->OutContext.getOrCreateParentFrameOffsetSymbol( - GlobalValue::getRealLinkageName(HT.Handler->getName())); + GlobalValue::getRealLinkageName( + HT.Handler.get<const Value *>()->getName())); const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext); OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset @@ -642,6 +655,19 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { BaseState = -2; } + if (!FuncInfo.SEHUnwindMap.empty()) { + for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { + MCSymbol *ExceptOrFinally = + UME.Handler.get<MachineBasicBlock *>()->getSymbol(); + OS.EmitIntValue(UME.ToState, 4); // ToState + OS.EmitValue(create32bitRef(UME.Filter), 4); // Filter + OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally + } + return; + } + // FIXME: The following code is for the old landingpad-based SEH + // implementation. Remove it when possible. + // Build a list of pointers to LandingPadInfos and then sort by WinEHState. const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); SmallVector<const LandingPadInfo *, 4> LPads; diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.h b/llvm/lib/CodeGen/AsmPrinter/WinException.h index 7a80984c32e..aa159f5cf6e 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.h +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.h @@ -36,7 +36,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { /// True if this is a 64-bit target and we should use image relative offsets. bool useImageRel32 = false; - void emitCSpecificHandlerTable(); + void emitCSpecificHandlerTable(const MachineFunction *MF); /// Emit the EH table data for 32-bit and 64-bit functions using /// the __CxxFrameHandler3 personality. diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 7bbb194ac19..15793f666ea 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -287,21 +287,31 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, addSEHHandlersForLPads(LPads); } + // Calculate state numbers if we haven't already. WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn); if (Personality == EHPersonality::MSVC_CXX) { - // Calculate state numbers and then map from funclet BBs to MBBs. const Function *WinEHParentFn = MMI.getWinEHParent(&fn); calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo); + } else { + const Function *WinEHParentFn = MMI.getWinEHParent(&fn); + calculateSEHStateNumbers(WinEHParentFn, EHInfo); + } + + // Map all BB references in the EH data to MBBs. for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) for (WinEHHandlerType &H : TBME.HandlerArray) - if (const auto *BB = dyn_cast<BasicBlock>(H.Handler)) - H.HandlerMBB = MBBMap[BB]; - // If there's an explicit EH registration node on the stack, record its - // frame index. - if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) { - assert(StaticAllocaMap.count(EHInfo.EHRegNode)); - EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode]; + if (const auto *BB = + dyn_cast<BasicBlock>(H.Handler.get<const Value *>())) + H.Handler = MBBMap[BB]; + for (SEHUnwindMapEntry &UME : EHInfo.SEHUnwindMap) { + const BasicBlock *BB = UME.Handler.get<const BasicBlock *>(); + UME.Handler = MBBMap[BB]; } + // If there's an explicit EH registration node on the stack, record its + // frame index. + if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) { + assert(StaticAllocaMap.count(EHInfo.EHRegNode)); + EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode]; } // Copy the state numbers to LandingPadInfo for the current function, which diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 1df4245bf0b..6fba18d60b2 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1989,7 +1989,6 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { // and catchendpads for successors. MachineBasicBlock *Return = FuncInfo.MBBMap[I.getSuccessor(0)]; const BasicBlock *EHPadBB = I.getSuccessor(1); - bool IsLandingPad = EHPadBB->isLandingPad(); const Value *Callee(I.getCalledValue()); const Function *Fn = dyn_cast<Function>(Callee); @@ -2025,16 +2024,26 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { // Catchpads are conditional branches that add real MBB destinations and // continue the loop. EH "end" pads are not real BBs and simply continue. SmallVector<MachineBasicBlock *, 1> UnwindDests; + bool IsMSVCCXX = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()) == + EHPersonality::MSVC_CXX; while (EHPadBB) { const Instruction *Pad = EHPadBB->getFirstNonPHI(); - if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) { - assert(FuncInfo.MBBMap[EHPadBB]); - // Stop on cleanup pads and landingpads. + if (isa<LandingPadInst>(Pad)) { + // Stop on landingpads. They are not funclets. UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]); break; + } else if (isa<CleanupPadInst>(Pad) || isa<LandingPadInst>(Pad)) { + // Stop on cleanup pads. Cleanups are always funclet entries for all known + // personalities. + UnwindDests.push_back(FuncInfo.MBBMap[EHPadBB]); + UnwindDests.back()->setIsEHFuncletEntry(); + break; } else if (const auto *CPI = dyn_cast<CatchPadInst>(Pad)) { // Add the catchpad handler to the possible destinations. UnwindDests.push_back(FuncInfo.MBBMap[CPI->getNormalDest()]); + // In MSVC C++, catchblocks are funclets and need prologues. + if (IsMSVCCXX) + UnwindDests.back()->setIsEHFuncletEntry(); EHPadBB = CPI->getUnwindDest(); } else if (const auto *CEPI = dyn_cast<CatchEndPadInst>(Pad)) { EHPadBB = CEPI->getUnwindDest(); @@ -2043,13 +2052,11 @@ void SelectionDAGBuilder::visitInvoke(const InvokeInst &I) { } } - // Update successor info + // Update successor info. // FIXME: The weights for catchpads will be wrong. addSuccessorWithWeight(InvokeMBB, Return); - for (auto *UnwindDest : UnwindDests) { + for (MachineBasicBlock *UnwindDest : UnwindDests) { UnwindDest->setIsEHPad(); - if (!IsLandingPad) - UnwindDest->setIsEHFuncletEntry(); addSuccessorWithWeight(InvokeMBB, UnwindDest); } diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index c333c074900..ed3cd5d400b 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -2616,7 +2616,6 @@ static void addTryBlockMapEntry(WinEHFuncInfo &FuncInfo, int TryLow, cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts()); } HT.Handler = CPI->getNormalDest(); - HT.HandlerMBB = nullptr; // FIXME: Pass CPI->getArgOperand(1). HT.CatchObjRecoverIdx = -1; TBME.HandlerArray.push_back(HT); @@ -2645,7 +2644,8 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh, continue; int N; for (N = 0; N < NumHandlers; ++N) { - if (Entry.HandlerArray[N].Handler != Handlers[N]->getHandlerBlockOrFunc()) + if (Entry.HandlerArray[N].Handler.get<const Value *>() != + Handlers[N]->getHandlerBlockOrFunc()) break; // breaks out of inner loop } // If all the handlers match, this is what we were looking for. @@ -2692,7 +2692,6 @@ void WinEHNumbering::createTryBlockMapEntry(int TryLow, int TryHigh, cast<GlobalVariable>(CS->getAggregateElement(1)->stripPointerCasts()); } HT.Handler = cast<Function>(CH->getHandlerBlockOrFunc()); - HT.HandlerMBB = nullptr; HT.CatchObjRecoverIdx = CH->getExceptionVarIndex(); TBME.HandlerArray.push_back(HT); } @@ -2949,13 +2948,45 @@ void WinEHNumbering::findActionRootLPads(const Function &F) { } } -static const BasicBlock *getSingleCatchPadPredecessor(const BasicBlock &BB) { - for (const BasicBlock *PredBlock : predecessors(&BB)) - if (isa<CatchPadInst>(PredBlock->getFirstNonPHI())) - return PredBlock; +static const CatchPadInst *getSingleCatchPadPredecessor(const BasicBlock *BB) { + for (const BasicBlock *PredBlock : predecessors(BB)) + if (auto *CPI = dyn_cast<CatchPadInst>(PredBlock->getFirstNonPHI())) + return CPI; return nullptr; } +/// Find all the catchpads that feed directly into the catchendpad. Frontends +/// using this personality should ensure that each catchendpad and catchpad has +/// one or zero catchpad predecessors. +/// +/// The following C++ generates the IR after it: +/// try { +/// } catch (A) { +/// } catch (B) { +/// } +/// +/// IR: +/// %catchpad.A +/// catchpad [i8* A typeinfo] +/// to label %catch.A unwind label %catchpad.B +/// %catchpad.B +/// catchpad [i8* B typeinfo] +/// to label %catch.B unwind label %endcatches +/// %endcatches +/// catchendblock unwind to caller +void findCatchPadsForCatchEndPad( + const BasicBlock *CatchEndBB, + SmallVectorImpl<const CatchPadInst *> &Handlers) { + const CatchPadInst *CPI = getSingleCatchPadPredecessor(CatchEndBB); + while (CPI) { + Handlers.push_back(CPI); + CPI = getSingleCatchPadPredecessor(CPI->getParent()); + } + // We've pushed these back into reverse source order. Reverse them to get + // the list back into source order. + std::reverse(Handlers.begin(), Handlers.end()); +} + // Given BB which ends in an unwind edge, return the EHPad that this BB belongs // to. If the unwind edge came from an invoke, return null. static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) { @@ -2970,9 +3001,9 @@ static const BasicBlock *getEHPadFromPredecessor(const BasicBlock *BB) { return cast<CleanupReturnInst>(TI)->getCleanupPad()->getParent(); } -static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo, - const BasicBlock &BB, - int ParentState) { +static void calculateExplicitCXXStateNumbers(WinEHFuncInfo &FuncInfo, + const BasicBlock &BB, + int ParentState) { assert(BB.isEHPad()); const Instruction *FirstNonPHI = BB.getFirstNonPHI(); // All catchpad instructions will be handled when we process their @@ -2981,36 +3012,30 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo, return; if (isa<CatchEndPadInst>(FirstNonPHI)) { - const BasicBlock *TryPad = &BB; - const BasicBlock *LastTryPad = nullptr; SmallVector<const CatchPadInst *, 2> Handlers; - do { - LastTryPad = TryPad; - TryPad = getSingleCatchPadPredecessor(*TryPad); - if (TryPad) - Handlers.push_back(cast<CatchPadInst>(TryPad->getFirstNonPHI())); - } while (TryPad); - // We've pushed these back into reverse source order. Reverse them to get - // the list back into source order. - std::reverse(Handlers.begin(), Handlers.end()); + findCatchPadsForCatchEndPad(&BB, Handlers); + const BasicBlock *FirstTryPad = Handlers.front()->getParent(); int TryLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr); FuncInfo.EHPadStateMap[Handlers.front()] = TryLow; - for (const BasicBlock *PredBlock : predecessors(LastTryPad)) + for (const BasicBlock *PredBlock : predecessors(FirstTryPad)) if ((PredBlock = getEHPadFromPredecessor(PredBlock))) - calculateExplicitStateNumbers(FuncInfo, *PredBlock, TryLow); + calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, TryLow); int CatchLow = addUnwindMapEntry(FuncInfo, ParentState, nullptr); + + // catchpads are separate funclets in C++ EH due to the way rethrow works. + // In SEH, they aren't, so no invokes will unwind to the catchendpad. FuncInfo.EHPadStateMap[FirstNonPHI] = CatchLow; int TryHigh = CatchLow - 1; for (const BasicBlock *PredBlock : predecessors(&BB)) if ((PredBlock = getEHPadFromPredecessor(PredBlock))) - calculateExplicitStateNumbers(FuncInfo, *PredBlock, CatchLow); + calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CatchLow); int CatchHigh = FuncInfo.getLastStateNumber(); addTryBlockMapEntry(FuncInfo, TryLow, TryHigh, CatchHigh, Handlers); - DEBUG(dbgs() << "TryLow[" << LastTryPad->getName() << "]: " << TryLow + DEBUG(dbgs() << "TryLow[" << FirstTryPad->getName() << "]: " << TryLow << '\n'); - DEBUG(dbgs() << "TryHigh[" << LastTryPad->getName() << "]: " << TryHigh + DEBUG(dbgs() << "TryHigh[" << FirstTryPad->getName() << "]: " << TryHigh << '\n'); - DEBUG(dbgs() << "CatchHigh[" << LastTryPad->getName() << "]: " << CatchHigh + DEBUG(dbgs() << "CatchHigh[" << FirstTryPad->getName() << "]: " << CatchHigh << '\n'); } else if (isa<CleanupPadInst>(FirstNonPHI)) { int CleanupState = addUnwindMapEntry(FuncInfo, ParentState, &BB); @@ -3019,7 +3044,73 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo, << BB.getName() << '\n'); for (const BasicBlock *PredBlock : predecessors(&BB)) if ((PredBlock = getEHPadFromPredecessor(PredBlock))) - calculateExplicitStateNumbers(FuncInfo, *PredBlock, CleanupState); + calculateExplicitCXXStateNumbers(FuncInfo, *PredBlock, CleanupState); + } else if (isa<TerminatePadInst>(FirstNonPHI)) { + report_fatal_error("Not yet implemented!"); + } else { + llvm_unreachable("unexpected EH Pad!"); + } +} + +static int addSEHHandler(WinEHFuncInfo &FuncInfo, int ParentState, + const Function *Filter, const BasicBlock *Handler) { + SEHUnwindMapEntry Entry; + Entry.ToState = ParentState; + Entry.Filter = Filter; + Entry.Handler = Handler; + FuncInfo.SEHUnwindMap.push_back(Entry); + return FuncInfo.SEHUnwindMap.size() - 1; +} + +static void calculateExplicitSEHStateNumbers(WinEHFuncInfo &FuncInfo, + const BasicBlock &BB, + int ParentState) { + assert(BB.isEHPad()); + const Instruction *FirstNonPHI = BB.getFirstNonPHI(); + // All catchpad instructions will be handled when we process their + // respective catchendpad instruction. + if (isa<CatchPadInst>(FirstNonPHI)) + return; + + if (isa<CatchEndPadInst>(FirstNonPHI)) { + // Extract the filter function and the __except basic block and create a + // state for them. + SmallVector<const CatchPadInst *, 1> Handlers; + findCatchPadsForCatchEndPad(&BB, Handlers); + assert(Handlers.size() == 1 && + "SEH doesn't have multiple handlers per __try"); + const CatchPadInst *CPI = Handlers.front(); + const BasicBlock *CatchPadBB = CPI->getParent(); + const Function *Filter = + cast<Function>(CPI->getArgOperand(0)->stripPointerCasts()); + int TryState = + addSEHHandler(FuncInfo, ParentState, Filter, CPI->getNormalDest()); + + // Everything in the __try block uses TryState as its parent state. + FuncInfo.EHPadStateMap[CPI] = TryState; + DEBUG(dbgs() << "Assigning state #" << TryState << " to BB " + << CatchPadBB->getName() << '\n'); + for (const BasicBlock *PredBlock : predecessors(CatchPadBB)) + if ((PredBlock = getEHPadFromPredecessor(PredBlock))) + calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, TryState); + + // Everything in the __except block unwinds to ParentState, just like code + // outside the __try. + FuncInfo.EHPadStateMap[FirstNonPHI] = ParentState; + DEBUG(dbgs() << "Assigning state #" << ParentState << " to BB " + << BB.getName() << '\n'); + for (const BasicBlock *PredBlock : predecessors(&BB)) + if ((PredBlock = getEHPadFromPredecessor(PredBlock))) + calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, ParentState); + } else if (isa<CleanupPadInst>(FirstNonPHI)) { + int CleanupState = + addSEHHandler(FuncInfo, ParentState, /*Filter=*/nullptr, &BB); + FuncInfo.EHPadStateMap[FirstNonPHI] = CleanupState; + DEBUG(dbgs() << "Assigning state #" << CleanupState << " to BB " + << BB.getName() << '\n'); + for (const BasicBlock *PredBlock : predecessors(&BB)) + if ((PredBlock = getEHPadFromPredecessor(PredBlock))) + calculateExplicitSEHStateNumbers(FuncInfo, *PredBlock, CleanupState); } else if (isa<TerminatePadInst>(FirstNonPHI)) { report_fatal_error("Not yet implemented!"); } else { @@ -3027,6 +3118,37 @@ static void calculateExplicitStateNumbers(WinEHFuncInfo &FuncInfo, } } +/// Check if the EH Pad unwinds to caller. Cleanups are a little bit of a +/// special case because we have to look at the cleanupret instruction that uses +/// the cleanuppad. +static bool doesEHPadUnwindToCaller(const Instruction *EHPad) { + auto *CPI = dyn_cast<CleanupPadInst>(EHPad); + if (!CPI) + return EHPad->mayThrow(); + + // This cleanup does not return or unwind, so we say it unwinds to caller. + if (CPI->use_empty()) + return true; + + const Instruction *User = CPI->user_back(); + if (auto *CRI = dyn_cast<CleanupReturnInst>(User)) + return CRI->unwindsToCaller(); + return cast<CleanupEndPadInst>(User)->unwindsToCaller(); +} + +void llvm::calculateSEHStateNumbers(const Function *ParentFn, + WinEHFuncInfo &FuncInfo) { + // Don't compute state numbers twice. + if (!FuncInfo.SEHUnwindMap.empty()) + return; + + for (const BasicBlock &BB : *ParentFn) { + if (!BB.isEHPad() || !doesEHPadUnwindToCaller(BB.getFirstNonPHI())) + continue; + calculateExplicitSEHStateNumbers(FuncInfo, BB, -1); + } +} + void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo) { // Return if it's already been done. @@ -3041,28 +3163,9 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *ParentFn, // Skip cleanupendpads; they are exits, not entries. if (isa<CleanupEndPadInst>(FirstNonPHI)) continue; - // Check if the EH Pad has no exceptional successors (i.e. it unwinds to - // caller). Cleanups are a little bit of a special case because their - // control flow cannot be determined by looking at the pad but instead by - // the pad's users. - bool HasNoSuccessors = false; - if (FirstNonPHI->mayThrow()) { - HasNoSuccessors = true; - } else if (auto *CPI = dyn_cast<CleanupPadInst>(FirstNonPHI)) { - if (CPI->use_empty()) { - HasNoSuccessors = true; - } else { - const Instruction *User = CPI->user_back(); - if (auto *CRI = dyn_cast<CleanupReturnInst>(User)) - HasNoSuccessors = CRI->unwindsToCaller(); - else - HasNoSuccessors = cast<CleanupEndPadInst>(User)->unwindsToCaller(); - } - } - - if (!HasNoSuccessors) + if (!doesEHPadUnwindToCaller(FirstNonPHI)) continue; - calculateExplicitStateNumbers(FuncInfo, BB, -1); + calculateExplicitCXXStateNumbers(FuncInfo, BB, -1); IsExplicit = true; } |