diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-06-11 22:32:23 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-06-11 22:32:23 +0000 |
commit | a9d62535727e23588c86dd6ad1d339cb331799ac (patch) | |
tree | 080dba998fbb1a75d1939d30c6428d450d08a5f2 /llvm/lib/Target | |
parent | 6bb26dafa4cda63c14da97e65eff1e982375fd16 (diff) | |
download | bcm5719-llvm-a9d62535727e23588c86dd6ad1d339cb331799ac.tar.gz bcm5719-llvm-a9d62535727e23588c86dd6ad1d339cb331799ac.zip |
[WinEH] Create an llvm.x86.seh.exceptioninfo intrinsic
This intrinsic is like framerecover plus a load. It recovers the EH
registration stack allocation from the parent frame and loads the
exception information field out of it, giving back a pointer to an
EXCEPTION_POINTERS struct. It's designed for clang to use in SEH filter
expressions instead of accessing the EXCEPTION_POINTERS parameter that
is available on x64.
This required a minor change to MC to allow defining a label variable to
another absolute framerecover label variable.
llvm-svn: 239567
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 54 | ||||
-rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 35 |
2 files changed, 42 insertions, 47 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp index 8e663097d71..a4c7d1620fc 100644 --- a/llvm/lib/Target/X86/X86ISelLowering.cpp +++ b/llvm/lib/Target/X86/X86ISelLowering.cpp @@ -15506,23 +15506,6 @@ static SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, const X86Subtarget *Subtarget DAG.getTargetExternalSymbol(Name.data(), VT, X86II::MO_NOPREFIX); return DAG.getNode(X86ISD::Wrapper, dl, VT, Result); } - - case Intrinsic::eh_exceptioninfo: { - // Compute the symbol for the LSDA. We know it'll get emitted later. - MachineFunction &MF = DAG.getMachineFunction(); - SDValue Op1 = Op.getOperand(1); - auto *Fn = cast<Function>(cast<GlobalAddressSDNode>(Op1)->getGlobal()); - MCSymbol *LSDASym = MF.getMMI().getContext().getOrCreateLSDASymbol( - GlobalValue::getRealLinkageName(Fn->getName())); - StringRef Name = LSDASym->getName(); - assert(Name.data()[Name.size()] == '\0' && "not null terminated"); - - // Generate a simple absolute symbol reference. This intrinsic is only - // supported on 32-bit Windows, which isn't PIC. - SDValue Result = - DAG.getTargetExternalSymbol(Name.data(), VT, X86II::MO_NOPREFIX); - return DAG.getNode(X86ISD::Wrapper, dl, VT, Result); - } } } @@ -15707,14 +15690,49 @@ static SDValue LowerREADCYCLECOUNTER(SDValue Op, const X86Subtarget *Subtarget, return DAG.getMergeValues(Results, DL); } +static SDValue LowerEXCEPTIONINFO(SDValue Op, const X86Subtarget *Subtarget, + SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + SDLoc dl(Op); + SDValue FnOp = Op.getOperand(2); + SDValue FPOp = Op.getOperand(3); + + // Compute the symbol for the parent EH registration. We know it'll get + // emitted later. + auto *Fn = cast<Function>(cast<GlobalAddressSDNode>(FnOp)->getGlobal()); + MCSymbol *ParentFrameSym = + MF.getMMI().getContext().getOrCreateParentFrameOffsetSymbol( + GlobalValue::getRealLinkageName(Fn->getName())); + StringRef Name = ParentFrameSym->getName(); + assert(Name.data()[Name.size()] == '\0' && "not null terminated"); + + // Create a TargetExternalSymbol for the label to avoid any target lowering + // that would make this PC relative. + MVT PtrVT = Op.getSimpleValueType(); + SDValue OffsetSym = DAG.getTargetExternalSymbol(Name.data(), PtrVT); + SDValue OffsetVal = + DAG.getNode(ISD::FRAME_ALLOC_RECOVER, dl, PtrVT, OffsetSym); + + // Add the offset to the FP. + SDValue Add = DAG.getNode(ISD::ADD, dl, PtrVT, FPOp, OffsetVal); + + // Load the second field of the struct, which is 4 bytes in. See + // WinEHStatePass for more info. + Add = DAG.getNode(ISD::ADD, dl, PtrVT, Add, DAG.getConstant(4, dl, PtrVT)); + return DAG.getLoad(PtrVT, dl, DAG.getEntryNode(), Add, MachinePointerInfo(), + false, false, false, 0); +} static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, SelectionDAG &DAG) { unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(1))->getZExtValue(); const IntrinsicData* IntrData = getIntrinsicWithChain(IntNo); - if (!IntrData) + if (!IntrData) { + if (IntNo == Intrinsic::x86_seh_exceptioninfo) + return LowerEXCEPTIONINFO(Op, Subtarget, DAG); return SDValue(); + } SDLoc dl(Op); switch(IntrData->Type) { diff --git a/llvm/lib/Target/X86/X86WinEHState.cpp b/llvm/lib/Target/X86/X86WinEHState.cpp index afad3f930da..e037f08790c 100644 --- a/llvm/lib/Target/X86/X86WinEHState.cpp +++ b/llvm/lib/Target/X86/X86WinEHState.cpp @@ -67,8 +67,6 @@ private: void addCXXStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, Function &F, int BaseState); void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); - iplist<Instruction>::iterator - rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin); Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); @@ -487,6 +485,12 @@ void WinEHStatePass::addCXXStateStoresToFunclet(Value *ParentRegNode, void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(&F); + // Remember and return the index that we used. We save it in WinEHFuncInfo so + // that we can lower llvm.x86.seh.exceptioninfo later in filter functions + // without too much trouble. + int RegNodeEscapeIndex = escapeRegNode(F); + FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; + // Iterate all the instructions and emit state number stores. int CurState = 0; SmallPtrSet<BasicBlock *, 4> ExceptBlocks; @@ -495,7 +499,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { if (auto *CI = dyn_cast<CallInst>(I)) { auto *Intrin = dyn_cast<IntrinsicInst>(CI); if (Intrin) { - I = rewriteExceptionInfoIntrinsics(Intrin); // Calls that "don't throw" are considered to be able to throw asynch // exceptions, but intrinsics cannot. continue; @@ -542,32 +545,6 @@ void WinEHStatePass::addSEHStateStores(Function &F, MachineModuleInfo &MMI) { } } -/// Rewrite llvm.eh.exceptioncode and llvm.eh.exceptioninfo to memory loads in -/// IR. -iplist<Instruction>::iterator -WinEHStatePass::rewriteExceptionInfoIntrinsics(IntrinsicInst *Intrin) { - Intrinsic::ID ID = Intrin->getIntrinsicID(); - if (ID != Intrinsic::eh_exceptioncode && ID != Intrinsic::eh_exceptioninfo) - return Intrin; - - // RegNode->ExceptionPointers - IRBuilder<> Builder(Intrin); - Value *Ptrs = - Builder.CreateLoad(Builder.CreateStructGEP(RegNodeTy, RegNode, 1)); - Value *Res; - if (ID == Intrinsic::eh_exceptioncode) { - // Ptrs->ExceptionRecord->Code - Ptrs = Builder.CreateBitCast( - Ptrs, Builder.getInt32Ty()->getPointerTo()->getPointerTo()); - Value *Rec = Builder.CreateLoad(Ptrs); - Res = Builder.CreateLoad(Rec); - } else { - Res = Ptrs; - } - Intrin->replaceAllUsesWith(Res); - return Intrin->eraseFromParent(); -} - void WinEHStatePass::insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State) { IRBuilder<> Builder(IP); |