forked from OSchip/llvm-project
[SEH] Add llvm.eh.exceptioncode intrinsic
This will support the Clang __exception_code intrinsic. llvm-svn: 249492
This commit is contained in:
parent
ee59282bfd
commit
72ba70418f
|
@ -72,7 +72,10 @@ public:
|
|||
/// ValueMap - Since we emit code for the function a basic block at a time,
|
||||
/// we must remember which virtual registers hold the values for
|
||||
/// cross-basic-block values.
|
||||
DenseMap<const Value*, unsigned> ValueMap;
|
||||
DenseMap<const Value *, unsigned> ValueMap;
|
||||
|
||||
/// Track virtual registers created for exception pointers.
|
||||
DenseMap<const Value *, unsigned> CatchPadExceptionPointers;
|
||||
|
||||
// Keep track of frame indices allocated for statepoints as they could be used
|
||||
// across basic block boundaries.
|
||||
|
@ -234,6 +237,9 @@ public:
|
|||
/// getArgumentFrameIndex - Get frame index for the byval argument.
|
||||
int getArgumentFrameIndex(const Argument *A);
|
||||
|
||||
unsigned getCatchPadExceptionPointerVReg(const Value *CPI,
|
||||
const TargetRegisterClass *RC);
|
||||
|
||||
private:
|
||||
void addSEHHandlersForLPads(ArrayRef<const LandingPadInst *> LPads);
|
||||
|
||||
|
|
|
@ -441,10 +441,14 @@ def int_eh_endcatch : Intrinsic<[], []>;
|
|||
def int_eh_exceptionpointer : Intrinsic<[llvm_anyptr_ty], [llvm_token_ty],
|
||||
[IntrNoMem]>;
|
||||
|
||||
// Gets the exception code from a catchpad token. Only used on some platforms.
|
||||
def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [llvm_token_ty], [IntrNoMem]>;
|
||||
|
||||
// Represents the list of actions to take when an exception is thrown.
|
||||
def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>;
|
||||
|
||||
def int_eh_exceptioncode : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
|
||||
// FIXME: Remove this when landing pad EH can be removed.
|
||||
def int_eh_exceptioncode_old : Intrinsic<[llvm_i32_ty], [], [IntrReadMem]>;
|
||||
|
||||
// __builtin_unwind_init is an undocumented GCC intrinsic that causes all
|
||||
// callee-saved registers to be saved and restored (regardless of whether they
|
||||
|
|
|
@ -577,6 +577,17 @@ int FunctionLoweringInfo::getArgumentFrameIndex(const Argument *A) {
|
|||
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
|
||||
|
|
|
@ -5240,7 +5240,7 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||
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 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
|
|||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -922,14 +922,46 @@ void SelectionDAGISel::DoInstructionSelection() {
|
|||
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 @@ bool SelectionDAGISel::PrepareEHLandingPad() {
|
|||
|
||||
// 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 @@ void SelectionDAGISel::SelectAllBasicBlocks(const Function &Fn) {
|
|||
// 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) {
|
||||
|
|
|
@ -1614,7 +1614,7 @@ void WinEHPrepare::processSEHCatchHandler(CatchHandler *CatchAction,
|
|||
}
|
||||
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 @@ colorFunclets(Function &F, SmallVectorImpl<BasicBlock *> &EntryBlocks,
|
|||
// 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 @@ void llvm::calculateCatchReturnSuccessorColors(const Function *Fn,
|
|||
|
||||
// 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!");
|
||||
|
|
|
@ -3681,6 +3681,7 @@ void Verifier::visitIntrinsicCallSite(Intrinsic::ID ID, CallSite CS) {
|
|||
"gc.relocate: relocating a pointer shouldn't change its address space", CS);
|
||||
break;
|
||||
}
|
||||
case Intrinsic::eh_exceptioncode:
|
||||
case Intrinsic::eh_exceptionpointer: {
|
||||
Assert(isa<CatchPadInst>(CS.getArgOperand(0)),
|
||||
"eh.exceptionpointer argument must be a catchpad", CS);
|
||||
|
|
|
@ -52,13 +52,13 @@ __try.cont: ; preds = %invoke.cont, %__exc
|
|||
; CHECK: landingpad
|
||||
; CHECK: indirectbr i8* %{{[^,]*}}, [label %[[except_split1:.*]]]
|
||||
; CHECK: [[except_split1]]:
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode()
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode.old()
|
||||
; CHECK: br label %__except
|
||||
;
|
||||
; CHECK: landingpad
|
||||
; CHECK: indirectbr i8* %{{[^,]*}}, [label %[[except_split2:.*]]]
|
||||
; CHECK: [[except_split2]]:
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode()
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode.old()
|
||||
; CHECK: br label %__except
|
||||
;
|
||||
; CHECK: __except:
|
||||
|
|
|
@ -87,5 +87,5 @@ entry:
|
|||
; CHECK-NEXT: indirectbr i8* %{{[^,]*}}, [label %__except]
|
||||
;
|
||||
; CHECK: __except:
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode()
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode.old()
|
||||
; CHECK: call i32 (i8*, ...) @printf
|
||||
|
|
|
@ -55,7 +55,7 @@ eh.resume:
|
|||
; CHECK-NEXT: indirectbr {{.*}} [label %__except]
|
||||
;
|
||||
; CHECK: __except:
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode()
|
||||
; CHECK: call i32 @llvm.eh.exceptioncode.old()
|
||||
; CHECK: invoke void @might_crash(i8* %{{.*}})
|
||||
; CHECK: landingpad { i8*, i32 }
|
||||
; CHECK-NEXT: cleanup
|
||||
|
|
Loading…
Reference in New Issue