diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/AsmPrinter/WinException.cpp | 21 | ||||
| -rw-r--r-- | llvm/lib/MC/WinCOFFObjectWriter.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelLowering.cpp | 54 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86WinEHState.cpp | 35 |
4 files changed, 64 insertions, 55 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp index 40d6bab8b6d..75287fd9855 100644 --- a/llvm/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/WinException.cpp @@ -449,7 +449,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { Asm->OutContext.getOrCreateParentFrameOffsetSymbol( GlobalValue::getRealLinkageName(HT.Handler->getName())); const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create( - ParentFrameOffset, MCSymbolRefExpr::VK_None, Asm->OutContext); + ParentFrameOffset, Asm->OutContext); OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset } } @@ -551,11 +551,26 @@ void WinException::extendIP2StateTable(const MachineFunction *MF, /// functionally equivalent to the __C_specific_handler table, except it is /// indexed by state number instead of IP. void WinException::emitExceptHandlerTable(const MachineFunction *MF) { - auto &OS = *Asm->OutStreamer; + MCStreamer &OS = *Asm->OutStreamer; - // Emit the __ehtable label that we use for llvm.x86.seh.lsda. + // Define the EH registration node offset label in terms of its frameescape + // label. The WinEHStatePass ensures that the registration node is passed to + // frameescape. This allows SEH filter functions to access the + // EXCEPTION_POINTERS field, which is filled in by the _except_handlerN. const Function *F = MF->getFunction(); + WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F); + assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX && + "no EH reg node frameescape index"); StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName()); + MCSymbol *ParentFrameOffset = + Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName); + MCSymbol *FrameAllocSym = Asm->OutContext.getOrCreateFrameAllocSymbol( + FLinkageName, FuncInfo.EHRegNodeEscapeIndex); + const MCSymbolRefExpr *FrameAllocSymRef = + MCSymbolRefExpr::create(FrameAllocSym, Asm->OutContext); + OS.EmitAssignment(ParentFrameOffset, FrameAllocSymRef); + + // Emit the __ehtable label that we use for llvm.x86.seh.lsda. MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName); OS.EmitLabel(LSDALabel); diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp index 423c7dce45d..56ef1c7a273 100644 --- a/llvm/lib/MC/WinCOFFObjectWriter.cpp +++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp @@ -526,13 +526,12 @@ bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol, if (!Symbol.isTemporary()) return true; - // Absolute temporary labels are never visible. - if (!Symbol.isInSection()) + // Temporary variable symbols are invisible. + if (Symbol.isVariable()) return false; - // For now, all non-variable symbols are exported, - // the linker will sort the rest out for us. - return !Symbol.isVariable(); + // Absolute temporary labels are never visible. + return !Symbol.isAbsolute(); } bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) { 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); |

