[llvm] r249457 - [WinEH] Implement state numbering for CoreCLR
Joseph Tremoulet via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 6 13:30:33 PDT 2015
Author: josepht
Date: Tue Oct 6 15:30:33 2015
New Revision: 249457
URL: http://llvm.org/viewvc/llvm-project?rev=249457&view=rev
Log:
[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
Modified:
llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
Modified: llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h?rev=249457&r1=249456&r2=249457&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h (original)
+++ llvm/trunk/include/llvm/CodeGen/WinEHFuncInfo.h Tue Oct 6 15:30:33 2015
@@ -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
void calculateSEHStateNumbers(const Function *ParentFn,
WinEHFuncInfo &FuncInfo);
+void calculateClrEHStateNumbers(const Function *Fn, WinEHFuncInfo &FuncInfo);
+
void calculateCatchReturnSuccessorColors(const Function *Fn,
WinEHFuncInfo &FuncInfo);
}
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp?rev=249457&r1=249456&r2=249457&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp Tue Oct 6 15:30:33 2015
@@ -292,6 +292,8 @@ void FunctionLoweringInfo::set(const Fun
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 Fun
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.
Modified: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=249457&r1=249456&r2=249457&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (original)
+++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Tue Oct 6 15:30:33 2015
@@ -2864,6 +2864,91 @@ void llvm::calculateWinCXXEHStateNumbers
}
}
+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;
More information about the llvm-commits
mailing list