[SEH] Implement GetExceptionCode in __except blocks
This introduces an intrinsic called llvm.eh.exceptioncode. It is lowered
by copying the EAX value live into whatever basic block it is called
from. Obviously, this only works if you insert it late during codegen,
because otherwise mid-level passes might reschedule it.
llvm-svn: 235768
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index b788232..fc5ca3e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -271,40 +271,49 @@
}
// Mark landing pad blocks.
- const LandingPadInst *LP = nullptr;
+ SmallVector<const LandingPadInst *, 4> LPads;
for (BB = Fn->begin(); BB != EB; ++BB) {
if (const auto *Invoke = dyn_cast<InvokeInst>(BB->getTerminator()))
MBBMap[Invoke->getSuccessor(1)]->setIsLandingPad();
if (BB->isLandingPad())
- LP = BB->getLandingPadInst();
+ LPads.push_back(BB->getLandingPadInst());
}
- // Calculate EH numbers for MSVC C++ EH and save SEH handlers if necessary.
+ // If this is an MSVC EH personality, we need to do a bit more work.
EHPersonality Personality = EHPersonality::Unknown;
- if (LP)
- Personality = classifyEHPersonality(LP->getPersonalityFn());
+ if (!LPads.empty())
+ Personality = classifyEHPersonality(LPads.back()->getPersonalityFn());
+ if (!isMSVCEHPersonality(Personality))
+ return;
+
+ WinEHFuncInfo *EHInfo = nullptr;
if (Personality == EHPersonality::MSVC_Win64SEH) {
- addSEHHandlersForLPads();
+ addSEHHandlersForLPads(LPads);
} else if (Personality == EHPersonality::MSVC_CXX) {
const Function *WinEHParentFn = MMI.getWinEHParent(&fn);
- WinEHFuncInfo &FI = MMI.getWinEHFuncInfo(WinEHParentFn);
- if (FI.LandingPadStateMap.empty()) {
- WinEHNumbering Num(FI);
+ EHInfo = &MMI.getWinEHFuncInfo(WinEHParentFn);
+ if (EHInfo->LandingPadStateMap.empty()) {
+ WinEHNumbering Num(*EHInfo);
Num.calculateStateNumbers(*WinEHParentFn);
// Pop everything on the handler stack.
Num.processCallSite(None, ImmutableCallSite());
}
+
+ // Copy the state numbers to LandingPadInfo for the current function, which
+ // could be a handler or the parent.
+ for (const LandingPadInst *LP : LPads) {
+ MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()];
+ MMI.addWinEHState(LPadMBB, EHInfo->LandingPadStateMap[LP]);
+ }
}
}
-void FunctionLoweringInfo::addSEHHandlersForLPads() {
+void FunctionLoweringInfo::addSEHHandlersForLPads(
+ ArrayRef<const LandingPadInst *> LPads) {
MachineModuleInfo &MMI = MF->getMMI();
// Iterate over all landing pads with llvm.eh.actions calls.
- for (const BasicBlock &BB : *Fn) {
- const LandingPadInst *LP = BB.getLandingPadInst();
- if (!LP)
- continue;
+ for (const LandingPadInst *LP : LPads) {
const IntrinsicInst *ActionsCall =
dyn_cast<IntrinsicInst>(LP->getNextNode());
if (!ActionsCall ||
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 01419cf..fd59d57 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -4817,6 +4817,18 @@
case Intrinsic::eh_begincatch:
case Intrinsic::eh_endcatch:
llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
+ case Intrinsic::eh_exceptioncode: {
+ unsigned Reg = TLI.getExceptionPointerRegister();
+ assert(Reg && "cannot get exception code on this platform");
+ MVT PtrVT = TLI.getPointerTy();
+ const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
+ unsigned VReg = FuncInfo.MBB->addLiveIn(Reg, PtrRC);
+ SDValue N =
+ DAG.getCopyFromReg(DAG.getEntryNode(), getCurSDLoc(), VReg, PtrVT);
+ N = DAG.getZExtOrTrunc(N, getCurSDLoc(), MVT::i32);
+ setValue(&I, N);
+ return nullptr;
+ }
}
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
index f3735cb..056ba4a 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -961,12 +961,6 @@
for (MachineBasicBlock *InvokeBB : InvokeBBs)
InvokeBB->removeSuccessor(MBB);
- // Transfer EH state number assigned to the IR block to the MBB.
- if (Personality == EHPersonality::MSVC_CXX) {
- WinEHFuncInfo &FI = MF->getMMI().getWinEHFuncInfo(MF->getFunction());
- MF->getMMI().addWinEHState(MBB, FI.LandingPadStateMap[LPadInst]);
- }
-
// Don't select instructions for the landingpad.
return false;
}
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 8a0fb7f..963692a 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -71,7 +71,7 @@
public:
static char ID; // Pass identification, replacement for typeid.
WinEHPrepare(const TargetMachine *TM = nullptr)
- : FunctionPass(ID), DT(nullptr) {}
+ : FunctionPass(ID), DT(nullptr), SEHExceptionCodeSlot(nullptr) {}
bool runOnFunction(Function &Fn) override;
@@ -133,6 +133,8 @@
// outlined into a handler. This is done after all handlers have been
// outlined but before the outlined code is pruned from the parent function.
DenseMap<const BasicBlock *, BasicBlock *> LPadTargetBlocks;
+
+ AllocaInst *SEHExceptionCodeSlot;
};
class WinEHFrameVariableMaterializer : public ValueMaterializer {
@@ -628,6 +630,13 @@
Type *Int32Type = Type::getInt32Ty(Context);
Function *ActionIntrin = Intrinsic::getDeclaration(M, Intrinsic::eh_actions);
+ if (isAsynchronousEHPersonality(Personality)) {
+ // FIXME: Switch the ehptr type to i32 and then switch this.
+ SEHExceptionCodeSlot =
+ new AllocaInst(Int8PtrType, nullptr, "seh_exception_code",
+ F.getEntryBlock().getFirstInsertionPt());
+ }
+
for (LandingPadInst *LPad : LPads) {
// Look for evidence that this landingpad has already been processed.
bool LPadHasActionList = false;
@@ -680,23 +689,48 @@
// Replace all extracted values with undef and ultimately replace the
// landingpad with undef.
- // FIXME: This doesn't handle SEH GetExceptionCode(). For now, we just give
- // out undef until we figure out the codegen support.
- SmallVector<Instruction *, 4> Extracts;
+ SmallVector<Instruction *, 4> SEHCodeUses;
+ SmallVector<Instruction *, 4> EHUndefs;
for (User *U : LPad->users()) {
auto *E = dyn_cast<ExtractValueInst>(U);
if (!E)
continue;
assert(E->getNumIndices() == 1 &&
"Unexpected operation: extracting both landing pad values");
- Extracts.push_back(E);
+ unsigned Idx = *E->idx_begin();
+ assert((Idx == 0 || Idx == 1) && "unexpected index");
+ if (Idx == 0 && isAsynchronousEHPersonality(Personality))
+ SEHCodeUses.push_back(E);
+ else
+ EHUndefs.push_back(E);
}
- for (Instruction *E : Extracts) {
+ for (Instruction *E : EHUndefs) {
E->replaceAllUsesWith(UndefValue::get(E->getType()));
E->eraseFromParent();
}
LPad->replaceAllUsesWith(UndefValue::get(LPad->getType()));
+ // Rewrite uses of the exception pointer to loads of an alloca.
+ for (Instruction *E : SEHCodeUses) {
+ SmallVector<Use *, 4> Uses;
+ for (Use &U : E->uses())
+ Uses.push_back(&U);
+ for (Use *U : Uses) {
+ auto *I = cast<Instruction>(U->getUser());
+ if (isa<ResumeInst>(I))
+ continue;
+ LoadInst *LI;
+ if (auto *Phi = dyn_cast<PHINode>(I))
+ LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false,
+ Phi->getIncomingBlock(*U));
+ else
+ LI = new LoadInst(SEHExceptionCodeSlot, "sehcode", false, I);
+ U->set(LI);
+ }
+ E->replaceAllUsesWith(UndefValue::get(E->getType()));
+ E->eraseFromParent();
+ }
+
// Add a call to describe the actions for this landing pad.
std::vector<Value *> ActionArgs;
for (ActionHandler *Action : Actions) {
@@ -820,6 +854,13 @@
Builder.SetInsertPoint(&F.getEntryBlock().back());
Builder.CreateCall(FrameEscapeFn, AllocasToEscape);
+ if (SEHExceptionCodeSlot) {
+ if (SEHExceptionCodeSlot->hasNUses(0))
+ SEHExceptionCodeSlot->eraseFromParent();
+ else
+ PromoteMemToReg(SEHExceptionCodeSlot, *DT);
+ }
+
// Clean up the handler action maps we created for this function
DeleteContainerSeconds(CatchHandlerMap);
CatchHandlerMap.clear();
@@ -1193,6 +1234,7 @@
/// target.
void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
BasicBlock *StartBB) {
+ LLVMContext &Context = StartBB->getContext();
BasicBlock *HandlerBB;
BasicBlock *NextBB;
Constant *Selector;
@@ -1210,6 +1252,12 @@
HandlerBB =
StartBB->splitBasicBlock(StartBB->getFirstInsertionPt(), "catch.all");
}
+ IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
+ Function *EHCodeFn = Intrinsic::getDeclaration(
+ StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
+ Value *Code = Builder.CreateCall(EHCodeFn, "sehcode");
+ Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
+ Builder.CreateStore(Code, SEHExceptionCodeSlot);
CatchAction->setHandlerBlockOrFunc(BlockAddress::get(HandlerBB));
TinyPtrVector<BasicBlock *> Targets(HandlerBB);
CatchAction->setReturnTargets(Targets);