Skip to content

Commit

Permalink
[SEH] Add llvm.eh.exceptioncode intrinsic
Browse files Browse the repository at this point in the history
This will support the Clang __exception_code intrinsic.

llvm-svn: 249492
  • Loading branch information
rnk committed Oct 7, 2015
1 parent ee59282 commit 72ba704
Show file tree
Hide file tree
Showing 10 changed files with 87 additions and 21 deletions.
8 changes: 7 additions & 1 deletion llvm/include/llvm/CodeGen/FunctionLoweringInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,10 @@ class FunctionLoweringInfo {
/// 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.
Expand Down Expand Up @@ -234,6 +237,9 @@ class FunctionLoweringInfo {
/// 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);

Expand Down
6 changes: 5 additions & 1 deletion llvm/include/llvm/IR/Intrinsics.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
11 changes: 11 additions & 0 deletions llvm/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
16 changes: 15 additions & 1 deletion llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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;
}
}
}

Expand Down
41 changes: 35 additions & 6 deletions llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
17 changes: 9 additions & 8 deletions llvm/lib/CodeGen/WinEHPrepare.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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!");
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/IR/Verifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/WinEH/seh-exception-code.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/WinEH/seh-exception-code2.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/WinEH/seh-resume-phi.ll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 72ba704

Please sign in to comment.