aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/X86/X86WinEHState.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2015-09-09 21:10:03 +0000
committerReid Kleckner <rnk@google.com>2015-09-09 21:10:03 +0000
commit94b704c4691a8b10eff156277976702475bdfd3e (patch)
treee1a2622631516e9ea1177e4bc60ef8c45dfcaa7f /llvm/lib/Target/X86/X86WinEHState.cpp
parent81f3ccb505f8a594703bfc574442bb5c8bb841e3 (diff)
downloadllvm-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.cpp63
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;