[SEH] Add llvm.eh.exceptioncode intrinsic
This will support the Clang __exception_code intrinsic.
llvm-svn: 249492
diff --git a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
index a7f5ba1..cf2d84f 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
@@ -577,6 +577,17 @@
return 0;
}
+unsigned FunctionLoweringInfo::getCatchPadExceptionPointerVReg(
+ const Value *CPI, const TargetRegisterClass *RC) {
+ MachineRegisterInfo &MRI = MF->getRegInfo();
+ auto I = CatchPadExceptionPointers.insert({CPI, 0});
+ unsigned &VReg = I.first->second;
+ if (I.second)
+ VReg = MRI.createVirtualRegister(RC);
+ assert(VReg && "null vreg in exception pointer table!");
+ return VReg;
+}
+
/// ComputeUsesVAFloatArgument - Determine if any floating-point values are
/// being passed to this variadic function, and set the MachineModuleInfo's
/// usesVAFloatArgument flag if so. This flag is used to emit an undefined
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 22809aa..ed96742 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5240,7 +5240,7 @@
case Intrinsic::eh_begincatch:
case Intrinsic::eh_endcatch:
llvm_unreachable("begin/end catch intrinsics not lowered in codegen");
- case Intrinsic::eh_exceptioncode: {
+ case Intrinsic::eh_exceptioncode_old: {
unsigned Reg = TLI.getExceptionPointerRegister();
assert(Reg && "cannot get exception code on this platform");
MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
@@ -5253,6 +5253,20 @@
setValue(&I, N);
return nullptr;
}
+
+ case Intrinsic::eh_exceptionpointer:
+ case Intrinsic::eh_exceptioncode: {
+ // Get the exception pointer vreg, copy from it, and resize it to fit.
+ const auto *CPI = cast<CatchPadInst>(I.getArgOperand(0));
+ MVT PtrVT = TLI.getPointerTy(DAG.getDataLayout());
+ const TargetRegisterClass *PtrRC = TLI.getRegClassFor(PtrVT);
+ unsigned VReg = FuncInfo.getCatchPadExceptionPointerVReg(CPI, 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 c20270d..bd60bba 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
@@ -922,14 +922,46 @@
PostprocessISelDAG();
}
+static bool hasExceptionPointerOrCodeUser(const CatchPadInst *CPI) {
+ for (const User *U : CPI->users()) {
+ if (const IntrinsicInst *EHPtrCall = dyn_cast<IntrinsicInst>(U)) {
+ Intrinsic::ID IID = EHPtrCall->getIntrinsicID();
+ if (IID == Intrinsic::eh_exceptionpointer ||
+ IID == Intrinsic::eh_exceptioncode)
+ return true;
+ }
+ }
+ return false;
+}
+
/// PrepareEHLandingPad - Emit an EH_LABEL, set up live-in registers, and
/// do other setup for EH landing-pad blocks.
bool SelectionDAGISel::PrepareEHLandingPad() {
MachineBasicBlock *MBB = FuncInfo->MBB;
-
+ const BasicBlock *LLVMBB = MBB->getBasicBlock();
const TargetRegisterClass *PtrRC =
TLI->getRegClassFor(TLI->getPointerTy(CurDAG->getDataLayout()));
+ // Catchpads have one live-in register, which typically holds the exception
+ // pointer or code.
+ if (const auto *CPI = dyn_cast<CatchPadInst>(LLVMBB->getFirstNonPHI())) {
+ if (hasExceptionPointerOrCodeUser(CPI)) {
+ // Get or create the virtual register to hold the pointer or code. Mark
+ // the live in physreg and copy into the vreg.
+ MCPhysReg EHPhysReg = TLI->getExceptionPointerRegister();
+ assert(EHPhysReg && "target lacks exception pointer register");
+ FuncInfo->ExceptionPointerVirtReg = MBB->addLiveIn(EHPhysReg, PtrRC);
+ unsigned VReg = FuncInfo->getCatchPadExceptionPointerVReg(CPI, PtrRC);
+ BuildMI(*MBB, FuncInfo->InsertPt, SDB->getCurDebugLoc(),
+ TII->get(TargetOpcode::COPY), VReg)
+ .addReg(EHPhysReg, RegState::Kill);
+ }
+ return true;
+ }
+
+ if (!LLVMBB->isLandingPad())
+ return true;
+
// Add a label to mark the beginning of the landing pad. Deletion of the
// landing pad can thus be detected via the MachineModuleInfo.
MCSymbol *Label = MF->getMMI().addLandingPad(MBB);
@@ -943,7 +975,6 @@
// If this personality function uses funclets, we need to split the landing
// pad into several BBs.
- const BasicBlock *LLVMBB = MBB->getBasicBlock();
const Constant *Personality = MF->getFunction()->getPersonalityFn();
if (const auto *PF = dyn_cast<Function>(Personality->stripPointerCasts()))
MF->getMMI().addPersonality(PF);
@@ -1159,10 +1190,8 @@
// Setup an EH landing-pad block.
FuncInfo->ExceptionPointerVirtReg = 0;
FuncInfo->ExceptionSelectorVirtReg = 0;
- if (LLVMBB->isLandingPad())
- if (!PrepareEHLandingPad())
- continue;
-
+ if (!PrepareEHLandingPad())
+ continue;
// Before doing SelectionDAG ISel, see if FastISel has been requested.
if (FastIS) {
diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index a9fec81..86b511c 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/lib/CodeGen/WinEHPrepare.cpp
@@ -1614,7 +1614,7 @@
}
IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
Function *EHCodeFn = Intrinsic::getDeclaration(
- StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode);
+ StartBB->getParent()->getParent(), Intrinsic::eh_exceptioncode_old);
Value *Code = Builder.CreateCall(EHCodeFn, {}, "sehcode");
Code = Builder.CreateIntToPtr(Code, SEHExceptionCodeSlot->getAllocatedType());
Builder.CreateStore(Code, SEHExceptionCodeSlot);
@@ -3019,12 +3019,11 @@
// Mark this as a funclet head as a member of itself.
FuncletBlocks[Visiting].insert(Visiting);
// Queue exits with the parent color.
- for (User *Exit : VisitingHead->users()) {
- for (BasicBlock *Succ :
- successors(cast<Instruction>(Exit)->getParent())) {
- if (BlockColors[Succ].insert(Color).second) {
- Worklist.push_back({Succ, Color});
- }
+ for (User *U : VisitingHead->users()) {
+ if (auto *Exit = dyn_cast<TerminatorInst>(U)) {
+ for (BasicBlock *Succ : successors(Exit->getParent()))
+ if (BlockColors[Succ].insert(Color).second)
+ Worklist.push_back({Succ, Color});
}
}
// Handle CatchPad specially since its successors need different colors.
@@ -3124,7 +3123,9 @@
// The users of a catchpad are always catchrets.
for (User *Exit : CatchPad->users()) {
- auto *CatchReturn = cast<CatchReturnInst>(Exit);
+ auto *CatchReturn = dyn_cast<CatchReturnInst>(Exit);
+ if (!CatchReturn)
+ continue;
BasicBlock *CatchRetSuccessor = CatchReturn->getSuccessor();
std::set<BasicBlock *> &SuccessorColors = BlockColors[CatchRetSuccessor];
assert(SuccessorColors.size() == 1 && "Expected BB to be monochrome!");