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/Target/X86/X86WinEHState.cpp | |
parent | 81f3ccb505f8a594703bfc574442bb5c8bb841e3 (diff) | |
download | llvm-94b704c4691a8b10eff156277976702475bdfd3e.zip llvm-94b704c4691a8b10eff156277976702475bdfd3e.tar.gz llvm-94b704c4691a8b10eff156277976702475bdfd3e.tar.bz2 |
[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/Target/X86/X86WinEHState.cpp')
-rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 63 |
1 files changed, 44 insertions, 19 deletions
diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index ccec774..38dc5db 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -68,9 +68,10 @@ private: void unlinkExceptionRegistration(IRBuilder<> &Builder); void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo); void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo); - void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, - Function &F, int BaseState); + void addStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, + Function &F, int BaseState); void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); + void insertRestoreFrame(BasicBlock *BB); Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); @@ -91,6 +92,7 @@ private: Function *FrameRecover = nullptr; Function *FrameAddress = nullptr; Function *FrameEscape = nullptr; + Function *RestoreFrame = nullptr; // Per-function state EHPersonality Personality = EHPersonality::Unknown; @@ -123,6 +125,8 @@ bool WinEHStatePass::doInitialization(Module &M) { FrameEscape = Intrinsic::getDeclaration(TheModule, Intrinsic::localescape); FrameRecover = Intrinsic::getDeclaration(TheModule, Intrinsic::localrecover); FrameAddress = Intrinsic::getDeclaration(TheModule, Intrinsic::frameaddress); + RestoreFrame = + Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); return false; } @@ -414,7 +418,7 @@ void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) { calculateWinCXXEHStateNumbers(&F, FuncInfo); // The base state for the parent is -1. - addCXXStateStoresToFunclet(RegNode, FuncInfo, F, -1); + addStateStoresToFunclet(RegNode, FuncInfo, F, -1); // Set up RegNodeEscapeIndex int RegNodeEscapeIndex = escapeRegNode(F); @@ -434,7 +438,7 @@ void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) { FrameRecover, {FI8, ParentFP, Builder.getInt32(RegNodeEscapeIndex)}); RecoveredRegNode = Builder.CreateBitCast(RecoveredRegNode, RegNodeTy->getPointerTo(0)); - addCXXStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState); + addStateStoresToFunclet(RecoveredRegNode, FuncInfo, *Handler, BaseState); } } @@ -470,11 +474,17 @@ int WinEHStatePass::escapeRegNode(Function &F) { return Args.size() - 1; } -void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, - WinEHFuncInfo &FuncInfo, - Function &F, int BaseState) { - Function *RestoreFrame = - Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_restoreframe); +void WinEHStatePass::insertRestoreFrame(BasicBlock *BB) { + Instruction *Start = BB->getFirstInsertionPt(); + if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>())) + return; + IRBuilder<> Builder(Start); + Builder.CreateCall(RestoreFrame, {}); +} + +void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode, + WinEHFuncInfo &FuncInfo, + Function &F, int BaseState) { // Iterate all the instructions and emit state number stores. for (BasicBlock &BB : F) { for (Instruction &I : BB) { @@ -494,16 +504,14 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, } } - // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. - if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator())) { - Instruction *Start = CR->getSuccessor()->begin(); - assert(!isa<PHINode>(Start) && - "winehprepare failed to demote phi after catchret"); - if (match(Start, m_Intrinsic<Intrinsic::x86_seh_restoreframe>())) - continue; - IRBuilder<> Builder(Start); - Builder.CreateCall(RestoreFrame, {}); - } + // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. In + // SEH, insert them before the catchret. + // FIXME: We should probably do this as part of catchret lowering in the + // DAG. + if (auto *CR = dyn_cast<CatchReturnInst>(BB.getTerminator())) + insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH + ? CR->getParent() + : CR->getSuccessor()); } } @@ -519,6 +527,23 @@ void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) { int RegNodeEscapeIndex = escapeRegNode(F); FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; + // If this funciton uses the new EH IR, use the explicit state numbering + // algorithm and return early. + bool UsesLPads = false; + for (BasicBlock &BB : F) { + if (BB.isLandingPad()) { + UsesLPads = true; + break; + } + } + if (!UsesLPads) { + calculateSEHStateNumbers(&F, FuncInfo); + addStateStoresToFunclet(RegNode, FuncInfo, F, -1); + return; + } + // FIXME: Delete the rest of this code and clean things up when new EH is + // done. + // Iterate all the instructions and emit state number stores. int CurState = 0; SmallPtrSet<BasicBlock *, 4> ExceptBlocks; |