diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index d163c971d4b..82c30d39afd 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -43,6 +43,7 @@ class TargetMachine; class TargetSubtargetInfo; class TargetRegisterClass; struct MachinePointerInfo; +struct WinEHFuncInfo; template <> struct ilist_traits @@ -107,6 +108,10 @@ class MachineFunction { // Keep track of jump tables for switch instructions MachineJumpTableInfo *JumpTableInfo; + // Keeps track of Windows exception handling related data. This will be null + // for functions that aren't using a funclet-based EH personality. + WinEHFuncInfo *WinEHInfo = nullptr; + // Function-level unique numbering for MachineBasicBlocks. When a // MachineBasicBlock is inserted into a MachineFunction is it automatically // numbered and this vector keeps track of the mapping from ID's to MBB's. @@ -221,6 +226,12 @@ public: MachineConstantPool *getConstantPool() { return ConstantPool; } const MachineConstantPool *getConstantPool() const { return ConstantPool; } + /// getWinEHFuncInfo - Return information about how the current function uses + /// Windows exception handling. Returns null for functions that don't use + /// funclets for exception handling. + const WinEHFuncInfo *getWinEHFuncInfo() const { return WinEHInfo; } + WinEHFuncInfo *getWinEHFuncInfo() { return WinEHInfo; } + /// getAlignment - Return the alignment (log2, not bytes) of the function. /// unsigned getAlignment() const { return Alignment; } diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 4df580f0dba..fd42b46476c 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -59,7 +59,6 @@ class MachineFunction; class Module; class PointerType; class StructType; -struct WinEHFuncInfo; struct SEHHandler { // Filter or finally function. Null indicates a catch-all. @@ -80,11 +79,9 @@ struct LandingPadInfo { SmallVector SEHHandlers; // SEH handlers active at this lpad. MCSymbol *LandingPadLabel; // Label at beginning of landing pad. std::vector TypeIds; // List of type ids (filters negative). - int WinEHState; // WinEH specific state number. explicit LandingPadInfo(MachineBasicBlock *MBB) - : LandingPadBlock(MBB), LandingPadLabel(nullptr), - WinEHState(-1) {} + : LandingPadBlock(MBB), LandingPadLabel(nullptr) {} }; //===----------------------------------------------------------------------===// @@ -182,8 +179,6 @@ class MachineModuleInfo : public ImmutablePass { EHPersonality PersonalityTypeCache; - DenseMap> FuncInfoMap; - public: static char ID; // Pass identification, replacement for typeid @@ -220,11 +215,6 @@ public: void setModule(const Module *M) { TheModule = M; } const Module *getModule() const { return TheModule; } - WinEHFuncInfo &getWinEHFuncInfo(const Function *F); - bool hasWinEHFuncInfo(const Function *F) const { - return FuncInfoMap.count(F) > 0; - } - /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// @@ -327,8 +317,6 @@ public: /// information. void addPersonality(const Function *Personality); - void addWinEHState(MachineBasicBlock *LandingPad, int State); - /// getPersonalities - Return array of personality functions ever seen. const std::vector& getPersonalities() const { return Personalities; diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h index 782119e84e2..5def70692ba 100644 --- a/include/llvm/CodeGen/WinEHFuncInfo.h +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -60,8 +60,8 @@ struct SEHUnwindMapEntry { struct WinEHHandlerType { int Adjectives; - /// The CatchObj starts out life as an LLVM alloca, is turned into a frame - /// index, and after PEI, becomes a raw offset. + /// The CatchObj starts out life as an LLVM alloca and is eventually turned + /// frame index. union { const AllocaInst *Alloca; int FrameIndex; @@ -103,10 +103,6 @@ struct WinEHFuncInfo { void addIPToStateRange(const BasicBlock *PadBB, MCSymbol *InvokeBegin, MCSymbol *InvokeEnd); - /// localescape index of the 32-bit EH registration node. Set by - /// WinEHStatePass and used indirectly by SEH filter functions of the parent. - int EHRegNodeEscapeIndex = INT_MAX; - const AllocaInst *EHRegNode = nullptr; int EHRegNodeFrameIndex = INT_MAX; int EHRegNodeEndOffset = INT_MAX; diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 3d6fa1c0662..2b5577cdad9 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -22,6 +22,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". let TargetPrefix = "x86" in { def int_x86_seh_lsda : Intrinsic<[llvm_ptr_ty], [llvm_ptr_ty], [IntrNoMem]>; + // Marks the EH registration node created in LLVM IR prior to code generation. + def int_x86_seh_ehregnode : Intrinsic<[], [llvm_ptr_ty], []>; + // Restores the frame, base, and stack pointers as necessary after recovering // from an exception. Any block resuming control flow in the parent function // should call this before accessing any stack memory. diff --git a/lib/CodeGen/AsmPrinter/WinException.cpp b/lib/CodeGen/AsmPrinter/WinException.cpp index 33eb3906fce..cd1f3f51bc4 100644 --- a/lib/CodeGen/AsmPrinter/WinException.cpp +++ b/lib/CodeGen/AsmPrinter/WinException.cpp @@ -299,7 +299,8 @@ const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf, Asm->OutContext); } -int WinException::getFrameIndexOffset(int FrameIndex, WinEHFuncInfo &FuncInfo) { +int WinException::getFrameIndexOffset(int FrameIndex, + const WinEHFuncInfo &FuncInfo) { const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering(); unsigned UnusedReg; if (Asm->MAI->usesWindowsCFI()) @@ -340,7 +341,7 @@ struct InvokeStateChange { /// reported is the first change to something other than NullState, and a /// change back to NullState is always reported at the end of iteration). class InvokeStateChangeIterator { - InvokeStateChangeIterator(WinEHFuncInfo &EHInfo, + InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator MFI, MachineFunction::const_iterator MFE, MachineBasicBlock::const_iterator MBBI) @@ -353,7 +354,7 @@ class InvokeStateChangeIterator { public: static iterator_range - range(WinEHFuncInfo &EHInfo, const MachineFunction &MF) { + range(const WinEHFuncInfo &EHInfo, const MachineFunction &MF) { // Reject empty MFs to simplify bookkeeping by ensuring that we can get the // end of the last block. assert(!MF.empty()); @@ -366,7 +367,7 @@ public: InvokeStateChangeIterator(EHInfo, FuncEnd, FuncEnd, BlockEnd)); } static iterator_range - range(WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin, + range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin, MachineFunction::const_iterator End) { // Reject empty ranges to simplify bookkeeping by ensuring that we can get // the end of the last block. @@ -402,7 +403,7 @@ public: private: InvokeStateChangeIterator &scan(); - WinEHFuncInfo &EHInfo; + const WinEHFuncInfo &EHInfo; const MCSymbol *CurrentEndLabel = nullptr; MachineFunction::const_iterator MFI; MachineFunction::const_iterator MFE; @@ -521,7 +522,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { auto &OS = *Asm->OutStreamer; MCContext &Ctx = Asm->OutContext; - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction()); + const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); // Use the assembler to compute the number of table entries through label // difference and division. MCSymbol *TableBegin = @@ -564,7 +565,7 @@ void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) { OS.EmitLabel(TableEnd); } -void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, +void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, const MCSymbol *BeginLabel, const MCSymbol *EndLabel, int State) { auto &OS = *Asm->OutStreamer; @@ -572,7 +573,7 @@ void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, assert(BeginLabel && EndLabel); while (State != -1) { - SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State]; + const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State]; const MCExpr *FilterOrFinally; const MCExpr *ExceptOrNull; auto *Handler = UME.Handler.get(); @@ -600,7 +601,7 @@ void WinException::emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { const Function *F = MF->getFunction(); auto &OS = *Asm->OutStreamer; - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F); + const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); StringRef FuncLinkageName = GlobalValue::getRealLinkageName(F->getName()); @@ -688,7 +689,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { OS.EmitLabel(TryBlockMapXData); SmallVector HandlerMaps; for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { - WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; + const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; MCSymbol *HandlerMapXData = nullptr; if (!TBME.HandlerArray.empty()) @@ -721,7 +722,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { } for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) { - WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; + const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I]; MCSymbol *HandlerMapXData = HandlerMaps[I]; if (!HandlerMapXData) continue; @@ -772,7 +773,7 @@ void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) { } void WinException::computeIP2StateTable( - const MachineFunction *MF, WinEHFuncInfo &FuncInfo, + const MachineFunction *MF, const WinEHFuncInfo &FuncInfo, SmallVectorImpl> &IPToStateTable) { // Indicate that all calls from the prologue to the first invoke unwind to // caller. We handle this as a special case since other ranges starting at end @@ -803,15 +804,15 @@ void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo, // registration in order to recover the parent frame pointer. Now that we know // we've code generated the parent, we can emit the label assignment that // those helpers use to get the offset of the registration node. - assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX && - "no EH reg node localescape index"); + MCContext &Ctx = Asm->OutContext; MCSymbol *ParentFrameOffset = - Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName); - MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol( - FLinkageName, FuncInfo.EHRegNodeEscapeIndex); - const MCExpr *RegistrationOffsetSymRef = - MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext); - Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef); + Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName); + unsigned UnusedReg; + const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering(); + int64_t Offset = TFI->getFrameIndexReference( + *Asm->MF, FuncInfo.EHRegNodeFrameIndex, UnusedReg); + const MCExpr *MCOffset = MCConstantExpr::create(Offset, Ctx); + Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset); } /// Emit the language-specific data that _except_handler3 and 4 expect. This is @@ -822,7 +823,7 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { const Function *F = MF->getFunction(); StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName()); - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F); + const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName); // Emit the __ehtable label that we use for llvm.x86.seh.lsda. @@ -857,7 +858,7 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { } assert(!FuncInfo.SEHUnwindMap.empty()); - for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { + for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) { MCSymbol *ExceptOrFinally = UME.Handler.get()->getSymbol(); // -1 is usually the base state for "unwind to caller", but for @@ -869,7 +870,7 @@ void WinException::emitExceptHandlerTable(const MachineFunction *MF) { } } -static int getRank(WinEHFuncInfo &FuncInfo, int State) { +static int getRank(const WinEHFuncInfo &FuncInfo, int State) { int Rank = 0; while (State != -1) { ++Rank; @@ -878,7 +879,7 @@ static int getRank(WinEHFuncInfo &FuncInfo, int State) { return Rank; } -static int getAncestor(WinEHFuncInfo &FuncInfo, int Left, int Right) { +static int getAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) { int LeftRank = getRank(FuncInfo, Left); int RightRank = getRank(FuncInfo, Right); @@ -905,8 +906,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { // states, handlers, and funclets all have 1:1 mappings between them, and a // handler/funclet's "state" is its index in the ClrEHUnwindMap. MCStreamer &OS = *Asm->OutStreamer; - const Function *F = MF->getFunction(); - WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F); + const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo(); MCSymbol *FuncBeginSym = Asm->getFunctionBegin(); MCSymbol *FuncEndSym = Asm->getFunctionEnd(); @@ -1085,7 +1085,7 @@ void WinException::emitCLRExceptionTable(const MachineFunction *MF) { getOffsetPlusOne(Clause.StartLabel, FuncBeginSym); const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym); - ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State]; + const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State]; MachineBasicBlock *HandlerBlock = Entry.Handler.get(); MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock); const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym); diff --git a/lib/CodeGen/AsmPrinter/WinException.h b/lib/CodeGen/AsmPrinter/WinException.h index 54c5f3a9a0e..acb30101691 100644 --- a/lib/CodeGen/AsmPrinter/WinException.h +++ b/lib/CodeGen/AsmPrinter/WinException.h @@ -42,7 +42,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { void emitCSpecificHandlerTable(const MachineFunction *MF); - void emitSEHActionsForRange(WinEHFuncInfo &FuncInfo, + void emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo, const MCSymbol *BeginLabel, const MCSymbol *EndLabel, int State); @@ -58,7 +58,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { void emitCLRExceptionTable(const MachineFunction *MF); void computeIP2StateTable( - const MachineFunction *MF, WinEHFuncInfo &FuncInfo, + const MachineFunction *MF, const WinEHFuncInfo &FuncInfo, SmallVectorImpl> &IPToStateTable); /// Emits the label used with llvm.x86.seh.recoverfp, which is used by @@ -77,7 +77,7 @@ class LLVM_LIBRARY_VISIBILITY WinException : public EHStreamer { /// given index. For targets using CFI (Win64, etc), this is relative to the /// established SP at the end of the prologue. For targets without CFI (Win32 /// only), it is relative to the frame pointer. - int getFrameIndexOffset(int FrameIndex, WinEHFuncInfo &FuncInfo); + int getFrameIndexOffset(int FrameIndex, const WinEHFuncInfo &FuncInfo); public: //===--------------------------------------------------------------------===// diff --git a/lib/CodeGen/MachineFunction.cpp b/lib/CodeGen/MachineFunction.cpp index fa6849fcfdc..7e4c9b779f2 100644 --- a/lib/CodeGen/MachineFunction.cpp +++ b/lib/CodeGen/MachineFunction.cpp @@ -17,6 +17,7 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/Analysis/ConstantFolding.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionInitializer.h" @@ -27,6 +28,7 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/PseudoSourceValue.h" +#include "llvm/CodeGen/WinEHFuncInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" @@ -88,6 +90,11 @@ MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM, FunctionNumber = FunctionNum; JumpTableInfo = nullptr; + if (isFuncletEHPersonality(classifyEHPersonality( + F->hasPersonalityFn() ? F->getPersonalityFn() : nullptr))) { + WinEHInfo = new (Allocator) WinEHFuncInfo(); + } + assert(TM.isCompatibleDataLayout(getDataLayout()) && "Can't create a MachineFunction using a Module with a " "Target-incompatible DataLayout attached\n"); @@ -125,6 +132,11 @@ MachineFunction::~MachineFunction() { JumpTableInfo->~MachineJumpTableInfo(); Allocator.Deallocate(JumpTableInfo); } + + if (WinEHInfo) { + WinEHInfo->~WinEHFuncInfo(); + Allocator.Deallocate(WinEHInfo); + } } const DataLayout &MachineFunction::getDataLayout() const { diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 33db3edffb7..18efcf39c45 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -9,12 +9,12 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/WinEHFuncInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" @@ -321,12 +321,6 @@ void MachineModuleInfo::addPersonality(const Function *Personality) { Personalities.push_back(Personality); } -void MachineModuleInfo::addWinEHState(MachineBasicBlock *LandingPad, - int State) { - LandingPadInfo &LP = getOrCreateLandingPadInfo(LandingPad); - LP.WinEHState = State; -} - /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. /// void MachineModuleInfo:: @@ -466,10 +460,3 @@ try_next:; FilterIds.push_back(0); // terminator return FilterID; } - -WinEHFuncInfo &MachineModuleInfo::getWinEHFuncInfo(const Function *F) { - auto &Ptr = FuncInfoMap[F]; - if (!Ptr) - Ptr.reset(new WinEHFuncInfo); - return *Ptr; -} diff --git a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp index 52216c2c1e8..8d42dcef140 100644 --- a/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp +++ b/lib/CodeGen/SelectionDAG/FunctionLoweringInfo.cpp @@ -287,7 +287,7 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, return; // Calculate state numbers if we haven't already. - WinEHFuncInfo &EHInfo = MMI.getWinEHFuncInfo(&fn); + WinEHFuncInfo &EHInfo = *MF->getWinEHFuncInfo(); if (Personality == EHPersonality::MSVC_CXX) calculateWinCXXEHStateNumbers(&fn, EHInfo); else if (isAsynchronousEHPersonality(Personality)) @@ -321,24 +321,6 @@ void FunctionLoweringInfo::set(const Function &fn, MachineFunction &mf, const BasicBlock *BB = CME.Handler.get(); CME.Handler = MBBMap[BB]; } - - // If there's an explicit EH registration node on the stack, record its - // frame index. - if (EHInfo.EHRegNode && EHInfo.EHRegNode->getParent()->getParent() == Fn) { - assert(StaticAllocaMap.count(EHInfo.EHRegNode)); - EHInfo.EHRegNodeFrameIndex = StaticAllocaMap[EHInfo.EHRegNode]; - } - - // Copy the state numbers to LandingPadInfo for the current function, which - // could be a handler or the parent. This should happen for 32-bit SEH and - // C++ EH. - if (Personality == EHPersonality::MSVC_CXX || - Personality == EHPersonality::MSVC_X86SEH) { - for (const LandingPadInst *LP : LPads) { - MachineBasicBlock *LPadMBB = MBBMap[LP->getParent()]; - MMI.addWinEHState(LPadMBB, EHInfo.EHPadStateMap[LP]); - } - } } /// clear - Clear out all the function-specific state. This returns this diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 63b5d02a65a..a699f9c56f2 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1221,10 +1221,8 @@ void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) { // Figure out the funclet membership for the catchret's successor. // This will be used by the FuncletLayout pass to determine how to order the // BB's. - MachineModuleInfo &MMI = DAG.getMachineFunction().getMMI(); - WinEHFuncInfo &EHInfo = - MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction()); - const BasicBlock *SuccessorColor = EHInfo.CatchRetSuccessorColorMap[&I]; + WinEHFuncInfo *EHInfo = DAG.getMachineFunction().getWinEHFuncInfo(); + const BasicBlock *SuccessorColor = EHInfo->CatchRetSuccessorColorMap[&I]; assert(SuccessorColor && "No parent funclet for catchret!"); MachineBasicBlock *SuccessorColorMBB = FuncInfo.MBBMap[SuccessorColor]; assert(SuccessorColorMBB && "No MBB for SuccessorColor!"); @@ -5341,9 +5339,8 @@ SelectionDAGBuilder::lowerInvokable(TargetLowering::CallLoweringInfo &CLI, // Inform MachineModuleInfo of range. if (MMI.hasEHFunclets()) { - WinEHFuncInfo &EHInfo = - MMI.getWinEHFuncInfo(DAG.getMachineFunction().getFunction()); - EHInfo.addIPToStateRange(EHPadBB, BeginLabel, EndLabel); + WinEHFuncInfo *EHInfo = DAG.getMachineFunction().getWinEHFuncInfo(); + EHInfo->addIPToStateRange(EHPadBB, BeginLabel, EndLabel); } else { MMI.addInvoke(FuncInfo.MBBMap[EHPadBB], BeginLabel, EndLabel); } diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 72baa078661..4fbe3613d1e 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -1252,7 +1252,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, assert(classifyEHPersonality(Fn->getPersonalityFn()) == EHPersonality::MSVC_CXX); unsigned FrameReg; - int FI = MMI.getWinEHFuncInfo(Fn).EHRegNodeFrameIndex; + int FI = MF.getWinEHFuncInfo()->EHRegNodeFrameIndex; int64_t EHRegOffset = getFrameIndexReference(MF, FI, FrameReg); // ESP is the first field, so no extra displacement is needed. addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32mr)), FrameReg, @@ -1292,7 +1292,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // and the GC can recover it. unsigned PSPSlotOffset = getPSPSlotOffsetFromSP(MF); auto PSPInfo = MachinePointerInfo::getFixedStack( - MF, MF.getMMI().getWinEHFuncInfo(Fn).PSPSymFrameIdx); + MF, MF.getWinEHFuncInfo()->PSPSymFrameIdx); addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64mr)), StackPtr, false, PSPSlotOffset) .addReg(StackPtr) @@ -1401,8 +1401,7 @@ static bool isFuncletReturnInstr(MachineInstr *MI) { // frame with only a single offset reported for the entire method. unsigned X86FrameLowering::getPSPSlotOffsetFromSP(const MachineFunction &MF) const { - MachineModuleInfo &MMI = MF.getMMI(); - WinEHFuncInfo &Info = MMI.getWinEHFuncInfo(MF.getFunction()); + const WinEHFuncInfo &Info = *MF.getWinEHFuncInfo(); // getFrameIndexReferenceFromSP has an out ref parameter for the stack // pointer register; pass a dummy that we ignore unsigned SPReg; @@ -2592,9 +2591,7 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( MachineFunction &MF = *MBB.getParent(); unsigned FramePtr = TRI->getFrameRegister(MF); unsigned BasePtr = TRI->getBaseRegister(); - MachineModuleInfo &MMI = MF.getMMI(); - const Function *Fn = MF.getFunction(); - WinEHFuncInfo &FuncInfo = MMI.getWinEHFuncInfo(Fn); + WinEHFuncInfo &FuncInfo = *MF.getWinEHFuncInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo(); MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -2679,7 +2676,7 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized( int64_t UnwindHelpOffset = MinFixedObjOffset - SlotSize; int UnwindHelpFI = MFI->CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false); - MF.getMMI().getWinEHFuncInfo(Fn).UnwindHelpFrameIdx = UnwindHelpFI; + MF.getWinEHFuncInfo()->UnwindHelpFrameIdx = UnwindHelpFI; // Store -2 into UnwindHelp on function entry. We have to scan forwards past // other frame setup instructions. diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index c944e3deec5..2be35511f18 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2721,8 +2721,6 @@ SDValue X86TargetLowering::LowerFormalArguments( MFI->CreateFixedObject(1, StackSize, true)); } - MachineModuleInfo &MMI = MF.getMMI(); - // Figure out if XMM registers are in use. assert(!(Subtarget->useSoftFloat() && Fn->hasFnAttribute(Attribute::NoImplicitFloat)) && @@ -2878,7 +2876,7 @@ SDValue X86TargetLowering::LowerFormalArguments( FuncInfo->setArgumentStackSize(StackSize); - if (MMI.hasWinEHFuncInfo(Fn)) { + if (WinEHFuncInfo *EHInfo = MF.getWinEHFuncInfo()) { EHPersonality Personality = classifyEHPersonality(Fn->getPersonalityFn()); if (Personality == EHPersonality::CoreCLR) { assert(Is64Bit); @@ -2891,7 +2889,7 @@ SDValue X86TargetLowering::LowerFormalArguments( // how far this slot is from the bottom (since they allocate just enough // space to accomodate holding this slot at the correct offset). int PSPSymFI = MFI->CreateStackObject(8, 8, /*isSS=*/false); - MMI.getWinEHFuncInfo(MF.getFunction()).PSPSymFrameIdx = PSPSymFI; + EHInfo->PSPSymFrameIdx = PSPSymFI; } } @@ -16940,6 +16938,24 @@ static SDValue LowerSEHRESTOREFRAME(SDValue Op, const X86Subtarget *Subtarget, return Chain; } +static SDValue MarkEHRegistrationNode(SDValue Op, SelectionDAG &DAG) { + MachineFunction &MF = DAG.getMachineFunction(); + SDValue Chain = Op.getOperand(0); + SDValue RegNode = Op.getOperand(2); + WinEHFuncInfo *EHInfo = MF.getWinEHFuncInfo(); + if (!EHInfo) + report_fatal_error("EH registrations only live in functions using WinEH"); + + // Cast the operand to an alloca, and remember the frame index. + auto *FINode = dyn_cast(RegNode); + if (!FINode) + report_fatal_error("llvm.x86.seh.ehregnode expects a static alloca"); + EHInfo->EHRegNodeFrameIndex = FINode->getIndex(); + + // Return the chain operand without making any DAG nodes. + return Chain; +} + /// \brief Lower intrinsics for TRUNCATE_TO_MEM case /// return truncate Store/MaskedStore Node static SDValue LowerINTRINSIC_TRUNCATE_TO_MEM(const SDValue & Op, @@ -16985,6 +17001,8 @@ static SDValue LowerINTRINSIC_W_CHAIN(SDValue Op, const X86Subtarget *Subtarget, if (!IntrData) { if (IntNo == llvm::Intrinsic::x86_seh_restoreframe) return LowerSEHRESTOREFRAME(Op, Subtarget, DAG); + else if (IntNo == llvm::Intrinsic::x86_seh_ehregnode) + return MarkEHRegistrationNode(Op, DAG); return SDValue(); } diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index db717385da6..8a5aa40bc7f 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -66,18 +66,13 @@ private: void linkExceptionRegistration(IRBuilder<> &Builder, Function *Handler); void unlinkExceptionRegistration(IRBuilder<> &Builder); - void addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo); - void addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo); - void addStateStoresToFunclet(Value *ParentRegNode, WinEHFuncInfo &FuncInfo, - Function &F, int BaseState); + void addStateStores(Function &F, WinEHFuncInfo &FuncInfo); void insertStateNumberStore(Value *ParentRegNode, Instruction *IP, int State); Value *emitEHLSDA(IRBuilder<> &Builder, Function *F); Function *generateLSDAInEAXThunk(Function *ParentFunc); - int escapeRegNode(Function &F); - // Module-level type getters. Type *getEHLinkRegistrationType(); Type *getSEHRegistrationType(); @@ -178,26 +173,13 @@ bool WinEHStatePass::runOnFunction(Function &F) { emitExceptionRegistrationRecord(&F); - auto *MMI = getAnalysisIfAvailable(); - // If MMI is null, create our own WinEHFuncInfo. This only happens in opt - // tests. - std::unique_ptr FuncInfoPtr; - if (!MMI) - FuncInfoPtr.reset(new WinEHFuncInfo()); - WinEHFuncInfo &FuncInfo = - *(MMI ? &MMI->getWinEHFuncInfo(&F) : FuncInfoPtr.get()); - - FuncInfo.EHRegNode = RegNode; - - switch (Personality) { - default: llvm_unreachable("unexpected personality function"); - case EHPersonality::MSVC_CXX: - addCXXStateStores(F, FuncInfo); - break; - case EHPersonality::MSVC_X86SEH: - addSEHStateStores(F, FuncInfo); - break; - } + // The state numbers calculated here in IR must agree with what we calculate + // later on for the MachineFunction. In particular, if an IR pass deletes an + // unreachable EH pad after this point before machine CFG construction, we + // will be in trouble. If this assumption is ever broken, we should turn the + // numbers into an immutable analysis pass. + WinEHFuncInfo FuncInfo; + addStateStores(F, FuncInfo); // Reset per-function state. PersonalityFn = nullptr; @@ -418,65 +400,21 @@ void WinEHStatePass::unlinkExceptionRegistration(IRBuilder<> &Builder) { Builder.CreateStore(Next, FSZero); } -void WinEHStatePass::addCXXStateStores(Function &F, WinEHFuncInfo &FuncInfo) { - // Set up RegNodeEscapeIndex - int RegNodeEscapeIndex = escapeRegNode(F); - FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; +void WinEHStatePass::addStateStores(Function &F, WinEHFuncInfo &FuncInfo) { + // Mark the registration node. The backend needs to know which alloca it is so + // that it can recover the original frame pointer. + IRBuilder<> Builder(RegNode->getParent(), std::next(RegNode->getIterator())); + Value *RegNodeI8 = Builder.CreateBitCast(RegNode, Builder.getInt8PtrTy()); + Builder.CreateCall( + Intrinsic::getDeclaration(TheModule, Intrinsic::x86_seh_ehregnode), + {RegNodeI8}); - calculateWinCXXEHStateNumbers(&F, FuncInfo); - addStateStoresToFunclet(RegNode, FuncInfo, F, -1); -} + // Calculate state numbers. + if (isAsynchronousEHPersonality(Personality)) + calculateSEHStateNumbers(&F, FuncInfo); + else + calculateWinCXXEHStateNumbers(&F, FuncInfo); -/// Assign every distinct landingpad a unique state number for SEH. Unlike C++ -/// EH, we can use this very simple algorithm while C++ EH cannot because catch -/// handlers aren't outlined and the runtime doesn't have to figure out which -/// catch handler frame to unwind to. -void WinEHStatePass::addSEHStateStores(Function &F, WinEHFuncInfo &FuncInfo) { - // Remember and return the index that we used. We save it in WinEHFuncInfo so - // that we can lower llvm.x86.seh.recoverfp later in filter functions without - // too much trouble. - int RegNodeEscapeIndex = escapeRegNode(F); - FuncInfo.EHRegNodeEscapeIndex = RegNodeEscapeIndex; - - calculateSEHStateNumbers(&F, FuncInfo); - addStateStoresToFunclet(RegNode, FuncInfo, F, -1); -} - -/// Escape RegNode so that we can access it from child handlers. Find the call -/// to localescape, if any, in the entry block and append RegNode to the list -/// of arguments. -int WinEHStatePass::escapeRegNode(Function &F) { - // Find the call to localescape and extract its arguments. - IntrinsicInst *EscapeCall = nullptr; - for (Instruction &I : F.getEntryBlock()) { - IntrinsicInst *II = dyn_cast(&I); - if (II && II->getIntrinsicID() == Intrinsic::localescape) { - EscapeCall = II; - break; - } - } - SmallVector Args; - if (EscapeCall) { - auto Ops = EscapeCall->arg_operands(); - Args.append(Ops.begin(), Ops.end()); - } - Args.push_back(RegNode); - - // Replace the call (if it exists) with new one. Otherwise, insert at the end - // of the entry block. - Instruction *InsertPt = EscapeCall; - if (!EscapeCall) - InsertPt = F.getEntryBlock().getTerminator(); - IRBuilder<> Builder(InsertPt); - Builder.CreateCall(FrameEscape, Args); - if (EscapeCall) - EscapeCall->eraseFromParent(); - return Args.size() - 1; -} - -void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode, - WinEHFuncInfo &FuncInfo, - Function &F, int BaseState) { // Iterate all the instructions and emit state number stores. for (BasicBlock &BB : F) { for (Instruction &I : BB) { @@ -485,14 +423,14 @@ void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode, // an unwind. Ensure they are in the -1 state. if (CI->doesNotThrow()) continue; - insertStateNumberStore(ParentRegNode, CI, BaseState); + insertStateNumberStore(RegNode, CI, -1); } else if (auto *II = dyn_cast(&I)) { // Look up the state number of the landingpad this unwinds to. Instruction *PadInst = II->getUnwindDest()->getFirstNonPHI(); // FIXME: Why does this assertion fail? //assert(FuncInfo.EHPadStateMap.count(PadInst) && "EH Pad has no state!"); int State = FuncInfo.EHPadStateMap[PadInst]; - insertStateNumberStore(ParentRegNode, II, State); + insertStateNumberStore(RegNode, II, State); } } } diff --git a/test/CodeGen/X86/seh-catch-all-win32.ll b/test/CodeGen/X86/seh-catch-all-win32.ll index 0ad385375f7..5d9d5038385 100644 --- a/test/CodeGen/X86/seh-catch-all-win32.ll +++ b/test/CodeGen/X86/seh-catch-all-win32.ll @@ -64,8 +64,7 @@ entry: ; CHECK: pushl %esi ; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]] -; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]] -; CHECK: movl %esp, [[reg_offs]](%ebp) +; CHECK: movl %esp, [[reg_offs:[-0-9]+]](%ebp) ; CHECK: movl $L__ehtable$main, ; EH state 0 ; CHECK: movl $0, -16(%ebp) @@ -84,7 +83,7 @@ entry: ; CHECK: calll _printf ; CHECK: .section .xdata,"dr" -; CHECK: Lmain$parent_frame_offset = Lmain$frame_escape_1 +; CHECK: Lmain$parent_frame_offset = [[reg_offs]] ; CHECK: .align 4 ; CHECK: L__ehtable$main ; CHECK-NEXT: .long -1 diff --git a/test/CodeGen/X86/seh-stack-realign.ll b/test/CodeGen/X86/seh-stack-realign.ll index a06b2360fff..8494cadddb7 100644 --- a/test/CodeGen/X86/seh-stack-realign.ll +++ b/test/CodeGen/X86/seh-stack-realign.ll @@ -57,8 +57,7 @@ entry: ; CHECK-LABEL: _main: ; CHECK: Lmain$frame_escape_0 = [[code_offs:[-0-9]+]] -; CHECK: Lmain$frame_escape_1 = [[reg_offs:[-0-9]+]] -; CHECK: movl %esp, [[reg_offs]](%esi) +; CHECK: movl %esp, [[reg_offs:[-0-9]+]](%esi) ; CHECK: movl $L__ehtable$main, ; EH state 0 ; CHECK: movl $0, 40(%esi) @@ -77,7 +76,7 @@ entry: ; CHECK: calll _printf ; CHECK: .section .xdata,"dr" -; CHECK: Lmain$parent_frame_offset = Lmain$frame_escape_1 +; CHECK: Lmain$parent_frame_offset = [[reg_offs]] ; CHECK: L__ehtable$main ; CHECK-NEXT: .long -1 ; CHECK-NEXT: .long _filt$main