mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[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
This commit is contained in:
parent
d1c89447ca
commit
afc5b7d966
@ -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);
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user