diff options
author | Joseph Tremoulet <jotrem@microsoft.com> | 2015-10-06 20:30:33 +0000 |
---|---|---|
committer | Joseph Tremoulet <jotrem@microsoft.com> | 2015-10-06 20:30:33 +0000 |
commit | 7f8c1165cdf3dcd614d4c56fc78c2fa378047bab (patch) | |
tree | 5715a9fed8476c89bec8e93427d8a3c0e1eae7e1 | |
parent | 07a1c459f2631f2ad3e95d4becc0cd38af6a9be4 (diff) | |
download | bcm5719-llvm-7f8c1165cdf3dcd614d4c56fc78c2fa378047bab.tar.gz bcm5719-llvm-7f8c1165cdf3dcd614d4c56fc78c2fa378047bab.zip |
[WinEH] Implement state numbering for CoreCLR
Summary:
Assign one state number per handler/funclet, tracking parent state,
handler type, and catch type token.
State numbers are arranged such that ancestors have lower state numbers
than their descendants.
Reviewers: majnemer, andrew.w.kaylor, rnk
Subscribers: pgavlin, AndyAyers, llvm-commits
Differential Revision: http://reviews.llvm.org/D13450
llvm-svn: 249457
-rw-r--r-- | llvm/include/llvm/CodeGen/WinEHFuncInfo.h | 12 | ||||
-rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 85 |
3 files changed, 103 insertions, 0 deletions
diff --git a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h index 5d122094ff8..11591a85d28 100644 --- a/llvm/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/llvm/include/llvm/CodeGen/WinEHFuncInfo.h @@ -161,6 +161,15 @@ struct WinEHTryBlockMapEntry { SmallVector<WinEHHandlerType, 1> HandlerArray; }; +enum class ClrHandlerType { Catch, Finally, Fault, Filter }; + +struct ClrEHUnwindMapEntry { + MBBOrBasicBlock Handler; + uint32_t TypeToken; + int Parent; + ClrHandlerType HandlerType; +}; + struct WinEHFuncInfo { DenseMap<const Instruction *, int> EHPadStateMap; DenseMap<const CatchReturnInst *, const BasicBlock *> @@ -169,6 +178,7 @@ struct WinEHFuncInfo { SmallVector<WinEHUnwindMapEntry, 4> UnwindMap; SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap; SmallVector<SEHUnwindMapEntry, 4> SEHUnwindMap; + SmallVector<ClrEHUnwindMapEntry, 4> ClrEHUnwindMap; int UnwindHelpFrameIdx = INT_MAX; int UnwindHelpFrameOffset = -1; @@ -196,6 +206,8 @@ void calculateWinCXXEHStateNumbers(const Function *ParentFn, void calculateSEHStateNumbers(const Function *ParentFn, WinEHFuncInfo &FuncInfo); +void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo); + void calculateCatchReturnSuccessorColors(const Function *Fn, WinEHFuncInfo &FuncInfo); } diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index fb455943f90..d718ede35cd 100644 --- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -292,6 +292,8 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, calculateWinCXXEHStateNumbers(WinEHParentFn, EHInfo); else if (isAsynchronousEHPersonality(Personality)) calculateSEHStateNumbers(WinEHParentFn, EHInfo); + else if (Personality == EHPersonality::CoreCLR) + calculateClrEHStateNumbers(WinEHParentFn, EHInfo); calculateCatchReturnSuccessorColors(WinEHParentFn, EHInfo); @@ -316,6 +318,10 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, const BasicBlock *BB = UME.Handler.get<const BasicBlock *>(); UME.Handler = MBBMap[BB]; } + for (ClrEHUnwindMapEntry &CME : EHInfo.ClrEHUnwindMap) { + const BasicBlock *BB = CME.Handler.get<const BasicBlock *>(); + CME.Handler = MBBMap[BB]; + } // If there's an explicit EH registration node on the stack, record its // frame index. diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp index 88a639e8778..cd813e6f9bc 100644 --- a/llvm/lib/CodeGen/WinEHPrepare.cpp +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -2864,6 +2864,91 @@ void llvm::calculateWinCXXEHStateNumbers(const Function *Fn, } } +static int addClrEHHandler(WinEHFuncInfo &FuncInfo, int ParentState, + ClrHandlerType HandlerType, uint32_t TypeToken, + const BasicBlock *Handler) { + ClrEHUnwindMapEntry Entry; + Entry.Parent = ParentState; + Entry.Handler = Handler; + Entry.HandlerType = HandlerType; + Entry.TypeToken = TypeToken; + FuncInfo.ClrEHUnwindMap.push_back(Entry); + return FuncInfo.ClrEHUnwindMap.size() - 1; +} + +void llvm::calculateClrEHStateNumbers(const Function *Fn, + WinEHFuncInfo &FuncInfo) { + // Return if it's already been done. + if (!FuncInfo.EHPadStateMap.empty()) + return; + + SmallVector<std::pair<const Instruction *, int>, 8> Worklist; + + // Each pad needs to be able to refer to its parent, so scan the function + // looking for top-level handlers and seed the worklist with them. + for (const BasicBlock &BB : *Fn) { + if (!BB.isEHPad()) + continue; + if (BB.isLandingPad()) + report_fatal_error("CoreCLR EH cannot use landingpads"); + const Instruction *FirstNonPHI = BB.getFirstNonPHI(); + if (!doesEHPadUnwindToCaller(FirstNonPHI)) + continue; + // queue this with sentinel parent state -1 to mean unwind to caller. + Worklist.emplace_back(FirstNonPHI, -1); + } + + while (!Worklist.empty()) { + const Instruction *Pad; + int ParentState; + std::tie(Pad, ParentState) = Worklist.pop_back_val(); + + int PredState; + if (const CleanupEndPadInst *EndPad = dyn_cast<CleanupEndPadInst>(Pad)) { + FuncInfo.EHPadStateMap[EndPad] = ParentState; + // Queue the cleanuppad, in case it doesn't have a cleanupret. + Worklist.emplace_back(EndPad->getCleanupPad(), ParentState); + // Preds of the endpad should get the parent state. + PredState = ParentState; + } else if (const CleanupPadInst *Cleanup = dyn_cast<CleanupPadInst>(Pad)) { + // A cleanup can have multiple exits; don't re-process after the first. + if (FuncInfo.EHPadStateMap.count(Pad)) + continue; + // CoreCLR personality uses arity to distinguish faults from finallies. + const BasicBlock *PadBlock = Cleanup->getParent(); + ClrHandlerType HandlerType = + (Cleanup->getNumOperands() ? ClrHandlerType::Fault + : ClrHandlerType::Finally); + int NewState = + addClrEHHandler(FuncInfo, ParentState, HandlerType, 0, PadBlock); + FuncInfo.EHPadStateMap[Cleanup] = NewState; + // Propagate the new state to all preds of the cleanup + PredState = NewState; + } else if (const CatchEndPadInst *EndPad = dyn_cast<CatchEndPadInst>(Pad)) { + FuncInfo.EHPadStateMap[EndPad] = ParentState; + // Preds of the endpad should get the parent state. + PredState = ParentState; + } else if (const CatchPadInst *Catch = dyn_cast<CatchPadInst>(Pad)) { + const BasicBlock *Handler = Catch->getNormalDest(); + uint32_t TypeToken = static_cast<uint32_t>( + cast<ConstantInt>(Catch->getArgOperand(0))->getZExtValue()); + int NewState = addClrEHHandler(FuncInfo, ParentState, + ClrHandlerType::Catch, TypeToken, Handler); + FuncInfo.EHPadStateMap[Catch] = NewState; + // Preds of the catch get its state + PredState = NewState; + } else { + llvm_unreachable("Unexpected EH pad"); + } + + // Queue all predecessors with the given state + for (const BasicBlock *Pred : predecessors(Pad->getParent())) { + if ((Pred = getEHPadFromPredecessor(Pred))) + Worklist.emplace_back(Pred->getFirstNonPHI(), PredState); + } + } +} + void WinEHPrepare::replaceTerminatePadWithCleanup(Function &F) { if (Personality != EHPersonality::MSVC_CXX) return; |