diff options
author | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:47:02 +0000 |
---|---|---|
committer | Pascal Stumpf <pascal@cvs.openbsd.org> | 2016-09-03 22:47:02 +0000 |
commit | c198ad09c18f3e76b43e376fbbc31e99e65a9137 (patch) | |
tree | 6520b546e1f252bad861cf5a29390bd3ecaf650a /gnu/llvm | |
parent | 42036bd5b84978c8bf5307aaac934c90fac325ac (diff) |
Use the space freed up by sparc and zaurus to import LLVM.
ok hackroom@
Diffstat (limited to 'gnu/llvm')
-rw-r--r-- | gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h | 233 | ||||
-rw-r--r-- | gnu/llvm/include/llvm/CodeGen/Passes.h | 498 | ||||
-rw-r--r-- | gnu/llvm/include/llvm/InitializePasses.h | 368 | ||||
-rw-r--r-- | gnu/llvm/lib/CodeGen/CMakeLists.txt | 87 | ||||
-rw-r--r-- | gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp | 836 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86FrameLowering.cpp | 1123 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86FrameLowering.h | 82 | ||||
-rw-r--r-- | gnu/llvm/lib/Target/X86/X86InstrCompiler.td | 653 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td | 245 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def | 160 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp | 1539 | ||||
-rw-r--r-- | gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp | 1443 |
12 files changed, 2596 insertions, 4671 deletions
diff --git a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h index f887517217e..e50779aacc2 100644 --- a/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h +++ b/gnu/llvm/include/llvm/CodeGen/MachineFrameInfo.h @@ -21,9 +21,15 @@ namespace llvm { class raw_ostream; +class DataLayout; +class TargetRegisterClass; +class Type; class MachineFunction; class MachineBasicBlock; +class TargetFrameLowering; +class TargetMachine; class BitVector; +class Value; class AllocaInst; /// The CalleeSavedInfo class tracks the information need to locate where a @@ -31,30 +37,15 @@ class AllocaInst; class CalleeSavedInfo { unsigned Reg; int FrameIdx; - /// Flag indicating whether the register is actually restored in the epilog. - /// In most cases, if a register is saved, it is also restored. There are - /// some situations, though, when this is not the case. For example, the - /// LR register on ARM is usually saved, but on exit from the function its - /// saved value may be loaded directly into PC. Since liveness tracking of - /// physical registers treats callee-saved registers are live outside of - /// the function, LR would be treated as live-on-exit, even though in these - /// scenarios it is not. This flag is added to indicate that the saved - /// register described by this object is not restored in the epilog. - /// The long-term solution is to model the liveness of callee-saved registers - /// by implicit uses on the return instructions, however, the required - /// changes in the ARM backend would be quite extensive. - bool Restored; public: explicit CalleeSavedInfo(unsigned R, int FI = 0) - : Reg(R), FrameIdx(FI), Restored(true) {} + : Reg(R), FrameIdx(FI) {} // Accessors. unsigned getReg() const { return Reg; } int getFrameIdx() const { return FrameIdx; } void setFrameIdx(int FI) { FrameIdx = FI; } - bool isRestored() const { return Restored; } - void setRestored(bool R) { Restored = R; } }; /// The MachineFrameInfo class represents an abstract stack frame until @@ -112,18 +103,10 @@ class MachineFrameInfo { /// If true, this stack slot is used to spill a value (could be deopt /// and/or GC related) over a statepoint. We know that the address of the - /// slot can't alias any LLVM IR value. This is very similar to a Spill + /// slot can't alias any LLVM IR value. This is very similiar to a Spill /// Slot, but is created by statepoint lowering is SelectionDAG, not the - /// register allocator. - bool isStatepointSpillSlot = false; - - /// Identifier for stack memory type analagous to address space. If this is - /// non-0, the meaning is target defined. Offsets cannot be directly - /// compared between objects with different stack IDs. The object may not - /// necessarily reside in the same contiguous memory block as other stack - /// objects. Objects with differing stack IDs should not be merged or - /// replaced substituted for each other. - uint8_t StackID; + /// register allocator. + bool isStatepointSpillSlot; /// If this stack object is originated from an Alloca instruction /// this value saves the original IR allocation. Can be NULL. @@ -131,7 +114,7 @@ class MachineFrameInfo { // If true, the object was mapped into the local frame // block and doesn't need additional handling for allocation beyond that. - bool PreAllocated = false; + bool PreAllocated; // If true, an LLVM IR value might point to this object. // Normally, spill slots and fixed-offset objects don't alias IR-accessible @@ -139,72 +122,62 @@ class MachineFrameInfo { // arguments have ABI-prescribed offsets). bool isAliased; - /// If true, the object has been zero-extended. - bool isZExt = false; - - /// If true, the object has been zero-extended. - bool isSExt = false; - - StackObject(uint64_t Size, unsigned Alignment, int64_t SPOffset, - bool IsImmutable, bool IsSpillSlot, const AllocaInst *Alloca, - bool IsAliased, uint8_t StackID = 0) - : SPOffset(SPOffset), Size(Size), Alignment(Alignment), - isImmutable(IsImmutable), isSpillSlot(IsSpillSlot), - StackID(StackID), Alloca(Alloca), isAliased(IsAliased) {} + StackObject(uint64_t Sz, unsigned Al, int64_t SP, bool IM, + bool isSS, const AllocaInst *Val, bool A) + : SPOffset(SP), Size(Sz), Alignment(Al), isImmutable(IM), + isSpillSlot(isSS), isStatepointSpillSlot(false), Alloca(Val), + PreAllocated(false), isAliased(A) {} }; /// The alignment of the stack. unsigned StackAlignment; - /// Can the stack be realigned. This can be false if the target does not - /// support stack realignment, or if the user asks us not to realign the - /// stack. In this situation, overaligned allocas are all treated as dynamic - /// allocations and the target must handle them as part of DYNAMIC_STACKALLOC - /// lowering. All non-alloca stack objects have their alignment clamped to the - /// base ABI stack alignment. + /// Can the stack be realigned. + /// Targets that set this to false don't have the ability to overalign + /// their stack frame, and thus, overaligned allocas are all treated + /// as dynamic allocations and the target must handle them as part + /// of DYNAMIC_STACKALLOC lowering. /// FIXME: There is room for improvement in this case, in terms of /// grouping overaligned allocas into a "secondary stack frame" and /// then only use a single alloca to allocate this frame and only a /// single virtual register to access it. Currently, without such an - /// optimization, each such alloca gets its own dynamic realignment. + /// optimization, each such alloca gets it's own dynamic + /// realignment. bool StackRealignable; - /// Whether the function has the \c alignstack attribute. - bool ForcedRealign; - /// The list of stack objects allocated. std::vector<StackObject> Objects; /// This contains the number of fixed objects contained on /// the stack. Because fixed objects are stored at a negative index in the /// Objects list, this is also the index to the 0th object in the list. - unsigned NumFixedObjects = 0; + unsigned NumFixedObjects; /// This boolean keeps track of whether any variable /// sized objects have been allocated yet. - bool HasVarSizedObjects = false; + bool HasVarSizedObjects; /// This boolean keeps track of whether there is a call /// to builtin \@llvm.frameaddress. - bool FrameAddressTaken = false; + bool FrameAddressTaken; /// This boolean keeps track of whether there is a call /// to builtin \@llvm.returnaddress. - bool ReturnAddressTaken = false; + bool ReturnAddressTaken; /// This boolean keeps track of whether there is a call /// to builtin \@llvm.experimental.stackmap. - bool HasStackMap = false; + bool HasStackMap; /// This boolean keeps track of whether there is a call /// to builtin \@llvm.experimental.patchpoint. - bool HasPatchPoint = false; + bool HasPatchPoint; /// The prolog/epilog code inserter calculates the final stack /// offsets for all of the fixed size objects, updating the Objects list /// above. It then updates StackSize to contain the number of bytes that need /// to be allocated on entry to the function. - uint64_t StackSize = 0; + uint64_t StackSize; /// The amount that a frame offset needs to be adjusted to /// have the actual offset from the stack/frame pointer. The exact usage of @@ -215,7 +188,7 @@ class MachineFrameInfo { /// targets, this value is only used when generating debug info (via /// TargetRegisterInfo::getFrameIndexReference); when generating code, the /// corresponding adjustments are performed directly. - int OffsetAdjustment = 0; + int OffsetAdjustment; /// The prolog/epilog code inserter may process objects that require greater /// alignment than the default alignment the target provides. @@ -224,27 +197,27 @@ class MachineFrameInfo { /// native alignment maintained by the compiler, dynamic alignment code will /// be needed. /// - unsigned MaxAlignment = 0; + unsigned MaxAlignment; /// Set to true if this function adjusts the stack -- e.g., /// when calling another function. This is only valid during and after /// prolog/epilog code insertion. - bool AdjustsStack = false; + bool AdjustsStack; /// Set to true if this function has any function calls. - bool HasCalls = false; + bool HasCalls; /// The frame index for the stack protector. - int StackProtectorIdx = -1; + int StackProtectorIdx; /// The frame index for the function context. Used for SjLj exceptions. - int FunctionContextIdx = -1; + int FunctionContextIdx; /// This contains the size of the largest call frame if the target uses frame /// setup/destroy pseudo instructions (as defined in the TargetFrameInfo /// class). This information is important for frame pointer elimination. /// It is only valid during and after prolog/epilog code insertion. - unsigned MaxCallFrameSize = ~0u; + unsigned MaxCallFrameSize; /// The prolog/epilog code inserter fills in this vector with each /// callee saved register saved in the frame. Beyond its use by the prolog/ @@ -253,53 +226,79 @@ class MachineFrameInfo { std::vector<CalleeSavedInfo> CSInfo; /// Has CSInfo been set yet? - bool CSIValid = false; + bool CSIValid; /// References to frame indices which are mapped /// into the local frame allocation block. <FrameIdx, LocalOffset> SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects; /// Size of the pre-allocated local frame block. - int64_t LocalFrameSize = 0; + int64_t LocalFrameSize; /// Required alignment of the local object blob, which is the strictest /// alignment of any object in it. - unsigned LocalFrameMaxAlign = 0; + unsigned LocalFrameMaxAlign; /// Whether the local object blob needs to be allocated together. If not, /// PEI should ignore the isPreAllocated flags on the stack objects and /// just allocate them normally. - bool UseLocalStackAllocationBlock = false; + bool UseLocalStackAllocationBlock; + + /// Whether the "realign-stack" option is on. + bool RealignOption; /// True if the function dynamically adjusts the stack pointer through some /// opaque mechanism like inline assembly or Win32 EH. - bool HasOpaqueSPAdjustment = false; + bool HasOpaqueSPAdjustment; /// True if the function contains operations which will lower down to /// instructions which manipulate the stack pointer. - bool HasCopyImplyingStackAdjustment = false; + bool HasCopyImplyingStackAdjustment; /// True if the function contains a call to the llvm.vastart intrinsic. - bool HasVAStart = false; + bool HasVAStart; /// True if this is a varargs function that contains a musttail call. - bool HasMustTailInVarArgFunc = false; + bool HasMustTailInVarArgFunc; /// True if this function contains a tail call. If so immutable objects like /// function arguments are no longer so. A tail call *can* override fixed /// stack objects like arguments so we can't treat them as immutable. - bool HasTailCall = false; + bool HasTailCall; /// Not null, if shrink-wrapping found a better place for the prologue. - MachineBasicBlock *Save = nullptr; + MachineBasicBlock *Save; /// Not null, if shrink-wrapping found a better place for the epilogue. - MachineBasicBlock *Restore = nullptr; + MachineBasicBlock *Restore; public: - explicit MachineFrameInfo(unsigned StackAlignment, bool StackRealignable, - bool ForcedRealign) - : StackAlignment(StackAlignment), StackRealignable(StackRealignable), - ForcedRealign(ForcedRealign) {} + explicit MachineFrameInfo(unsigned StackAlign, bool isStackRealign, + bool RealignOpt) + : StackAlignment(StackAlign), StackRealignable(isStackRealign), + RealignOption(RealignOpt) { + StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; + HasVarSizedObjects = false; + FrameAddressTaken = false; + ReturnAddressTaken = false; + HasStackMap = false; + HasPatchPoint = false; + AdjustsStack = false; + HasCalls = false; + StackProtectorIdx = -1; + FunctionContextIdx = -1; + MaxCallFrameSize = 0; + CSIValid = false; + LocalFrameSize = 0; + LocalFrameMaxAlign = 0; + UseLocalStackAllocationBlock = false; + HasOpaqueSPAdjustment = false; + HasCopyImplyingStackAdjustment = false; + HasVAStart = false; + HasMustTailInVarArgFunc = false; + Save = nullptr; + Restore = nullptr; + HasTailCall = false; + } /// Return true if there are any stack objects in this function. bool hasStackObjects() const { return !Objects.empty(); } @@ -451,30 +450,6 @@ public: return Objects[ObjectIdx+NumFixedObjects].SPOffset; } - bool isObjectZExt(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isZExt; - } - - void setObjectZExt(int ObjectIdx, bool IsZExt) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isZExt = IsZExt; - } - - bool isObjectSExt(int ObjectIdx) const { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - return Objects[ObjectIdx+NumFixedObjects].isSExt; - } - - void setObjectSExt(int ObjectIdx, bool IsSExt) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isSExt = IsSExt; - } - /// Set the stack frame offset of the specified object. The /// offset is relative to the stack pointer on entry to the function. void setObjectOffset(int ObjectIdx, int64_t SPOffset) { @@ -544,42 +519,24 @@ public: bool hasTailCall() const { return HasTailCall; } void setHasTailCall() { HasTailCall = true; } - /// Computes the maximum size of a callframe and the AdjustsStack property. - /// This only works for targets defining - /// TargetInstrInfo::getCallFrameSetupOpcode(), getCallFrameDestroyOpcode(), - /// and getFrameSize(). - /// This is usually computed by the prologue epilogue inserter but some - /// targets may call this to compute it earlier. - void computeMaxCallFrameSize(const MachineFunction &MF); - /// Return the maximum size of a call frame that must be /// allocated for an outgoing function call. This is only available if /// CallFrameSetup/Destroy pseudo instructions are used by the target, and /// then only during or after prolog/epilog code insertion. /// - unsigned getMaxCallFrameSize() const { - // TODO: Enable this assert when targets are fixed. - //assert(isMaxCallFrameSizeComputed() && "MaxCallFrameSize not computed yet"); - if (!isMaxCallFrameSizeComputed()) - return 0; - return MaxCallFrameSize; - } - bool isMaxCallFrameSizeComputed() const { - return MaxCallFrameSize != ~0u; - } + unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } /// Create a new object at a fixed location on the stack. /// All fixed objects should be created before other objects are created for /// efficiency. By default, fixed objects are not pointed to by LLVM IR /// values. This returns an index with a negative value. - int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, + int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable, bool isAliased = false); /// Create a spill slot at a fixed location on the stack. /// Returns an index with a negative value. - int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset, - bool IsImmutable = false); + int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); /// Returns true if the specified index corresponds to a fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { @@ -594,7 +551,8 @@ public: return Objects[ObjectIdx+NumFixedObjects].isAliased; } - /// Returns true if the specified index corresponds to an immutable object. + /// isImmutableObjectIndex - Returns true if the specified index corresponds + /// to an immutable object. bool isImmutableObjectIndex(int ObjectIdx) const { // Tail calling functions can clobber their function arguments. if (HasTailCall) @@ -604,13 +562,6 @@ public: return Objects[ObjectIdx+NumFixedObjects].isImmutable; } - /// Marks the immutability of an object. - void setIsImmutableObjectIndex(int ObjectIdx, bool IsImmutable) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].isImmutable = IsImmutable; - } - /// Returns true if the specified index corresponds to a spill slot. bool isSpillSlotObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && @@ -624,18 +575,6 @@ public: return Objects[ObjectIdx+NumFixedObjects].isStatepointSpillSlot; } - /// \see StackID - uint8_t getStackID(int ObjectIdx) const { - return Objects[ObjectIdx+NumFixedObjects].StackID; - } - - /// \see StackID - void setStackID(int ObjectIdx, uint8_t ID) { - assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && - "Invalid Object Idx!"); - Objects[ObjectIdx+NumFixedObjects].StackID = ID; - } - /// Returns true if the specified index corresponds to a dead object. bool isDeadObjectIndex(int ObjectIdx) const { assert(unsigned(ObjectIdx+NumFixedObjects) < Objects.size() && @@ -660,8 +599,8 @@ public: /// Create a new statically sized stack object, returning /// a nonnegative identifier to represent it. - int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSpillSlot, - const AllocaInst *Alloca = nullptr, uint8_t ID = 0); + int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, + const AllocaInst *Alloca = nullptr); /// Create a new statically sized stack object that represents a spill slot, /// returning a nonnegative identifier to represent it. @@ -682,8 +621,6 @@ public: const std::vector<CalleeSavedInfo> &getCalleeSavedInfo() const { return CSInfo; } - /// \copydoc getCalleeSavedInfo() - std::vector<CalleeSavedInfo> &getCalleeSavedInfo() { return CSInfo; } /// Used by prolog/epilog inserter to set the function's callee saved /// information. diff --git a/gnu/llvm/include/llvm/CodeGen/Passes.h b/gnu/llvm/include/llvm/CodeGen/Passes.h index 064526b1efa..f45f0ed57d6 100644 --- a/gnu/llvm/include/llvm/CodeGen/Passes.h +++ b/gnu/llvm/include/llvm/CodeGen/Passes.h @@ -15,25 +15,356 @@ #ifndef LLVM_CODEGEN_PASSES_H #define LLVM_CODEGEN_PASSES_H +#include "llvm/Pass.h" +#include "llvm/Target/TargetMachine.h" #include <functional> #include <string> namespace llvm { -class FunctionPass; -class MachineFunction; class MachineFunctionPass; -class ModulePass; -class Pass; -class TargetMachine; +class PassConfigImpl; +class PassInfo; +class ScheduleDAGInstrs; +class TargetLowering; +class TargetLoweringBase; class TargetRegisterClass; class raw_ostream; +struct MachineSchedContext; + +// The old pass manager infrastructure is hidden in a legacy namespace now. +namespace legacy { +class PassManagerBase; +} +using legacy::PassManagerBase; + +/// Discriminated union of Pass ID types. +/// +/// The PassConfig API prefers dealing with IDs because they are safer and more +/// efficient. IDs decouple configuration from instantiation. This way, when a +/// pass is overriden, it isn't unnecessarily instantiated. It is also unsafe to +/// refer to a Pass pointer after adding it to a pass manager, which deletes +/// redundant pass instances. +/// +/// However, it is convient to directly instantiate target passes with +/// non-default ctors. These often don't have a registered PassInfo. Rather than +/// force all target passes to implement the pass registry boilerplate, allow +/// the PassConfig API to handle either type. +/// +/// AnalysisID is sadly char*, so PointerIntPair won't work. +class IdentifyingPassPtr { + union { + AnalysisID ID; + Pass *P; + }; + bool IsInstance; +public: + IdentifyingPassPtr() : P(nullptr), IsInstance(false) {} + IdentifyingPassPtr(AnalysisID IDPtr) : ID(IDPtr), IsInstance(false) {} + IdentifyingPassPtr(Pass *InstancePtr) : P(InstancePtr), IsInstance(true) {} + + bool isValid() const { return P; } + bool isInstance() const { return IsInstance; } + + AnalysisID getID() const { + assert(!IsInstance && "Not a Pass ID"); + return ID; + } + Pass *getInstance() const { + assert(IsInstance && "Not a Pass Instance"); + return P; + } +}; + +template <> struct isPodLike<IdentifyingPassPtr> { + static const bool value = true; +}; + +/// Target-Independent Code Generator Pass Configuration Options. +/// +/// This is an ImmutablePass solely for the purpose of exposing CodeGen options +/// to the internals of other CodeGen passes. +class TargetPassConfig : public ImmutablePass { +public: + /// Pseudo Pass IDs. These are defined within TargetPassConfig because they + /// are unregistered pass IDs. They are only useful for use with + /// TargetPassConfig APIs to identify multiple occurrences of the same pass. + /// -} // End llvm namespace + /// EarlyTailDuplicate - A clone of the TailDuplicate pass that runs early + /// during codegen, on SSA form. + static char EarlyTailDuplicateID; + + /// PostRAMachineLICM - A clone of the LICM pass that runs during late machine + /// optimization after regalloc. + static char PostRAMachineLICMID; + +private: + PassManagerBase *PM; + AnalysisID StartBefore, StartAfter; + AnalysisID StopAfter; + bool Started; + bool Stopped; + bool AddingMachinePasses; + +protected: + TargetMachine *TM; + PassConfigImpl *Impl; // Internal data structures + bool Initialized; // Flagged after all passes are configured. + + // Target Pass Options + // Targets provide a default setting, user flags override. + // + bool DisableVerify; + + /// Default setting for -enable-tail-merge on this target. + bool EnableTailMerge; + +public: + TargetPassConfig(TargetMachine *tm, PassManagerBase &pm); + // Dummy constructor. + TargetPassConfig(); + + ~TargetPassConfig() override; + + static char ID; + + /// Get the right type of TargetMachine for this target. + template<typename TMC> TMC &getTM() const { + return *static_cast<TMC*>(TM); + } + + // + void setInitialized() { Initialized = true; } + + CodeGenOpt::Level getOptLevel() const { return TM->getOptLevel(); } + + /// Set the StartAfter, StartBefore and StopAfter passes to allow running only + /// a portion of the normal code-gen pass sequence. + /// + /// If the StartAfter and StartBefore pass ID is zero, then compilation will + /// begin at the normal point; otherwise, clear the Started flag to indicate + /// that passes should not be added until the starting pass is seen. If the + /// Stop pass ID is zero, then compilation will continue to the end. + /// + /// This function expects that at least one of the StartAfter or the + /// StartBefore pass IDs is null. + void setStartStopPasses(AnalysisID StartBefore, AnalysisID StartAfter, + AnalysisID StopAfter) { + if (StartAfter) + assert(!StartBefore && "Start after and start before passes are given"); + this->StartBefore = StartBefore; + this->StartAfter = StartAfter; + this->StopAfter = StopAfter; + Started = (StartAfter == nullptr) && (StartBefore == nullptr); + } + + void setDisableVerify(bool Disable) { setOpt(DisableVerify, Disable); } + + bool getEnableTailMerge() const { return EnableTailMerge; } + void setEnableTailMerge(bool Enable) { setOpt(EnableTailMerge, Enable); } + + /// Allow the target to override a specific pass without overriding the pass + /// pipeline. When passes are added to the standard pipeline at the + /// point where StandardID is expected, add TargetID in its place. + void substitutePass(AnalysisID StandardID, IdentifyingPassPtr TargetID); + + /// Insert InsertedPassID pass after TargetPassID pass. + void insertPass(AnalysisID TargetPassID, IdentifyingPassPtr InsertedPassID, + bool VerifyAfter = true, bool PrintAfter = true); + + /// Allow the target to enable a specific standard pass by default. + void enablePass(AnalysisID PassID) { substitutePass(PassID, PassID); } + + /// Allow the target to disable a specific standard pass by default. + void disablePass(AnalysisID PassID) { + substitutePass(PassID, IdentifyingPassPtr()); + } + + /// Return the pass substituted for StandardID by the target. + /// If no substitution exists, return StandardID. + IdentifyingPassPtr getPassSubstitution(AnalysisID StandardID) const; + + /// Return true if the optimized regalloc pipeline is enabled. + bool getOptimizeRegAlloc() const; + + /// Return true if shrink wrapping is enabled. + bool getEnableShrinkWrap() const; + + /// Return true if the default global register allocator is in use and + /// has not be overriden on the command line with '-regalloc=...' + bool usingDefaultRegAlloc() const; + + /// Add common target configurable passes that perform LLVM IR to IR + /// transforms following machine independent optimization. + virtual void addIRPasses(); + + /// Add passes to lower exception handling for the code generator. + void addPassesToHandleExceptions(); + + /// Add pass to prepare the LLVM IR for code generation. This should be done + /// before exception handling preparation passes. + virtual void addCodeGenPrepare(); + + /// Add common passes that perform LLVM IR to IR transforms in preparation for + /// instruction selection. + virtual void addISelPrepare(); + + /// addInstSelector - This method should install an instruction selector pass, + /// which converts from LLVM code to machine instructions. + virtual bool addInstSelector() { + return true; + } + + /// Add the complete, standard set of LLVM CodeGen passes. + /// Fully developed targets will not generally override this. + virtual void addMachinePasses(); + + /// Create an instance of ScheduleDAGInstrs to be run within the standard + /// MachineScheduler pass for this function and target at the current + /// optimization level. + /// + /// This can also be used to plug a new MachineSchedStrategy into an instance + /// of the standard ScheduleDAGMI: + /// return new ScheduleDAGMI(C, make_unique<MyStrategy>(C), /*RemoveKillFlags=*/false) + /// + /// Return NULL to select the default (generic) machine scheduler. + virtual ScheduleDAGInstrs * + createMachineScheduler(MachineSchedContext *C) const { + return nullptr; + } + + /// Similar to createMachineScheduler but used when postRA machine scheduling + /// is enabled. + virtual ScheduleDAGInstrs * + createPostMachineScheduler(MachineSchedContext *C) const { + return nullptr; + } + +protected: + // Helper to verify the analysis is really immutable. + void setOpt(bool &Opt, bool Val); + + /// Methods with trivial inline returns are convenient points in the common + /// codegen pass pipeline where targets may insert passes. Methods with + /// out-of-line standard implementations are major CodeGen stages called by + /// addMachinePasses. Some targets may override major stages when inserting + /// passes is insufficient, but maintaining overriden stages is more work. + /// + + /// addPreISelPasses - This method should add any "last minute" LLVM->LLVM + /// passes (which are run just before instruction selector). + virtual bool addPreISel() { + return true; + } + + /// addMachineSSAOptimization - Add standard passes that optimize machine + /// instructions in SSA form. + virtual void addMachineSSAOptimization(); + + /// Add passes that optimize instruction level parallelism for out-of-order + /// targets. These passes are run while the machine code is still in SSA + /// form, so they can use MachineTraceMetrics to control their heuristics. + /// + /// All passes added here should preserve the MachineDominatorTree, + /// MachineLoopInfo, and MachineTraceMetrics analyses. + virtual bool addILPOpts() { + return false; + } + + /// This method may be implemented by targets that want to run passes + /// immediately before register allocation. + virtual void addPreRegAlloc() { } + + /// createTargetRegisterAllocator - Create the register allocator pass for + /// this target at the current optimization level. + virtual FunctionPass *createTargetRegisterAllocator(bool Optimized); + + /// addFastRegAlloc - Add the minimum set of target-independent passes that + /// are required for fast register allocation. + virtual void addFastRegAlloc(FunctionPass *RegAllocPass); + + /// addOptimizedRegAlloc - Add passes related to register allocation. + /// LLVMTargetMachine provides standard regalloc passes for most targets. + virtual void addOptimizedRegAlloc(FunctionPass *RegAllocPass); + + /// addPreRewrite - Add passes to the optimized register allocation pipeline + /// after register allocation is complete, but before virtual registers are + /// rewritten to physical registers. + /// + /// These passes must preserve VirtRegMap and LiveIntervals, and when running + /// after RABasic or RAGreedy, they should take advantage of LiveRegMatrix. + /// When these passes run, VirtRegMap contains legal physreg assignments for + /// all virtual registers. + virtual bool addPreRewrite() { + return false; + } + + /// This method may be implemented by targets that want to run passes after + /// register allocation pass pipeline but before prolog-epilog insertion. + virtual void addPostRegAlloc() { } + + /// Add passes that optimize machine instructions after register allocation. + virtual void addMachineLateOptimization(); + + /// This method may be implemented by targets that want to run passes after + /// prolog-epilog insertion and before the second instruction scheduling pass. + virtual void addPreSched2() { } + + /// addGCPasses - Add late codegen passes that analyze code for garbage + /// collection. This should return true if GC info should be printed after + /// these passes. + virtual bool addGCPasses(); + + /// Add standard basic block placement passes. + virtual void addBlockPlacement(); + + /// This pass may be implemented by targets that want to run passes + /// immediately before machine code is emitted. + virtual void addPreEmitPass() { } + + /// Utilities for targets to add passes to the pass manager. + /// + + /// Add a CodeGen pass at this point in the pipeline after checking overrides. + /// Return the pass that was added, or zero if no pass was added. + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + AnalysisID addPass(AnalysisID PassID, bool verifyAfter = true, + bool printAfter = true); + + /// Add a pass to the PassManager if that pass is supposed to be run, as + /// determined by the StartAfter and StopAfter options. Takes ownership of the + /// pass. + /// @p printAfter if true and adding a machine function pass add an extra + /// machine printer pass afterwards + /// @p verifyAfter if true and adding a machine function pass add an extra + /// machine verification pass afterwards. + void addPass(Pass *P, bool verifyAfter = true, bool printAfter = true); + + /// addMachinePasses helper to create the target-selected or overriden + /// regalloc pass. + FunctionPass *createRegAllocPass(bool Optimized); + + /// printAndVerify - Add a pass to dump then verify the machine function, if + /// those steps are enabled. + /// + void printAndVerify(const std::string &Banner); + + /// Add a pass to print the machine function if printing is enabled. + void addPrintPass(const std::string &Banner); + + /// Add a pass to perform basic verification of the machine function if + /// verification is enabled. + void addVerifyPass(const std::string &Banner); +}; +} // namespace llvm /// List of target independent CodeGen pass IDs. namespace llvm { - FunctionPass *createAtomicExpandPass(); + FunctionPass *createAtomicExpandPass(const TargetMachine *TM); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -53,21 +384,9 @@ namespace llvm { /// using the MIR serialization format. MachineFunctionPass *createPrintMIRPass(raw_ostream &OS); - /// This pass resets a MachineFunction when it has the FailedISel property - /// as if it was just created. - /// If EmitFallbackDiag is true, the pass will emit a - /// DiagnosticInfoISelFallback for every MachineFunction it resets. - /// If AbortOnFailedISel is true, abort compilation instead of resetting. - MachineFunctionPass *createResetMachineFunctionPass(bool EmitFallbackDiag, - bool AbortOnFailedISel); - /// createCodeGenPreparePass - Transform the code to expose more pattern /// matching during instruction selection. - FunctionPass *createCodeGenPreparePass(); - - /// createScalarizeMaskedMemIntrinPass - Replace masked load, store, gather - /// and scatter intrinsics with scalar code when target doesn't support them. - FunctionPass *createScalarizeMaskedMemIntrinPass(); + FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr); /// AtomicExpandID -- Lowers atomic operations in terms of either cmpxchg /// load-linked/store-conditional loops. @@ -82,9 +401,6 @@ namespace llvm { /// MachineDominanaceFrontier - This pass is a machine dominators analysis pass. extern char &MachineDominanceFrontierID; - /// MachineRegionInfo - This pass computes SESE regions for machine functions. - extern char &MachineRegionInfoPassID; - /// EdgeBundles analysis - Bundle machine CFG edges. extern char &EdgeBundlesID; @@ -130,16 +446,6 @@ namespace llvm { // instruction and update the MachineFunctionInfo with that information. extern char &ShrinkWrapID; - /// LiveRangeShrink pass. Move instruction close to its definition to shrink - /// the definition's live range. - extern char &LiveRangeShrinkID; - - /// Greedy register allocator. - extern char &RAGreedyID; - - /// Basic register allocator. - extern char &RABasicID; - /// VirtRegRewriter pass. Rewrite virtual registers to physical registers as /// assigned in VirtRegMap. extern char &VirtRegRewriterID; @@ -151,9 +457,6 @@ namespace llvm { /// DeadMachineInstructionElim - This pass removes dead machine instructions. extern char &DeadMachineInstructionElimID; - /// This pass adds dead/undef flags after analyzing subregister lanes. - extern char &DetectDeadLanesID; - /// FastRegisterAllocation Pass - This pass register allocates as fast as /// possible. It is best suited for debug code where live ranges are short. /// @@ -177,16 +480,11 @@ namespace llvm { /// PrologEpilogCodeInserter - This pass inserts prolog and epilog code, /// and eliminates abstract frame references. extern char &PrologEpilogCodeInserterID; - MachineFunctionPass *createPrologEpilogInserterPass(); /// ExpandPostRAPseudos - This pass expands pseudo instructions after /// register allocation. extern char &ExpandPostRAPseudosID; - /// createPostRAHazardRecognizer - This pass runs the post-ra hazard - /// recognizer. - extern char &PostRAHazardRecognizerID; - /// createPostRAScheduler - This pass performs post register allocation /// scheduling. extern char &PostRASchedulerID; @@ -197,10 +495,6 @@ namespace llvm { /// branches. extern char &BranchFolderPassID; - /// BranchRelaxation - This pass replaces branches that need to jump further - /// than is supported by a branch instruction. - extern char &BranchRelaxationPassID; - /// MachineFunctionPrinterPass - This pass prints out MachineInstr's. extern char &MachineFunctionPrinterPassID; @@ -231,8 +525,7 @@ namespace llvm { /// IfConverter - This pass performs machine code if conversion. extern char &IfConverterID; - FunctionPass *createIfConverter( - std::function<bool(const MachineFunction &)> Ftor); + FunctionPass *createIfConverter(std::function<bool(const Function &)> Ftor); /// MachineBlockPlacement - This pass places basic blocks based on branch /// probabilities. @@ -293,19 +586,9 @@ namespace llvm { /// \brief This pass lays out funclets contiguously. extern char &FuncletLayoutID; - /// This pass inserts the XRay instrumentation sleds if they are supported by - /// the target platform. - extern char &XRayInstrumentationID; - - /// This pass inserts FEntry calls - extern char &FEntryInserterID; - - /// \brief This pass implements the "patchable-function" attribute. - extern char &PatchableFunctionID; - /// createStackProtectorPass - This pass adds stack protectors to functions. /// - FunctionPass *createStackProtectorPass(); + FunctionPass *createStackProtectorPass(const TargetMachine *TM); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. @@ -314,11 +597,11 @@ namespace llvm { /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. - FunctionPass *createDwarfEHPass(); + FunctionPass *createDwarfEHPass(const TargetMachine *TM); /// createWinEHPass - Prepares personality functions used by MSVC on Windows, /// in addition to the Itanium LSDA based personalities. - FunctionPass *createWinEHPass(); + FunctionPass *createWinEHPass(const TargetMachine *TM); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. @@ -334,11 +617,19 @@ namespace llvm { /// ExpandISelPseudos - This pass expands pseudo-instructions. extern char &ExpandISelPseudosID; + /// createExecutionDependencyFixPass - This pass fixes execution time + /// problems with dependent instructions, such as switching execution + /// domains to match. + /// + /// The pass will examine instructions using and defining registers in RC. + /// + FunctionPass *createExecutionDependencyFixPass(const TargetRegisterClass *RC); + /// UnpackMachineBundles - This pass unpack machine instruction bundles. extern char &UnpackMachineBundlesID; FunctionPass * - createUnpackMachineBundles(std::function<bool(const MachineFunction &)> Ftor); + createUnpackMachineBundles(std::function<bool(const Function &)> Ftor); /// FinalizeMachineBundles - This pass finalize machine instruction /// bundles (created earlier, e.g. during pre-RA scheduling). @@ -362,64 +653,33 @@ namespace llvm { /// InterleavedAccess Pass - This pass identifies and matches interleaved /// memory accesses to target specific intrinsics. /// - FunctionPass *createInterleavedAccessPass(); - - /// LowerEmuTLS - This pass generates __emutls_[vt].xyz variables for all - /// TLS variables for the emulated TLS model. - /// - ModulePass *createLowerEmuTLSPass(); - - /// This pass lowers the @llvm.load.relative intrinsic to instructions. - /// This is unsafe to do earlier because a pass may combine the constant - /// initializer into the load, which may result in an overflowing evaluation. - ModulePass *createPreISelIntrinsicLoweringPass(); - - /// GlobalMerge - This pass merges internal (by default) globals into structs - /// to enable reuse of a base pointer by indexed addressing modes. - /// It can also be configured to focus on size optimizations only. - /// - Pass *createGlobalMergePass(const TargetMachine *TM, unsigned MaximalOffset, - bool OnlyOptimizeForSize = false, - bool MergeExternalByDefault = false); - - /// This pass splits the stack into a safe stack and an unsafe stack to - /// protect against stack-based overflow vulnerabilities. - FunctionPass *createSafeStackPass(); - - /// This pass detects subregister lanes in a virtual register that are used - /// independently of other lanes and splits them into separate virtual - /// registers. - extern char &RenameIndependentSubregsID; - - /// This pass is executed POST-RA to collect which physical registers are - /// preserved by given machine function. - FunctionPass *createRegUsageInfoCollector(); - - /// Return a MachineFunction pass that identifies call sites - /// and propagates register usage information of callee to caller - /// if available with PysicalRegisterUsageInfo pass. - FunctionPass *createRegUsageInfoPropPass(); - - /// This pass performs software pipelining on machine instructions. - extern char &MachinePipelinerID; - - /// This pass frees the memory occupied by the MachineFunction. - FunctionPass *createFreeMachineFunctionPass(); - - /// This pass performs outlining on machine instructions directly before - /// printing assembly. - ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs = false); - - /// This pass expands the experimental reduction intrinsics into sequences of - /// shuffles. - FunctionPass *createExpandReductionsPass(); - - // This pass expands memcmp() to load/stores. - FunctionPass *createExpandMemCmpPass(); - - // This pass expands indirectbr instructions. - FunctionPass *createIndirectBrExpandPass(); - + FunctionPass *createInterleavedAccessPass(const TargetMachine *TM); } // End llvm namespace +/// Target machine pass initializer for passes with dependencies. Use with +/// INITIALIZE_TM_PASS_END. +#define INITIALIZE_TM_PASS_BEGIN INITIALIZE_PASS_BEGIN + +/// Target machine pass initializer for passes with dependencies. Use with +/// INITIALIZE_TM_PASS_BEGIN. +#define INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) \ + PassInfo *PI = new PassInfo(name, arg, & passName ::ID, \ + PassInfo::NormalCtor_t(callDefaultCtor< passName >), cfg, analysis, \ + PassInfo::TargetMachineCtor_t(callTargetMachineCtor< passName >)); \ + Registry.registerPass(*PI, true); \ + return PI; \ + } \ + void llvm::initialize##passName##Pass(PassRegistry &Registry) { \ + CALL_ONCE_INITIALIZATION(initialize##passName##PassOnce) \ + } + +/// This initializer registers TargetMachine constructor, so the pass being +/// initialized can use target dependent interfaces. Please do not move this +/// macro to be together with INITIALIZE_PASS, which is a complete target +/// independent initializer, and we don't want to make libScalarOpts depend +/// on libCodeGen. +#define INITIALIZE_TM_PASS(passName, arg, name, cfg, analysis) \ + INITIALIZE_TM_PASS_BEGIN(passName, arg, name, cfg, analysis) \ + INITIALIZE_TM_PASS_END(passName, arg, name, cfg, analysis) + #endif diff --git a/gnu/llvm/include/llvm/InitializePasses.h b/gnu/llvm/include/llvm/InitializePasses.h index 4c79333f5d2..90fbc1d891b 100644 --- a/gnu/llvm/include/llvm/InitializePasses.h +++ b/gnu/llvm/include/llvm/InitializePasses.h @@ -1,4 +1,4 @@ -//===- llvm/InitializePasses.h - Initialize All Passes ----------*- C++ -*-===// +//===- llvm/InitializePasses.h -------- Initialize All Passes ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,371 +19,297 @@ namespace llvm { class PassRegistry; -/// Initialize all passes linked into the TransformUtils library. +/// initializeCore - Initialize all passes linked into the +/// TransformUtils library. void initializeCore(PassRegistry&); -/// Initialize all passes linked into the TransformUtils library. +/// initializeTransformUtils - Initialize all passes linked into the +/// TransformUtils library. void initializeTransformUtils(PassRegistry&); -/// Initialize all passes linked into the ScalarOpts library. +/// initializeScalarOpts - Initialize all passes linked into the +/// ScalarOpts library. void initializeScalarOpts(PassRegistry&); -/// Initialize all passes linked into the ObjCARCOpts library. +/// initializeObjCARCOpts - Initialize all passes linked into the ObjCARCOpts +/// library. void initializeObjCARCOpts(PassRegistry&); -/// Initialize all passes linked into the Vectorize library. +/// initializeVectorization - Initialize all passes linked into the +/// Vectorize library. void initializeVectorization(PassRegistry&); -/// Initialize all passes linked into the InstCombine library. +/// initializeInstCombine - Initialize all passes linked into the +/// InstCombine library. void initializeInstCombine(PassRegistry&); -/// Initialize all passes linked into the IPO library. +/// initializeIPO - Initialize all passes linked into the IPO library. void initializeIPO(PassRegistry&); -/// Initialize all passes linked into the Instrumentation library. +/// initializeInstrumentation - Initialize all passes linked into the +/// Instrumentation library. void initializeInstrumentation(PassRegistry&); -/// Initialize all passes linked into the Analysis library. +/// initializeAnalysis - Initialize all passes linked into the Analysis library. void initializeAnalysis(PassRegistry&); -/// Initialize all passes linked into the Coroutines library. -void initializeCoroutines(PassRegistry&); - -/// Initialize all passes linked into the CodeGen library. +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. void initializeCodeGen(PassRegistry&); -/// Initialize all passes linked into the GlobalISel library. -void initializeGlobalISel(PassRegistry&); - -/// Initialize all passes linked into the CodeGen library. +/// initializeCodeGen - Initialize all passes linked into the CodeGen library. void initializeTarget(PassRegistry&); -void initializeAAEvalLegacyPassPass(PassRegistry&); -void initializeAAResultsWrapperPassPass(PassRegistry&); +void initializeAAEvalPass(PassRegistry&); +void initializeAddDiscriminatorsPass(PassRegistry&); void initializeADCELegacyPassPass(PassRegistry&); -void initializeAddDiscriminatorsLegacyPassPass(PassRegistry&); -void initializeAddressSanitizerModulePass(PassRegistry&); -void initializeAddressSanitizerPass(PassRegistry&); +void initializeBDCEPass(PassRegistry&); void initializeAliasSetPrinterPass(PassRegistry&); -void initializeAlignmentFromAssumptionsPass(PassRegistry&); -void initializeAlwaysInlinerLegacyPassPass(PassRegistry&); +void initializeAlwaysInlinerPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&); -void initializeAssumptionCacheTrackerPass(PassRegistry&); void initializeAtomicExpandPass(PassRegistry&); -void initializeBDCELegacyPassPass(PassRegistry&); +void initializeSampleProfileLoaderPass(PassRegistry&); +void initializeAlignmentFromAssumptionsPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&); void initializeBasicAAWrapperPassPass(PassRegistry&); +void initializeCallGraphWrapperPassPass(PassRegistry &); void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockFrequencyInfoWrapperPassPass(PassRegistry&); -void initializeBoundsCheckingLegacyPassPass(PassRegistry&); +void initializeBoundsCheckingPass(PassRegistry&); void initializeBranchFolderPassPass(PassRegistry&); void initializeBranchProbabilityInfoWrapperPassPass(PassRegistry&); -void initializeBranchRelaxationPass(PassRegistry&); void initializeBreakCriticalEdgesPass(PassRegistry&); -void initializeCallSiteSplittingLegacyPassPass(PassRegistry&); -void initializeCFGOnlyPrinterLegacyPassPass(PassRegistry&); -void initializeCFGOnlyViewerLegacyPassPass(PassRegistry&); -void initializeCFGPrinterLegacyPassPass(PassRegistry&); -void initializeCFGSimplifyPassPass(PassRegistry&); -void initializeCFGViewerLegacyPassPass(PassRegistry&); -void initializeCFLAndersAAWrapperPassPass(PassRegistry&); -void initializeCFLSteensAAWrapperPassPass(PassRegistry&); -void initializeCallGraphDOTPrinterPass(PassRegistry&); -void initializeCallGraphPrinterLegacyPassPass(PassRegistry&); +void initializeCallGraphPrinterPass(PassRegistry&); void initializeCallGraphViewerPass(PassRegistry&); -void initializeCallGraphWrapperPassPass(PassRegistry&); +void initializeCFGOnlyPrinterPass(PassRegistry&); +void initializeCFGOnlyViewerPass(PassRegistry&); +void initializeCFGPrinterPass(PassRegistry&); +void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeCFLAAWrapperPassPass(PassRegistry&); +void initializeExternalAAWrapperPassPass(PassRegistry&); +void initializeForwardControlFlowIntegrityPass(PassRegistry&); +void initializeFlattenCFGPassPass(PassRegistry&); +void initializeStructurizeCFGPass(PassRegistry&); +void initializeCFGViewerPass(PassRegistry&); +void initializeConstantHoistingPass(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&); -void initializeConstantHoistingLegacyPassPass(PassRegistry&); -void initializeCalledValuePropagationLegacyPassPass(PassRegistry &); -void initializeConstantMergeLegacyPassPass(PassRegistry&); +void initializeConstantMergePass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&); -void initializeCorrelatedValuePropagationPass(PassRegistry&); +void initializeMachineCopyPropagationPass(PassRegistry&); void initializeCostModelAnalysisPass(PassRegistry&); -void initializeEntryExitInstrumenterPass(PassRegistry&); -void initializePostInlineEntryExitInstrumenterPass(PassRegistry&); +void initializeCorrelatedValuePropagationPass(PassRegistry&); void initializeCrossDSOCFIPass(PassRegistry&); void initializeDAEPass(PassRegistry&); void initializeDAHPass(PassRegistry&); -void initializeDCELegacyPassPass(PassRegistry&); -void initializeDSELegacyPassPass(PassRegistry&); -void initializeDataFlowSanitizerPass(PassRegistry&); +void initializeDCEPass(PassRegistry&); +void initializeDSEPass(PassRegistry&); void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); -void initializeDelinearizationPass(PassRegistry&); -void initializeDemandedBitsWrapperPassPass(PassRegistry&); +void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); -void initializeDependenceAnalysisWrapperPassPass(PassRegistry&); -void initializeDetectDeadLanesPass(PassRegistry&); void initializeDivergenceAnalysisPass(PassRegistry&); -void initializeDivRemPairsLegacyPassPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); void initializeDomViewerPass(PassRegistry&); -void initializeDominanceFrontierWrapperPassPass(PassRegistry&); +void initializeDominanceFrontierPass(PassRegistry&); void initializeDominatorTreeWrapperPassPass(PassRegistry&); -void initializeDwarfEHPreparePass(PassRegistry&); -void initializeEarlyCSELegacyPassPass(PassRegistry&); -void initializeEarlyCSEMemSSALegacyPassPass(PassRegistry&); void initializeEarlyIfConverterPass(PassRegistry&); void initializeEdgeBundlesPass(PassRegistry&); -void initializeEfficiencySanitizerPass(PassRegistry&); -void initializeEliminateAvailableExternallyLegacyPassPass(PassRegistry&); -void initializeExpandISelPseudosPass(PassRegistry&); -void initializeExpandMemCmpPassPass(PassRegistry&); void initializeExpandPostRAPass(PassRegistry&); -void initializeExpandReductionsPass(PassRegistry&); -void initializeExternalAAWrapperPassPass(PassRegistry&); -void initializeFEntryInserterPass(PassRegistry&); -void initializeFinalizeMachineBundlesPass(PassRegistry&); -void initializeFlattenCFGPassPass(PassRegistry&); -void initializeFloat2IntLegacyPassPass(PassRegistry&); +void initializeAAResultsWrapperPassPass(PassRegistry &); +void initializeGCOVProfilerPass(PassRegistry&); +void initializePGOInstrumentationGenPass(PassRegistry&); +void initializePGOInstrumentationUsePass(PassRegistry&); +void initializeInstrProfilingPass(PassRegistry&); +void initializeAddressSanitizerPass(PassRegistry&); +void initializeAddressSanitizerModulePass(PassRegistry&); +void initializeMemorySanitizerPass(PassRegistry&); +void initializeThreadSanitizerPass(PassRegistry&); +void initializeSanitizerCoverageModulePass(PassRegistry&); +void initializeDataFlowSanitizerPass(PassRegistry&); +void initializeScalarizerPass(PassRegistry&); +void initializeEarlyCSELegacyPassPass(PassRegistry &); +void initializeEliminateAvailableExternallyPass(PassRegistry&); +void initializeExpandISelPseudosPass(PassRegistry&); void initializeForceFunctionAttrsLegacyPassPass(PassRegistry&); -void initializeForwardControlFlowIntegrityPass(PassRegistry&); -void initializeFuncletLayoutPass(PassRegistry&); -void initializeFunctionImportLegacyPassPass(PassRegistry&); void initializeGCMachineCodeAnalysisPass(PassRegistry&); void initializeGCModuleInfoPass(PassRegistry&); -void initializeGCOVProfilerLegacyPassPass(PassRegistry&); -void initializeGVNHoistLegacyPassPass(PassRegistry&); -void initializeGVNLegacyPassPass(PassRegistry&); -void initializeGVNSinkLegacyPassPass(PassRegistry&); -void initializeGlobalDCELegacyPassPass(PassRegistry&); -void initializeGlobalMergePass(PassRegistry&); -void initializeGlobalOptLegacyPassPass(PassRegistry&); -void initializeGlobalSplitPass(PassRegistry&); +void initializeGVNPass(PassRegistry&); +void initializeGlobalDCEPass(PassRegistry&); +void initializeGlobalOptPass(PassRegistry&); void initializeGlobalsAAWrapperPassPass(PassRegistry&); -void initializeGuardWideningLegacyPassPass(PassRegistry&); void initializeIPCPPass(PassRegistry&); -void initializeIPSCCPLegacyPassPass(PassRegistry&); -void initializeIRTranslatorPass(PassRegistry&); -void initializeIVUsersWrapperPassPass(PassRegistry&); +void initializeIPSCCPPass(PassRegistry&); +void initializeIVUsersPass(PassRegistry&); void initializeIfConverterPass(PassRegistry&); -void initializeImplicitNullChecksPass(PassRegistry&); -void initializeIndVarSimplifyLegacyPassPass(PassRegistry&); -void initializeIndirectBrExpandPassPass(PassRegistry&); void initializeInductiveRangeCheckEliminationPass(PassRegistry&); -void initializeInferAddressSpacesPass(PassRegistry&); +void initializeIndVarSimplifyPass(PassRegistry&); void initializeInferFunctionAttrsLegacyPassPass(PassRegistry&); void initializeInlineCostAnalysisPass(PassRegistry&); +void initializeInstructionCombiningPassPass(PassRegistry&); void initializeInstCountPass(PassRegistry&); void initializeInstNamerPass(PassRegistry&); -void initializeInstSimplifierPass(PassRegistry&); -void initializeInstrProfilingLegacyPassPass(PassRegistry&); -void initializeInstructionCombiningPassPass(PassRegistry&); -void initializeInstructionSelectPass(PassRegistry&); -void initializeInterleavedAccessPass(PassRegistry&); -void initializeInternalizeLegacyPassPass(PassRegistry&); +void initializeInternalizePassPass(PassRegistry&); void initializeIntervalPartitionPass(PassRegistry&); void initializeJumpThreadingPass(PassRegistry&); -void initializeLCSSAVerificationPassPass(PassRegistry&); -void initializeLCSSAWrapperPassPass(PassRegistry&); -void initializeLazyBlockFrequencyInfoPassPass(PassRegistry&); -void initializeLazyBranchProbabilityInfoPassPass(PassRegistry&); -void initializeLazyMachineBlockFrequencyInfoPassPass(PassRegistry&); -void initializeLazyValueInfoPrinterPass(PassRegistry&); -void initializeLazyValueInfoWrapperPassPass(PassRegistry&); -void initializeLegacyLICMPassPass(PassRegistry&); -void initializeLegacyLoopSinkPassPass(PassRegistry&); -void initializeLegalizerPass(PassRegistry&); -void initializeLibCallsShrinkWrapLegacyPassPass(PassRegistry&); +void initializeLCSSAPass(PassRegistry&); +void initializeLICMPass(PassRegistry&); +void initializeLazyValueInfoPass(PassRegistry&); void initializeLintPass(PassRegistry&); -void initializeLiveDebugValuesPass(PassRegistry&); void initializeLiveDebugVariablesPass(PassRegistry&); void initializeLiveIntervalsPass(PassRegistry&); -void initializeLiveRangeShrinkPass(PassRegistry&); void initializeLiveRegMatrixPass(PassRegistry&); void initializeLiveStacksPass(PassRegistry&); void initializeLiveVariablesPass(PassRegistry&); -void initializeLoadStoreVectorizerPass(PassRegistry&); void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); -void initializeLocalizerPass(PassRegistry&); -void initializeLoopAccessLegacyAnalysisPass(PassRegistry&); -void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&); -void initializeLoopDeletionLegacyPassPass(PassRegistry&); -void initializeLoopDistributeLegacyPass(PassRegistry&); +void initializeLoopDeletionPass(PassRegistry&); void initializeLoopExtractorPass(PassRegistry&); -void initializeLoopIdiomRecognizeLegacyPassPass(PassRegistry&); void initializeLoopInfoWrapperPassPass(PassRegistry&); -void initializeLoopInstSimplifyLegacyPassPass(PassRegistry&); -void initializeLoopInterchangePass(PassRegistry&); -void initializeLoopLoadEliminationPass(PassRegistry&); -void initializeLoopPassPass(PassRegistry&); -void initializeLoopPredicationLegacyPassPass(PassRegistry&); -void initializeLoopRerollPass(PassRegistry&); -void initializeLoopRotateLegacyPassPass(PassRegistry&); -void initializeLoopSimplifyCFGLegacyPassPass(PassRegistry&); +void initializeLoopInterchangePass(PassRegistry &); +void initializeLoopInstSimplifyPass(PassRegistry&); +void initializeLoopRotatePass(PassRegistry&); void initializeLoopSimplifyPass(PassRegistry&); void initializeLoopStrengthReducePass(PassRegistry&); +void initializeGlobalMergePass(PassRegistry&); +void initializeLoopRerollPass(PassRegistry&); void initializeLoopUnrollPass(PassRegistry&); void initializeLoopUnswitchPass(PassRegistry&); -void initializeLoopVectorizePass(PassRegistry&); -void initializeLoopVersioningLICMPass(PassRegistry&); -void initializeLoopVersioningPassPass(PassRegistry&); -void initializeLowerAtomicLegacyPassPass(PassRegistry&); -void initializeLowerEmuTLSPass(PassRegistry&); +void initializeLoopIdiomRecognizePass(PassRegistry&); +void initializeLowerAtomicPass(PassRegistry&); +void initializeLowerBitSetsPass(PassRegistry&); void initializeLowerExpectIntrinsicPass(PassRegistry&); -void initializeLowerGuardIntrinsicLegacyPassPass(PassRegistry&); void initializeLowerIntrinsicsPass(PassRegistry&); -void initializeLowerInvokeLegacyPassPass(PassRegistry&); +void initializeLowerInvokePass(PassRegistry&); void initializeLowerSwitchPass(PassRegistry&); -void initializeLowerTypeTestsPass(PassRegistry&); -void initializeMIRPrintingPassPass(PassRegistry&); void initializeMachineBlockFrequencyInfoPass(PassRegistry&); void initializeMachineBlockPlacementPass(PassRegistry&); void initializeMachineBlockPlacementStatsPass(PassRegistry&); void initializeMachineBranchProbabilityInfoPass(PassRegistry&); void initializeMachineCSEPass(PassRegistry&); -void initializeMachineCombinerPass(PassRegistry&); -void initializeMachineCopyPropagationPass(PassRegistry&); -void initializeMachineDominanceFrontierPass(PassRegistry&); +void initializeImplicitNullChecksPass(PassRegistry&); void initializeMachineDominatorTreePass(PassRegistry&); -void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeMachineDominanceFrontierPass(PassRegistry&); +void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineLICMPass(PassRegistry&); void initializeMachineLoopInfoPass(PassRegistry&); void initializeMachineModuleInfoPass(PassRegistry&); -void initializeMachineOptimizationRemarkEmitterPassPass(PassRegistry&); -void initializeMachineOutlinerPass(PassRegistry&); -void initializeMachinePipelinerPass(PassRegistry&); -void initializeMachinePostDominatorTreePass(PassRegistry&); void initializeMachineRegionInfoPassPass(PassRegistry&); void initializeMachineSchedulerPass(PassRegistry&); void initializeMachineSinkingPass(PassRegistry&); void initializeMachineTraceMetricsPass(PassRegistry&); void initializeMachineVerifierPassPass(PassRegistry&); -void initializeMemCpyOptLegacyPassPass(PassRegistry&); +void initializeMemCpyOptPass(PassRegistry&); void initializeMemDepPrinterPass(PassRegistry&); void initializeMemDerefPrinterPass(PassRegistry&); -void initializeMemoryDependenceWrapperPassPass(PassRegistry&); -void initializeMemorySSAPrinterLegacyPassPass(PassRegistry&); -void initializeMemorySSAWrapperPassPass(PassRegistry&); -void initializeMemorySanitizerPass(PassRegistry&); -void initializeMergeFunctionsPass(PassRegistry&); -void initializeMergeICmpsPass(PassRegistry&); -void initializeMergedLoadStoreMotionLegacyPassPass(PassRegistry&); +void initializeMemoryDependenceAnalysisPass(PassRegistry&); +void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); +void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); -void initializeModuleSummaryIndexWrapperPassPass(PassRegistry&); -void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); -void initializeNaryReassociateLegacyPassPass(PassRegistry&); -void initializeNewGVNLegacyPassPass(PassRegistry&); +void initializeNaryReassociatePass(PassRegistry&); +void initializeNoAAPass(PassRegistry&); void initializeObjCARCAAWrapperPassPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); -void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); +void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCOptPass(PassRegistry&); -void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&); +void initializePAEvalPass(PassRegistry &); void initializeOptimizePHIsPass(PassRegistry&); -void initializePAEvalPass(PassRegistry&); +void initializePartiallyInlineLibCallsPass(PassRegistry&); void initializePEIPass(PassRegistry&); -void initializePGOIndirectCallPromotionLegacyPassPass(PassRegistry&); -void initializePGOInstrumentationGenLegacyPassPass(PassRegistry&); -void initializePGOInstrumentationUseLegacyPassPass(PassRegistry&); -void initializePGOMemOPSizeOptLegacyPassPass(PassRegistry&); void initializePHIEliminationPass(PassRegistry&); -void initializePartialInlinerLegacyPassPass(PassRegistry&); -void initializePartiallyInlineLibCallsLegacyPassPass(PassRegistry&); -void initializePatchableFunctionPass(PassRegistry&); +void initializePartialInlinerPass(PassRegistry&); void initializePeepholeOptimizerPass(PassRegistry&); -void initializePhysicalRegisterUsageInfoPass(PassRegistry&); -void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); -void initializePlaceSafepointsPass(PassRegistry&); void initializePostDomOnlyPrinterPass(PassRegistry&); void initializePostDomOnlyViewerPass(PassRegistry&); void initializePostDomPrinterPass(PassRegistry&); void initializePostDomViewerPass(PassRegistry&); -void initializePostDominatorTreeWrapperPassPass(PassRegistry&); -void initializePostMachineSchedulerPass(PassRegistry&); -void initializePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); -void initializePostRAHazardRecognizerPass(PassRegistry&); +void initializePostDominatorTreePass(PassRegistry&); +void initializePostOrderFunctionAttrsPass(PassRegistry&); void initializePostRASchedulerPass(PassRegistry&); -void initializePreISelIntrinsicLoweringLegacyPassPass(PassRegistry&); -void initializePredicateInfoPrinterLegacyPassPass(PassRegistry&); -void initializePrintBasicBlockPassPass(PassRegistry&); +void initializePostMachineSchedulerPass(PassRegistry&); void initializePrintFunctionPassWrapperPass(PassRegistry&); void initializePrintModulePassWrapperPass(PassRegistry&); +void initializePrintBasicBlockPassPass(PassRegistry&); void initializeProcessImplicitDefsPass(PassRegistry&); -void initializeProfileSummaryInfoWrapperPassPass(PassRegistry&); -void initializePromoteLegacyPassPass(PassRegistry&); +void initializePromotePassPass(PassRegistry&); void initializePruneEHPass(PassRegistry&); -void initializeRABasicPass(PassRegistry&); -void initializeRegAllocFastPass(PassRegistry&); -void initializeRAGreedyPass(PassRegistry&); -void initializeReassociateLegacyPassPass(PassRegistry&); -void initializeRegBankSelectPass(PassRegistry&); +void initializeReassociatePass(PassRegistry&); void initializeRegToMemPass(PassRegistry&); void initializeRegionInfoPassPass(PassRegistry&); void initializeRegionOnlyPrinterPass(PassRegistry&); void initializeRegionOnlyViewerPass(PassRegistry&); void initializeRegionPrinterPass(PassRegistry&); void initializeRegionViewerPass(PassRegistry&); -void initializeRegisterCoalescerPass(PassRegistry&); -void initializeRenameIndependentSubregsPass(PassRegistry&); -void initializeResetMachineFunctionPass(PassRegistry&); -void initializeReversePostOrderFunctionAttrsLegacyPassPass(PassRegistry&); -void initializeRewriteStatepointsForGCLegacyPassPass(PassRegistry &); -void initializeRewriteSymbolsLegacyPassPass(PassRegistry&); -void initializeSafepointIRVerifierPass(PassRegistry&); -void initializeSCCPLegacyPassPass(PassRegistry&); -void initializeSCEVAAWrapperPassPass(PassRegistry&); -void initializeSLPVectorizerPass(PassRegistry&); +void initializeReversePostOrderFunctionAttrsPass(PassRegistry&); +void initializeRewriteStatepointsForGCPass(PassRegistry&); +void initializeSafeStackPass(PassRegistry&); +void initializeSCCPPass(PassRegistry&); void initializeSROALegacyPassPass(PassRegistry&); -void initializeSafeStackLegacyPassPass(PassRegistry&); -void initializeSampleProfileLoaderLegacyPassPass(PassRegistry&); -void initializeSanitizerCoverageModulePass(PassRegistry&); +void initializeSROA_DTPass(PassRegistry&); +void initializeSROA_SSAUpPass(PassRegistry&); +void initializeSCEVAAWrapperPassPass(PassRegistry&); void initializeScalarEvolutionWrapperPassPass(PassRegistry&); -void initializeScalarizeMaskedMemIntrinPass(PassRegistry&); -void initializeScalarizerPass(PassRegistry&); -void initializeScavengerTestPass(PassRegistry&); -void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&); -void initializeSeparateConstOffsetFromGEPPass(PassRegistry&); -void initializeShadowStackGCLoweringPass(PassRegistry&); -void initializeShrinkWrapPass(PassRegistry&); +void initializeShrinkWrapPass(PassRegistry &); void initializeSimpleInlinerPass(PassRegistry&); -void initializeSimpleLoopUnswitchLegacyPassPass(PassRegistry&); +void initializeShadowStackGCLoweringPass(PassRegistry&); +void initializeRegisterCoalescerPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); -void initializeSinkingLegacyPassPass(PassRegistry&); -void initializeSjLjEHPreparePass(PassRegistry&); +void initializeSinkingPass(PassRegistry&); +void initializeSeparateConstOffsetFromGEPPass(PassRegistry &); void initializeSlotIndexesPass(PassRegistry&); -void initializeSpeculativeExecutionLegacyPassPass(PassRegistry&); void initializeSpillPlacementPass(PassRegistry&); -void initializeStackColoringPass(PassRegistry&); -void initializeStackMapLivenessPass(PassRegistry&); +void initializeSpeculativeExecutionPass(PassRegistry&); void initializeStackProtectorPass(PassRegistry&); +void initializeStackColoringPass(PassRegistry&); void initializeStackSlotColoringPass(PassRegistry&); -void initializeStraightLineStrengthReducePass(PassRegistry&); +void initializeStraightLineStrengthReducePass(PassRegistry &); void initializeStripDeadDebugInfoPass(PassRegistry&); void initializeStripDeadPrototypesLegacyPassPass(PassRegistry&); void initializeStripDebugDeclarePass(PassRegistry&); -void initializeStripGCRelocatesPass(PassRegistry&); void initializeStripNonDebugSymbolsPass(PassRegistry&); -void initializeStripNonLineTableDebugInfoPass(PassRegistry&); void initializeStripSymbolsPass(PassRegistry&); -void initializeStructurizeCFGPass(PassRegistry&); -void initializeHWAddressSanitizerPass(PassRegistry&); void initializeTailCallElimPass(PassRegistry&); void initializeTailDuplicatePassPass(PassRegistry&); -void initializeTargetLibraryInfoWrapperPassPass(PassRegistry&); void initializeTargetPassConfigPass(PassRegistry&); -void initializeTargetTransformInfoWrapperPassPass(PassRegistry&); -void initializeThreadSanitizerPass(PassRegistry&); +void initializeTargetTransformInfoWrapperPassPass(PassRegistry &); +void initializeTargetLibraryInfoWrapperPassPass(PassRegistry &); +void initializeAssumptionCacheTrackerPass(PassRegistry &); void initializeTwoAddressInstructionPassPass(PassRegistry&); void initializeTypeBasedAAWrapperPassPass(PassRegistry&); +void initializeScopedNoAliasAAWrapperPassPass(PassRegistry&); void initializeUnifyFunctionExitNodesPass(PassRegistry&); -void initializeUnpackMachineBundlesPass(PassRegistry&); -void initializeUnreachableBlockElimLegacyPassPass(PassRegistry&); +void initializeUnreachableBlockElimPass(PassRegistry&); void initializeUnreachableMachineBlockElimPass(PassRegistry&); void initializeVerifierLegacyPassPass(PassRegistry&); void initializeVirtRegMapPass(PassRegistry&); void initializeVirtRegRewriterPass(PassRegistry&); -void initializeWholeProgramDevirtPass(PassRegistry&); +void initializeInstSimplifierPass(PassRegistry&); +void initializeUnpackMachineBundlesPass(PassRegistry&); +void initializeFinalizeMachineBundlesPass(PassRegistry&); +void initializeLoopAccessAnalysisPass(PassRegistry&); +void initializeLoopVectorizePass(PassRegistry&); +void initializeSLPVectorizerPass(PassRegistry&); +void initializeBBVectorizePass(PassRegistry&); +void initializeMachineFunctionPrinterPassPass(PassRegistry&); +void initializeMIRPrintingPassPass(PassRegistry&); +void initializeStackMapLivenessPass(PassRegistry&); +void initializeLiveDebugValuesPass(PassRegistry&); +void initializeMachineCombinerPass(PassRegistry &); +void initializeLoadCombinePass(PassRegistry&); +void initializeRewriteSymbolsPass(PassRegistry&); void initializeWinEHPreparePass(PassRegistry&); -void initializeWriteBitcodePassPass(PassRegistry&); -void initializeWriteThinLTOBitcodePass(PassRegistry&); -void initializeXRayInstrumentationPass(PassRegistry&); -void initializeMIRCanonicalizerPass(PassRegistry &); - -} // end namespace llvm +void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); +void initializePlaceSafepointsPass(PassRegistry&); +void initializeDwarfEHPreparePass(PassRegistry&); +void initializeFloat2IntPass(PassRegistry&); +void initializeLoopDistributePass(PassRegistry&); +void initializeSjLjEHPreparePass(PassRegistry&); +void initializeDemandedBitsPass(PassRegistry&); +void initializeFuncletLayoutPass(PassRegistry &); +void initializeLoopLoadEliminationPass(PassRegistry&); +void initializeFunctionImportPassPass(PassRegistry &); +} -#endif // LLVM_INITIALIZEPASSES_H +#endif diff --git a/gnu/llvm/lib/CodeGen/CMakeLists.txt b/gnu/llvm/lib/CodeGen/CMakeLists.txt index 865de4f47af..a078c3c707a 100644 --- a/gnu/llvm/lib/CodeGen/CMakeLists.txt +++ b/gnu/llvm/lib/CodeGen/CMakeLists.txt @@ -1,3 +1,8 @@ +set(system_libs) +if(CMAKE_HOST_UNIX AND LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD) + set(system_libs ${system_libs} pthread) +endif() + add_llvm_library(LLVMCodeGen AggressiveAntiDepBreaker.cpp AllocationOrder.cpp @@ -5,26 +10,23 @@ add_llvm_library(LLVMCodeGen AtomicExpandPass.cpp BasicTargetTransformInfo.cpp BranchFolding.cpp - BranchRelaxation.cpp - BuiltinGCs.cpp CalcSpillWeights.cpp CallingConvLower.cpp CodeGen.cpp CodeGenPrepare.cpp + CoreCLRGC.cpp CriticalAntiDepBreaker.cpp - DeadMachineInstructionElim.cpp - DetectDeadLanes.cpp DFAPacketizer.cpp + DeadMachineInstructionElim.cpp DwarfEHPrepare.cpp EarlyIfConversion.cpp EdgeBundles.cpp + ErlangGC.cpp ExecutionDepsFix.cpp ExpandISelPseudos.cpp - ExpandMemCmp.cpp ExpandPostRAPseudos.cpp - ExpandReductions.cpp + LiveDebugValues.cpp FaultMaps.cpp - FEntryInserter.cpp FuncletLayout.cpp GCMetadata.cpp GCMetadataPrinter.cpp @@ -33,75 +35,62 @@ add_llvm_library(LLVMCodeGen GlobalMerge.cpp IfConversion.cpp ImplicitNullChecks.cpp - IndirectBrExpandPass.cpp InlineSpiller.cpp InterferenceCache.cpp InterleavedAccessPass.cpp IntrinsicLowering.cpp + LLVMTargetMachine.cpp LatencyPriorityQueue.cpp - LazyMachineBlockFrequencyInfo.cpp LexicalScopes.cpp - LiveDebugValues.cpp LiveDebugVariables.cpp - LiveIntervals.cpp LiveInterval.cpp + LiveIntervalAnalysis.cpp LiveIntervalUnion.cpp - LivePhysRegs.cpp LiveRangeCalc.cpp LiveRangeEdit.cpp - LiveRangeShrink.cpp LiveRegMatrix.cpp - LiveRegUnits.cpp - LiveStacks.cpp + LivePhysRegs.cpp + LiveStackAnalysis.cpp LiveVariables.cpp - LLVMTargetMachine.cpp LocalStackSlotAllocation.cpp - LowLevelType.cpp - LowerEmuTLS.cpp MachineBasicBlock.cpp MachineBlockFrequencyInfo.cpp MachineBlockPlacement.cpp MachineBranchProbabilityInfo.cpp + MachineCSE.cpp MachineCombiner.cpp MachineCopyPropagation.cpp - MachineCSE.cpp - MachineDominanceFrontier.cpp MachineDominators.cpp - MachineFrameInfo.cpp + MachineDominanceFrontier.cpp MachineFunction.cpp + MachineFunctionAnalysis.cpp MachineFunctionPass.cpp MachineFunctionPrinterPass.cpp - MachineInstrBundle.cpp MachineInstr.cpp + MachineInstrBundle.cpp MachineLICM.cpp MachineLoopInfo.cpp MachineModuleInfo.cpp MachineModuleInfoImpls.cpp - MachineOperand.cpp - MachineOptimizationRemarkEmitter.cpp - MachineOutliner.cpp MachinePassRegistry.cpp - MachinePipeliner.cpp MachinePostDominators.cpp - MachineRegionInfo.cpp MachineRegisterInfo.cpp + MachineRegionInfo.cpp + MachineSSAUpdater.cpp MachineScheduler.cpp MachineSink.cpp - MachineSSAUpdater.cpp MachineTraceMetrics.cpp MachineVerifier.cpp - PatchableFunction.cpp MIRPrinter.cpp MIRPrintingPass.cpp - MacroFusion.cpp + OcamlGC.cpp OptimizePHIs.cpp - ParallelCG.cpp - PeepholeOptimizer.cpp PHIElimination.cpp PHIEliminationUtils.cpp - PostRAHazardRecognizer.cpp + ParallelCG.cpp + Passes.cpp + PeepholeOptimizer.cpp PostRASchedulerList.cpp - PreISelIntrinsicLowering.cpp ProcessImplicitDefs.cpp PrologEpilogInserter.cpp PseudoSourceValue.cpp @@ -114,59 +103,45 @@ add_llvm_library(LLVMCodeGen RegisterCoalescer.cpp RegisterPressure.cpp RegisterScavenging.cpp - RenameIndependentSubregs.cpp - MIRCanonicalizerPass.cpp - RegisterUsageInfo.cpp - RegUsageInfoCollector.cpp - RegUsageInfoPropagate.cpp - ResetMachineFunctionPass.cpp - SafeStack.cpp - SafeStackColoring.cpp - SafeStackLayout.cpp - ScalarizeMaskedMemIntrin.cpp ScheduleDAG.cpp ScheduleDAGInstrs.cpp ScheduleDAGPrinter.cpp ScoreboardHazardRecognizer.cpp - ShadowStackGCLowering.cpp ShrinkWrap.cpp + ShadowStackGC.cpp + ShadowStackGCLowering.cpp SjLjEHPrepare.cpp SlotIndexes.cpp SpillPlacement.cpp SplitKit.cpp StackColoring.cpp - StackMapLivenessAnalysis.cpp - StackMaps.cpp StackProtector.cpp StackSlotColoring.cpp + StackMapLivenessAnalysis.cpp + StackMaps.cpp + StatepointExampleGC.cpp TailDuplication.cpp - TailDuplicator.cpp TargetFrameLoweringImpl.cpp TargetInstrInfo.cpp TargetLoweringBase.cpp TargetLoweringObjectFileImpl.cpp TargetOptionsImpl.cpp - TargetPassConfig.cpp TargetRegisterInfo.cpp TargetSchedule.cpp - TargetSubtargetInfo.cpp TwoAddressInstructionPass.cpp UnreachableBlockElim.cpp VirtRegMap.cpp WinEHPrepare.cpp - XRayInstrumentation.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen ${LLVM_MAIN_INCLUDE_DIR}/llvm/CodeGen/PBQP - LINK_LIBS ${LLVM_PTHREAD_LIB} - - DEPENDS - intrinsics_gen + LINK_LIBS ${system_libs} ) +add_dependencies(LLVMCodeGen intrinsics_gen) + add_subdirectory(SelectionDAG) add_subdirectory(AsmPrinter) add_subdirectory(MIRParser) -add_subdirectory(GlobalISel) diff --git a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp index a8d8ad8ac7d..939c50027b0 100644 --- a/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp +++ b/gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp @@ -1,4 +1,4 @@ -//===- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function ---===// +//===-- PrologEpilogInserter.cpp - Insert Prolog/Epilog code in function --===// // // The LLVM Compiler Infrastructure // @@ -16,72 +16,43 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/BitVector.h" -#include "llvm/ADT/DepthFirstIterator.h" +#include "llvm/ADT/IndexedMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" -#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" -#include "llvm/Analysis/OptimizationRemarkEmitter.h" -#include "llvm/CodeGen/MachineBasicBlock.h" #include "llvm/CodeGen/MachineDominators.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineModuleInfo.h" -#include "llvm/CodeGen/MachineOperand.h" -#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/CodeGen/StackProtector.h" -#include "llvm/CodeGen/TargetFrameLowering.h" -#include "llvm/CodeGen/TargetInstrInfo.h" -#include "llvm/CodeGen/TargetOpcodes.h" -#include "llvm/CodeGen/TargetRegisterInfo.h" -#include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/CodeGen/WinEHFuncInfo.h" -#include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" -#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/Function.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/LLVMContext.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/Pass.h" -#include "llvm/Support/CodeGen.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetFrameLowering.h" +#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" -#include "llvm/Target/TargetOptions.h" -#include <algorithm> -#include <cassert> -#include <cstdint> -#include <functional> -#include <limits> -#include <utility> -#include <vector> +#include "llvm/Target/TargetRegisterInfo.h" +#include "llvm/Target/TargetSubtargetInfo.h" +#include <climits> using namespace llvm; -#define DEBUG_TYPE "prologepilog" - -using MBBVector = SmallVector<MachineBasicBlock *, 4>; +#define DEBUG_TYPE "pei" namespace { - class PEI : public MachineFunctionPass { public: static char ID; - PEI() : MachineFunctionPass(ID) { initializePEIPass(*PassRegistry::getPassRegistry()); } @@ -90,6 +61,7 @@ public: /// runOnMachineFunction - Insert prolog/epilog code and replace abstract /// frame indexes with appropriate references. + /// bool runOnMachineFunction(MachineFunction &Fn) override; private: @@ -97,41 +69,33 @@ private: // MinCSFrameIndex, MaxCSFrameIndex - Keeps the range of callee saved // stack frame indexes. - unsigned MinCSFrameIndex = std::numeric_limits<unsigned>::max(); - unsigned MaxCSFrameIndex = 0; + unsigned MinCSFrameIndex, MaxCSFrameIndex; // Save and Restore blocks of the current function. Typically there is a // single save block, unless Windows EH funclets are involved. - MBBVector SaveBlocks; - MBBVector RestoreBlocks; + SmallVector<MachineBasicBlock *, 1> SaveBlocks; + SmallVector<MachineBasicBlock *, 4> RestoreBlocks; // Flag to control whether to use the register scavenger to resolve // frame index materialization registers. Set according to // TRI->requiresFrameIndexScavenging() for the current function. bool FrameIndexVirtualScavenging; - // Flag to control whether the scavenger should be passed even though - // FrameIndexVirtualScavenging is used. - bool FrameIndexEliminationScavenging; - - // Emit remarks. - MachineOptimizationRemarkEmitter *ORE = nullptr; - - void calculateCallFrameInfo(MachineFunction &Fn); - void calculateSaveRestoreBlocks(MachineFunction &Fn); - void spillCalleeSavedRegs(MachineFunction &MF); - + void calculateSets(MachineFunction &Fn); + void calculateCallsInformation(MachineFunction &Fn); + void assignCalleeSavedSpillSlots(MachineFunction &Fn, + const BitVector &SavedRegs); + void insertCSRSpillsAndRestores(MachineFunction &Fn); void calculateFrameObjectOffsets(MachineFunction &Fn); void replaceFrameIndices(MachineFunction &Fn); void replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, int &SPAdj); + void scavengeFrameVirtualRegs(MachineFunction &Fn); void insertPrologEpilogCode(MachineFunction &Fn); }; - -} // end anonymous namespace +} // namespace char PEI::ID = 0; - char &llvm::PrologEpilogCodeInserterID = PEI::ID; static cl::opt<unsigned> @@ -139,20 +103,17 @@ WarnStackSize("warn-stack-size", cl::Hidden, cl::init((unsigned)-1), cl::desc("Warn for stack size bigger than the given" " number")); -INITIALIZE_PASS_BEGIN(PEI, DEBUG_TYPE, "Prologue/Epilogue Insertion", false, - false) +INITIALIZE_PASS_BEGIN(PEI, "prologepilog", + "Prologue/Epilogue Insertion", false, false) INITIALIZE_PASS_DEPENDENCY(MachineLoopInfo) INITIALIZE_PASS_DEPENDENCY(MachineDominatorTree) INITIALIZE_PASS_DEPENDENCY(StackProtector) -INITIALIZE_PASS_DEPENDENCY(MachineOptimizationRemarkEmitterPass) -INITIALIZE_PASS_END(PEI, DEBUG_TYPE, - "Prologue/Epilogue Insertion & Frame Finalization", false, - false) - -MachineFunctionPass *llvm::createPrologEpilogInserterPass() { - return new PEI(); -} +INITIALIZE_PASS_DEPENDENCY(TargetPassConfig) +INITIALIZE_PASS_END(PEI, "prologepilog", + "Prologue/Epilogue Insertion & Frame Finalization", + false, false) +STATISTIC(NumScavengedRegs, "Number of frame index regs scavenged"); STATISTIC(NumBytesStackSpace, "Number of bytes used for stack in all functions"); @@ -161,38 +122,76 @@ void PEI::getAnalysisUsage(AnalysisUsage &AU) const { AU.addPreserved<MachineLoopInfo>(); AU.addPreserved<MachineDominatorTree>(); AU.addRequired<StackProtector>(); - AU.addRequired<MachineOptimizationRemarkEmitterPass>(); + AU.addRequired<TargetPassConfig>(); MachineFunctionPass::getAnalysisUsage(AU); } +/// Compute the set of return blocks +void PEI::calculateSets(MachineFunction &Fn) { + const MachineFrameInfo *MFI = Fn.getFrameInfo(); + + // Even when we do not change any CSR, we still want to insert the + // prologue and epilogue of the function. + // So set the save points for those. + + // Use the points found by shrink-wrapping, if any. + if (MFI->getSavePoint()) { + SaveBlocks.push_back(MFI->getSavePoint()); + assert(MFI->getRestorePoint() && "Both restore and save must be set"); + MachineBasicBlock *RestoreBlock = MFI->getRestorePoint(); + // If RestoreBlock does not have any successor and is not a return block + // then the end point is unreachable and we do not need to insert any + // epilogue. + if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) + RestoreBlocks.push_back(RestoreBlock); + return; + } + + // Save refs to entry and return blocks. + SaveBlocks.push_back(&Fn.front()); + for (MachineBasicBlock &MBB : Fn) { + if (MBB.isEHFuncletEntry()) + SaveBlocks.push_back(&MBB); + if (MBB.isReturnBlock()) + RestoreBlocks.push_back(&MBB); + } +} + /// StackObjSet - A set of stack object indexes -using StackObjSet = SmallSetVector<int, 8>; +typedef SmallSetVector<int, 8> StackObjSet; /// runOnMachineFunction - Insert prolog/epilog code and replace abstract /// frame indexes with appropriate references. +/// bool PEI::runOnMachineFunction(MachineFunction &Fn) { - const Function &F = Fn.getFunction(); + const Function* F = Fn.getFunction(); const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); + assert(!Fn.getRegInfo().getNumVirtRegs() && "Regalloc must assign all vregs"); + RS = TRI->requiresRegisterScavenging(Fn) ? new RegScavenger() : nullptr; FrameIndexVirtualScavenging = TRI->requiresFrameIndexScavenging(Fn); - FrameIndexEliminationScavenging = (RS && !FrameIndexVirtualScavenging) || - TRI->requiresFrameIndexReplacementScavenging(Fn); - ORE = &getAnalysis<MachineOptimizationRemarkEmitterPass>().getORE(); // Calculate the MaxCallFrameSize and AdjustsStack variables for the // function's frame information. Also eliminates call frame pseudo // instructions. - calculateCallFrameInfo(Fn); + calculateCallsInformation(Fn); - // Determine placement of CSR spill/restore code and prolog/epilog code: + // Determine which of the registers in the callee save list should be saved. + BitVector SavedRegs; + TFI->determineCalleeSaves(Fn, SavedRegs, RS); + + // Insert spill code for any callee saved registers that are modified. + assignCalleeSavedSpillSlots(Fn, SavedRegs); + + // Determine placement of CSR spill/restore code: // place all spills in the entry block, all restores in return blocks. - calculateSaveRestoreBlocks(Fn); + calculateSets(Fn); - // Handle CSR spilling and restoring, for targets that need it. - if (Fn.getTarget().usesPhysRegsForPEI()) - spillCalleeSavedRegs(Fn); + // Add the code to save and restore the callee saved registers. + if (!F->hasFnAttribute(Attribute::Naked)) + insertCSRSpillsAndRestores(Fn); // Allow the target machine to make final modifications to the function // before the frame layout is finalized. @@ -206,7 +205,7 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { // called functions. Because of this, calculateCalleeSavedRegisters() // must be called before this function in order to set the AdjustsStack // and MaxCallFrameSize variables. - if (!F.hasFnAttribute(Attribute::Naked)) + if (!F->hasFnAttribute(Attribute::Naked)) insertPrologEpilogCode(Fn); // Replace all MO_FrameIndex operands with physical register references @@ -218,34 +217,35 @@ bool PEI::runOnMachineFunction(MachineFunction &Fn) { // post-pass, scavenge the virtual registers that frame index elimination // inserted. if (TRI->requiresRegisterScavenging(Fn) && FrameIndexVirtualScavenging) - scavengeFrameVirtualRegs(Fn, *RS); + scavengeFrameVirtualRegs(Fn); + + // Clear any vregs created by virtual scavenging. + Fn.getRegInfo().clearVirtRegs(); // Warn on stack size when we exceeds the given limit. - MachineFrameInfo &MFI = Fn.getFrameInfo(); - uint64_t StackSize = MFI.getStackSize(); + MachineFrameInfo *MFI = Fn.getFrameInfo(); + uint64_t StackSize = MFI->getStackSize(); if (WarnStackSize.getNumOccurrences() > 0 && WarnStackSize < StackSize) { - DiagnosticInfoStackSize DiagStackSize(F, StackSize); - F.getContext().diagnose(DiagStackSize); + DiagnosticInfoStackSize DiagStackSize(*F, StackSize); + F->getContext().diagnose(DiagStackSize); } delete RS; SaveBlocks.clear(); RestoreBlocks.clear(); - MFI.setSavePoint(nullptr); - MFI.setRestorePoint(nullptr); return true; } -/// Calculate the MaxCallFrameSize and AdjustsStack +/// calculateCallsInformation - Calculate the MaxCallFrameSize and AdjustsStack /// variables for the function's frame information and eliminate call frame /// pseudo instructions. -void PEI::calculateCallFrameInfo(MachineFunction &Fn) { +void PEI::calculateCallsInformation(MachineFunction &Fn) { const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - MachineFrameInfo &MFI = Fn.getFrameInfo(); + MachineFrameInfo *MFI = Fn.getFrameInfo(); unsigned MaxCallFrameSize = 0; - bool AdjustsStack = MFI.adjustsStack(); + bool AdjustsStack = MFI->adjustsStack(); // Get the function call frame set-up and tear-down instruction opcode unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); @@ -259,8 +259,11 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) { std::vector<MachineBasicBlock::iterator> FrameSDOps; for (MachineFunction::iterator BB = Fn.begin(), E = Fn.end(); BB != E; ++BB) for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ++I) - if (TII.isFrameInstr(*I)) { - unsigned Size = TII.getFrameSize(*I); + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { + assert(I->getNumOperands() >= 1 && "Call Frame Setup/Destroy Pseudo" + " instructions should have a single immediate argument!"); + unsigned Size = I->getOperand(0).getImm(); if (Size > MaxCallFrameSize) MaxCallFrameSize = Size; AdjustsStack = true; FrameSDOps.push_back(I); @@ -271,11 +274,8 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) { AdjustsStack = true; } - assert(!MFI.isMaxCallFrameSizeComputed() || - (MFI.getMaxCallFrameSize() == MaxCallFrameSize && - MFI.adjustsStack() == AdjustsStack)); - MFI.setAdjustsStack(AdjustsStack); - MFI.setMaxCallFrameSize(MaxCallFrameSize); + MFI->setAdjustsStack(AdjustsStack); + MFI->setMaxCallFrameSize(MaxCallFrameSize); for (std::vector<MachineBasicBlock::iterator>::iterator i = FrameSDOps.begin(), e = FrameSDOps.end(); i != e; ++i) { @@ -290,47 +290,17 @@ void PEI::calculateCallFrameInfo(MachineFunction &Fn) { } } -/// Compute the sets of entry and return blocks for saving and restoring -/// callee-saved registers, and placing prolog and epilog code. -void PEI::calculateSaveRestoreBlocks(MachineFunction &Fn) { - const MachineFrameInfo &MFI = Fn.getFrameInfo(); - - // Even when we do not change any CSR, we still want to insert the - // prologue and epilogue of the function. - // So set the save points for those. - - // Use the points found by shrink-wrapping, if any. - if (MFI.getSavePoint()) { - SaveBlocks.push_back(MFI.getSavePoint()); - assert(MFI.getRestorePoint() && "Both restore and save must be set"); - MachineBasicBlock *RestoreBlock = MFI.getRestorePoint(); - // If RestoreBlock does not have any successor and is not a return block - // then the end point is unreachable and we do not need to insert any - // epilogue. - if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock()) - RestoreBlocks.push_back(RestoreBlock); - return; - } - - // Save refs to entry and return blocks. - SaveBlocks.push_back(&Fn.front()); - for (MachineBasicBlock &MBB : Fn) { - if (MBB.isEHFuncletEntry()) - SaveBlocks.push_back(&MBB); - if (MBB.isReturnBlock()) - RestoreBlocks.push_back(&MBB); - } -} +void PEI::assignCalleeSavedSpillSlots(MachineFunction &F, + const BitVector &SavedRegs) { + // These are used to keep track the callee-save area. Initialize them. + MinCSFrameIndex = INT_MAX; + MaxCSFrameIndex = 0; -static void assignCalleeSavedSpillSlots(MachineFunction &F, - const BitVector &SavedRegs, - unsigned &MinCSFrameIndex, - unsigned &MaxCSFrameIndex) { if (SavedRegs.empty()) return; const TargetRegisterInfo *RegInfo = F.getSubtarget().getRegisterInfo(); - const MCPhysReg *CSRegs = F.getRegInfo().getCalleeSavedRegs(); + const MCPhysReg *CSRegs = RegInfo->getCalleeSavedRegs(&F); std::vector<CalleeSavedInfo> CSI; for (unsigned i = 0; CSRegs[i]; ++i) { @@ -340,7 +310,7 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, } const TargetFrameLowering *TFI = F.getSubtarget().getFrameLowering(); - MachineFrameInfo &MFI = F.getFrameInfo(); + MachineFrameInfo *MFI = F.getFrameInfo(); if (!TFI->assignCalleeSavedSpillSlots(F, RegInfo, CSI)) { // If target doesn't implement this, use generic code. @@ -353,13 +323,14 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, // Now that we know which registers need to be saved and restored, allocate // stack slots for them. - for (auto &CS : CSI) { - unsigned Reg = CS.getReg(); + for (std::vector<CalleeSavedInfo>::iterator I = CSI.begin(), E = CSI.end(); + I != E; ++I) { + unsigned Reg = I->getReg(); const TargetRegisterClass *RC = RegInfo->getMinimalPhysRegClass(Reg); int FrameIdx; if (RegInfo->hasReservedSpillSlot(F, Reg, FrameIdx)) { - CS.setFrameIdx(FrameIdx); + I->setFrameIdx(FrameIdx); continue; } @@ -370,35 +341,35 @@ static void assignCalleeSavedSpillSlots(MachineFunction &F, FixedSlot->Reg != Reg) ++FixedSlot; - unsigned Size = RegInfo->getSpillSize(*RC); if (FixedSlot == FixedSpillSlots + NumFixedSpillSlots) { // Nope, just spill it anywhere convenient. - unsigned Align = RegInfo->getSpillAlignment(*RC); + unsigned Align = RC->getAlignment(); unsigned StackAlign = TFI->getStackAlignment(); // We may not be able to satisfy the desired alignment specification of // the TargetRegisterClass if the stack alignment is smaller. Use the // min. Align = std::min(Align, StackAlign); - FrameIdx = MFI.CreateStackObject(Size, Align, true); + FrameIdx = MFI->CreateStackObject(RC->getSize(), Align, true); if ((unsigned)FrameIdx < MinCSFrameIndex) MinCSFrameIndex = FrameIdx; if ((unsigned)FrameIdx > MaxCSFrameIndex) MaxCSFrameIndex = FrameIdx; } else { // Spill it to the stack where we must. - FrameIdx = MFI.CreateFixedSpillStackObject(Size, FixedSlot->Offset); + FrameIdx = + MFI->CreateFixedSpillStackObject(RC->getSize(), FixedSlot->Offset); } - CS.setFrameIdx(FrameIdx); + I->setFrameIdx(FrameIdx); } } - MFI.setCalleeSavedInfo(CSI); + MFI->setCalleeSavedInfo(CSI); } /// Helper function to update the liveness information for the callee-saved /// registers. static void updateLiveness(MachineFunction &MF) { - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); // Visited will contain all the basic blocks that are in the region // where the callee saved registers are alive: // - Anything that is not Save or Restore -> LiveThrough. @@ -409,7 +380,7 @@ static void updateLiveness(MachineFunction &MF) { SmallPtrSet<MachineBasicBlock *, 8> Visited; SmallVector<MachineBasicBlock *, 8> WorkList; MachineBasicBlock *Entry = &MF.front(); - MachineBasicBlock *Save = MFI.getSavePoint(); + MachineBasicBlock *Save = MFI->getSavePoint(); if (!Save) Save = Entry; @@ -420,7 +391,7 @@ static void updateLiveness(MachineFunction &MF) { } Visited.insert(Save); - MachineBasicBlock *Restore = MFI.getRestorePoint(); + MachineBasicBlock *Restore = MFI->getRestorePoint(); if (Restore) // By construction Restore cannot be visited, otherwise it // means there exists a path to Restore that does not go @@ -440,239 +411,125 @@ static void updateLiveness(MachineFunction &MF) { WorkList.push_back(SuccBB); } - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - MachineRegisterInfo &MRI = MF.getRegInfo(); for (unsigned i = 0, e = CSI.size(); i != e; ++i) { for (MachineBasicBlock *MBB : Visited) { MCPhysReg Reg = CSI[i].getReg(); // Add the callee-saved register as live-in. // It's killed at the spill. - if (!MRI.isReserved(Reg) && !MBB->isLiveIn(Reg)) + if (!MBB->isLiveIn(Reg)) MBB->addLiveIn(Reg); } } } -/// Insert restore code for the callee-saved registers used in the function. -static void insertCSRSaves(MachineBasicBlock &SaveBlock, - ArrayRef<CalleeSavedInfo> CSI) { - MachineFunction &Fn = *SaveBlock.getParent(); - const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); +/// insertCSRSpillsAndRestores - Insert spill and restore code for +/// callee saved registers used in the function. +/// +void PEI::insertCSRSpillsAndRestores(MachineFunction &Fn) { + // Get callee saved register information. + MachineFrameInfo *MFI = Fn.getFrameInfo(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); - MachineBasicBlock::iterator I = SaveBlock.begin(); - if (!TFI->spillCalleeSavedRegisters(SaveBlock, I, CSI, TRI)) { - for (const CalleeSavedInfo &CS : CSI) { - // Insert the spill to the stack frame. - unsigned Reg = CS.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(SaveBlock, I, Reg, true, CS.getFrameIdx(), RC, - TRI); - } - } -} + MFI->setCalleeSavedInfoValid(true); + + // Early exit if no callee saved registers are modified! + if (CSI.empty()) + return; -/// Insert restore code for the callee-saved registers used in the function. -static void insertCSRRestores(MachineBasicBlock &RestoreBlock, - std::vector<CalleeSavedInfo> &CSI) { - MachineFunction &Fn = *RestoreBlock.getParent(); const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); const TargetRegisterInfo *TRI = Fn.getSubtarget().getRegisterInfo(); - - // Restore all registers immediately before the return and any - // terminators that precede it. - MachineBasicBlock::iterator I = RestoreBlock.getFirstTerminator(); - - if (!TFI->restoreCalleeSavedRegisters(RestoreBlock, I, CSI, TRI)) { - for (const CalleeSavedInfo &CI : reverse(CSI)) { - unsigned Reg = CI.getReg(); - const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.loadRegFromStackSlot(RestoreBlock, I, Reg, CI.getFrameIdx(), RC, TRI); - assert(I != RestoreBlock.begin() && - "loadRegFromStackSlot didn't insert any code!"); - // Insert in reverse order. loadRegFromStackSlot can insert - // multiple instructions. + MachineBasicBlock::iterator I; + + // Spill using target interface. + for (MachineBasicBlock *SaveBlock : SaveBlocks) { + I = SaveBlock->begin(); + if (!TFI->spillCalleeSavedRegisters(*SaveBlock, I, CSI, TRI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + // Insert the spill to the stack frame. + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.storeRegToStackSlot(*SaveBlock, I, Reg, true, CSI[i].getFrameIdx(), + RC, TRI); + } } + // Update the live-in information of all the blocks up to the save point. + updateLiveness(Fn); } -} - -void PEI::spillCalleeSavedRegs(MachineFunction &Fn) { - // We can't list this requirement in getRequiredProperties because some - // targets (WebAssembly) use virtual registers past this point, and the pass - // pipeline is set up without giving the passes a chance to look at the - // TargetMachine. - // FIXME: Find a way to express this in getRequiredProperties. - assert(Fn.getProperties().hasProperty( - MachineFunctionProperties::Property::NoVRegs)); - - const Function &F = Fn.getFunction(); - const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); - MachineFrameInfo &MFI = Fn.getFrameInfo(); - MinCSFrameIndex = std::numeric_limits<unsigned>::max(); - MaxCSFrameIndex = 0; - - // Determine which of the registers in the callee save list should be saved. - BitVector SavedRegs; - TFI->determineCalleeSaves(Fn, SavedRegs, RS); - // Assign stack slots for any callee-saved registers that must be spilled. - assignCalleeSavedSpillSlots(Fn, SavedRegs, MinCSFrameIndex, MaxCSFrameIndex); - - // Add the code to save and restore the callee saved registers. - if (!F.hasFnAttribute(Attribute::Naked)) { - MFI.setCalleeSavedInfoValid(true); - - std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); - if (!CSI.empty()) { - for (MachineBasicBlock *SaveBlock : SaveBlocks) { - insertCSRSaves(*SaveBlock, CSI); - // Update the live-in information of all the blocks up to the save - // point. - updateLiveness(Fn); + // Restore using target interface. + for (MachineBasicBlock *MBB : RestoreBlocks) { + I = MBB->end(); + + // Skip over all terminator instructions, which are part of the return + // sequence. + MachineBasicBlock::iterator I2 = I; + while (I2 != MBB->begin() && (--I2)->isTerminator()) + I = I2; + + bool AtStart = I == MBB->begin(); + MachineBasicBlock::iterator BeforeI = I; + if (!AtStart) + --BeforeI; + + // Restore all registers immediately before the return and any + // terminators that precede it. + if (!TFI->restoreCalleeSavedRegisters(*MBB, I, CSI, TRI)) { + for (unsigned i = 0, e = CSI.size(); i != e; ++i) { + unsigned Reg = CSI[i].getReg(); + const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); + TII.loadRegFromStackSlot(*MBB, I, Reg, CSI[i].getFrameIdx(), RC, TRI); + assert(I != MBB->begin() && + "loadRegFromStackSlot didn't insert any code!"); + // Insert in reverse order. loadRegFromStackSlot can insert + // multiple instructions. + if (AtStart) + I = MBB->begin(); + else { + I = BeforeI; + ++I; + } } - for (MachineBasicBlock *RestoreBlock : RestoreBlocks) - insertCSRRestores(*RestoreBlock, CSI); } } } /// AdjustStackOffset - Helper function used to adjust the stack frame offset. static inline void -AdjustStackOffset(MachineFrameInfo &MFI, int FrameIdx, +AdjustStackOffset(MachineFrameInfo *MFI, int FrameIdx, bool StackGrowsDown, int64_t &Offset, unsigned &MaxAlign, unsigned Skew) { // If the stack grows down, add the object size to find the lowest address. if (StackGrowsDown) - Offset += MFI.getObjectSize(FrameIdx); + Offset += MFI->getObjectSize(FrameIdx); - unsigned Align = MFI.getObjectAlignment(FrameIdx); + unsigned Align = MFI->getObjectAlignment(FrameIdx); // If the alignment of this object is greater than that of the stack, then // increase the stack alignment to match. MaxAlign = std::max(MaxAlign, Align); // Adjust to alignment boundary. - Offset = alignTo(Offset, Align, Skew); + Offset = RoundUpToAlignment(Offset, Align, Skew); if (StackGrowsDown) { DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << -Offset << "]\n"); - MFI.setObjectOffset(FrameIdx, -Offset); // Set the computed offset + MFI->setObjectOffset(FrameIdx, -Offset); // Set the computed offset } else { DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") at SP[" << Offset << "]\n"); - MFI.setObjectOffset(FrameIdx, Offset); - Offset += MFI.getObjectSize(FrameIdx); - } -} - -/// Compute which bytes of fixed and callee-save stack area are unused and keep -/// track of them in StackBytesFree. -static inline void -computeFreeStackSlots(MachineFrameInfo &MFI, bool StackGrowsDown, - unsigned MinCSFrameIndex, unsigned MaxCSFrameIndex, - int64_t FixedCSEnd, BitVector &StackBytesFree) { - // Avoid undefined int64_t -> int conversion below in extreme case. - if (FixedCSEnd > std::numeric_limits<int>::max()) - return; - - StackBytesFree.resize(FixedCSEnd, true); - - SmallVector<int, 16> AllocatedFrameSlots; - // Add fixed objects. - for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) - AllocatedFrameSlots.push_back(i); - // Add callee-save objects. - for (int i = MinCSFrameIndex; i <= (int)MaxCSFrameIndex; ++i) - AllocatedFrameSlots.push_back(i); - - for (int i : AllocatedFrameSlots) { - // These are converted from int64_t, but they should always fit in int - // because of the FixedCSEnd check above. - int ObjOffset = MFI.getObjectOffset(i); - int ObjSize = MFI.getObjectSize(i); - int ObjStart, ObjEnd; - if (StackGrowsDown) { - // ObjOffset is negative when StackGrowsDown is true. - ObjStart = -ObjOffset - ObjSize; - ObjEnd = -ObjOffset; - } else { - ObjStart = ObjOffset; - ObjEnd = ObjOffset + ObjSize; - } - // Ignore fixed holes that are in the previous stack frame. - if (ObjEnd > 0) - StackBytesFree.reset(ObjStart, ObjEnd); + MFI->setObjectOffset(FrameIdx, Offset); + Offset += MFI->getObjectSize(FrameIdx); } } -/// Assign frame object to an unused portion of the stack in the fixed stack -/// object range. Return true if the allocation was successful. -static inline bool scavengeStackSlot(MachineFrameInfo &MFI, int FrameIdx, - bool StackGrowsDown, unsigned MaxAlign, - BitVector &StackBytesFree) { - if (MFI.isVariableSizedObjectIndex(FrameIdx)) - return false; - - if (StackBytesFree.none()) { - // clear it to speed up later scavengeStackSlot calls to - // StackBytesFree.none() - StackBytesFree.clear(); - return false; - } - - unsigned ObjAlign = MFI.getObjectAlignment(FrameIdx); - if (ObjAlign > MaxAlign) - return false; - - int64_t ObjSize = MFI.getObjectSize(FrameIdx); - int FreeStart; - for (FreeStart = StackBytesFree.find_first(); FreeStart != -1; - FreeStart = StackBytesFree.find_next(FreeStart)) { - - // Check that free space has suitable alignment. - unsigned ObjStart = StackGrowsDown ? FreeStart + ObjSize : FreeStart; - if (alignTo(ObjStart, ObjAlign) != ObjStart) - continue; - - if (FreeStart + ObjSize > StackBytesFree.size()) - return false; - - bool AllBytesFree = true; - for (unsigned Byte = 0; Byte < ObjSize; ++Byte) - if (!StackBytesFree.test(FreeStart + Byte)) { - AllBytesFree = false; - break; - } - if (AllBytesFree) - break; - } - - if (FreeStart == -1) - return false; - - if (StackGrowsDown) { - int ObjStart = -(FreeStart + ObjSize); - DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") scavenged at SP[" << ObjStart - << "]\n"); - MFI.setObjectOffset(FrameIdx, ObjStart); - } else { - DEBUG(dbgs() << "alloc FI(" << FrameIdx << ") scavenged at SP[" << FreeStart - << "]\n"); - MFI.setObjectOffset(FrameIdx, FreeStart); - } - - StackBytesFree.reset(FreeStart, FreeStart + ObjSize); - return true; -} - /// AssignProtectedObjSet - Helper function to assign large stack objects (i.e., /// those required to be close to the Stack Protector) to stack offsets. static void AssignProtectedObjSet(const StackObjSet &UnassignedObjs, SmallSet<int, 16> &ProtectedObjs, - MachineFrameInfo &MFI, bool StackGrowsDown, + MachineFrameInfo *MFI, bool StackGrowsDown, int64_t &Offset, unsigned &MaxAlign, unsigned Skew) { for (StackObjSet::const_iterator I = UnassignedObjs.begin(), @@ -685,6 +542,7 @@ AssignProtectedObjSet(const StackObjSet &UnassignedObjs, /// calculateFrameObjectOffsets - Calculate actual frame offsets for all of the /// abstract stack objects. +/// void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); StackProtector *SP = &getAnalysis<StackProtector>(); @@ -693,7 +551,7 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; // Loop over all of the stack objects, assigning sequential addresses... - MachineFrameInfo &MFI = Fn.getFrameInfo(); + MachineFrameInfo *MFI = Fn.getFrameInfo(); // Start at the beginning of the local area. // The Offset is the distance from the stack top in the direction @@ -710,19 +568,20 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // If there are fixed sized objects that are preallocated in the local area, // non-fixed objects can't be allocated right at the start of local area. - // Adjust 'Offset' to point to the end of last fixed sized preallocated - // object. - for (int i = MFI.getObjectIndexBegin(); i != 0; ++i) { + // We currently don't support filling in holes in between fixed sized + // objects, so we adjust 'Offset' to point to the end of last fixed sized + // preallocated object. + for (int i = MFI->getObjectIndexBegin(); i != 0; ++i) { int64_t FixedOff; if (StackGrowsDown) { // The maximum distance from the stack pointer is at lower address of // the object -- which is given by offset. For down growing stack // the offset is negative, so we negate the offset to get the distance. - FixedOff = -MFI.getObjectOffset(i); + FixedOff = -MFI->getObjectOffset(i); } else { // The maximum distance from the start pointer is at the upper // address of the object. - FixedOff = MFI.getObjectOffset(i) + MFI.getObjectSize(i); + FixedOff = MFI->getObjectOffset(i) + MFI->getObjectSize(i); } if (FixedOff > Offset) Offset = FixedOff; } @@ -733,35 +592,27 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { for (unsigned i = MinCSFrameIndex; i <= MaxCSFrameIndex; ++i) { // If the stack grows down, we need to add the size to find the lowest // address of the object. - Offset += MFI.getObjectSize(i); + Offset += MFI->getObjectSize(i); - unsigned Align = MFI.getObjectAlignment(i); + unsigned Align = MFI->getObjectAlignment(i); // Adjust to alignment boundary - Offset = alignTo(Offset, Align, Skew); + Offset = RoundUpToAlignment(Offset, Align, Skew); - DEBUG(dbgs() << "alloc FI(" << i << ") at SP[" << -Offset << "]\n"); - MFI.setObjectOffset(i, -Offset); // Set the computed offset + MFI->setObjectOffset(i, -Offset); // Set the computed offset } - } else if (MaxCSFrameIndex >= MinCSFrameIndex) { - // Be careful about underflow in comparisons agains MinCSFrameIndex. - for (unsigned i = MaxCSFrameIndex; i != MinCSFrameIndex - 1; --i) { - if (MFI.isDeadObjectIndex(i)) - continue; - - unsigned Align = MFI.getObjectAlignment(i); + } else { + int MaxCSFI = MaxCSFrameIndex, MinCSFI = MinCSFrameIndex; + for (int i = MaxCSFI; i >= MinCSFI ; --i) { + unsigned Align = MFI->getObjectAlignment(i); // Adjust to alignment boundary - Offset = alignTo(Offset, Align, Skew); + Offset = RoundUpToAlignment(Offset, Align, Skew); - DEBUG(dbgs() << "alloc FI(" << i << ") at SP[" << Offset << "]\n"); - MFI.setObjectOffset(i, Offset); - Offset += MFI.getObjectSize(i); + MFI->setObjectOffset(i, Offset); + Offset += MFI->getObjectSize(i); } } - // FixedCSEnd is the stack offset to the end of the fixed and callee-save - // stack area. - int64_t FixedCSEnd = Offset; - unsigned MaxAlign = MFI.getMaxAlignment(); + unsigned MaxAlign = MFI->getMaxAlignment(); // Make sure the special register scavenging spill slot is closest to the // incoming stack pointer if a frame pointer is required and is closer @@ -783,60 +634,54 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // check for whether the frame is large enough to want to use virtual // frame index registers. Functions which don't want/need this optimization // will continue to use the existing code path. - if (MFI.getUseLocalStackAllocationBlock()) { - unsigned Align = MFI.getLocalFrameMaxAlign(); + if (MFI->getUseLocalStackAllocationBlock()) { + unsigned Align = MFI->getLocalFrameMaxAlign(); // Adjust to alignment boundary. - Offset = alignTo(Offset, Align, Skew); + Offset = RoundUpToAlignment(Offset, Align, Skew); DEBUG(dbgs() << "Local frame base offset: " << Offset << "\n"); // Resolve offsets for objects in the local block. - for (unsigned i = 0, e = MFI.getLocalFrameObjectCount(); i != e; ++i) { - std::pair<int, int64_t> Entry = MFI.getLocalFrameObjectMap(i); + for (unsigned i = 0, e = MFI->getLocalFrameObjectCount(); i != e; ++i) { + std::pair<int, int64_t> Entry = MFI->getLocalFrameObjectMap(i); int64_t FIOffset = (StackGrowsDown ? -Offset : Offset) + Entry.second; DEBUG(dbgs() << "alloc FI(" << Entry.first << ") at SP[" << FIOffset << "]\n"); - MFI.setObjectOffset(Entry.first, FIOffset); + MFI->setObjectOffset(Entry.first, FIOffset); } // Allocate the local block - Offset += MFI.getLocalFrameSize(); + Offset += MFI->getLocalFrameSize(); MaxAlign = std::max(Align, MaxAlign); } - // Retrieve the Exception Handler registration node. - int EHRegNodeFrameIndex = std::numeric_limits<int>::max(); - if (const WinEHFuncInfo *FuncInfo = Fn.getWinEHFuncInfo()) - EHRegNodeFrameIndex = FuncInfo->EHRegNodeFrameIndex; - // Make sure that the stack protector comes before the local variables on the // stack. SmallSet<int, 16> ProtectedObjs; - if (MFI.getStackProtectorIndex() >= 0) { + if (MFI->getStackProtectorIndex() >= 0) { StackObjSet LargeArrayObjs; StackObjSet SmallArrayObjs; StackObjSet AddrOfObjs; - AdjustStackOffset(MFI, MFI.getStackProtectorIndex(), StackGrowsDown, + AdjustStackOffset(MFI, MFI->getStackProtectorIndex(), StackGrowsDown, Offset, MaxAlign, Skew); // Assign large stack objects first. - for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { - if (MFI.isObjectPreAllocated(i) && - MFI.getUseLocalStackAllocationBlock()) + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isObjectPreAllocated(i) && + MFI->getUseLocalStackAllocationBlock()) continue; if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) continue; if (RS && RS->isScavengingFrameIndex((int)i)) continue; - if (MFI.isDeadObjectIndex(i)) + if (MFI->isDeadObjectIndex(i)) continue; - if (MFI.getStackProtectorIndex() == (int)i || - EHRegNodeFrameIndex == (int)i) + if (MFI->getStackProtectorIndex() == (int)i) continue; - switch (SP->getSSPLayout(MFI.getObjectAllocation(i))) { + switch (SP->getSSPLayout(MFI->getObjectAllocation(i))) { case StackProtector::SSPLK_None: continue; case StackProtector::SSPLK_SmallArray: @@ -860,56 +705,26 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { Offset, MaxAlign, Skew); } - SmallVector<int, 8> ObjectsToAllocate; - - // Then prepare to assign frame offsets to stack objects that are not used to - // spill callee saved registers. - for (unsigned i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) { - if (MFI.isObjectPreAllocated(i) && MFI.getUseLocalStackAllocationBlock()) + // Then assign frame offsets to stack objects that are not used to spill + // callee saved registers. + for (unsigned i = 0, e = MFI->getObjectIndexEnd(); i != e; ++i) { + if (MFI->isObjectPreAllocated(i) && + MFI->getUseLocalStackAllocationBlock()) continue; if (i >= MinCSFrameIndex && i <= MaxCSFrameIndex) continue; if (RS && RS->isScavengingFrameIndex((int)i)) continue; - if (MFI.isDeadObjectIndex(i)) + if (MFI->isDeadObjectIndex(i)) continue; - if (MFI.getStackProtectorIndex() == (int)i || - EHRegNodeFrameIndex == (int)i) + if (MFI->getStackProtectorIndex() == (int)i) continue; if (ProtectedObjs.count(i)) continue; - // Add the objects that we need to allocate to our working set. - ObjectsToAllocate.push_back(i); + AdjustStackOffset(MFI, i, StackGrowsDown, Offset, MaxAlign, Skew); } - // Allocate the EH registration node first if one is present. - if (EHRegNodeFrameIndex != std::numeric_limits<int>::max()) - AdjustStackOffset(MFI, EHRegNodeFrameIndex, StackGrowsDown, Offset, - MaxAlign, Skew); - - // Give the targets a chance to order the objects the way they like it. - if (Fn.getTarget().getOptLevel() != CodeGenOpt::None && - Fn.getTarget().Options.StackSymbolOrdering) - TFI.orderFrameObjects(Fn, ObjectsToAllocate); - - // Keep track of which bytes in the fixed and callee-save range are used so we - // can use the holes when allocating later stack objects. Only do this if - // stack protector isn't being used and the target requests it and we're - // optimizing. - BitVector StackBytesFree; - if (!ObjectsToAllocate.empty() && - Fn.getTarget().getOptLevel() != CodeGenOpt::None && - MFI.getStackProtectorIndex() < 0 && TFI.enableStackSlotScavenging(Fn)) - computeFreeStackSlots(MFI, StackGrowsDown, MinCSFrameIndex, MaxCSFrameIndex, - FixedCSEnd, StackBytesFree); - - // Now walk the objects and actually assign base offsets to them. - for (auto &Object : ObjectsToAllocate) - if (!scavengeStackSlot(MFI, Object, StackGrowsDown, MaxAlign, - StackBytesFree)) - AdjustStackOffset(MFI, Object, StackGrowsDown, Offset, MaxAlign, Skew); - // Make sure the special register scavenging spill slot is closest to the // stack pointer. if (RS && !EarlyScavengingSlots) { @@ -924,8 +739,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // If we have reserved argument space for call sites in the function // immediately on entry to the current function, count it as part of the // overall stack size. - if (MFI.adjustsStack() && TFI.hasReservedCallFrame(Fn)) - Offset += MFI.getMaxCallFrameSize(); + if (MFI->adjustsStack() && TFI.hasReservedCallFrame(Fn)) + Offset += MFI->getMaxCallFrameSize(); // Round up the size to a multiple of the alignment. If the function has // any calls or alloca's, align to the target's StackAlignment value to @@ -933,8 +748,8 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // otherwise, for leaf functions, align to the TransientStackAlignment // value. unsigned StackAlign; - if (MFI.adjustsStack() || MFI.hasVarSizedObjects() || - (RegInfo->needsStackRealignment(Fn) && MFI.getObjectIndexEnd() != 0)) + if (MFI->adjustsStack() || MFI->hasVarSizedObjects() || + (RegInfo->needsStackRealignment(Fn) && MFI->getObjectIndexEnd() != 0)) StackAlign = TFI.getStackAlignment(); else StackAlign = TFI.getTransientStackAlignment(); @@ -942,25 +757,19 @@ void PEI::calculateFrameObjectOffsets(MachineFunction &Fn) { // If the frame pointer is eliminated, all frame offsets will be relative to // SP not FP. Align to MaxAlign so this works. StackAlign = std::max(StackAlign, MaxAlign); - Offset = alignTo(Offset, StackAlign, Skew); + Offset = RoundUpToAlignment(Offset, StackAlign, Skew); } // Update frame info to pretend that this is part of the stack... int64_t StackSize = Offset - LocalAreaOffset; - MFI.setStackSize(StackSize); + MFI->setStackSize(StackSize); NumBytesStackSpace += StackSize; - - ORE->emit([&]() { - return MachineOptimizationRemarkAnalysis(DEBUG_TYPE, "StackSize", - Fn.getFunction().getSubprogram(), - &Fn.front()) - << ore::NV("NumStackBytes", StackSize) << " stack bytes in function"; - }); } /// insertPrologEpilogCode - Scan the function for modified callee saved /// registers, insert spill code for these callee saved registers, then add /// prolog and epilog code to the function. +/// void PEI::insertPrologEpilogCode(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); @@ -982,24 +791,21 @@ void PEI::insertPrologEpilogCode(MachineFunction &Fn) { if (Fn.shouldSplitStack()) { for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForSegmentedStacks(Fn, *SaveBlock); - // Record that there are split-stack functions, so we will emit a - // special section to tell the linker. - Fn.getMMI().setHasSplitStack(true); - } else - Fn.getMMI().setHasNosplitStack(true); + } // Emit additional code that is required to explicitly handle the stack in // HiPE native code (if needed) when loaded in the Erlang/OTP runtime. The // approach is rather similar to that of Segmented Stacks, but it uses a // different conditional check and another BIF for allocating more stack // space. - if (Fn.getFunction().getCallingConv() == CallingConv::HiPE) + if (Fn.getFunction()->getCallingConv() == CallingConv::HiPE) for (MachineBasicBlock *SaveBlock : SaveBlocks) TFI.adjustForHiPEPrologue(Fn, *SaveBlock); } /// replaceFrameIndices - Replace all MO_FrameIndex operands with physical /// register references and actual offsets. +/// void PEI::replaceFrameIndices(MachineFunction &Fn) { const TargetFrameLowering &TFI = *Fn.getSubtarget().getFrameLowering(); if (!TFI.needsFrameIndexResolution(Fn)) return; @@ -1007,7 +813,7 @@ void PEI::replaceFrameIndices(MachineFunction &Fn) { // Store SPAdj at exit of a basic block. SmallVector<int, 8> SPState; SPState.resize(Fn.getNumBlockIDs()); - df_iterator_default_set<MachineBasicBlock*> Reachable; + SmallPtrSet<MachineBasicBlock*, 8> Reachable; // Iterate over the reachable blocks in DFS order. for (auto DFI = df_ext_begin(&Fn, Reachable), DFE = df_ext_end(&Fn, Reachable); @@ -1042,40 +848,50 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, const TargetInstrInfo &TII = *Fn.getSubtarget().getInstrInfo(); const TargetRegisterInfo &TRI = *Fn.getSubtarget().getRegisterInfo(); const TargetFrameLowering *TFI = Fn.getSubtarget().getFrameLowering(); + unsigned FrameSetupOpcode = TII.getCallFrameSetupOpcode(); + unsigned FrameDestroyOpcode = TII.getCallFrameDestroyOpcode(); - if (RS && FrameIndexEliminationScavenging) - RS->enterBasicBlock(*BB); + if (RS && !FrameIndexVirtualScavenging) RS->enterBasicBlock(BB); bool InsideCallSequence = false; for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { - if (TII.isFrameInstr(*I)) { - InsideCallSequence = TII.isFrameSetup(*I); - SPAdj += TII.getSPAdjust(*I); - I = TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); + + if (I->getOpcode() == FrameSetupOpcode || + I->getOpcode() == FrameDestroyOpcode) { + InsideCallSequence = (I->getOpcode() == FrameSetupOpcode); + SPAdj += TII.getSPAdjust(I); + + MachineBasicBlock::iterator PrevI = BB->end(); + if (I != BB->begin()) PrevI = std::prev(I); + TFI->eliminateCallFramePseudoInstr(Fn, *BB, I); + + // Visit the instructions created by eliminateCallFramePseudoInstr(). + if (PrevI == BB->end()) + I = BB->begin(); // The replaced instr was the first in the block. + else + I = std::next(PrevI); continue; } - MachineInstr &MI = *I; + MachineInstr *MI = I; bool DoIncr = true; - bool DidFinishLoop = true; - for (unsigned i = 0, e = MI.getNumOperands(); i != e; ++i) { - if (!MI.getOperand(i).isFI()) + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (!MI->getOperand(i).isFI()) continue; // Frame indices in debug values are encoded in a target independent // way with simply the frame index and offset rather than any // target-specific addressing mode. - if (MI.isDebugValue()) { + if (MI->isDebugValue()) { assert(i == 0 && "Frame indices can only appear as the first " "operand of a DBG_VALUE machine instruction"); unsigned Reg; - int64_t Offset = - TFI->getFrameIndexReference(Fn, MI.getOperand(0).getIndex(), Reg); - MI.getOperand(0).ChangeToRegister(Reg, false /*isDef*/); - auto *DIExpr = DIExpression::prepend(MI.getDebugExpression(), - DIExpression::NoDeref, Offset); - MI.getOperand(3).setMetadata(DIExpr); + MachineOperand &Offset = MI->getOperand(1); + Offset.setImm(Offset.getImm() + + TFI->getFrameIndexReference( + Fn, MI->getOperand(0).getIndex(), Reg)); + MI->getOperand(0).ChangeToRegister(Reg, false /*isDef*/); continue; } @@ -1084,16 +900,18 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, // implementation other than historical accident. The only // remaining difference is the unconditional use of the stack // pointer as the base register. - if (MI.getOpcode() == TargetOpcode::STATEPOINT) { - assert((!MI.isDebugValue() || i == 0) && + if (MI->getOpcode() == TargetOpcode::STATEPOINT) { + assert((!MI->isDebugValue() || i == 0) && "Frame indicies can only appear as the first operand of a " "DBG_VALUE machine instruction"); unsigned Reg; - MachineOperand &Offset = MI.getOperand(i + 1); - int refOffset = TFI->getFrameIndexReferencePreferSP( - Fn, MI.getOperand(i).getIndex(), Reg, /*IgnoreSPUpdates*/ false); + MachineOperand &Offset = MI->getOperand(i + 1); + const unsigned refOffset = + TFI->getFrameIndexReferenceFromSP(Fn, MI->getOperand(i).getIndex(), + Reg); + Offset.setImm(Offset.getImm() + refOffset); - MI.getOperand(i).ChangeToRegister(Reg, false /*isDef*/); + MI->getOperand(i).ChangeToRegister(Reg, false /*isDef*/); continue; } @@ -1111,7 +929,7 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, // use that target machine register info object to eliminate // it. TRI.eliminateFrameIndex(MI, SPAdj, i, - FrameIndexEliminationScavenging ? RS : nullptr); + FrameIndexVirtualScavenging ? nullptr : RS); // Reset the iterator if we were at the beginning of the BB. if (AtBeginning) { @@ -1119,7 +937,7 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, DoIncr = false; } - DidFinishLoop = false; + MI = nullptr; break; } @@ -1127,16 +945,106 @@ void PEI::replaceFrameIndices(MachineBasicBlock *BB, MachineFunction &Fn, // the SP adjustment made by each instruction in the sequence. // This includes both the frame setup/destroy pseudos (handled above), // as well as other instructions that have side effects w.r.t the SP. - // Note that this must come after eliminateFrameIndex, because + // Note that this must come after eliminateFrameIndex, because // if I itself referred to a frame index, we shouldn't count its own // adjustment. - if (DidFinishLoop && InsideCallSequence) + if (MI && InsideCallSequence) SPAdj += TII.getSPAdjust(MI); if (DoIncr && I != BB->end()) ++I; // Update register states. - if (RS && FrameIndexEliminationScavenging && DidFinishLoop) - RS->forward(MI); + if (RS && !FrameIndexVirtualScavenging && MI) RS->forward(MI); + } +} + +/// scavengeFrameVirtualRegs - Replace all frame index virtual registers +/// with physical registers. Use the register scavenger to find an +/// appropriate register to use. +/// +/// FIXME: Iterating over the instruction stream is unnecessary. We can simply +/// iterate over the vreg use list, which at this point only contains machine +/// operands for which eliminateFrameIndex need a new scratch reg. +void +PEI::scavengeFrameVirtualRegs(MachineFunction &Fn) { + // Run through the instructions and find any virtual registers. + for (MachineFunction::iterator BB = Fn.begin(), + E = Fn.end(); BB != E; ++BB) { + RS->enterBasicBlock(&*BB); + + int SPAdj = 0; + + // The instruction stream may change in the loop, so check BB->end() + // directly. + for (MachineBasicBlock::iterator I = BB->begin(); I != BB->end(); ) { + // We might end up here again with a NULL iterator if we scavenged a + // register for which we inserted spill code for definition by what was + // originally the first instruction in BB. + if (I == MachineBasicBlock::iterator(nullptr)) + I = BB->begin(); + + MachineInstr *MI = I; + MachineBasicBlock::iterator J = std::next(I); + MachineBasicBlock::iterator P = + I == BB->begin() ? MachineBasicBlock::iterator(nullptr) + : std::prev(I); + + // RS should process this instruction before we might scavenge at this + // location. This is because we might be replacing a virtual register + // defined by this instruction, and if so, registers killed by this + // instruction are available, and defined registers are not. + RS->forward(I); + + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + if (MI->getOperand(i).isReg()) { + MachineOperand &MO = MI->getOperand(i); + unsigned Reg = MO.getReg(); + if (Reg == 0) + continue; + if (!TargetRegisterInfo::isVirtualRegister(Reg)) + continue; + + // When we first encounter a new virtual register, it + // must be a definition. + assert(MI->getOperand(i).isDef() && + "frame index virtual missing def!"); + // Scavenge a new scratch register + const TargetRegisterClass *RC = Fn.getRegInfo().getRegClass(Reg); + unsigned ScratchReg = RS->scavengeRegister(RC, J, SPAdj); + + ++NumScavengedRegs; + + // Replace this reference to the virtual register with the + // scratch register. + assert (ScratchReg && "Missing scratch register!"); + Fn.getRegInfo().replaceRegWith(Reg, ScratchReg); + + // Because this instruction was processed by the RS before this + // register was allocated, make sure that the RS now records the + // register as being used. + RS->setRegUsed(ScratchReg); + } + } + + // If the scavenger needed to use one of its spill slots, the + // spill code will have been inserted in between I and J. This is a + // problem because we need the spill code before I: Move I to just + // prior to J. + if (I != std::prev(J)) { + BB->splice(J, &*BB, I); + + // Before we move I, we need to prepare the RS to visit I again. + // Specifically, RS will assert if it sees uses of registers that + // it believes are undefined. Because we have already processed + // register kills in I, when it visits I again, it will believe that + // those registers are undefined. To avoid this situation, unprocess + // the instruction I. + assert(RS->getCurrentPosition() == I && + "The register scavenger has an unexpected position"); + I = P; + RS->unprocess(P); + } else + ++I; + } } } diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp index 11808f8995f..3348e56bc77 100644 --- a/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -29,8 +29,8 @@ #include "llvm/IR/Function.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/Support/Debug.h" #include "llvm/Target/TargetOptions.h" +#include "llvm/Support/Debug.h" #include <cstdlib> using namespace llvm; @@ -50,7 +50,7 @@ X86FrameLowering::X86FrameLowering(const X86Subtarget &STI, } bool X86FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { - return !MF.getFrameInfo().hasVarSizedObjects() && + return !MF.getFrameInfo()->hasVarSizedObjects() && !MF.getInfo<X86MachineFunctionInfo>()->getHasPushSequences(); } @@ -74,7 +74,7 @@ X86FrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const { // when there are no stack objects. bool X86FrameLowering::needsFrameIndexResolution(const MachineFunction &MF) const { - return MF.getFrameInfo().hasStackObjects() || + return MF.getFrameInfo()->hasStackObjects() || MF.getInfo<X86MachineFunctionInfo>()->getHasPushSequences(); } @@ -82,15 +82,17 @@ X86FrameLowering::needsFrameIndexResolution(const MachineFunction &MF) const { /// pointer register. This is true if the function has variable sized allocas /// or if frame pointer elimination is disabled. bool X86FrameLowering::hasFP(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const MachineModuleInfo &MMI = MF.getMMI(); + return (MF.getTarget().Options.DisableFramePointerElim(MF) || TRI->needsStackRealignment(MF) || - MFI.hasVarSizedObjects() || - MFI.isFrameAddressTaken() || MFI.hasOpaqueSPAdjustment() || + MFI->hasVarSizedObjects() || + MFI->isFrameAddressTaken() || MFI->hasOpaqueSPAdjustment() || MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() || - MF.callsUnwindInit() || MF.hasEHFunclets() || MF.callsEHReturn() || - MFI.hasStackMap() || MFI.hasPatchPoint() || - MFI.hasCopyImplyingStackAdjustment()); + MMI.callsUnwindInit() || MMI.hasEHFunclets() || MMI.callsEHReturn() || + MFI->hasStackMap() || MFI->hasPatchPoint() || + MFI->hasCopyImplyingStackAdjustment()); } static unsigned getSUBriOpcode(unsigned IsLP64, int64_t Imm) { @@ -148,18 +150,15 @@ static unsigned findDeadCallerSavedReg(MachineBasicBlock &MBB, const X86RegisterInfo *TRI, bool Is64Bit) { const MachineFunction *MF = MBB.getParent(); - if (MF->callsEHReturn()) + const Function *F = MF->getFunction(); + if (!F || MF->getMMI().callsEHReturn()) return 0; const TargetRegisterClass &AvailableRegs = *TRI->getGPRsForTailCall(*MF); - if (MBBI == MBB.end()) - return 0; - - switch (MBBI->getOpcode()) { + unsigned Opc = MBBI->getOpcode(); + switch (Opc) { default: return 0; - case TargetOpcode::PATCHABLE_RET: - case X86::RET: case X86::RETL: case X86::RETQ: case X86::RETIL: @@ -251,76 +250,40 @@ void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB, int64_t NumBytes, bool InEpilogue) const { bool isSub = NumBytes < 0; uint64_t Offset = isSub ? -NumBytes : NumBytes; - MachineInstr::MIFlag Flag = - isSub ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy; uint64_t Chunk = (1LL << 31) - 1; DebugLoc DL = MBB.findDebugLoc(MBBI); - if (Offset > Chunk) { - // Rather than emit a long series of instructions for large offsets, - // load the offset into a register and do one sub/add - unsigned Reg = 0; - unsigned Rax = (unsigned)(Is64Bit ? X86::RAX : X86::EAX); + while (Offset) { + if (Offset > Chunk) { + // Rather than emit a long series of instructions for large offsets, + // load the offset into a register and do one sub/add + unsigned Reg = 0; - if (isSub && !isEAXLiveIn(MBB)) - Reg = Rax; - else - Reg = findDeadCallerSavedReg(MBB, MBBI, TRI, Is64Bit); - - unsigned MovRIOpc = Is64Bit ? X86::MOV64ri : X86::MOV32ri; - unsigned AddSubRROpc = - isSub ? getSUBrrOpcode(Is64Bit) : getADDrrOpcode(Is64Bit); - if (Reg) { - BuildMI(MBB, MBBI, DL, TII.get(MovRIOpc), Reg) - .addImm(Offset) - .setMIFlag(Flag); - MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(AddSubRROpc), StackPtr) - .addReg(StackPtr) - .addReg(Reg); - MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. - return; - } else if (Offset > 8 * Chunk) { - // If we would need more than 8 add or sub instructions (a >16GB stack - // frame), it's worth spilling RAX to materialize this immediate. - // pushq %rax - // movabsq +-$Offset+-SlotSize, %rax - // addq %rsp, %rax - // xchg %rax, (%rsp) - // movq (%rsp), %rsp - assert(Is64Bit && "can't have 32-bit 16GB stack frame"); - BuildMI(MBB, MBBI, DL, TII.get(X86::PUSH64r)) - .addReg(Rax, RegState::Kill) - .setMIFlag(Flag); - // Subtract is not commutative, so negate the offset and always use add. - // Subtract 8 less and add 8 more to account for the PUSH we just did. - if (isSub) - Offset = -(Offset - SlotSize); + if (isSub && !isEAXLiveIn(MBB)) + Reg = (unsigned)(Is64Bit ? X86::RAX : X86::EAX); else - Offset = Offset + SlotSize; - BuildMI(MBB, MBBI, DL, TII.get(MovRIOpc), Rax) - .addImm(Offset) - .setMIFlag(Flag); - MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(X86::ADD64rr), Rax) - .addReg(Rax) - .addReg(StackPtr); - MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. - // Exchange the new SP in RAX with the top of the stack. - addRegOffset( - BuildMI(MBB, MBBI, DL, TII.get(X86::XCHG64rm), Rax).addReg(Rax), - StackPtr, false, 0); - // Load new SP from the top of the stack into RSP. - addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64rm), StackPtr), - StackPtr, false, 0); - return; + Reg = findDeadCallerSavedReg(MBB, MBBI, TRI, Is64Bit); + + if (Reg) { + unsigned Opc = Is64Bit ? X86::MOV64ri : X86::MOV32ri; + BuildMI(MBB, MBBI, DL, TII.get(Opc), Reg) + .addImm(Offset); + Opc = isSub + ? getSUBrrOpcode(Is64Bit) + : getADDrrOpcode(Is64Bit); + MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc), StackPtr) + .addReg(StackPtr) + .addReg(Reg); + MI->getOperand(3).setIsDead(); // The EFLAGS implicit def is dead. + Offset = 0; + continue; + } } - } - while (Offset) { uint64_t ThisVal = std::min(Offset, Chunk); - if (ThisVal == SlotSize) { - // Use push / pop for slot sized adjustments as a size optimization. We - // need to find a dead register when using pop. + if (ThisVal == (Is64Bit ? 8 : 4)) { + // Use push / pop instead. unsigned Reg = isSub ? (unsigned)(Is64Bit ? X86::RAX : X86::EAX) : findDeadCallerSavedReg(MBB, MBBI, TRI, Is64Bit); @@ -328,24 +291,31 @@ void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB, unsigned Opc = isSub ? (Is64Bit ? X86::PUSH64r : X86::PUSH32r) : (Is64Bit ? X86::POP64r : X86::POP32r); - BuildMI(MBB, MBBI, DL, TII.get(Opc)) - .addReg(Reg, getDefRegState(!isSub) | getUndefRegState(isSub)) - .setMIFlag(Flag); + MachineInstr *MI = BuildMI(MBB, MBBI, DL, TII.get(Opc)) + .addReg(Reg, getDefRegState(!isSub) | getUndefRegState(isSub)); + if (isSub) + MI->setFlag(MachineInstr::FrameSetup); + else + MI->setFlag(MachineInstr::FrameDestroy); Offset -= ThisVal; continue; } } - BuildStackAdjustment(MBB, MBBI, DL, isSub ? -ThisVal : ThisVal, InEpilogue) - .setMIFlag(Flag); + MachineInstrBuilder MI = BuildStackAdjustment( + MBB, MBBI, DL, isSub ? -ThisVal : ThisVal, InEpilogue); + if (isSub) + MI.setMIFlag(MachineInstr::FrameSetup); + else + MI.setMIFlag(MachineInstr::FrameDestroy); Offset -= ThisVal; } } MachineInstrBuilder X86FrameLowering::BuildStackAdjustment( - MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, int64_t Offset, bool InEpilogue) const { + MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, DebugLoc DL, + int64_t Offset, bool InEpilogue) const { assert(Offset != 0 && "zero offset stack adjustment requested"); // On Atom, using LEA to adjust SP is preferred, but using it in the epilogue @@ -401,40 +371,19 @@ int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, MachineBasicBlock::iterator PI = doMergeWithPrevious ? std::prev(MBBI) : MBBI; MachineBasicBlock::iterator NI = doMergeWithPrevious ? nullptr : std::next(MBBI); - PI = skipDebugInstructionsBackward(PI, MBB.begin()); - if (NI != nullptr) - NI = skipDebugInstructionsForward(NI, MBB.end()); - unsigned Opc = PI->getOpcode(); int Offset = 0; - if (!doMergeWithPrevious && NI != MBB.end() && - NI->getOpcode() == TargetOpcode::CFI_INSTRUCTION) { - // Don't merge with the next instruction if it has CFI. - return Offset; - } - if ((Opc == X86::ADD64ri32 || Opc == X86::ADD64ri8 || - Opc == X86::ADD32ri || Opc == X86::ADD32ri8) && + Opc == X86::ADD32ri || Opc == X86::ADD32ri8 || + Opc == X86::LEA32r || Opc == X86::LEA64_32r) && PI->getOperand(0).getReg() == StackPtr){ - assert(PI->getOperand(1).getReg() == StackPtr); Offset += PI->getOperand(2).getImm(); MBB.erase(PI); if (!doMergeWithPrevious) MBBI = NI; - } else if ((Opc == X86::LEA32r || Opc == X86::LEA64_32r) && - PI->getOperand(0).getReg() == StackPtr && - PI->getOperand(1).getReg() == StackPtr && - PI->getOperand(2).getImm() == 1 && - PI->getOperand(3).getReg() == X86::NoRegister && - PI->getOperand(5).getReg() == X86::NoRegister) { - // For LEAs we have: def = lea SP, FI, noreg, Offset, noreg. - Offset += PI->getOperand(4).getImm(); - MBB.erase(PI); - if (!doMergeWithPrevious) MBBI = NI; } else if ((Opc == X86::SUB64ri32 || Opc == X86::SUB64ri8 || Opc == X86::SUB32ri || Opc == X86::SUB32ri8) && PI->getOperand(0).getReg() == StackPtr) { - assert(PI->getOperand(1).getReg() == StackPtr); Offset -= PI->getOperand(2).getImm(); MBB.erase(PI); if (!doMergeWithPrevious) MBBI = NI; @@ -444,31 +393,31 @@ int X86FrameLowering::mergeSPUpdates(MachineBasicBlock &MBB, } void X86FrameLowering::BuildCFI(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, - const MCCFIInstruction &CFIInst) const { + MachineBasicBlock::iterator MBBI, DebugLoc DL, + MCCFIInstruction CFIInst) const { MachineFunction &MF = *MBB.getParent(); - unsigned CFIIndex = MF.addFrameInst(CFIInst); + unsigned CFIIndex = MF.getMMI().addFrameInst(CFIInst); BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); } -void X86FrameLowering::emitCalleeSavedFrameMoves( - MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL) const { +void +X86FrameLowering::emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL) const { MachineFunction &MF = *MBB.getParent(); - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); MachineModuleInfo &MMI = MF.getMMI(); const MCRegisterInfo *MRI = MMI.getContext().getRegisterInfo(); // Add callee saved registers to move list. - const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo(); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); if (CSI.empty()) return; // Calculate offsets. for (std::vector<CalleeSavedInfo>::const_iterator I = CSI.begin(), E = CSI.end(); I != E; ++I) { - int64_t Offset = MFI.getObjectOffset(I->getFrameIdx()); + int64_t Offset = MFI->getObjectOffset(I->getFrameIdx()); unsigned Reg = I->getReg(); unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); @@ -477,19 +426,20 @@ void X86FrameLowering::emitCalleeSavedFrameMoves( } } -void X86FrameLowering::emitStackProbe(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, bool InProlog) const { +MachineInstr *X86FrameLowering::emitStackProbe(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL, + bool InProlog) const { const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); if (STI.isTargetWindowsCoreCLR()) { if (InProlog) { - emitStackProbeInlineStub(MF, MBB, MBBI, DL, true); + return emitStackProbeInlineStub(MF, MBB, MBBI, DL, true); } else { - emitStackProbeInline(MF, MBB, MBBI, DL, false); + return emitStackProbeInline(MF, MBB, MBBI, DL, false); } } else { - emitStackProbeCall(MF, MBB, MBBI, DL, InProlog); + return emitStackProbeCall(MF, MBB, MBBI, DL, InProlog); } } @@ -507,22 +457,18 @@ void X86FrameLowering::inlineStackProbe(MachineFunction &MF, } if (ChkStkStub != nullptr) { - assert(!ChkStkStub->isBundled() && - "Not expecting bundled instructions here"); MachineBasicBlock::iterator MBBI = std::next(ChkStkStub->getIterator()); - assert(std::prev(MBBI) == ChkStkStub && - "MBBI expected after __chkstk_stub."); + assert(std::prev(MBBI).operator==(ChkStkStub) && + "MBBI expected after __chkstk_stub."); DebugLoc DL = PrologMBB.findDebugLoc(MBBI); emitStackProbeInline(MF, PrologMBB, MBBI, DL, true); ChkStkStub->eraseFromParent(); } } -void X86FrameLowering::emitStackProbeInline(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, - bool InProlog) const { +MachineInstr *X86FrameLowering::emitStackProbeInline( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc DL, bool InProlog) const { const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>(); assert(STI.is64Bit() && "different expansion needed for 32 bit"); assert(STI.isTargetWindowsCoreCLR() && "custom expansion expects CoreCLR"); @@ -645,7 +591,7 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF, // lowest touched page on the stack, not the point at which the OS // will cause an overflow exception, so this is just an optimization // to avoid unnecessarily touching pages that are below the current - // SP but already committed to the stack by the OS. + // SP but already commited to the stack by the OS. BuildMI(&MBB, DL, TII.get(X86::MOV64rm), LimitReg) .addReg(0) .addImm(1) @@ -732,27 +678,32 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF, } // Possible TODO: physreg liveness for InProlog case. + + return ContinueMBBI; } -void X86FrameLowering::emitStackProbeCall(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, - bool InProlog) const { +MachineInstr *X86FrameLowering::emitStackProbeCall( + MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc DL, bool InProlog) const { bool IsLargeCodeModel = MF.getTarget().getCodeModel() == CodeModel::Large; - // FIXME: Add retpoline support and remove this. - if (Is64Bit && IsLargeCodeModel && STI.useRetpoline()) - report_fatal_error("Emitting stack probe calls on 64-bit with the large " - "code model and retpoline not yet implemented."); - unsigned CallOp; if (Is64Bit) CallOp = IsLargeCodeModel ? X86::CALL64r : X86::CALL64pcrel32; else CallOp = X86::CALLpcrel32; - StringRef Symbol = STI.getTargetLowering()->getStackProbeSymbolName(MF); + const char *Symbol; + if (Is64Bit) { + if (STI.isTargetCygMing()) { + Symbol = "___chkstk_ms"; + } else { + Symbol = "__chkstk"; + } + } else if (STI.isTargetCygMing()) + Symbol = "_alloca"; + else + Symbol = "_chkstk"; MachineInstrBuilder CI; MachineBasicBlock::iterator ExpansionMBBI = std::prev(MBBI); @@ -763,11 +714,10 @@ void X86FrameLowering::emitStackProbeCall(MachineFunction &MF, // For the large code model, we have to call through a register. Use R11, // as it is scratch in all supported calling conventions. BuildMI(MBB, MBBI, DL, TII.get(X86::MOV64ri), X86::R11) - .addExternalSymbol(MF.createExternalSymbolName(Symbol)); + .addExternalSymbol(Symbol); CI = BuildMI(MBB, MBBI, DL, TII.get(CallOp)).addReg(X86::R11); } else { - CI = BuildMI(MBB, MBBI, DL, TII.get(CallOp)) - .addExternalSymbol(MF.createExternalSymbolName(Symbol)); + CI = BuildMI(MBB, MBBI, DL, TII.get(CallOp)).addExternalSymbol(Symbol); } unsigned AX = Is64Bit ? X86::RAX : X86::EAX; @@ -778,16 +728,13 @@ void X86FrameLowering::emitStackProbeCall(MachineFunction &MF, .addReg(SP, RegState::Define | RegState::Implicit) .addReg(X86::EFLAGS, RegState::Define | RegState::Implicit); - if (STI.isTargetWin64() || !STI.isOSWindows()) { - // MSVC x32's _chkstk and cygwin/mingw's _alloca adjust %esp themselves. + if (Is64Bit) { // MSVC x64's __chkstk and cygwin/mingw's ___chkstk_ms do not adjust %rsp - // themselves. They also does not clobber %rax so we can reuse it when + // themselves. It also does not clobber %rax so we can reuse it when // adjusting %rsp. - // All other platforms do not specify a particular ABI for the stack probe - // function, so we arbitrarily define it to not adjust %esp/%rsp itself. - BuildMI(MBB, MBBI, DL, TII.get(getSUBrrOpcode(Is64Bit)), SP) - .addReg(SP) - .addReg(AX); + BuildMI(MBB, MBBI, DL, TII.get(X86::SUB64rr), X86::RSP) + .addReg(X86::RSP) + .addReg(X86::RAX); } if (InProlog) { @@ -795,16 +742,20 @@ void X86FrameLowering::emitStackProbeCall(MachineFunction &MF, for (++ExpansionMBBI; ExpansionMBBI != MBBI; ++ExpansionMBBI) ExpansionMBBI->setFlag(MachineInstr::FrameSetup); } + + return MBBI; } -void X86FrameLowering::emitStackProbeInlineStub( +MachineInstr *X86FrameLowering::emitStackProbeInlineStub( MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool InProlog) const { + MachineBasicBlock::iterator MBBI, DebugLoc DL, bool InProlog) const { assert(InProlog && "ChkStkStub called outside prolog!"); BuildMI(MBB, MBBI, DL, TII.get(X86::CALLpcrel32)) .addExternalSymbol("__chkstk_stub"); + + return MBBI; } static unsigned calculateSetFPREG(uint64_t SPAdjust) { @@ -821,11 +772,11 @@ static unsigned calculateSetFPREG(uint64_t SPAdjust) { // have a call out. Otherwise just make sure we have some alignment - we'll // go with the minimum SlotSize. uint64_t X86FrameLowering::calculateMaxStackAlign(const MachineFunction &MF) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - uint64_t MaxAlign = MFI.getMaxAlignment(); // Desired stack alignment. + const MachineFrameInfo *MFI = MF.getFrameInfo(); + uint64_t MaxAlign = MFI->getMaxAlignment(); // Desired stack alignment. unsigned StackAlign = getStackAlignment(); - if (MF.getFunction().hasFnAttribute("stackrealign")) { - if (MFI.hasCalls()) + if (MF.getFunction()->hasFnAttribute("stackrealign")) { + if (MFI->hasCalls()) MaxAlign = (StackAlign > MaxAlign) ? StackAlign : MaxAlign; else if (MaxAlign < SlotSize) MaxAlign = SlotSize; @@ -835,7 +786,7 @@ uint64_t X86FrameLowering::calculateMaxStackAlign(const MachineFunction &MF) con void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, unsigned Reg, + DebugLoc DL, unsigned Reg, uint64_t MaxAlign) const { uint64_t Val = -MaxAlign; unsigned AndOp = getANDriOpcode(Uses64BitFramePtr, Val); @@ -928,7 +879,6 @@ void X86FrameLowering::BuildStackAlignAND(MachineBasicBlock &MBB, Notes: - .seh directives are emitted only for Windows 64 ABI - - .cv_fpo directives are emitted on win32 when emitting CodeView - .cfi directives are emitted for all other ABIs - for 32-bit code, substitute %e?? registers for %r?? */ @@ -938,36 +888,31 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, assert(&STI == &MF.getSubtarget<X86Subtarget>() && "MF used frame lowering for wrong subtarget"); MachineBasicBlock::iterator MBBI = MBB.begin(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - const Function &Fn = MF.getFunction(); + MachineFrameInfo *MFI = MF.getFrameInfo(); + const Function *Fn = MF.getFunction(); MachineModuleInfo &MMI = MF.getMMI(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); uint64_t MaxAlign = calculateMaxStackAlign(MF); // Desired stack alignment. - uint64_t StackSize = MFI.getStackSize(); // Number of bytes to allocate. + uint64_t StackSize = MFI->getStackSize(); // Number of bytes to allocate. bool IsFunclet = MBB.isEHFuncletEntry(); EHPersonality Personality = EHPersonality::Unknown; - if (Fn.hasPersonalityFn()) - Personality = classifyEHPersonality(Fn.getPersonalityFn()); + if (Fn->hasPersonalityFn()) + Personality = classifyEHPersonality(Fn->getPersonalityFn()); bool FnHasClrFunclet = - MF.hasEHFunclets() && Personality == EHPersonality::CoreCLR; + MMI.hasEHFunclets() && Personality == EHPersonality::CoreCLR; bool IsClrFunclet = IsFunclet && FnHasClrFunclet; bool HasFP = hasFP(MF); - bool IsWin64CC = STI.isCallingConvWin64(Fn.getCallingConv()); + bool IsWin64CC = STI.isCallingConvWin64(Fn->getCallingConv()); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool NeedsWin64CFI = IsWin64Prologue && Fn.needsUnwindTableEntry(); - // FIXME: Emit FPO data for EH funclets. - bool NeedsWinFPO = - !IsFunclet && STI.isTargetWin32() && MMI.getModule()->getCodeViewFlag(); - bool NeedsWinCFI = NeedsWin64CFI || NeedsWinFPO; + bool NeedsWinCFI = IsWin64Prologue && Fn->needsUnwindTableEntry(); bool NeedsDwarfCFI = - !IsWin64Prologue && (MMI.hasDebugInfo() || Fn.needsUnwindTableEntry()); + !IsWin64Prologue && (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); unsigned FramePtr = TRI->getFrameRegister(MF); const unsigned MachineFramePtr = STI.isTarget64BitILP32() ? getX86SubSuperRegister(FramePtr, 64) : FramePtr; unsigned BasePtr = TRI->getBaseRegister(); - bool HasWinCFI = false; - + // Debug location must be unknown since the first debug location is used // to determine the end of the prologue. DebugLoc DL; @@ -981,44 +926,32 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, X86FI->setCalleeSavedFrameSize( X86FI->getCalleeSavedFrameSize() - TailCallReturnAddrDelta); - bool UseStackProbe = !STI.getTargetLowering()->getStackProbeSymbolName(MF).empty(); + bool UseStackProbe = (STI.isOSWindows() && !STI.isTargetMachO()); // The default stack probe size is 4096 if the function has no stackprobesize // attribute. unsigned StackProbeSize = 4096; - if (Fn.hasFnAttribute("stack-probe-size")) - Fn.getFnAttribute("stack-probe-size") + if (Fn->hasFnAttribute("stack-probe-size")) + Fn->getFnAttribute("stack-probe-size") .getValueAsString() .getAsInteger(0, StackProbeSize); - // Re-align the stack on 64-bit if the x86-interrupt calling convention is - // used and an error code was pushed, since the x86-64 ABI requires a 16-byte - // stack alignment. - if (Fn.getCallingConv() == CallingConv::X86_INTR && Is64Bit && - Fn.arg_size() == 2) { - StackSize += 8; - MFI.setStackSize(StackSize); - emitSPUpdate(MBB, MBBI, -8, /*InEpilogue=*/false); - } - // If this is x86-64 and the Red Zone is not disabled, if we are a leaf // function, and use up to 128 bytes of stack space, don't have a frame // pointer, calls, or dynamic alloca then we do not need to adjust the // stack pointer (we fit in the Red Zone). We also check that we don't // push and pop from the stack. - if (Is64Bit && !Fn.hasFnAttribute(Attribute::NoRedZone) && + if (Is64Bit && !Fn->hasFnAttribute(Attribute::NoRedZone) && !TRI->needsStackRealignment(MF) && - !MFI.hasVarSizedObjects() && // No dynamic alloca. - !MFI.adjustsStack() && // No calls. - !UseStackProbe && // No stack probes. - !IsWin64CC && // Win64 has no Red Zone - !MFI.hasCopyImplyingStackAdjustment() && // Don't push and pop. - !MF.shouldSplitStack()) { // Regular stack + !MFI->hasVarSizedObjects() && // No dynamic alloca. + !MFI->adjustsStack() && // No calls. + !IsWin64CC && // Win64 has no Red Zone + !MFI->hasCopyImplyingStackAdjustment() && // Don't push and pop. + !MF.shouldSplitStack()) { // Regular stack uint64_t MinSize = X86FI->getCalleeSavedFrameSize(); if (HasFP) MinSize += SlotSize; - X86FI->setUsesRedZone(MinSize > 0 || StackSize > 0); StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0); - MFI.setStackSize(StackSize); + MFI->setStackSize(StackSize); } // Insert stack pointer adjustment for later moving of return addr. Only @@ -1066,8 +999,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } if (HasFP) { - assert(MF.getRegInfo().isReserved(MachineFramePtr) && "FP reserved"); - // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; // If required, include space for extra hidden slot for stashing base pointer. @@ -1078,15 +1009,15 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // Callee-saved registers are pushed on stack before the stack is realigned. if (TRI->needsStackRealignment(MF) && !IsWin64Prologue) - NumBytes = alignTo(NumBytes, MaxAlign); + NumBytes = RoundUpToAlignment(NumBytes, MaxAlign); // Get the offset of the stack slot for the EBP register, which is // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. // Update the frame offset adjustment. if (!IsFunclet) - MFI.setOffsetAdjustment(-NumBytes); + MFI->setOffsetAdjustment(-NumBytes); else - assert(MFI.getOffsetAdjustment() == -(int)NumBytes && + assert(MFI->getOffsetAdjustment() == -(int)NumBytes && "should calculate same local variable offset for funclets"); // Save EBP/RBP into the appropriate stack slot. @@ -1108,7 +1039,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } if (NeedsWinCFI) { - HasWinCFI = true; BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)) .addImm(FramePtr) .setMIFlag(MachineInstr::FrameSetup); @@ -1129,15 +1059,13 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, BuildCFI(MBB, MBBI, DL, MCCFIInstruction::createDefCfaRegister( nullptr, DwarfFramePtr)); } + } - if (NeedsWinFPO) { - // .cv_fpo_setframe $FramePtr - HasWinCFI = true; - BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame)) - .addImm(FramePtr) - .addImm(0) - .setMIFlag(MachineInstr::FrameSetup); - } + // Mark the FramePtr as live-in in every block. Don't do this again for + // funclet prologues. + if (!IsFunclet) { + for (MachineBasicBlock &EveryMBB : MF) + EveryMBB.addLiveIn(MachineFramePtr); } } else { assert(!IsFunclet && "funclets without FPs not yet implemented"); @@ -1172,10 +1100,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } if (NeedsWinCFI) { - HasWinCFI = true; - BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)) - .addImm(Reg) - .setMIFlag(MachineInstr::FrameSetup); + BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_PushReg)).addImm(Reg).setMIFlag( + MachineInstr::FrameSetup); } } @@ -1204,11 +1130,8 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // virtual memory manager are allocated in correct sequence. uint64_t AlignedNumBytes = NumBytes; if (IsWin64Prologue && !IsFunclet && TRI->needsStackRealignment(MF)) - AlignedNumBytes = alignTo(AlignedNumBytes, MaxAlign); + AlignedNumBytes = RoundUpToAlignment(AlignedNumBytes, MaxAlign); if (AlignedNumBytes >= StackProbeSize && UseStackProbe) { - assert(!X86FI->getUsesRedZone() && - "The Red Zone is not accounted for in stack probes"); - // Check whether EAX is livein for this block. bool isEAXAlive = isEAXLiveIn(MBB); @@ -1262,12 +1185,10 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, emitSPUpdate(MBB, MBBI, -(int64_t)NumBytes, /*InEpilogue=*/false); } - if (NeedsWinCFI && NumBytes) { - HasWinCFI = true; + if (NeedsWinCFI && NumBytes) BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_StackAlloc)) .addImm(NumBytes) .setMIFlag(MachineInstr::FrameSetup); - } int SEHFrameOffset = 0; unsigned SPOrEstablisher; @@ -1314,8 +1235,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, // If this is not a funclet, emit the CFI describing our frame pointer. if (NeedsWinCFI && !IsFunclet) { - assert(!NeedsWinFPO && "this setframe incompatible with FPO data"); - HasWinCFI = true; BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SetFrame)) .addImm(FramePtr) .addImm(SEHFrameOffset) @@ -1341,7 +1260,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup)) { - const MachineInstr &FrameInstr = *MBBI; + const MachineInstr *FrameInstr = &*MBBI; ++MBBI; if (NeedsWinCFI) { @@ -1352,8 +1271,6 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, int Offset = getFrameIndexReference(MF, FI, IgnoredFrameReg); Offset += SEHFrameOffset; - HasWinCFI = true; - assert(!NeedsWinFPO && "SEH_SaveXMM incompatible with FPO data"); BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_SaveXMM)) .addImm(Reg) .addImm(Offset) @@ -1363,7 +1280,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } } - if (NeedsWinCFI && HasWinCFI) + if (NeedsWinCFI) BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_EndPrologue)) .setMIFlag(MachineInstr::FrameSetup); @@ -1440,38 +1357,24 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } // Emit DWARF info specifying the offsets of the callee-saved registers. - emitCalleeSavedFrameMoves(MBB, MBBI, DL); + if (PushedRegs) + emitCalleeSavedFrameMoves(MBB, MBBI, DL); } - - // X86 Interrupt handling function cannot assume anything about the direction - // flag (DF in EFLAGS register). Clear this flag by creating "cld" instruction - // in each prologue of interrupt handler function. - // - // FIXME: Create "cld" instruction only in these cases: - // 1. The interrupt handling function uses any of the "rep" instructions. - // 2. Interrupt handling function calls another function. - // - if (Fn.getCallingConv() == CallingConv::X86_INTR) - BuildMI(MBB, MBBI, DL, TII.get(X86::CLD)) - .setMIFlag(MachineInstr::FrameSetup); - - // At this point we know if the function has WinCFI or not. - MF.setHasWinCFI(HasWinCFI); } bool X86FrameLowering::canUseLEAForSPInEpilogue( const MachineFunction &MF) const { - // We can't use LEA instructions for adjusting the stack pointer if we don't - // have a frame pointer in the Win64 ABI. Only ADD instructions may be used - // to deallocate the stack. + // We can't use LEA instructions for adjusting the stack pointer if this is a + // leaf function in the Win64 ABI. Only ADD instructions may be used to + // deallocate the stack. // This means that we can use LEA for SP in two situations: // 1. We *aren't* using the Win64 ABI which means we are free to use LEA. // 2. We *have* a frame pointer which means we are permitted to use LEA. return !MF.getTarget().getMCAsmInfo()->usesWindowsCFI() || hasFP(MF); } -static bool isFuncletReturnInstr(MachineInstr &MI) { - switch (MI.getOpcode()) { +static bool isFuncletReturnInstr(MachineInstr *MI) { + switch (MI->getOpcode()) { case X86::CATCHRET: case X86::CLEANUPRET: return true; @@ -1497,10 +1400,11 @@ static bool isFuncletReturnInstr(MachineInstr &MI) { unsigned X86FrameLowering::getPSPSlotOffsetFromSP(const MachineFunction &MF) const { const WinEHFuncInfo &Info = *MF.getWinEHFuncInfo(); + // getFrameIndexReferenceFromSP has an out ref parameter for the stack + // pointer register; pass a dummy that we ignore unsigned SPReg; - int Offset = getFrameIndexReferencePreferSP(MF, Info.PSPSymFrameIdx, SPReg, - /*IgnoreSPUpdates*/ true); - assert(Offset >= 0 && SPReg == TRI->getStackRegister()); + int Offset = getFrameIndexReferenceFromSP(MF, Info.PSPSymFrameIdx, SPReg); + assert(Offset >= 0); return static_cast<unsigned>(Offset); } @@ -1512,7 +1416,7 @@ X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const { // This is the amount of stack a funclet needs to allocate. unsigned UsedSize; EHPersonality Personality = - classifyEHPersonality(MF.getFunction().getPersonalityFn()); + classifyEHPersonality(MF.getFunction()->getPersonalityFn()); if (Personality == EHPersonality::CoreCLR) { // CLR funclets need to hold enough space to include the PSPSym, at the // same offset from the stack pointer (immediately after the prolog) as it @@ -1520,30 +1424,23 @@ X86FrameLowering::getWinEHFuncletFrameSize(const MachineFunction &MF) const { UsedSize = getPSPSlotOffsetFromSP(MF) + SlotSize; } else { // Other funclets just need enough stack for outgoing call arguments. - UsedSize = MF.getFrameInfo().getMaxCallFrameSize(); + UsedSize = MF.getFrameInfo()->getMaxCallFrameSize(); } // RBP is not included in the callee saved register block. After pushing RBP, // everything is 16 byte aligned. Everything we allocate before an outgoing // call must also be 16 byte aligned. - unsigned FrameSizeMinusRBP = alignTo(CSSize + UsedSize, getStackAlignment()); + unsigned FrameSizeMinusRBP = + RoundUpToAlignment(CSSize + UsedSize, getStackAlignment()); // Subtract out the size of the callee saved registers. This is how much stack // each funclet will allocate. return FrameSizeMinusRBP - CSSize; } -static bool isTailCallOpcode(unsigned Opc) { - return Opc == X86::TCRETURNri || Opc == X86::TCRETURNdi || - Opc == X86::TCRETURNmi || - Opc == X86::TCRETURNri64 || Opc == X86::TCRETURNdi64 || - Opc == X86::TCRETURNmi64; -} - void X86FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); - MachineBasicBlock::iterator Terminator = MBB.getFirstTerminator(); - MachineBasicBlock::iterator MBBI = Terminator; + MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); DebugLoc DL; if (MBBI != MBB.end()) DL = MBBI->getDebugLoc(); @@ -1554,21 +1451,38 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, Is64BitILP32 ? getX86SubSuperRegister(FramePtr, 64) : FramePtr; bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool NeedsWin64CFI = - IsWin64Prologue && MF.getFunction().needsUnwindTableEntry(); - bool IsFunclet = MBBI == MBB.end() ? false : isFuncletReturnInstr(*MBBI); + bool NeedsWinCFI = + IsWin64Prologue && MF.getFunction()->needsUnwindTableEntry(); + bool IsFunclet = isFuncletReturnInstr(MBBI); + MachineBasicBlock *TargetMBB = nullptr; // Get the number of bytes to allocate from the FrameInfo. - uint64_t StackSize = MFI.getStackSize(); + uint64_t StackSize = MFI->getStackSize(); uint64_t MaxAlign = calculateMaxStackAlign(MF); unsigned CSSize = X86FI->getCalleeSavedFrameSize(); - bool HasFP = hasFP(MF); uint64_t NumBytes = 0; - if (IsFunclet) { - assert(HasFP && "EH funclets without FP not yet implemented"); + if (MBBI->getOpcode() == X86::CATCHRET) { + // SEH shouldn't use catchret. + assert(!isAsynchronousEHPersonality( + classifyEHPersonality(MF.getFunction()->getPersonalityFn())) && + "SEH should not use CATCHRET"); + NumBytes = getWinEHFuncletFrameSize(MF); - } else if (HasFP) { + assert(hasFP(MF) && "EH funclets without FP not yet implemented"); + TargetMBB = MBBI->getOperand(0).getMBB(); + + // Pop EBP. + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + } else if (MBBI->getOpcode() == X86::CLEANUPRET) { + NumBytes = getWinEHFuncletFrameSize(MF); + assert(hasFP(MF) && "EH funclets without FP not yet implemented"); + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + } else if (hasFP(MF)) { // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; NumBytes = FrameSize - CSSize; @@ -1576,52 +1490,65 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // Callee-saved registers were pushed on stack before the stack was // realigned. if (TRI->needsStackRealignment(MF) && !IsWin64Prologue) - NumBytes = alignTo(FrameSize, MaxAlign); - } else { - NumBytes = StackSize - CSSize; - } - uint64_t SEHStackAllocAmt = NumBytes; + NumBytes = RoundUpToAlignment(FrameSize, MaxAlign); - if (HasFP) { // Pop EBP. - BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), - MachineFramePtr) + BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::POP64r : X86::POP32r), MachineFramePtr) .setMIFlag(MachineInstr::FrameDestroy); + } else { + NumBytes = StackSize - CSSize; } + uint64_t SEHStackAllocAmt = NumBytes; - MachineBasicBlock::iterator FirstCSPop = MBBI; // Skip the callee-saved pop instructions. while (MBBI != MBB.begin()) { MachineBasicBlock::iterator PI = std::prev(MBBI); unsigned Opc = PI->getOpcode(); - if (Opc != X86::DBG_VALUE && !PI->isTerminator()) { - if ((Opc != X86::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) && - (Opc != X86::POP64r || !PI->getFlag(MachineInstr::FrameDestroy))) - break; - FirstCSPop = PI; - } + if ((Opc != X86::POP32r || !PI->getFlag(MachineInstr::FrameDestroy)) && + (Opc != X86::POP64r || !PI->getFlag(MachineInstr::FrameDestroy)) && + Opc != X86::DBG_VALUE && !PI->isTerminator()) + break; --MBBI; } - MBBI = FirstCSPop; + MachineBasicBlock::iterator FirstCSPop = MBBI; - if (IsFunclet && Terminator->getOpcode() == X86::CATCHRET) - emitCatchRetReturnValue(MBB, FirstCSPop, &*Terminator); + if (TargetMBB) { + // Fill EAX/RAX with the address of the target block. + unsigned ReturnReg = STI.is64Bit() ? X86::RAX : X86::EAX; + if (STI.is64Bit()) { + // LEA64r TargetMBB(%rip), %rax + BuildMI(MBB, FirstCSPop, DL, TII.get(X86::LEA64r), ReturnReg) + .addReg(X86::RIP) + .addImm(0) + .addReg(0) + .addMBB(TargetMBB) + .addReg(0); + } else { + // MOV32ri $TargetMBB, %eax + BuildMI(MBB, FirstCSPop, DL, TII.get(X86::MOV32ri), ReturnReg) + .addMBB(TargetMBB); + } + // Record that we've taken the address of TargetMBB and no longer just + // reference it in a terminator. + TargetMBB->setHasAddressTaken(); + } if (MBBI != MBB.end()) DL = MBBI->getDebugLoc(); // If there is an ADD32ri or SUB32ri of ESP immediately before this // instruction, merge the two instructions. - if (NumBytes || MFI.hasVarSizedObjects()) + if (NumBytes || MFI->hasVarSizedObjects()) NumBytes += mergeSPUpdates(MBB, MBBI, true); // If dynamic alloca is used, then reset esp to point to the last callee-saved // slot before popping them off! Same applies for the case, when stack was // realigned. Don't do this if this was a funclet epilogue, since the funclets // will not do realignment or dynamic stack allocation. - if ((TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) && + if ((TRI->needsStackRealignment(MF) || MFI->hasVarSizedObjects()) && !IsFunclet) { if (TRI->needsStackRealignment(MF)) MBBI = FirstCSPop; @@ -1659,33 +1586,36 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // into the epilogue. To cope with that, we insert an epilogue marker here, // then replace it with a 'nop' if it ends up immediately after a CALL in the // final emitted code. - if (NeedsWin64CFI && MF.hasWinCFI()) + if (NeedsWinCFI) BuildMI(MBB, MBBI, DL, TII.get(X86::SEH_Epilogue)); - if (Terminator == MBB.end() || !isTailCallOpcode(Terminator->getOpcode())) { - // Add the return addr area delta back since we are not tail calling. - int Offset = -1 * X86FI->getTCReturnAddrDelta(); - assert(Offset >= 0 && "TCDelta should never be positive"); - if (Offset) { - // Check for possible merge with preceding ADD instruction. - Offset += mergeSPUpdates(MBB, Terminator, true); - emitSPUpdate(MBB, Terminator, Offset, /*InEpilogue=*/true); - } + // Add the return addr area delta back since we are not tail calling. + int Offset = -1 * X86FI->getTCReturnAddrDelta(); + assert(Offset >= 0 && "TCDelta should never be positive"); + if (Offset) { + MBBI = MBB.getFirstTerminator(); + + // Check for possible merge with preceding ADD instruction. + Offset += mergeSPUpdates(MBB, MBBI, true); + emitSPUpdate(MBB, MBBI, Offset, /*InEpilogue=*/true); } } +// NOTE: this only has a subset of the full frame index logic. In +// particular, the FI < 0 and AfterFPPop logic is handled in +// X86RegisterInfo::eliminateFrameIndex, but not here. Possibly +// (probably?) it should be moved into here. int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); - bool IsFixed = MFI.isFixedObjectIndex(FI); // We can't calculate offset from frame pointer if the stack is realigned, // so enforce usage of stack/base pointer. The base pointer is used when we // have dynamic allocas in addition to dynamic realignment. if (TRI->hasBasePointer(MF)) - FrameReg = IsFixed ? TRI->getFramePtr() : TRI->getBaseRegister(); + FrameReg = TRI->getBaseRegister(); else if (TRI->needsStackRealignment(MF)) - FrameReg = IsFixed ? TRI->getFramePtr() : TRI->getStackRegister(); + FrameReg = TRI->getStackRegister(); else FrameReg = TRI->getFrameRegister(MF); @@ -1693,16 +1623,16 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, // object. // We need to factor in additional offsets applied during the prologue to the // frame, base, and stack pointer depending on which is used. - int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea(); + int Offset = MFI->getObjectOffset(FI) - getOffsetOfLocalArea(); const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); unsigned CSSize = X86FI->getCalleeSavedFrameSize(); - uint64_t StackSize = MFI.getStackSize(); + uint64_t StackSize = MFI->getStackSize(); bool HasFP = hasFP(MF); bool IsWin64Prologue = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); int64_t FPDelta = 0; if (IsWin64Prologue) { - assert(!MFI.hasCalls() || (StackSize % 16) == 8); + assert(!MFI->hasCalls() || (StackSize % 16) == 8); // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; @@ -1720,7 +1650,7 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, // restricted Win64 prologue. // Add FPDelta to all offsets below that go through the frame pointer. FPDelta = FrameSize - SEHFrameOffset; - assert((!MFI.hasCalls() || (FPDelta % 16) == 0) && + assert((!MFI->hasCalls() || (FPDelta % 16) == 0) && "FPDelta isn't aligned per the Win64 ABI!"); } @@ -1731,7 +1661,7 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, // Skip the saved EBP. return Offset + SlotSize + FPDelta; } else { - assert((-(Offset + StackSize)) % MFI.getObjectAlignment(FI) == 0); + assert((-(Offset + StackSize)) % MFI->getObjectAlignment(FI) == 0); return Offset + StackSize; } } else if (TRI->needsStackRealignment(MF)) { @@ -1739,7 +1669,7 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, // Skip the saved EBP. return Offset + SlotSize + FPDelta; } else { - assert((-(Offset + StackSize)) % MFI.getObjectAlignment(FI) == 0); + assert((-(Offset + StackSize)) % MFI->getObjectAlignment(FI) == 0); return Offset + StackSize; } // FIXME: Support tail calls @@ -1759,69 +1689,61 @@ int X86FrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI, return Offset + FPDelta; } -int X86FrameLowering::getFrameIndexReferenceSP(const MachineFunction &MF, - int FI, unsigned &FrameReg, - int Adjustment) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - FrameReg = TRI->getStackRegister(); - return MFI.getObjectOffset(FI) - getOffsetOfLocalArea() + Adjustment; -} - -int -X86FrameLowering::getFrameIndexReferencePreferSP(const MachineFunction &MF, - int FI, unsigned &FrameReg, - bool IgnoreSPUpdates) const { - - const MachineFrameInfo &MFI = MF.getFrameInfo(); +// Simplified from getFrameIndexReference keeping only StackPointer cases +int X86FrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF, + int FI, + unsigned &FrameReg) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); // Does not include any dynamic realign. - const uint64_t StackSize = MFI.getStackSize(); - // LLVM arranges the stack as follows: - // ... - // ARG2 - // ARG1 - // RETADDR - // PUSH RBP <-- RBP points here - // PUSH CSRs - // ~~~~~~~ <-- possible stack realignment (non-win64) - // ... - // STACK OBJECTS - // ... <-- RSP after prologue points here - // ~~~~~~~ <-- possible stack realignment (win64) - // - // if (hasVarSizedObjects()): - // ... <-- "base pointer" (ESI/RBX) points here - // DYNAMIC ALLOCAS - // ... <-- RSP points here - // - // Case 1: In the simple case of no stack realignment and no dynamic - // allocas, both "fixed" stack objects (arguments and CSRs) are addressable - // with fixed offsets from RSP. - // - // Case 2: In the case of stack realignment with no dynamic allocas, fixed - // stack objects are addressed with RBP and regular stack objects with RSP. - // - // Case 3: In the case of dynamic allocas and stack realignment, RSP is used - // to address stack arguments for outgoing calls and nothing else. The "base - // pointer" points to local variables, and RBP points to fixed objects. - // - // In cases 2 and 3, we can only answer for non-fixed stack objects, and the - // answer we give is relative to the SP after the prologue, and not the - // SP in the middle of the function. - - if (MFI.isFixedObjectIndex(FI) && TRI->needsStackRealignment(MF) && - !STI.isTargetWin64()) - return getFrameIndexReference(MF, FI, FrameReg); - - // If !hasReservedCallFrame the function might have SP adjustement in the - // body. So, even though the offset is statically known, it depends on where - // we are in the function. - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - if (!IgnoreSPUpdates && !TFI->hasReservedCallFrame(MF)) - return getFrameIndexReference(MF, FI, FrameReg); + const uint64_t StackSize = MFI->getStackSize(); + { +#ifndef NDEBUG + // LLVM arranges the stack as follows: + // ... + // ARG2 + // ARG1 + // RETADDR + // PUSH RBP <-- RBP points here + // PUSH CSRs + // ~~~~~~~ <-- possible stack realignment (non-win64) + // ... + // STACK OBJECTS + // ... <-- RSP after prologue points here + // ~~~~~~~ <-- possible stack realignment (win64) + // + // if (hasVarSizedObjects()): + // ... <-- "base pointer" (ESI/RBX) points here + // DYNAMIC ALLOCAS + // ... <-- RSP points here + // + // Case 1: In the simple case of no stack realignment and no dynamic + // allocas, both "fixed" stack objects (arguments and CSRs) are addressable + // with fixed offsets from RSP. + // + // Case 2: In the case of stack realignment with no dynamic allocas, fixed + // stack objects are addressed with RBP and regular stack objects with RSP. + // + // Case 3: In the case of dynamic allocas and stack realignment, RSP is used + // to address stack arguments for outgoing calls and nothing else. The "base + // pointer" points to local variables, and RBP points to fixed objects. + // + // In cases 2 and 3, we can only answer for non-fixed stack objects, and the + // answer we give is relative to the SP after the prologue, and not the + // SP in the middle of the function. + + assert((!MFI->isFixedObjectIndex(FI) || !TRI->needsStackRealignment(MF) || + STI.isTargetWin64()) && + "offset from fixed object to SP is not static"); + + // We don't handle tail calls, and shouldn't be seeing them either. + int TailCallReturnAddrDelta = + MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta(); + assert(!(TailCallReturnAddrDelta < 0) && "we don't handle this case!"); +#endif + } - // We don't handle tail calls, and shouldn't be seeing them either. - assert(MF.getInfo<X86MachineFunctionInfo>()->getTCReturnAddrDelta() >= 0 && - "we don't handle this case!"); + // Fill in FrameReg output argument. + FrameReg = TRI->getStackRegister(); // This is how the math works out: // @@ -1837,7 +1759,7 @@ X86FrameLowering::getFrameIndexReferencePreferSP(const MachineFunction &MF, // // A is the incoming stack pointer. // (B - A) is the local area offset (-8 for x86-64) [1] - // (C - A) is the Offset returned by MFI.getObjectOffset for Obj0 [2] + // (C - A) is the Offset returned by MFI->getObjectOffset for Obj0 [2] // // |(E - B)| is the StackSize (absolute value, positive). For a // stack that grown down, this works out to be (B - E). [3] @@ -1847,14 +1769,18 @@ X86FrameLowering::getFrameIndexReferencePreferSP(const MachineFunction &MF, // (C - E) == (C - A) - (B - A) + (B - E) // { Using [1], [2] and [3] above } // == getObjectOffset - LocalAreaOffset + StackSize + // + + // Get the Offset from the StackPointer + int Offset = MFI->getObjectOffset(FI) - getOffsetOfLocalArea(); - return getFrameIndexReferenceSP(MF, FI, FrameReg, StackSize); + return Offset + StackSize; } bool X86FrameLowering::assignCalleeSavedSpillSlots( MachineFunction &MF, const TargetRegisterInfo *TRI, std::vector<CalleeSavedInfo> &CSI) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); unsigned CalleeSavedFrameSize = 0; @@ -1863,7 +1789,7 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( if (hasFP(MF)) { // emitPrologue always spills frame register the first thing. SpillSlotOffset -= SlotSize; - MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + MFI->CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); // Since emitPrologue and emitEpilogue will handle spilling and restoring of // the frame register, we can delete it from CSI list and not have to worry @@ -1887,7 +1813,7 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( SpillSlotOffset -= SlotSize; CalleeSavedFrameSize += SlotSize; - int SlotIndex = MFI.CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); + int SlotIndex = MFI->CreateFixedSpillStackObject(SlotSize, SpillSlotOffset); CSI[i - 1].setFrameIdx(SlotIndex); } @@ -1900,15 +1826,14 @@ bool X86FrameLowering::assignCalleeSavedSpillSlots( continue; const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - unsigned Size = TRI->getSpillSize(*RC); - unsigned Align = TRI->getSpillAlignment(*RC); // ensure alignment - SpillSlotOffset -= std::abs(SpillSlotOffset) % Align; + SpillSlotOffset -= std::abs(SpillSlotOffset) % RC->getAlignment(); // spill into slot - SpillSlotOffset -= Size; - int SlotIndex = MFI.CreateFixedSpillStackObject(Size, SpillSlotOffset); + SpillSlotOffset -= RC->getSize(); + int SlotIndex = + MFI->CreateFixedSpillStackObject(RC->getSize(), SpillSlotOffset); CSI[i - 1].setFrameIdx(SlotIndex); - MFI.ensureMaxAlignment(Align); + MFI->ensureMaxAlignment(RC->getAlignment()); } return true; @@ -1926,37 +1851,16 @@ bool X86FrameLowering::spillCalleeSavedRegisters( return true; // Push GPRs. It increases frame size. - const MachineFunction &MF = *MBB.getParent(); unsigned Opc = STI.is64Bit() ? X86::PUSH64r : X86::PUSH32r; for (unsigned i = CSI.size(); i != 0; --i) { unsigned Reg = CSI[i - 1].getReg(); if (!X86::GR64RegClass.contains(Reg) && !X86::GR32RegClass.contains(Reg)) continue; + // Add the callee-saved register as live-in. It's killed at the spill. + MBB.addLiveIn(Reg); - const MachineRegisterInfo &MRI = MF.getRegInfo(); - bool isLiveIn = MRI.isLiveIn(Reg); - if (!isLiveIn) - MBB.addLiveIn(Reg); - - // Decide whether we can add a kill flag to the use. - bool CanKill = !isLiveIn; - // Check if any subregister is live-in - if (CanKill) { - for (MCRegAliasIterator AReg(Reg, TRI, false); AReg.isValid(); ++AReg) { - if (MRI.isLiveIn(*AReg)) { - CanKill = false; - break; - } - } - } - - // Do not set a kill flag on values that are also marked as live-in. This - // happens with the @llvm-returnaddress intrinsic and with arguments - // passed in callee saved registers. - // Omitting the kill flags is conservatively correct even if the live-in - // is not used after all. - BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, getKillRegState(CanKill)) + BuildMI(MBB, MI, DL, TII.get(Opc)).addReg(Reg, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); } @@ -1980,44 +1884,14 @@ bool X86FrameLowering::spillCalleeSavedRegisters( return true; } -void X86FrameLowering::emitCatchRetReturnValue(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - MachineInstr *CatchRet) const { - // SEH shouldn't use catchret. - assert(!isAsynchronousEHPersonality(classifyEHPersonality( - MBB.getParent()->getFunction().getPersonalityFn())) && - "SEH should not use CATCHRET"); - DebugLoc DL = CatchRet->getDebugLoc(); - MachineBasicBlock *CatchRetTarget = CatchRet->getOperand(0).getMBB(); - - // Fill EAX/RAX with the address of the target block. - if (STI.is64Bit()) { - // LEA64r CatchRetTarget(%rip), %rax - BuildMI(MBB, MBBI, DL, TII.get(X86::LEA64r), X86::RAX) - .addReg(X86::RIP) - .addImm(0) - .addReg(0) - .addMBB(CatchRetTarget) - .addReg(0); - } else { - // MOV32ri $CatchRetTarget, %eax - BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32ri), X86::EAX) - .addMBB(CatchRetTarget); - } - - // Record that we've taken the address of CatchRetTarget and no longer just - // reference it in a terminator. - CatchRetTarget->setHasAddressTaken(); -} - bool X86FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - std::vector<CalleeSavedInfo> &CSI, + const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { if (CSI.empty()) return false; - if (MI != MBB.end() && isFuncletReturnInstr(*MI) && STI.isOSWindows()) { + if (isFuncletReturnInstr(MI) && STI.isOSWindows()) { // Don't restore CSRs in 32-bit EH funclets. Matches // spillCalleeSavedRegisters. if (STI.is32Bit()) @@ -2025,9 +1899,9 @@ bool X86FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, // Don't restore CSRs before an SEH catchret. SEH except blocks do not form // funclets. emitEpilogue transforms these to normal jumps. if (MI->getOpcode() == X86::CATCHRET) { - const Function &F = MBB.getParent()->getFunction(); + const Function *Func = MBB.getParent()->getFunction(); bool IsSEH = isAsynchronousEHPersonality( - classifyEHPersonality(F.getPersonalityFn())); + classifyEHPersonality(Func->getPersonalityFn())); if (IsSEH) return true; } @@ -2065,7 +1939,7 @@ void X86FrameLowering::determineCalleeSaves(MachineFunction &MF, RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); int64_t TailCallReturnAddrDelta = X86FI->getTCReturnAddrDelta(); @@ -2080,7 +1954,7 @@ void X86FrameLowering::determineCalleeSaves(MachineFunction &MF, // ... // } // [EBP] - MFI.CreateFixedObject(-TailCallReturnAddrDelta, + MFI->CreateFixedObject(-TailCallReturnAddrDelta, TailCallReturnAddrDelta - SlotSize, true); } @@ -2089,8 +1963,8 @@ void X86FrameLowering::determineCalleeSaves(MachineFunction &MF, SavedRegs.set(TRI->getBaseRegister()); // Allocate a spill slot for EBP if we have a base pointer and EH funclets. - if (MF.hasEHFunclets()) { - int FI = MFI.CreateSpillStackObject(SlotSize, SlotSize); + if (MF.getMMI().hasEHFunclets()) { + int FI = MFI->CreateSpillStackObject(SlotSize, SlotSize); X86FI->setHasSEHFramePtrSave(true); X86FI->setSEHFramePtrSaveIndex(FI); } @@ -2099,8 +1973,8 @@ void X86FrameLowering::determineCalleeSaves(MachineFunction &MF, static bool HasNestArgument(const MachineFunction *MF) { - const Function &F = MF->getFunction(); - for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); + const Function *F = MF->getFunction(); + for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; I++) { if (I->hasNestAttr()) return true; @@ -2114,7 +1988,7 @@ HasNestArgument(const MachineFunction *MF) { /// needed. Set primary to true for the first register, false for the second. static unsigned GetScratchRegister(bool Is64Bit, bool IsLP64, const MachineFunction &MF, bool Primary) { - CallingConv::ID CallingConvention = MF.getFunction().getCallingConv(); + CallingConv::ID CallingConvention = MF.getFunction()->getCallingConv(); // Erlang stuff. if (CallingConvention == CallingConv::HiPE) { @@ -2151,7 +2025,7 @@ static const uint64_t kSplitStackAvailable = 256; void X86FrameLowering::adjustForSegmentedStacks( MachineFunction &MF, MachineBasicBlock &PrologueMBB) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); uint64_t StackSize; unsigned TlsReg, TlsOffset; DebugLoc DL; @@ -2164,7 +2038,7 @@ void X86FrameLowering::adjustForSegmentedStacks( assert(!MF.getRegInfo().isLiveIn(ScratchReg) && "Scratch register is live-in"); - if (MF.getFunction().isVarArg()) + if (MF.getFunction()->isVarArg()) report_fatal_error("Segmented stacks do not support vararg functions."); if (!STI.isTargetLinux() && !STI.isTargetDarwin() && !STI.isTargetWin32() && !STI.isTargetWin64() && !STI.isTargetFreeBSD() && @@ -2174,7 +2048,7 @@ void X86FrameLowering::adjustForSegmentedStacks( // Eventually StackSize will be calculated by a link-time pass; which will // also decide whether checking code needs to be injected into this particular // prologue. - StackSize = MFI.getStackSize(); + StackSize = MFI->getStackSize(); // Do not generate a prologue for functions with a stack of size zero if (StackSize == 0) @@ -2350,10 +2224,6 @@ void X86FrameLowering::adjustForSegmentedStacks( // This solution is not perfect, as it assumes that the .rodata section // is laid out within 2^31 bytes of each function body, but this seems // to be sufficient for JIT. - // FIXME: Add retpoline support and remove the error here.. - if (STI.useRetpoline()) - report_fatal_error("Emitting morestack calls on 64-bit with the large " - "code model and retpoline not yet implemented."); BuildMI(allocMBB, DL, TII.get(X86::CALL64m)) .addReg(X86::RIP) .addImm(0) @@ -2380,33 +2250,11 @@ void X86FrameLowering::adjustForSegmentedStacks( checkMBB->addSuccessor(allocMBB); checkMBB->addSuccessor(&PrologueMBB); -#ifdef EXPENSIVE_CHECKS +#ifdef XDEBUG MF.verify(); #endif } -/// Lookup an ERTS parameter in the !hipe.literals named metadata node. -/// HiPE provides Erlang Runtime System-internal parameters, such as PCB offsets -/// to fields it needs, through a named metadata node "hipe.literals" containing -/// name-value pairs. -static unsigned getHiPELiteral( - NamedMDNode *HiPELiteralsMD, const StringRef LiteralName) { - for (int i = 0, e = HiPELiteralsMD->getNumOperands(); i != e; ++i) { - MDNode *Node = HiPELiteralsMD->getOperand(i); - if (Node->getNumOperands() != 2) continue; - MDString *NodeName = dyn_cast<MDString>(Node->getOperand(0)); - ValueAsMetadata *NodeVal = dyn_cast<ValueAsMetadata>(Node->getOperand(1)); - if (!NodeName || !NodeVal) continue; - ConstantInt *ValConst = dyn_cast_or_null<ConstantInt>(NodeVal->getValue()); - if (ValConst && NodeName->getString() == LiteralName) { - return ValConst->getZExtValue(); - } - } - - report_fatal_error("HiPE literal " + LiteralName - + " required but not provided"); -} - /// Erlang programs may need a special prologue to handle the stack size they /// might need at runtime. That is because Erlang/OTP does not implement a C /// stack but uses a custom implementation of hybrid stack/heap architecture. @@ -2424,7 +2272,7 @@ static unsigned getHiPELiteral( /// if( temp0 < SP_LIMIT(P) ) goto IncStack else goto OldStart void X86FrameLowering::adjustForHiPEPrologue( MachineFunction &MF, MachineBasicBlock &PrologueMBB) const { - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); DebugLoc DL; // To support shrink-wrapping we would need to insert the new blocks @@ -2432,19 +2280,12 @@ void X86FrameLowering::adjustForHiPEPrologue( assert(&(*MF.begin()) == &PrologueMBB && "Shrink-wrapping not supported yet"); // HiPE-specific values - NamedMDNode *HiPELiteralsMD = MF.getMMI().getModule() - ->getNamedMetadata("hipe.literals"); - if (!HiPELiteralsMD) - report_fatal_error( - "Can't generate HiPE prologue without runtime parameters"); - const unsigned HipeLeafWords - = getHiPELiteral(HiPELiteralsMD, - Is64Bit ? "AMD64_LEAF_WORDS" : "X86_LEAF_WORDS"); + const unsigned HipeLeafWords = 24; const unsigned CCRegisteredArgs = Is64Bit ? 6 : 5; const unsigned Guaranteed = HipeLeafWords * SlotSize; - unsigned CallerStkArity = MF.getFunction().arg_size() > CCRegisteredArgs ? - MF.getFunction().arg_size() - CCRegisteredArgs : 0; - unsigned MaxStack = MFI.getStackSize() + CallerStkArity*SlotSize + SlotSize; + unsigned CallerStkArity = MF.getFunction()->arg_size() > CCRegisteredArgs ? + MF.getFunction()->arg_size() - CCRegisteredArgs : 0; + unsigned MaxStack = MFI->getStackSize() + CallerStkArity*SlotSize + SlotSize; assert(STI.isTargetLinux() && "HiPE prologue is only supported on Linux operating systems."); @@ -2456,16 +2297,18 @@ void X86FrameLowering::adjustForHiPEPrologue( // b) outgoing on-stack parameter areas, and // c) the minimum stack space this function needs to make available for the // functions it calls (a tunable ABI property). - if (MFI.hasCalls()) { + if (MFI->hasCalls()) { unsigned MoreStackForCalls = 0; - for (auto &MBB : MF) { - for (auto &MI : MBB) { - if (!MI.isCall()) + for (MachineFunction::iterator MBBI = MF.begin(), MBBE = MF.end(); + MBBI != MBBE; ++MBBI) + for (MachineBasicBlock::iterator MI = MBBI->begin(), ME = MBBI->end(); + MI != ME; ++MI) { + if (!MI->isCall()) continue; // Get callee operand. - const MachineOperand &MO = MI.getOperand(0); + const MachineOperand &MO = MI->getOperand(0); // Only take account of global function calls (no closures etc.). if (!MO.isGlobal()) @@ -2491,7 +2334,6 @@ void X86FrameLowering::adjustForHiPEPrologue( MoreStackForCalls = std::max(MoreStackForCalls, (HipeLeafWords - 1 - CalleeStkArity) * SlotSize); } - } MaxStack += MoreStackForCalls; } @@ -2511,19 +2353,20 @@ void X86FrameLowering::adjustForHiPEPrologue( unsigned ScratchReg, SPReg, PReg, SPLimitOffset; unsigned LEAop, CMPop, CALLop; - SPLimitOffset = getHiPELiteral(HiPELiteralsMD, "P_NSP_LIMIT"); if (Is64Bit) { SPReg = X86::RSP; PReg = X86::RBP; LEAop = X86::LEA64r; CMPop = X86::CMP64rm; CALLop = X86::CALL64pcrel32; + SPLimitOffset = 0x90; } else { SPReg = X86::ESP; PReg = X86::EBP; LEAop = X86::LEA32r; CMPop = X86::CMP32rm; CALLop = X86::CALLpcrel32; + SPLimitOffset = 0x4c; } ScratchReg = GetScratchRegister(Is64Bit, IsLP64, MF, true); @@ -2552,15 +2395,13 @@ void X86FrameLowering::adjustForHiPEPrologue( incStackMBB->addSuccessor(&PrologueMBB, {99, 100}); incStackMBB->addSuccessor(incStackMBB, {1, 100}); } -#ifdef EXPENSIVE_CHECKS +#ifdef XDEBUG MF.verify(); #endif } bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, - int Offset) const { + MachineBasicBlock::iterator MBBI, DebugLoc DL, int Offset) const { if (Offset <= 0) return false; @@ -2584,7 +2425,6 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, unsigned Regs[2]; unsigned FoundRegs = 0; - auto &MRI = MBB.getParent()->getRegInfo(); auto RegMask = Prev->getOperand(1); auto &RegClass = @@ -2598,14 +2438,11 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, if (!RegMask.clobbersPhysReg(Candidate)) continue; - // Don't clobber reserved registers - if (MRI.isReserved(Candidate)) - continue; - bool IsDef = false; for (const MachineOperand &MO : Prev->implicit_operands()) { if (MO.isReg() && MO.isDef() && - TRI->isSuperOrSubRegisterEq(MO.getReg(), Candidate)) { + (TRI->isSubRegisterEq(MO.getReg(), Candidate) || + TRI->isSuperRegister(MO.getReg(), Candidate))) { IsDef = true; break; } @@ -2633,17 +2470,16 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, return true; } -MachineBasicBlock::iterator X86FrameLowering:: +void X86FrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { bool reserveCallFrame = hasReservedCallFrame(MF); unsigned Opcode = I->getOpcode(); bool isDestroy = Opcode == TII.getCallFrameDestroyOpcode(); DebugLoc DL = I->getDebugLoc(); - uint64_t Amount = !reserveCallFrame ? TII.getFrameSize(*I) : 0; - uint64_t InternalAmt = (isDestroy || Amount) ? TII.getFrameAdjustment(*I) : 0; + uint64_t Amount = !reserveCallFrame ? I->getOperand(0).getImm() : 0; + uint64_t InternalAmt = (isDestroy || Amount) ? I->getOperand(1).getImm() : 0; I = MBB.erase(I); - auto InsertPos = skipDebugInstructionsForward(I, MBB.end()); if (!reserveCallFrame) { // If the stack pointer can be changed after prologue, turn the @@ -2654,13 +2490,13 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // amount of space needed for the outgoing arguments up to the next // alignment boundary. unsigned StackAlign = getStackAlignment(); - Amount = alignTo(Amount, StackAlign); + Amount = RoundUpToAlignment(Amount, StackAlign); MachineModuleInfo &MMI = MF.getMMI(); - const Function &F = MF.getFunction(); + const Function *Fn = MF.getFunction(); bool WindowsCFI = MF.getTarget().getMCAsmInfo()->usesWindowsCFI(); - bool DwarfCFI = !WindowsCFI && - (MMI.hasDebugInfo() || F.needsUnwindTableEntry()); + bool DwarfCFI = !WindowsCFI && + (MMI.hasDebugInfo() || Fn->needsUnwindTableEntry()); // If we have any exception handlers in this function, and we adjust // the SP before calls, we may need to indicate this to the unwinder @@ -2669,15 +2505,16 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // GNU_ARGS_SIZE. // TODO: We don't need to reset this between subsequent functions, // if it didn't change. - bool HasDwarfEHHandlers = !WindowsCFI && !MF.getLandingPads().empty(); + bool HasDwarfEHHandlers = !WindowsCFI && + !MF.getMMI().getLandingPads().empty(); if (HasDwarfEHHandlers && !isDestroy && MF.getInfo<X86MachineFunctionInfo>()->getHasPushSequences()) - BuildCFI(MBB, InsertPos, DL, + BuildCFI(MBB, I, DL, MCCFIInstruction::createGnuArgsSize(nullptr, Amount)); if (Amount == 0) - return I; + return; // Factor out the amount that gets handled inside the sequence // (Pushes of argument for frame setup, callee pops for frame destroy) @@ -2687,26 +2524,16 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // If this is a callee-pop calling convention, emit a CFA adjust for // the amount the callee popped. if (isDestroy && InternalAmt && DwarfCFI && !hasFP(MF)) - BuildCFI(MBB, InsertPos, DL, + BuildCFI(MBB, I, DL, MCCFIInstruction::createAdjustCfaOffset(nullptr, -InternalAmt)); - // Add Amount to SP to destroy a frame, or subtract to setup. - int64_t StackAdjustment = isDestroy ? Amount : -Amount; - int64_t CfaAdjustment = -StackAdjustment; - - if (StackAdjustment) { - // Merge with any previous or following adjustment instruction. Note: the - // instructions merged with here do not have CFI, so their stack - // adjustments do not feed into CfaAdjustment. - StackAdjustment += mergeSPUpdates(MBB, InsertPos, true); - StackAdjustment += mergeSPUpdates(MBB, InsertPos, false); - - if (StackAdjustment) { - if (!(F.optForMinSize() && - adjustStackWithPops(MBB, InsertPos, DL, StackAdjustment))) - BuildStackAdjustment(MBB, InsertPos, DL, StackAdjustment, - /*InEpilogue=*/false); - } + if (Amount) { + // Add Amount to SP to destroy a frame, and subtract to setup. + int Offset = isDestroy ? Amount : -Amount; + + if (!(Fn->optForMinSize() && + adjustStackWithPops(MBB, I, DL, Offset))) + BuildStackAdjustment(MBB, I, DL, Offset, /*InEpilogue=*/false); } if (DwarfCFI && !hasFP(MF)) { @@ -2716,17 +2543,18 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // CFI only for EH purposes or for debugging. EH only requires the CFA // offset to be correct at each call site, while for debugging we want // it to be more precise. - + int CFAOffset = Amount; // TODO: When not using precise CFA, we also need to adjust for the // InternalAmt here. - if (CfaAdjustment) { - BuildCFI(MBB, InsertPos, DL, - MCCFIInstruction::createAdjustCfaOffset(nullptr, - CfaAdjustment)); + + if (CFAOffset) { + CFAOffset = isDestroy ? -CFAOffset : CFAOffset; + BuildCFI(MBB, I, DL, + MCCFIInstruction::createAdjustCfaOffset(nullptr, CFAOffset)); } } - return I; + return; } if (isDestroy && InternalAmt) { @@ -2736,14 +2564,11 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, // We are not tracking the stack pointer adjustment by the callee, so make // sure we restore the stack pointer immediately after the call, there may // be spill code inserted between the CALL and ADJCALLSTACKUP instructions. - MachineBasicBlock::iterator CI = I; MachineBasicBlock::iterator B = MBB.begin(); - while (CI != B && !std::prev(CI)->isCall()) - --CI; - BuildStackAdjustment(MBB, CI, DL, -InternalAmt, /*InEpilogue=*/false); + while (I != B && !std::prev(I)->isCall()) + --I; + BuildStackAdjustment(MBB, I, DL, -InternalAmt, /*InEpilogue=*/false); } - - return I; } bool X86FrameLowering::canUseAsPrologue(const MachineBasicBlock &MBB) const { @@ -2775,19 +2600,19 @@ bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { bool X86FrameLowering::enableShrinkWrapping(const MachineFunction &MF) const { // If we may need to emit frameless compact unwind information, give // up as this is currently broken: PR25614. - return (MF.getFunction().hasFnAttribute(Attribute::NoUnwind) || hasFP(MF)) && + return (MF.getFunction()->hasFnAttribute(Attribute::NoUnwind) || hasFP(MF)) && // The lowering of segmented stack and HiPE only support entry blocks // as prologue blocks: PR26107. // This limitation may be lifted if we fix: // - adjustForSegmentedStacks // - adjustForHiPEPrologue - MF.getFunction().getCallingConv() != CallingConv::HiPE && + MF.getFunction()->getCallingConv() != CallingConv::HiPE && !MF.shouldSplitStack(); } MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, bool RestoreSP) const { + DebugLoc DL, bool RestoreSP) const { assert(STI.isTargetWindowsMSVC() && "funclets only supported in MSVC env"); assert(STI.isTargetWin32() && "EBP/ESI restoration only required on win32"); assert(STI.is32Bit() && !Uses64BitFramePtr && @@ -2798,12 +2623,12 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( unsigned BasePtr = TRI->getBaseRegister(); WinEHFuncInfo &FuncInfo = *MF.getWinEHFuncInfo(); X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>(); - MachineFrameInfo &MFI = MF.getFrameInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); // FIXME: Don't set FrameSetup flag in catchret case. int FI = FuncInfo.EHRegNodeFrameIndex; - int EHRegSize = MFI.getObjectSize(FI); + int EHRegSize = MFI->getObjectSize(FI); if (RestoreSP) { // MOV32rm -EHRegSize(%ebp), %esp @@ -2847,150 +2672,6 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( return MBBI; } -namespace { -// Struct used by orderFrameObjects to help sort the stack objects. -struct X86FrameSortingObject { - bool IsValid = false; // true if we care about this Object. - unsigned ObjectIndex = 0; // Index of Object into MFI list. - unsigned ObjectSize = 0; // Size of Object in bytes. - unsigned ObjectAlignment = 1; // Alignment of Object in bytes. - unsigned ObjectNumUses = 0; // Object static number of uses. -}; - -// The comparison function we use for std::sort to order our local -// stack symbols. The current algorithm is to use an estimated -// "density". This takes into consideration the size and number of -// uses each object has in order to roughly minimize code size. -// So, for example, an object of size 16B that is referenced 5 times -// will get higher priority than 4 4B objects referenced 1 time each. -// It's not perfect and we may be able to squeeze a few more bytes out of -// it (for example : 0(esp) requires fewer bytes, symbols allocated at the -// fringe end can have special consideration, given their size is less -// important, etc.), but the algorithmic complexity grows too much to be -// worth the extra gains we get. This gets us pretty close. -// The final order leaves us with objects with highest priority going -// at the end of our list. -struct X86FrameSortingComparator { - inline bool operator()(const X86FrameSortingObject &A, - const X86FrameSortingObject &B) { - uint64_t DensityAScaled, DensityBScaled; - - // For consistency in our comparison, all invalid objects are placed - // at the end. This also allows us to stop walking when we hit the - // first invalid item after it's all sorted. - if (!A.IsValid) - return false; - if (!B.IsValid) - return true; - - // The density is calculated by doing : - // (double)DensityA = A.ObjectNumUses / A.ObjectSize - // (double)DensityB = B.ObjectNumUses / B.ObjectSize - // Since this approach may cause inconsistencies in - // the floating point <, >, == comparisons, depending on the floating - // point model with which the compiler was built, we're going - // to scale both sides by multiplying with - // A.ObjectSize * B.ObjectSize. This ends up factoring away - // the division and, with it, the need for any floating point - // arithmetic. - DensityAScaled = static_cast<uint64_t>(A.ObjectNumUses) * - static_cast<uint64_t>(B.ObjectSize); - DensityBScaled = static_cast<uint64_t>(B.ObjectNumUses) * - static_cast<uint64_t>(A.ObjectSize); - - // If the two densities are equal, prioritize highest alignment - // objects. This allows for similar alignment objects - // to be packed together (given the same density). - // There's room for improvement here, also, since we can pack - // similar alignment (different density) objects next to each - // other to save padding. This will also require further - // complexity/iterations, and the overall gain isn't worth it, - // in general. Something to keep in mind, though. - if (DensityAScaled == DensityBScaled) - return A.ObjectAlignment < B.ObjectAlignment; - - return DensityAScaled < DensityBScaled; - } -}; -} // namespace - -// Order the symbols in the local stack. -// We want to place the local stack objects in some sort of sensible order. -// The heuristic we use is to try and pack them according to static number -// of uses and size of object in order to minimize code size. -void X86FrameLowering::orderFrameObjects( - const MachineFunction &MF, SmallVectorImpl<int> &ObjectsToAllocate) const { - const MachineFrameInfo &MFI = MF.getFrameInfo(); - - // Don't waste time if there's nothing to do. - if (ObjectsToAllocate.empty()) - return; - - // Create an array of all MFI objects. We won't need all of these - // objects, but we're going to create a full array of them to make - // it easier to index into when we're counting "uses" down below. - // We want to be able to easily/cheaply access an object by simply - // indexing into it, instead of having to search for it every time. - std::vector<X86FrameSortingObject> SortingObjects(MFI.getObjectIndexEnd()); - - // Walk the objects we care about and mark them as such in our working - // struct. - for (auto &Obj : ObjectsToAllocate) { - SortingObjects[Obj].IsValid = true; - SortingObjects[Obj].ObjectIndex = Obj; - SortingObjects[Obj].ObjectAlignment = MFI.getObjectAlignment(Obj); - // Set the size. - int ObjectSize = MFI.getObjectSize(Obj); - if (ObjectSize == 0) - // Variable size. Just use 4. - SortingObjects[Obj].ObjectSize = 4; - else - SortingObjects[Obj].ObjectSize = ObjectSize; - } - - // Count the number of uses for each object. - for (auto &MBB : MF) { - for (auto &MI : MBB) { - if (MI.isDebugValue()) - continue; - for (const MachineOperand &MO : MI.operands()) { - // Check to see if it's a local stack symbol. - if (!MO.isFI()) - continue; - int Index = MO.getIndex(); - // Check to see if it falls within our range, and is tagged - // to require ordering. - if (Index >= 0 && Index < MFI.getObjectIndexEnd() && - SortingObjects[Index].IsValid) - SortingObjects[Index].ObjectNumUses++; - } - } - } - - // Sort the objects using X86FrameSortingAlgorithm (see its comment for - // info). - std::stable_sort(SortingObjects.begin(), SortingObjects.end(), - X86FrameSortingComparator()); - - // Now modify the original list to represent the final order that - // we want. The order will depend on whether we're going to access them - // from the stack pointer or the frame pointer. For SP, the list should - // end up with the END containing objects that we want with smaller offsets. - // For FP, it should be flipped. - int i = 0; - for (auto &Obj : SortingObjects) { - // All invalid items are sorted at the end, so it's safe to stop. - if (!Obj.IsValid) - break; - ObjectsToAllocate[i++] = Obj.ObjectIndex; - } - - // Flip it if we're accessing off of the FP. - if (!TRI->needsStackRealignment(MF) && hasFP(MF)) - std::reverse(ObjectsToAllocate.begin(), ObjectsToAllocate.end()); -} - - unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF) const { // RDX, the parent frame pointer, is homed into 16(%rsp) in the prologue. unsigned Offset = 16; @@ -3005,15 +2686,11 @@ unsigned X86FrameLowering::getWinEHParentFrameOffset(const MachineFunction &MF) void X86FrameLowering::processFunctionBeforeFrameFinalized( MachineFunction &MF, RegScavenger *RS) const { - // Mark the function as not having WinCFI. We will set it back to true in - // emitPrologue if it gets called and emits CFI. - MF.setHasWinCFI(false); - // If this function isn't doing Win64-style C++ EH, we don't need to do // anything. - const Function &F = MF.getFunction(); - if (!STI.is64Bit() || !MF.hasEHFunclets() || - classifyEHPersonality(F.getPersonalityFn()) != EHPersonality::MSVC_CXX) + const Function *Fn = MF.getFunction(); + if (!STI.is64Bit() || !MF.getMMI().hasEHFunclets() || + classifyEHPersonality(Fn->getPersonalityFn()) != EHPersonality::MSVC_CXX) return; // Win64 C++ EH needs to allocate the UnwindHelp object at some fixed offset @@ -3021,31 +2698,15 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized( // object, so that we can allocate a slot immediately following it. If there // were no fixed objects, use offset -SlotSize, which is immediately after the // return address. Fixed objects have negative frame indices. - MachineFrameInfo &MFI = MF.getFrameInfo(); - WinEHFuncInfo &EHInfo = *MF.getWinEHFuncInfo(); + MachineFrameInfo *MFI = MF.getFrameInfo(); int64_t MinFixedObjOffset = -SlotSize; - for (int I = MFI.getObjectIndexBegin(); I < 0; ++I) - MinFixedObjOffset = std::min(MinFixedObjOffset, MFI.getObjectOffset(I)); - - for (WinEHTryBlockMapEntry &TBME : EHInfo.TryBlockMap) { - for (WinEHHandlerType &H : TBME.HandlerArray) { - int FrameIndex = H.CatchObj.FrameIndex; - if (FrameIndex != INT_MAX) { - // Ensure alignment. - unsigned Align = MFI.getObjectAlignment(FrameIndex); - MinFixedObjOffset -= std::abs(MinFixedObjOffset) % Align; - MinFixedObjOffset -= MFI.getObjectSize(FrameIndex); - MFI.setObjectOffset(FrameIndex, MinFixedObjOffset); - } - } - } + for (int I = MFI->getObjectIndexBegin(); I < 0; ++I) + MinFixedObjOffset = std::min(MinFixedObjOffset, MFI->getObjectOffset(I)); - // Ensure alignment. - MinFixedObjOffset -= std::abs(MinFixedObjOffset) % 8; int64_t UnwindHelpOffset = MinFixedObjOffset - SlotSize; int UnwindHelpFI = - MFI.CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false); - EHInfo.UnwindHelpFrameIdx = UnwindHelpFI; + MFI->CreateFixedObject(SlotSize, UnwindHelpOffset, /*Immutable=*/false); + MF.getWinEHFuncInfo()->UnwindHelpFrameIdx = UnwindHelpFI; // Store -2 into UnwindHelp on function entry. We have to scan forwards past // other frame setup instructions. diff --git a/gnu/llvm/lib/Target/X86/X86FrameLowering.h b/gnu/llvm/lib/Target/X86/X86FrameLowering.h index 909319fc18f..65fed3ddb29 100644 --- a/gnu/llvm/lib/Target/X86/X86FrameLowering.h +++ b/gnu/llvm/lib/Target/X86/X86FrameLowering.h @@ -14,13 +14,12 @@ #ifndef LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H #define LLVM_LIB_TARGET_X86_X86FRAMELOWERING_H -#include "llvm/CodeGen/TargetFrameLowering.h" +#include "llvm/Target/TargetFrameLowering.h" namespace llvm { class MachineInstrBuilder; class MCCFIInstruction; -class X86InstrInfo; class X86Subtarget; class X86RegisterInfo; @@ -31,7 +30,7 @@ public: // Cached subtarget predicates. const X86Subtarget &STI; - const X86InstrInfo &TII; + const TargetInstrInfo &TII; const X86RegisterInfo *TRI; unsigned SlotSize; @@ -50,10 +49,11 @@ public: /// Emit target stack probe code. This is required for all /// large stack allocations on Windows. The caller is required to materialize - /// the number of bytes to probe in RAX/EAX. - void emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, const DebugLoc &DL, - bool InProlog) const; + /// the number of bytes to probe in RAX/EAX. Returns instruction just + /// after the expansion. + MachineInstr *emitStackProbe(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc DL, + bool InProlog) const; /// Replace a StackProbe inline-stub with the actual probe code inline. void inlineStackProbe(MachineFunction &MF, @@ -61,7 +61,7 @@ public: void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL) const; + DebugLoc DL) const; /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. @@ -89,7 +89,7 @@ public: bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - std::vector<CalleeSavedInfo> &CSI, + const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const override; bool hasFP(const MachineFunction &MF) const override; @@ -100,15 +100,12 @@ public: int getFrameIndexReference(const MachineFunction &MF, int FI, unsigned &FrameReg) const override; - int getFrameIndexReferenceSP(const MachineFunction &MF, - int FI, unsigned &SPReg, int Adjustment) const; - int getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, - unsigned &FrameReg, - bool IgnoreSPUpdates) const override; + int getFrameIndexReferenceFromSP(const MachineFunction &MF, int FI, + unsigned &FrameReg) const override; - MachineBasicBlock::iterator - eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const override; + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const override; unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const override; @@ -150,66 +147,65 @@ public: /// Returns true if the target will correctly handle shrink wrapping. bool enableShrinkWrapping(const MachineFunction &MF) const override; - /// Order the symbols in the local stack. - /// We want to place the local stack objects in some sort of sensible order. - /// The heuristic we use is to try and pack them according to static number - /// of uses and size in order to minimize code size. - void orderFrameObjects(const MachineFunction &MF, - SmallVectorImpl<int> &ObjectsToAllocate) const override; + /// convertArgMovsToPushes - This method tries to convert a call sequence + /// that uses sub and mov instructions to put the argument onto the stack + /// into a series of pushes. + /// Returns true if the transformation succeeded, false if not. + bool convertArgMovsToPushes(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + uint64_t Amount) const; /// Wraps up getting a CFI index and building a MachineInstr for it. void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, const MCCFIInstruction &CFIInst) const; + DebugLoc DL, MCCFIInstruction CFIInst) const; /// Sets up EBP and optionally ESI based on the incoming EBP value. Only /// needed for 32-bit. Used in funclet prologues and at catchret destinations. MachineBasicBlock::iterator restoreWin32EHStackPointers(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, bool RestoreSP = false) const; + MachineBasicBlock::iterator MBBI, DebugLoc DL, + bool RestoreSP = false) const; private: uint64_t calculateMaxStackAlign(const MachineFunction &MF) const; /// Emit target stack probe as a call to a helper function - void emitStackProbeCall(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, const DebugLoc &DL, - bool InProlog) const; + MachineInstr *emitStackProbeCall(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL, bool InProlog) const; /// Emit target stack probe as an inline sequence. - void emitStackProbeInline(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, bool InProlog) const; + MachineInstr *emitStackProbeInline(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL, bool InProlog) const; /// Emit a stub to later inline the target stack probe. - void emitStackProbeInlineStub(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, bool InProlog) const; + MachineInstr *emitStackProbeInlineStub(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + DebugLoc DL, bool InProlog) const; /// Aligns the stack pointer by ANDing it with -MaxAlign. void BuildStackAlignAND(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, const DebugLoc &DL, + MachineBasicBlock::iterator MBBI, DebugLoc DL, unsigned Reg, uint64_t MaxAlign) const; /// Make small positive stack adjustments using POPs. bool adjustStackWithPops(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, const DebugLoc &DL, + MachineBasicBlock::iterator MBBI, DebugLoc DL, int Offset) const; /// Adjusts the stack pointer using LEA, SUB, or ADD. MachineInstrBuilder BuildStackAdjustment(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - const DebugLoc &DL, int64_t Offset, + DebugLoc DL, int64_t Offset, bool InEpilogue) const; unsigned getPSPSlotOffsetFromSP(const MachineFunction &MF) const; unsigned getWinEHFuncletFrameSize(const MachineFunction &MF) const; - - /// Materialize the catchret target MBB in RAX. - void emitCatchRetReturnValue(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - MachineInstr *CatchRet) const; }; } // End llvm namespace diff --git a/gnu/llvm/lib/Target/X86/X86InstrCompiler.td b/gnu/llvm/lib/Target/X86/X86InstrCompiler.td index d66d9258e96..1cee25a26e7 100644 --- a/gnu/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/gnu/llvm/lib/Target/X86/X86InstrCompiler.td @@ -32,10 +32,9 @@ def GetLo8XForm : SDNodeXForm<imm, [{ // PIC base construction. This expands to code that looks like this: // call $next_inst // popl %destreg" -let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP], - SchedRW = [WriteJump] in +let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP] in def MOVPC32r : Ii32<0xE8, Pseudo, (outs GR32:$reg), (ins i32imm:$label), - "", [], IIC_CALL_RI>; + "", []>; // ADJCALLSTACKDOWN/UP implicitly use/def ESP because they may be expanded into @@ -43,18 +42,18 @@ let hasSideEffects = 0, isNotDuplicable = 1, Uses = [ESP, SSP], // pointer before prolog-epilog rewriting occurs. // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become // sub / add which can clobber EFLAGS. -let Defs = [ESP, EFLAGS, SSP], Uses = [ESP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), - "#ADJCALLSTACKDOWN", [], IIC_ALU_NONMEM>, - Requires<[NotLP64]>; +let Defs = [ESP, EFLAGS], Uses = [ESP] in { +def ADJCALLSTACKDOWN32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), + "#ADJCALLSTACKDOWN", + []>, + Requires<[NotLP64]>; def ADJCALLSTACKUP32 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)], - IIC_ALU_NONMEM>, Requires<[NotLP64]>; + [(X86callseq_end timm:$amt1, timm:$amt2)]>, + Requires<[NotLP64]>; } -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN32 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[NotLP64]>; +def : Pat<(X86callseq_start timm:$amt1), + (ADJCALLSTACKDOWN32 i32imm:$amt1, 0)>, Requires<[NotLP64]>; // ADJCALLSTACKDOWN/UP implicitly use/def RSP because they may be expanded into @@ -62,20 +61,19 @@ def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), // pointer before prolog-epilog rewriting occurs. // Pessimistically assume ADJCALLSTACKDOWN / ADJCALLSTACKUP will become // sub / add which can clobber EFLAGS. -let Defs = [RSP, EFLAGS, SSP], Uses = [RSP, SSP], SchedRW = [WriteALU] in { -def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), - (ins i32imm:$amt1, i32imm:$amt2, i32imm:$amt3), +let Defs = [RSP, EFLAGS], Uses = [RSP] in { +def ADJCALLSTACKDOWN64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKDOWN", - [], IIC_ALU_NONMEM>, Requires<[IsLP64]>; + []>, + Requires<[IsLP64]>; def ADJCALLSTACKUP64 : I<0, Pseudo, (outs), (ins i32imm:$amt1, i32imm:$amt2), "#ADJCALLSTACKUP", - [(X86callseq_end timm:$amt1, timm:$amt2)], - IIC_ALU_NONMEM>, Requires<[IsLP64]>; + [(X86callseq_end timm:$amt1, timm:$amt2)]>, + Requires<[IsLP64]>; } -def : Pat<(X86callseq_start timm:$amt1, timm:$amt2), - (ADJCALLSTACKDOWN64 i32imm:$amt1, i32imm:$amt2, 0)>, Requires<[IsLP64]>; +def : Pat<(X86callseq_start timm:$amt1), + (ADJCALLSTACKDOWN64 i32imm:$amt1, 0)>, Requires<[IsLP64]>; -let SchedRW = [WriteSystem] in { // x86-64 va_start lowering magic. let usesCustomInserter = 1, Defs = [EFLAGS] in { @@ -101,6 +99,18 @@ def VAARG_64 : I<0, Pseudo, (X86vaarg64 addr:$ap, imm:$size, imm:$mode, imm:$align)), (implicit EFLAGS)]>; +// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows +// targets. These calls are needed to probe the stack when allocating more than +// 4k bytes in one go. Touching the stack at 4K increments is necessary to +// ensure that the guard pages used by the OS virtual memory manager are +// allocated in correct sequence. +// The main point of having separate instruction are extra unmodelled effects +// (compared to ordinary calls) like stack pointer change. + +let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in + def WIN_ALLOCA : I<0, Pseudo, (outs), (ins), + "# dynamic stack allocation", + [(X86WinAlloca)]>; // When using segmented stacks these are lowered into instructions which first // check if the current stacklet has enough free memory. If it does, memory is @@ -122,39 +132,6 @@ def SEG_ALLOCA_64 : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$size), Requires<[In64BitMode]>; } -// Dynamic stack allocation yields a _chkstk or _alloca call for all Windows -// targets. These calls are needed to probe the stack when allocating more than -// 4k bytes in one go. Touching the stack at 4K increments is necessary to -// ensure that the guard pages used by the OS virtual memory manager are -// allocated in correct sequence. -// The main point of having separate instruction are extra unmodelled effects -// (compared to ordinary calls) like stack pointer change. - -let Defs = [EAX, ESP, EFLAGS], Uses = [ESP] in -def WIN_ALLOCA_32 : I<0, Pseudo, (outs), (ins GR32:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR32:$size)]>, - Requires<[NotLP64]>; - -let Defs = [RAX, RSP, EFLAGS], Uses = [RSP] in -def WIN_ALLOCA_64 : I<0, Pseudo, (outs), (ins GR64:$size), - "# dynamic stack allocation", - [(X86WinAlloca GR64:$size)]>, - Requires<[In64BitMode]>; -} // SchedRW - -// These instructions XOR the frame pointer into a GPR. They are used in some -// stack protection schemes. These are post-RA pseudos because we only know the -// frame register after register allocation. -let Constraints = "$src = $dst", isPseudo = 1, Defs = [EFLAGS] in { - def XOR32_FP : I<0, Pseudo, (outs GR32:$dst), (ins GR32:$src), - "xorl\t$$FP, $src", [], IIC_BIN_NONMEM>, - Requires<[NotLP64]>, Sched<[WriteALU]>; - def XOR64_FP : I<0, Pseudo, (outs GR64:$dst), (ins GR64:$src), - "xorq\t$$FP $src", [], IIC_BIN_NONMEM>, - Requires<[In64BitMode]>, Sched<[WriteALU]>; -} - //===----------------------------------------------------------------------===// // EH Pseudo Instructions // @@ -219,17 +196,17 @@ let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, Requires<[In64BitMode]>; } } +} // SchedRW let isBranch = 1, isTerminator = 1, isCodeGenOnly = 1 in { def EH_SjLj_Setup : I<0, Pseudo, (outs), (ins brtarget:$dst), "#EH_SjLj_Setup\t$dst", []>; } -} // SchedRW //===----------------------------------------------------------------------===// // Pseudo instructions used by unwind info. // -let isPseudo = 1, SchedRW = [WriteSystem] in { +let isPseudo = 1 in { def SEH_PushReg : I<0, Pseudo, (outs), (ins i32imm:$reg), "#SEH_PushReg $reg", []>; def SEH_SaveReg : I<0, Pseudo, (outs), (ins i32imm:$reg, i32imm:$dst), @@ -255,15 +232,15 @@ let isPseudo = 1, SchedRW = [WriteSystem] in { // This is lowered into a RET instruction by MCInstLower. We need // this so that we don't have to have a MachineBasicBlock which ends // with a RET and also has successors. -let isPseudo = 1, SchedRW = [WriteJumpLd] in { +let isPseudo = 1 in { def MORESTACK_RET: I<0, Pseudo, (outs), (ins), - "", [], IIC_RET>; + "", []>; // This instruction is lowered to a RET followed by a MOV. The two // instructions are not generated on a higher level since then the // verifier sees a MachineBasicBlock ending with a non-terminator. def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), - "", [], IIC_RET>; + "", []>; } //===----------------------------------------------------------------------===// @@ -273,54 +250,40 @@ def MORESTACK_RET_RESTORE_R10 : I<0, Pseudo, (outs), (ins), // Alias instruction mapping movr0 to xor. // FIXME: remove when we can teach regalloc that xor reg, reg is ok. let Defs = [EFLAGS], isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, AddedComplexity = 10 in + isPseudo = 1 in def MOV32r0 : I<0, Pseudo, (outs GR32:$dst), (ins), "", [(set GR32:$dst, 0)], IIC_ALU_NONMEM>, Sched<[WriteZero]>; // Other widths can also make use of the 32-bit xor, which may have a smaller // encoding and avoid partial register updates. -let AddedComplexity = 10 in { def : Pat<(i8 0), (EXTRACT_SUBREG (MOV32r0), sub_8bit)>; def : Pat<(i16 0), (EXTRACT_SUBREG (MOV32r0), sub_16bit)>; -def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)>; +def : Pat<(i64 0), (SUBREG_TO_REG (i64 0), (MOV32r0), sub_32bit)> { + let AddedComplexity = 20; } -let Predicates = [OptForSize, Not64BitMode], - AddedComplexity = 10 in { - let SchedRW = [WriteALU] in { +let Predicates = [OptForSize, NotSlowIncDec, Not64BitMode], + AddedComplexity = 1 in { // Pseudo instructions for materializing 1 and -1 using XOR+INC/DEC, // which only require 3 bytes compared to MOV32ri which requires 5. let Defs = [EFLAGS], isReMaterializable = 1, isPseudo = 1 in { def MOV32r1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, 1)], IIC_ALU_NONMEM>; + [(set GR32:$dst, 1)]>; def MOV32r_1 : I<0, Pseudo, (outs GR32:$dst), (ins), "", - [(set GR32:$dst, -1)], IIC_ALU_NONMEM>; + [(set GR32:$dst, -1)]>; } - } // SchedRW // MOV16ri is 4 bytes, so the instructions above are smaller. def : Pat<(i16 1), (EXTRACT_SUBREG (MOV32r1), sub_16bit)>; def : Pat<(i16 -1), (EXTRACT_SUBREG (MOV32r_1), sub_16bit)>; } -let isReMaterializable = 1, isPseudo = 1, AddedComplexity = 5, - SchedRW = [WriteALU] in { -// AddedComplexity higher than MOV64ri but lower than MOV32r0 and MOV32r1. -def MOV32ImmSExti8 : I<0, Pseudo, (outs GR32:$dst), (ins i32i8imm:$src), "", - [(set GR32:$dst, i32immSExt8:$src)], IIC_ALU_NONMEM>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -def MOV64ImmSExti8 : I<0, Pseudo, (outs GR64:$dst), (ins i64i8imm:$src), "", - [(set GR64:$dst, i64immSExt8:$src)], IIC_ALU_NONMEM>, - Requires<[OptForMinSize, NotWin64WithoutFP]>; -} - // Materialize i64 constant where top 32-bits are zero. This could theoretically // use MOV32ri with a SUBREG_TO_REG to represent the zero-extension, however // that would make it more difficult to rematerialize. let isReMaterializable = 1, isAsCheapAsAMove = 1, - isPseudo = 1, hasSideEffects = 0, SchedRW = [WriteALU] in -def MOV32ri64 : I<0, Pseudo, (outs GR32:$dst), (ins i64i32imm:$src), "", [], - IIC_ALU_NONMEM>; + isPseudo = 1, hasSideEffects = 0 in +def MOV32ri64 : I<0, Pseudo, (outs GR32:$dst), (ins i64i32imm:$src), "", []>; // This 64-bit pseudo-move can be used for both a 64-bit constant that is // actually the zero-extension of a 32-bit constant and for labels in the @@ -463,7 +426,6 @@ let Defs = [RCX,RDI], isCodeGenOnly = 1 in { //===----------------------------------------------------------------------===// // Thread Local Storage Instructions // -let SchedRW = [WriteSystem] in { // ELF TLS Support // All calls clobber the non-callee saved registers. ESP is marked as @@ -474,7 +436,7 @@ let Defs = [EAX, ECX, EDX, FP0, FP1, FP2, FP3, FP4, FP5, FP6, FP7, MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], - usesCustomInserter = 1, Uses = [ESP, SSP] in { + usesCustomInserter = 1, Uses = [ESP] in { def TLS_addr32 : I<0, Pseudo, (outs), (ins i32mem:$sym), "# TLS_addr32", [(X86tlsaddr tls32addr:$sym)]>, @@ -494,7 +456,7 @@ let Defs = [RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11, MM0, MM1, MM2, MM3, MM4, MM5, MM6, MM7, XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, EFLAGS], - usesCustomInserter = 1, Uses = [RSP, SSP] in { + usesCustomInserter = 1, Uses = [RSP] in { def TLS_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), "# TLS_addr64", [(X86tlsaddr tls64addr:$sym)]>, @@ -510,26 +472,23 @@ def TLS_base_addr64 : I<0, Pseudo, (outs), (ins i64mem:$sym), // address of the variable is in %eax. %ecx is trashed during the function // call. All other registers are preserved. let Defs = [EAX, ECX, EFLAGS], - Uses = [ESP, SSP], + Uses = [ESP], usesCustomInserter = 1 in def TLSCall_32 : I<0, Pseudo, (outs), (ins i32mem:$sym), "# TLSCall_32", [(X86TLSCall addr:$sym)]>, Requires<[Not64BitMode]>; -// For x86_64, the address of the thunk is passed in %rdi, but the -// pseudo directly use the symbol, so do not add an implicit use of -// %rdi. The lowering will do the right thing with RDI. -// On return the address of the variable is in %rax. All other -// registers are preserved. +// For x86_64, the address of the thunk is passed in %rdi, on return +// the address of the variable is in %rax. All other registers are preserved. let Defs = [RAX, EFLAGS], - Uses = [RSP, SSP], + Uses = [RSP, RDI], usesCustomInserter = 1 in def TLSCall_64 : I<0, Pseudo, (outs), (ins i64mem:$sym), "# TLSCall_64", [(X86TLSCall addr:$sym)]>, Requires<[In64BitMode]>; -} // SchedRW + //===----------------------------------------------------------------------===// // Conditional Move Pseudo Instructions @@ -544,7 +503,7 @@ multiclass CMOVrr_PSEUDO<RegisterClass RC, ValueType VT> { EFLAGS)))]>; } -let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in { +let usesCustomInserter = 1, Uses = [EFLAGS] in { // X86 doesn't have 8-bit conditional moves. Use a customInserter to // emit control flow. An alternative to this is to mark i8 SELECT as Promote, // however that requires promoting the operands, and can induce additional @@ -582,7 +541,7 @@ let usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] in { defm _V16I1 : CMOVrr_PSEUDO<VK16, v16i1>; defm _V32I1 : CMOVrr_PSEUDO<VK32, v32i1>; defm _V64I1 : CMOVrr_PSEUDO<VK64, v64i1>; -} // usesCustomInserter = 1, hasNoSchedulingInfo = 1, Uses = [EFLAGS] +} // usesCustomInserter = 1, Uses = [EFLAGS] //===----------------------------------------------------------------------===// // Normal-Instructions-With-Lock-Prefix Pseudo Instructions @@ -609,7 +568,7 @@ def Int_MemBarrier : I<0, Pseudo, (outs), (ins), // ImmOpc8 corresponds to the mi8 version of the instruction // ImmMod corresponds to the instruction format of the mi and mi8 versions multiclass LOCK_ArithBinOp<bits<8> RegOpc, bits<8> ImmOpc, bits<8> ImmOpc8, - Format ImmMod, SDNode Op, string mnemonic> { + Format ImmMod, string mnemonic> { let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, SchedRW = [WriteALULd, WriteRMW] in { @@ -618,152 +577,112 @@ def NAME#8mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, MRMDestMem, (outs), (ins i8mem:$dst, GR8:$src2), !strconcat(mnemonic, "{b}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR8:$src2))], - IIC_ALU_NONMEM>, LOCK; - + [], IIC_ALU_NONMEM>, LOCK; def NAME#16mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, MRMDestMem, (outs), (ins i16mem:$dst, GR16:$src2), !strconcat(mnemonic, "{w}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR16:$src2))], - IIC_ALU_NONMEM>, OpSize16, LOCK; - + [], IIC_ALU_NONMEM>, OpSize16, LOCK; def NAME#32mr : I<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, MRMDestMem, (outs), (ins i32mem:$dst, GR32:$src2), !strconcat(mnemonic, "{l}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR32:$src2))], - IIC_ALU_NONMEM>, OpSize32, LOCK; - + [], IIC_ALU_NONMEM>, OpSize32, LOCK; def NAME#64mr : RI<{RegOpc{7}, RegOpc{6}, RegOpc{5}, RegOpc{4}, RegOpc{3}, RegOpc{2}, RegOpc{1}, 1 }, MRMDestMem, (outs), (ins i64mem:$dst, GR64:$src2), !strconcat(mnemonic, "{q}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, GR64:$src2))], - IIC_ALU_NONMEM>, LOCK; + [], IIC_ALU_NONMEM>, LOCK; def NAME#8mi : Ii8<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 0 }, ImmMod, (outs), (ins i8mem :$dst, i8imm :$src2), !strconcat(mnemonic, "{b}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i8 imm:$src2)))], - IIC_ALU_MEM>, LOCK; + [], IIC_ALU_MEM>, LOCK; def NAME#16mi : Ii16<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, ImmMod, (outs), (ins i16mem :$dst, i16imm :$src2), !strconcat(mnemonic, "{w}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i16 imm:$src2)))], - IIC_ALU_MEM>, OpSize16, LOCK; + [], IIC_ALU_MEM>, OpSize16, LOCK; def NAME#32mi : Ii32<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, ImmMod, (outs), (ins i32mem :$dst, i32imm :$src2), !strconcat(mnemonic, "{l}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, (i32 imm:$src2)))], - IIC_ALU_MEM>, OpSize32, LOCK; + [], IIC_ALU_MEM>, OpSize32, LOCK; def NAME#64mi32 : RIi32S<{ImmOpc{7}, ImmOpc{6}, ImmOpc{5}, ImmOpc{4}, ImmOpc{3}, ImmOpc{2}, ImmOpc{1}, 1 }, ImmMod, (outs), (ins i64mem :$dst, i64i32imm :$src2), !strconcat(mnemonic, "{q}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt32:$src2))], - IIC_ALU_MEM>, LOCK; + [], IIC_ALU_MEM>, LOCK; def NAME#16mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, ImmMod, (outs), (ins i16mem :$dst, i16i8imm :$src2), !strconcat(mnemonic, "{w}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i16immSExt8:$src2))], - IIC_ALU_MEM>, OpSize16, LOCK; - + [], IIC_ALU_MEM>, OpSize16, LOCK; def NAME#32mi8 : Ii8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, ImmMod, (outs), (ins i32mem :$dst, i32i8imm :$src2), !strconcat(mnemonic, "{l}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i32immSExt8:$src2))], - IIC_ALU_MEM>, OpSize32, LOCK; - + [], IIC_ALU_MEM>, OpSize32, LOCK; def NAME#64mi8 : RIi8<{ImmOpc8{7}, ImmOpc8{6}, ImmOpc8{5}, ImmOpc8{4}, ImmOpc8{3}, ImmOpc8{2}, ImmOpc8{1}, 1 }, ImmMod, (outs), (ins i64mem :$dst, i64i8imm :$src2), !strconcat(mnemonic, "{q}\t", "{$src2, $dst|$dst, $src2}"), - [(set EFLAGS, (Op addr:$dst, i64immSExt8:$src2))], - IIC_ALU_MEM>, LOCK; + [], IIC_ALU_MEM>, LOCK; } } -defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, X86lock_add, "add">; -defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, X86lock_sub, "sub">; -defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, X86lock_or , "or">; -defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, X86lock_and, "and">; -defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, X86lock_xor, "xor">; +defm LOCK_ADD : LOCK_ArithBinOp<0x00, 0x80, 0x83, MRM0m, "add">; +defm LOCK_SUB : LOCK_ArithBinOp<0x28, 0x80, 0x83, MRM5m, "sub">; +defm LOCK_OR : LOCK_ArithBinOp<0x08, 0x80, 0x83, MRM1m, "or">; +defm LOCK_AND : LOCK_ArithBinOp<0x20, 0x80, 0x83, MRM4m, "and">; +defm LOCK_XOR : LOCK_ArithBinOp<0x30, 0x80, 0x83, MRM6m, "xor">; +// Optimized codegen when the non-memory output is not used. multiclass LOCK_ArithUnOp<bits<8> Opc8, bits<8> Opc, Format Form, - string frag, string mnemonic> { + string mnemonic> { let Defs = [EFLAGS], mayLoad = 1, mayStore = 1, isCodeGenOnly = 1, SchedRW = [WriteALULd, WriteRMW] in { + def NAME#8m : I<Opc8, Form, (outs), (ins i8mem :$dst), !strconcat(mnemonic, "{b}\t$dst"), - [(set EFLAGS, (!cast<PatFrag>(frag # "_8") addr:$dst))], - IIC_UNARY_MEM>, LOCK; + [], IIC_UNARY_MEM>, LOCK; def NAME#16m : I<Opc, Form, (outs), (ins i16mem:$dst), !strconcat(mnemonic, "{w}\t$dst"), - [(set EFLAGS, (!cast<PatFrag>(frag # "_16") addr:$dst))], - IIC_UNARY_MEM>, OpSize16, LOCK; + [], IIC_UNARY_MEM>, OpSize16, LOCK; def NAME#32m : I<Opc, Form, (outs), (ins i32mem:$dst), !strconcat(mnemonic, "{l}\t$dst"), - [(set EFLAGS, (!cast<PatFrag>(frag # "_32") addr:$dst))], - IIC_UNARY_MEM>, OpSize32, LOCK; + [], IIC_UNARY_MEM>, OpSize32, LOCK; def NAME#64m : RI<Opc, Form, (outs), (ins i64mem:$dst), !strconcat(mnemonic, "{q}\t$dst"), - [(set EFLAGS, (!cast<PatFrag>(frag # "_64") addr:$dst))], - IIC_UNARY_MEM>, LOCK; + [], IIC_UNARY_MEM>, LOCK; } } -multiclass unary_atomic_intrin<SDNode atomic_op> { - def _8 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i8; - }]>; - def _16 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i16; - }]>; - def _32 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i32; - }]>; - def _64 : PatFrag<(ops node:$ptr), - (atomic_op node:$ptr), [{ - return cast<MemIntrinsicSDNode>(N)->getMemoryVT() == MVT::i64; - }]>; -} - -defm X86lock_inc : unary_atomic_intrin<X86lock_inc>; -defm X86lock_dec : unary_atomic_intrin<X86lock_dec>; - -defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, "X86lock_inc", "inc">; -defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, "X86lock_dec", "dec">; +defm LOCK_INC : LOCK_ArithUnOp<0xFE, 0xFF, MRM0m, "inc">; +defm LOCK_DEC : LOCK_ArithUnOp<0xFE, 0xFF, MRM1m, "dec">; // Atomic compare and swap. multiclass LCMPXCHG_UnOp<bits<8> Opc, Format Form, string mnemonic, SDPatternOperator frag, X86MemOperand x86memop, InstrItinClass itin> { -let isCodeGenOnly = 1, usesCustomInserter = 1 in { +let isCodeGenOnly = 1 in { def NAME : I<Opc, Form, (outs), (ins x86memop:$ptr), !strconcat(mnemonic, "\t$ptr"), [(frag addr:$ptr)], itin>, TB, LOCK; @@ -805,18 +724,18 @@ defm LCMPXCHG8B : LCMPXCHG_UnOp<0xC7, MRM1m, "cmpxchg8b", // register and the register allocator will ignore any use/def of // it. In other words, the register will not fix the clobbering of // RBX that will happen when setting the arguments for the instrucion. -// +// // Unlike the actual related instuction, we mark that this one // defines EBX (instead of using EBX). // The rationale is that we will define RBX during the expansion of // the pseudo. The argument feeding EBX is ebx_input. // // The additional argument, $ebx_save, is a temporary register used to -// save the value of RBX across the actual instruction. +// save the value of RBX accross the actual instruction. // // To make sure the register assigned to $ebx_save does not interfere with // the definition of the actual instruction, we use a definition $dst which -// is tied to $rbx_save. That way, the live-range of $rbx_save spans across +// is tied to $rbx_save. That way, the live-range of $rbx_save spans accross // the instruction and we are sure we will have a valid register to restore // the value of RBX. let Defs = [EAX, EDX, EBX, EFLAGS], Uses = [EAX, ECX, EDX], @@ -933,7 +852,7 @@ multiclass RELEASE_BINOP_MI<SDNode op> { [(atomic_store_64 addr:$dst, (op (atomic_load_64 addr:$dst), GR64:$src))]>; } -let Defs = [EFLAGS], SchedRW = [WriteMicrocoded] in { +let Defs = [EFLAGS] in { defm RELEASE_ADD : RELEASE_BINOP_MI<add>; defm RELEASE_AND : RELEASE_BINOP_MI<and>; defm RELEASE_OR : RELEASE_BINOP_MI<or>; @@ -946,20 +865,20 @@ let Defs = [EFLAGS], SchedRW = [WriteMicrocoded] in { // FIXME: imm version. // FIXME: Version that doesn't clobber $src, using AVX's VADDSS. // FIXME: This could also handle SIMD operations with *ps and *pd instructions. -let usesCustomInserter = 1, SchedRW = [WriteMicrocoded] in { +let usesCustomInserter = 1 in { multiclass RELEASE_FP_BINOP_MI<SDNode op> { def NAME#32mr : I<0, Pseudo, (outs), (ins i32mem:$dst, FR32:$src), "#BINOP "#NAME#"32mr PSEUDO!", [(atomic_store_32 addr:$dst, - (i32 (bitconvert (op + (i32 (bitconvert (op (f32 (bitconvert (i32 (atomic_load_32 addr:$dst)))), - FR32:$src))))]>, Requires<[HasSSE1]>; + FR32:$src))))]>, Requires<[HasSSE1]>; def NAME#64mr : I<0, Pseudo, (outs), (ins i64mem:$dst, FR64:$src), "#BINOP "#NAME#"64mr PSEUDO!", [(atomic_store_64 addr:$dst, - (i64 (bitconvert (op + (i64 (bitconvert (op (f64 (bitconvert (i64 (atomic_load_64 addr:$dst)))), - FR64:$src))))]>, Requires<[HasSSE2]>; + FR64:$src))))]>, Requires<[HasSSE2]>; } defm RELEASE_FADD : RELEASE_FP_BINOP_MI<fadd>; // FIXME: Add fsub, fmul, fdiv, ... @@ -980,17 +899,17 @@ multiclass RELEASE_UNOP<dag dag8, dag dag16, dag dag32, dag dag64> { [(atomic_store_64 addr:$dst, dag64)]>; } -let Defs = [EFLAGS], Predicates = [UseIncDec], SchedRW = [WriteMicrocoded] in { +let Defs = [EFLAGS] in { defm RELEASE_INC : RELEASE_UNOP< (add (atomic_load_8 addr:$dst), (i8 1)), (add (atomic_load_16 addr:$dst), (i16 1)), (add (atomic_load_32 addr:$dst), (i32 1)), - (add (atomic_load_64 addr:$dst), (i64 1))>; + (add (atomic_load_64 addr:$dst), (i64 1))>, Requires<[NotSlowIncDec]>; defm RELEASE_DEC : RELEASE_UNOP< (add (atomic_load_8 addr:$dst), (i8 -1)), (add (atomic_load_16 addr:$dst), (i16 -1)), (add (atomic_load_32 addr:$dst), (i32 -1)), - (add (atomic_load_64 addr:$dst), (i64 -1))>; + (add (atomic_load_64 addr:$dst), (i64 -1))>, Requires<[NotSlowIncDec]>; } /* TODO: These don't work because the type inference of TableGen fails. @@ -1010,19 +929,18 @@ defm RELEASE_NOT : RELEASE_UNOP< (not (atomic_load_64 addr:$dst))>; */ -let SchedRW = [WriteMicrocoded] in { def RELEASE_MOV8mi : I<0, Pseudo, (outs), (ins i8mem:$dst, i8imm:$src), - "#RELEASE_MOV8mi PSEUDO!", - [(atomic_store_8 addr:$dst, (i8 imm:$src))]>; + "#RELEASE_MOV8mi PSEUDO!", + [(atomic_store_8 addr:$dst, (i8 imm:$src))]>; def RELEASE_MOV16mi : I<0, Pseudo, (outs), (ins i16mem:$dst, i16imm:$src), - "#RELEASE_MOV16mi PSEUDO!", - [(atomic_store_16 addr:$dst, (i16 imm:$src))]>; + "#RELEASE_MOV16mi PSEUDO!", + [(atomic_store_16 addr:$dst, (i16 imm:$src))]>; def RELEASE_MOV32mi : I<0, Pseudo, (outs), (ins i32mem:$dst, i32imm:$src), - "#RELEASE_MOV32mi PSEUDO!", - [(atomic_store_32 addr:$dst, (i32 imm:$src))]>; + "#RELEASE_MOV32mi PSEUDO!", + [(atomic_store_32 addr:$dst, (i32 imm:$src))]>; def RELEASE_MOV64mi32 : I<0, Pseudo, (outs), (ins i64mem:$dst, i64i32imm:$src), - "#RELEASE_MOV64mi32 PSEUDO!", - [(atomic_store_64 addr:$dst, i64immSExt32:$src)]>; + "#RELEASE_MOV64mi32 PSEUDO!", + [(atomic_store_64 addr:$dst, i64immSExt32:$src)]>; def RELEASE_MOV8mr : I<0, Pseudo, (outs), (ins i8mem :$dst, GR8 :$src), "#RELEASE_MOV8mr PSEUDO!", @@ -1049,23 +967,57 @@ def ACQUIRE_MOV32rm : I<0, Pseudo, (outs GR32:$dst), (ins i32mem:$src), def ACQUIRE_MOV64rm : I<0, Pseudo, (outs GR64:$dst), (ins i64mem:$src), "#ACQUIRE_MOV64rm PSEUDO!", [(set GR64:$dst, (atomic_load_64 addr:$src))]>; -} // SchedRW //===----------------------------------------------------------------------===// // DAG Pattern Matching Rules //===----------------------------------------------------------------------===// -// Use AND/OR to store 0/-1 in memory when optimizing for minsize. This saves -// binary size compared to a regular MOV, but it introduces an unnecessary -// load, so is not suitable for regular or optsize functions. -let Predicates = [OptForMinSize] in { -def : Pat<(store (i16 0), addr:$dst), (AND16mi8 addr:$dst, 0)>; -def : Pat<(store (i32 0), addr:$dst), (AND32mi8 addr:$dst, 0)>; -def : Pat<(store (i64 0), addr:$dst), (AND64mi8 addr:$dst, 0)>; -def : Pat<(store (i16 -1), addr:$dst), (OR16mi8 addr:$dst, -1)>; -def : Pat<(store (i32 -1), addr:$dst), (OR32mi8 addr:$dst, -1)>; -def : Pat<(store (i64 -1), addr:$dst), (OR64mi8 addr:$dst, -1)>; -} +// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable +def : Pat<(i32 (X86Wrapper tconstpool :$dst)), (MOV32ri tconstpool :$dst)>; +def : Pat<(i32 (X86Wrapper tjumptable :$dst)), (MOV32ri tjumptable :$dst)>; +def : Pat<(i32 (X86Wrapper tglobaltlsaddr:$dst)),(MOV32ri tglobaltlsaddr:$dst)>; +def : Pat<(i32 (X86Wrapper tglobaladdr :$dst)), (MOV32ri tglobaladdr :$dst)>; +def : Pat<(i32 (X86Wrapper texternalsym:$dst)), (MOV32ri texternalsym:$dst)>; +def : Pat<(i32 (X86Wrapper mcsym:$dst)), (MOV32ri mcsym:$dst)>; +def : Pat<(i32 (X86Wrapper tblockaddress:$dst)), (MOV32ri tblockaddress:$dst)>; + +def : Pat<(add GR32:$src1, (X86Wrapper tconstpool:$src2)), + (ADD32ri GR32:$src1, tconstpool:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tjumptable:$src2)), + (ADD32ri GR32:$src1, tjumptable:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tglobaladdr :$src2)), + (ADD32ri GR32:$src1, tglobaladdr:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper texternalsym:$src2)), + (ADD32ri GR32:$src1, texternalsym:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper mcsym:$src2)), + (ADD32ri GR32:$src1, mcsym:$src2)>; +def : Pat<(add GR32:$src1, (X86Wrapper tblockaddress:$src2)), + (ADD32ri GR32:$src1, tblockaddress:$src2)>; + +def : Pat<(store (i32 (X86Wrapper tglobaladdr:$src)), addr:$dst), + (MOV32mi addr:$dst, tglobaladdr:$src)>; +def : Pat<(store (i32 (X86Wrapper texternalsym:$src)), addr:$dst), + (MOV32mi addr:$dst, texternalsym:$src)>; +def : Pat<(store (i32 (X86Wrapper mcsym:$src)), addr:$dst), + (MOV32mi addr:$dst, mcsym:$src)>; +def : Pat<(store (i32 (X86Wrapper tblockaddress:$src)), addr:$dst), + (MOV32mi addr:$dst, tblockaddress:$src)>; + +// ConstantPool GlobalAddress, ExternalSymbol, and JumpTable when not in small +// code model mode, should use 'movabs'. FIXME: This is really a hack, the +// 'movabs' predicate should handle this sort of thing. +def : Pat<(i64 (X86Wrapper tconstpool :$dst)), + (MOV64ri tconstpool :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tjumptable :$dst)), + (MOV64ri tjumptable :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tglobaladdr :$dst)), + (MOV64ri tglobaladdr :$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper texternalsym:$dst)), + (MOV64ri texternalsym:$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper mcsym:$dst)), + (MOV64ri mcsym:$dst)>, Requires<[FarData]>; +def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), + (MOV64ri tblockaddress:$dst)>, Requires<[FarData]>; // In kernel code model, we can get the address of a label // into a register with 'movq'. FIXME: This is a hack, the 'imm' predicate of @@ -1088,22 +1040,22 @@ def : Pat<(i64 (X86Wrapper tblockaddress:$dst)), // for MOV64mi32 should handle this sort of thing. def : Pat<(store (i64 (X86Wrapper tconstpool:$src)), addr:$dst), (MOV64mi32 addr:$dst, tconstpool:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(store (i64 (X86Wrapper tjumptable:$src)), addr:$dst), (MOV64mi32 addr:$dst, tjumptable:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(store (i64 (X86Wrapper tglobaladdr:$src)), addr:$dst), (MOV64mi32 addr:$dst, tglobaladdr:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(store (i64 (X86Wrapper texternalsym:$src)), addr:$dst), (MOV64mi32 addr:$dst, texternalsym:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(store (i64 (X86Wrapper mcsym:$src)), addr:$dst), (MOV64mi32 addr:$dst, mcsym:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(store (i64 (X86Wrapper tblockaddress:$src)), addr:$dst), (MOV64mi32 addr:$dst, tblockaddress:$src)>, - Requires<[NearData, IsNotPIC]>; + Requires<[NearData, IsStatic]>; def : Pat<(i32 (X86RecoverFrameAlloc mcsym:$dst)), (MOV32ri mcsym:$dst)>; def : Pat<(i64 (X86RecoverFrameAlloc mcsym:$dst)), (MOV64ri mcsym:$dst)>; @@ -1146,14 +1098,14 @@ def X86tcret_6regs : PatFrag<(ops node:$ptr, node:$off), def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), (TCRETURNri ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, NotUseRetpoline]>; + Requires<[Not64BitMode]>; // FIXME: This is disabled for 32-bit PIC mode because the global base // register which is part of the address mode may be assigned a // callee-saved register. def : Pat<(X86tcret (load addr:$dst), imm:$off), (TCRETURNmi addr:$dst, imm:$off)>, - Requires<[Not64BitMode, IsNotPIC, NotUseRetpoline]>; + Requires<[Not64BitMode, IsNotPIC]>; def : Pat<(X86tcret (i32 tglobaladdr:$dst), imm:$off), (TCRETURNdi tglobaladdr:$dst, imm:$off)>, @@ -1165,21 +1117,13 @@ def : Pat<(X86tcret (i32 texternalsym:$dst), imm:$off), def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), (TCRETURNri64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; + Requires<[In64BitMode]>; // Don't fold loads into X86tcret requiring more than 6 regs. // There wouldn't be enough scratch registers for base+index. def : Pat<(X86tcret_6regs (load addr:$dst), imm:$off), (TCRETURNmi64 addr:$dst, imm:$off)>, - Requires<[In64BitMode, NotUseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN64 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[In64BitMode, UseRetpoline]>; - -def : Pat<(X86tcret ptr_rc_tailcall:$dst, imm:$off), - (RETPOLINE_TCRETURN32 ptr_rc_tailcall:$dst, imm:$off)>, - Requires<[Not64BitMode, UseRetpoline]>; + Requires<[In64BitMode]>; def : Pat<(X86tcret (i64 tglobaladdr:$dst), imm:$off), (TCRETURNdi64 tglobaladdr:$dst, imm:$off)>, @@ -1241,13 +1185,12 @@ defm : CMOVmr<X86_COND_O , CMOVNO16rm, CMOVNO32rm, CMOVNO64rm>; defm : CMOVmr<X86_COND_NO, CMOVO16rm , CMOVO32rm , CMOVO64rm>; // zextload bool -> zextload byte -// i1 stored in one byte in zero-extended form. -// Upper bits cleanup should be executed before Store. -def : Pat<(zextloadi8i1 addr:$src), (MOV8rm addr:$src)>; -def : Pat<(zextloadi16i1 addr:$src), (MOVZX16rm8 addr:$src)>; -def : Pat<(zextloadi32i1 addr:$src), (MOVZX32rm8 addr:$src)>; +def : Pat<(zextloadi8i1 addr:$src), (AND8ri (MOV8rm addr:$src), (i8 1))>; +def : Pat<(zextloadi16i1 addr:$src), (AND16ri8 (MOVZX16rm8 addr:$src), (i16 1))>; +def : Pat<(zextloadi32i1 addr:$src), (AND32ri8 (MOVZX32rm8 addr:$src), (i32 1))>; def : Pat<(zextloadi64i1 addr:$src), - (SUBREG_TO_REG (i64 0), (MOVZX32rm8 addr:$src), sub_32bit)>; + (SUBREG_TO_REG (i64 0), + (AND32ri8 (MOVZX32rm8 addr:$src), (i32 1)), sub_32bit)>; // extload bool -> extload byte // When extloading from 16-bit and smaller memory locations into 64-bit @@ -1287,20 +1230,20 @@ def : Pat<(i64 (anyext GR8 :$src)), def : Pat<(i64 (anyext GR16:$src)), (SUBREG_TO_REG (i64 0), (MOVZX32rr16 GR16 :$src), sub_32bit)>; def : Pat<(i64 (anyext GR32:$src)), - (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$src, sub_32bit)>; + (SUBREG_TO_REG (i64 0), GR32:$src, sub_32bit)>; // Any instruction that defines a 32-bit result leaves the high half of the // register. Truncate can be lowered to EXTRACT_SUBREG. CopyFromReg may -// be copying from a truncate. Any other 32-bit operation will zero-extend -// up to 64 bits. AssertSext/AssertZext aren't saying anything about the upper -// 32 bits, they're probably just qualifying a CopyFromReg. +// be copying from a truncate. And x86's cmov doesn't do anything if the +// condition is false. But any other 32-bit operation will zero-extend +// up to 64 bits. def def32 : PatLeaf<(i32 GR32:$src), [{ return N->getOpcode() != ISD::TRUNCATE && N->getOpcode() != TargetOpcode::EXTRACT_SUBREG && N->getOpcode() != ISD::CopyFromReg && N->getOpcode() != ISD::AssertSext && - N->getOpcode() != ISD::AssertZext; + N->getOpcode() != X86ISD::CMOV; }]>; // In the case of a 32-bit def that is known to implicitly zero-extend, @@ -1323,11 +1266,11 @@ def or_is_add : PatFrag<(ops node:$lhs, node:$rhs), (or node:$lhs, node:$rhs),[{ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1))) return CurDAG->MaskedValueIsZero(N->getOperand(0), CN->getAPIntValue()); - KnownBits Known0; - CurDAG->computeKnownBits(N->getOperand(0), Known0, 0); - KnownBits Known1; - CurDAG->computeKnownBits(N->getOperand(1), Known1, 0); - return (~Known0.Zero & ~Known1.Zero) == 0; + APInt KnownZero0, KnownOne0; + CurDAG->computeKnownBits(N->getOperand(0), KnownZero0, KnownOne0, 0); + APInt KnownZero1, KnownOne1; + CurDAG->computeKnownBits(N->getOperand(1), KnownZero1, KnownOne1, 0); + return (~KnownZero0 & ~KnownZero1) == 0; }]>; @@ -1408,7 +1351,7 @@ def : Pat<(store (add (loadi64 addr:$dst), 128), addr:$dst), // instructions. def : Pat<(add GR64:$src1, 0x0000000080000000), (SUB64ri32 GR64:$src1, 0xffffffff80000000)>; -def : Pat<(store (add (loadi64 addr:$dst), 0x0000000080000000), addr:$dst), +def : Pat<(store (add (loadi64 addr:$dst), 0x00000000800000000), addr:$dst), (SUB64mi32 addr:$dst, 0xffffffff80000000)>; // To avoid needing to materialize an immediate in a register, use a 32-bit and @@ -1447,11 +1390,16 @@ def : Pat<(and GR32:$src1, 0xffff), (MOVZX32rr16 (EXTRACT_SUBREG GR32:$src1, sub_16bit))>; // r & (2^8-1) ==> movz def : Pat<(and GR32:$src1, 0xff), - (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>; + (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src1, + GR32_ABCD)), + sub_8bit))>, + Requires<[Not64BitMode]>; // r & (2^8-1) ==> movz def : Pat<(and GR16:$src1, 0xff), - (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG GR16:$src1, sub_8bit)), - sub_16bit)>; + (EXTRACT_SUBREG (MOVZX32rr8 (EXTRACT_SUBREG + (i16 (COPY_TO_REGCLASS GR16:$src1, GR16_ABCD)), sub_8bit)), + sub_16bit)>, + Requires<[Not64BitMode]>; // r & (2^32-1) ==> movz def : Pat<(and GR64:$src, 0x00000000FFFFFFFF), @@ -1468,6 +1416,15 @@ def : Pat<(and GR64:$src, 0xff), (SUBREG_TO_REG (i64 0), (MOVZX32rr8 (i8 (EXTRACT_SUBREG GR64:$src, sub_8bit))), sub_32bit)>; +// r & (2^8-1) ==> movz +def : Pat<(and GR32:$src1, 0xff), + (MOVZX32rr8 (EXTRACT_SUBREG GR32:$src1, sub_8bit))>, + Requires<[In64BitMode]>; +// r & (2^8-1) ==> movz +def : Pat<(and GR16:$src1, 0xff), + (EXTRACT_SUBREG (MOVZX32rr8 (i8 + (EXTRACT_SUBREG GR16:$src1, sub_8bit))), sub_16bit)>, + Requires<[In64BitMode]>; } // AddedComplexity = 1 @@ -1475,11 +1432,16 @@ def : Pat<(and GR64:$src, 0xff), def : Pat<(sext_inreg GR32:$src, i16), (MOVSX32rr16 (EXTRACT_SUBREG GR32:$src, sub_16bit))>; def : Pat<(sext_inreg GR32:$src, i8), - (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>; + (MOVSX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, + GR32_ABCD)), + sub_8bit))>, + Requires<[Not64BitMode]>; def : Pat<(sext_inreg GR16:$src, i8), - (EXTRACT_SUBREG (MOVSX32rr8 (EXTRACT_SUBREG GR16:$src, sub_8bit)), - sub_16bit)>; + (EXTRACT_SUBREG (i32 (MOVSX32rr8 (EXTRACT_SUBREG + (i32 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), sub_8bit))), + sub_16bit)>, + Requires<[Not64BitMode]>; def : Pat<(sext_inreg GR64:$src, i32), (MOVSX64rr32 (EXTRACT_SUBREG GR64:$src, sub_32bit))>; @@ -1487,6 +1449,13 @@ def : Pat<(sext_inreg GR64:$src, i16), (MOVSX64rr16 (EXTRACT_SUBREG GR64:$src, sub_16bit))>; def : Pat<(sext_inreg GR64:$src, i8), (MOVSX64rr8 (EXTRACT_SUBREG GR64:$src, sub_8bit))>; +def : Pat<(sext_inreg GR32:$src, i8), + (MOVSX32rr8 (EXTRACT_SUBREG GR32:$src, sub_8bit))>, + Requires<[In64BitMode]>; +def : Pat<(sext_inreg GR16:$src, i8), + (EXTRACT_SUBREG (MOVSX32rr8 + (EXTRACT_SUBREG GR16:$src, sub_8bit)), sub_16bit)>, + Requires<[In64BitMode]>; // sext, sext_load, zext, zext_load def: Pat<(i16 (sext GR8:$src)), @@ -1524,26 +1493,40 @@ def : Pat<(i8 (trunc GR16:$src)), // h-register tricks def : Pat<(i8 (trunc (srl_su GR16:$src, (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, - Requires<[Not64BitMode]>; -def : Pat<(i8 (trunc (srl_su (i32 (anyext GR16:$src)), (i8 8)))), - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)>, + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi)>, Requires<[Not64BitMode]>; def : Pat<(i8 (trunc (srl_su GR32:$src, (i8 8)))), - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi)>, + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + sub_8bit_hi)>, Requires<[Not64BitMode]>; def : Pat<(srl GR16:$src, (i8 8)), (EXTRACT_SUBREG - (MOVZX32_NOREXrr8 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), - sub_16bit)>; + (MOVZX32rr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi)), + sub_16bit)>, + Requires<[Not64BitMode]>; def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), - (MOVZX32_NOREXrr8 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; + (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, + GR16_ABCD)), + sub_8bit_hi))>, + Requires<[Not64BitMode]>; def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), - (MOVZX32_NOREXrr8 (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>; + (MOVZX32rr8 (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, + GR16_ABCD)), + sub_8bit_hi))>, + Requires<[Not64BitMode]>; def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), - (MOVZX32_NOREXrr8 (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; + (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, + GR32_ABCD)), + sub_8bit_hi))>, + Requires<[Not64BitMode]>; def : Pat<(srl (and_su GR32:$src, 0xff00), (i8 8)), - (MOVZX32_NOREXrr8 (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>; + (MOVZX32rr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, + GR32_ABCD)), + sub_8bit_hi))>, + Requires<[Not64BitMode]>; // h-register tricks. // For now, be conservative on x86-64 and use an h-register extract only if the @@ -1557,35 +1540,68 @@ def : Pat<(and (srl_su GR64:$src, (i8 8)), (i64 255)), (SUBREG_TO_REG (i64 0), (MOVZX32_NOREXrr8 - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi)), + (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), + sub_8bit_hi)), sub_32bit)>; +def : Pat<(and (srl_su GR32:$src, (i8 8)), (i32 255)), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + sub_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(srl (and_su GR32:$src, 0xff00), (i8 8)), + (MOVZX32_NOREXrr8 (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, + GR32_ABCD)), + sub_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(srl GR16:$src, (i8 8)), + (EXTRACT_SUBREG + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi)), + sub_16bit)>, + Requires<[In64BitMode]>; +def : Pat<(i32 (zext (srl_su GR16:$src, (i8 8)))), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi))>, + Requires<[In64BitMode]>; +def : Pat<(i32 (anyext (srl_su GR16:$src, (i8 8)))), + (MOVZX32_NOREXrr8 + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi))>, + Requires<[In64BitMode]>; def : Pat<(i64 (zext (srl_su GR16:$src, (i8 8)))), (SUBREG_TO_REG (i64 0), (MOVZX32_NOREXrr8 - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi)), sub_32bit)>; def : Pat<(i64 (anyext (srl_su GR16:$src, (i8 8)))), (SUBREG_TO_REG (i64 0), (MOVZX32_NOREXrr8 - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi)), + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi)), sub_32bit)>; // h-register extract and store. def : Pat<(store (i8 (trunc_su (srl_su GR64:$src, (i8 8)))), addr:$dst), (MOV8mr_NOREX addr:$dst, - (EXTRACT_SUBREG GR64:$src, sub_8bit_hi))>; + (EXTRACT_SUBREG (i64 (COPY_TO_REGCLASS GR64:$src, GR64_ABCD)), + sub_8bit_hi))>; def : Pat<(store (i8 (trunc_su (srl_su GR32:$src, (i8 8)))), addr:$dst), (MOV8mr_NOREX addr:$dst, - (EXTRACT_SUBREG GR32:$src, sub_8bit_hi))>, + (EXTRACT_SUBREG (i32 (COPY_TO_REGCLASS GR32:$src, GR32_ABCD)), + sub_8bit_hi))>, Requires<[In64BitMode]>; def : Pat<(store (i8 (trunc_su (srl_su GR16:$src, (i8 8)))), addr:$dst), (MOV8mr_NOREX addr:$dst, - (EXTRACT_SUBREG GR16:$src, sub_8bit_hi))>, + (EXTRACT_SUBREG (i16 (COPY_TO_REGCLASS GR16:$src, GR16_ABCD)), + sub_8bit_hi))>, Requires<[In64BitMode]>; @@ -1600,13 +1616,7 @@ def : Pat<(shl GR16:$src1, (i8 1)), (ADD16rr GR16:$src1, GR16:$src1)>; def : Pat<(shl GR32:$src1, (i8 1)), (ADD32rr GR32:$src1, GR32:$src1)>; def : Pat<(shl GR64:$src1, (i8 1)), (ADD64rr GR64:$src1, GR64:$src1)>; -// Helper imms to check if a mask doesn't change significant shift/rotate bits. -def immShift8 : ImmLeaf<i8, [{ - return countTrailingOnes<uint64_t>(Imm) >= 3; -}]>; -def immShift16 : ImmLeaf<i8, [{ - return countTrailingOnes<uint64_t>(Imm) >= 4; -}]>; +// Helper imms that check if a mask doesn't change significant shift bits. def immShift32 : ImmLeaf<i8, [{ return countTrailingOnes<uint64_t>(Imm) >= 5; }]>; @@ -1633,121 +1643,15 @@ multiclass MaskedShiftAmountPats<SDNode frag, string name> { // (shift x (and y, 63)) ==> (shift x, y) def : Pat<(frag GR64:$src1, (and CL, immShift64)), (!cast<Instruction>(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), + def : Pat<(store (frag (loadi64 addr:$dst), (and CL, 63)), addr:$dst), (!cast<Instruction>(name # "64mCL") addr:$dst)>; } defm : MaskedShiftAmountPats<shl, "SHL">; defm : MaskedShiftAmountPats<srl, "SHR">; defm : MaskedShiftAmountPats<sra, "SAR">; - -// ROL/ROR instructions allow a stronger mask optimization than shift for 8- and -// 16-bit. We can remove a mask of any (bitwidth - 1) on the rotation amount -// because over-rotating produces the same result. This is noted in the Intel -// docs with: "tempCOUNT <- (COUNT & COUNTMASK) MOD SIZE". Masking the rotation -// amount could affect EFLAGS results, but that does not matter because we are -// not tracking flags for these nodes. -multiclass MaskedRotateAmountPats<SDNode frag, string name> { - // (rot x (and y, BitWidth - 1)) ==> (rot x, y) - def : Pat<(frag GR8:$src1, (and CL, immShift8)), - (!cast<Instruction>(name # "8rCL") GR8:$src1)>; - def : Pat<(frag GR16:$src1, (and CL, immShift16)), - (!cast<Instruction>(name # "16rCL") GR16:$src1)>; - def : Pat<(frag GR32:$src1, (and CL, immShift32)), - (!cast<Instruction>(name # "32rCL") GR32:$src1)>; - def : Pat<(store (frag (loadi8 addr:$dst), (and CL, immShift8)), addr:$dst), - (!cast<Instruction>(name # "8mCL") addr:$dst)>; - def : Pat<(store (frag (loadi16 addr:$dst), (and CL, immShift16)), addr:$dst), - (!cast<Instruction>(name # "16mCL") addr:$dst)>; - def : Pat<(store (frag (loadi32 addr:$dst), (and CL, immShift32)), addr:$dst), - (!cast<Instruction>(name # "32mCL") addr:$dst)>; - - // (rot x (and y, 63)) ==> (rot x, y) - def : Pat<(frag GR64:$src1, (and CL, immShift64)), - (!cast<Instruction>(name # "64rCL") GR64:$src1)>; - def : Pat<(store (frag (loadi64 addr:$dst), (and CL, immShift64)), addr:$dst), - (!cast<Instruction>(name # "64mCL") addr:$dst)>; -} - - -defm : MaskedRotateAmountPats<rotl, "ROL">; -defm : MaskedRotateAmountPats<rotr, "ROR">; - -// Double shift amount is implicitly masked. -multiclass MaskedDoubleShiftAmountPats<SDNode frag, string name> { - // (shift x (and y, 31)) ==> (shift x, y) - def : Pat<(frag GR16:$src1, GR16:$src2, (and CL, immShift32)), - (!cast<Instruction>(name # "16rrCL") GR16:$src1, GR16:$src2)>; - def : Pat<(frag GR32:$src1, GR32:$src2, (and CL, immShift32)), - (!cast<Instruction>(name # "32rrCL") GR32:$src1, GR32:$src2)>; - - // (shift x (and y, 63)) ==> (shift x, y) - def : Pat<(frag GR64:$src1, GR64:$src2, (and CL, immShift64)), - (!cast<Instruction>(name # "64rrCL") GR64:$src1, GR64:$src2)>; -} - -defm : MaskedDoubleShiftAmountPats<X86shld, "SHLD">; -defm : MaskedDoubleShiftAmountPats<X86shrd, "SHRD">; - -let Predicates = [HasBMI2] in { - let AddedComplexity = 1 in { - def : Pat<(sra GR32:$src1, (and GR8:$src2, immShift32)), - (SARX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra GR64:$src1, (and GR8:$src2, immShift64)), - (SARX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl GR32:$src1, (and GR8:$src2, immShift32)), - (SHRX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl GR64:$src1, (and GR8:$src2, immShift64)), - (SHRX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl GR32:$src1, (and GR8:$src2, immShift32)), - (SHLX32rr GR32:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl GR64:$src1, (and GR8:$src2, immShift64)), - (SHLX64rr GR64:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } - - let AddedComplexity = -20 in { - def : Pat<(sra (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SARX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(sra (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SARX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(srl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHRX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(srl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHRX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - - def : Pat<(shl (loadi32 addr:$src1), (and GR8:$src2, immShift32)), - (SHLX32rm addr:$src1, - (INSERT_SUBREG - (i32 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - def : Pat<(shl (loadi64 addr:$src1), (and GR8:$src2, immShift64)), - (SHLX64rm addr:$src1, - (INSERT_SUBREG - (i64 (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; - } -} +defm : MaskedShiftAmountPats<rotl, "ROL">; +defm : MaskedShiftAmountPats<rotr, "ROR">; // (anyext (setcc_carry)) -> (setcc_carry) def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), @@ -1757,6 +1661,9 @@ def : Pat<(i32 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), def : Pat<(i32 (anyext (i16 (X86setcc_c X86_COND_B, EFLAGS)))), (SETB_C32r)>; + + + //===----------------------------------------------------------------------===// // EFLAGS-defining Patterns //===----------------------------------------------------------------------===// @@ -1814,12 +1721,6 @@ def : Pat<(X86sub_flag 0, GR16:$src), (NEG16r GR16:$src)>; def : Pat<(X86sub_flag 0, GR32:$src), (NEG32r GR32:$src)>; def : Pat<(X86sub_flag 0, GR64:$src), (NEG64r GR64:$src)>; -// sub reg, relocImm -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt8_su:$src2), - (SUB64ri8 GR64:$src1, i64relocImmSExt8_su:$src2)>; -def : Pat<(X86sub_flag GR64:$src1, i64relocImmSExt32_su:$src2), - (SUB64ri32 GR64:$src1, i64relocImmSExt32_su:$src2)>; - // mul reg, reg def : Pat<(mul GR16:$src1, GR16:$src2), (IMUL16rr GR16:$src1, GR16:$src2)>; @@ -1890,7 +1791,7 @@ def : Pat<(mul (loadi64 addr:$src1), i64immSExt32:$src2), // Increment/Decrement reg. // Do not make INC/DEC if it is slow -let Predicates = [UseIncDec] in { +let Predicates = [NotSlowIncDec] in { def : Pat<(add GR8:$src, 1), (INC8r GR8:$src)>; def : Pat<(add GR16:$src, 1), (INC16r GR16:$src)>; def : Pat<(add GR32:$src, 1), (INC32r GR32:$src)>; diff --git a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td index 7dea88b62cc..051f9033756 100644 --- a/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td +++ b/gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td @@ -70,7 +70,7 @@ def analyzer_opt_analyze_nested_blocks : Flag<["-"], "analyzer-opt-analyze-neste def analyzer_display_progress : Flag<["-"], "analyzer-display-progress">, HelpText<"Emit verbose output about the analyzer's progress">; def analyze_function : Separate<["-"], "analyze-function">, - HelpText<"Run analysis on specific function (for C++ include parameters in name)">; + HelpText<"Run analysis on specific function">; def analyze_function_EQ : Joined<["-"], "analyze-function=">, Alias<analyze_function>; def analyzer_eagerly_assume : Flag<["-"], "analyzer-eagerly-assume">, HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">; @@ -99,19 +99,7 @@ def analyzer_stats : Flag<["-"], "analyzer-stats">, HelpText<"Print internal analyzer statistics.">; def analyzer_checker : Separate<["-"], "analyzer-checker">, - HelpText<"Choose analyzer checkers to enable">, - ValuesCode<[{ - const char *Values = - #define GET_CHECKERS - #define CHECKER(FULLNAME, CLASS, DESCFILE, HT, G, H) FULLNAME "," - #include "clang/StaticAnalyzer/Checkers/Checkers.inc" - #undef GET_CHECKERS - #define GET_PACKAGES - #define PACKAGE(FULLNAME, G, D) FULLNAME "," - #include "clang/StaticAnalyzer/Checkers/Checkers.inc" - #undef GET_PACKAGES - ; - }]>; + HelpText<"Choose analyzer checkers to enable">; def analyzer_checker_EQ : Joined<["-"], "analyzer-checker=">, Alias<analyzer_checker>; @@ -126,9 +114,6 @@ def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">, def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; -def analyzer_list_enabled_checkers : Flag<["-"], "analyzer-list-enabled-checkers">, - HelpText<"Display the list of enabled analyzer checkers">; - def analyzer_config : Separate<["-"], "analyzer-config">, HelpText<"Choose analyzer options to enable">; @@ -146,47 +131,35 @@ def migrator_no_finalize_removal : Flag<["-"], "no-finalize-removal">, //===----------------------------------------------------------------------===// let Flags = [CC1Option, CC1AsOption, NoDriverOption] in { + def debug_info_kind_EQ : Joined<["-"], "debug-info-kind=">; -def debug_info_macro : Flag<["-"], "debug-info-macro">, - HelpText<"Emit macro debug information">; def dwarf_version_EQ : Joined<["-"], "dwarf-version=">; def debugger_tuning_EQ : Joined<["-"], "debugger-tuning=">; def fdebug_compilation_dir : Separate<["-"], "fdebug-compilation-dir">, HelpText<"The compilation directory to embed in the debug info.">; def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; -def compress_debug_sections : Flag<["-", "--"], "compress-debug-sections">, - HelpText<"DWARF debug sections compression">; -def compress_debug_sections_EQ : Joined<["-"], "compress-debug-sections=">, - HelpText<"DWARF debug sections compression type">; def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">, HelpText<"Make assembler warnings fatal">; -def mrelax_relocations : Flag<["--"], "mrelax-relocations">, - HelpText<"Use relaxable elf relocations">; +def compress_debug_sections : Flag<["-"], "compress-debug-sections">, + HelpText<"Compress DWARF debug sections using zlib">; def msave_temp_labels : Flag<["-"], "msave-temp-labels">, HelpText<"Save temporary labels in the symbol table. " "Note this may change .s semantics and shouldn't generally be used " "on compiler-generated code.">; def mrelocation_model : Separate<["-"], "mrelocation-model">, - HelpText<"The relocation model to use">, Values<"static,pic,ropi,rwpi,ropi-rwpi,dynamic-no-pic">; -def fno_math_builtin : Flag<["-"], "fno-math-builtin">, - HelpText<"Disable implicit builtin knowledge of math functions">; + HelpText<"The relocation model to use">; } +def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">, + HelpText<"Don't run LLVM optimization passes">; def disable_llvm_verifier : Flag<["-"], "disable-llvm-verifier">, HelpText<"Don't run the LLVM IR verifier pass">; def disable_llvm_passes : Flag<["-"], "disable-llvm-passes">, HelpText<"Use together with -emit-llvm to get pristine LLVM IR from the " "frontend by not running any LLVM passes at all">; -def disable_llvm_optzns : Flag<["-"], "disable-llvm-optzns">, - Alias<disable_llvm_passes>; -def disable_lifetimemarkers : Flag<["-"], "disable-lifetime-markers">, - HelpText<"Disable lifetime-markers emission even when optimizations are " - "enabled">; -def disable_O0_optnone : Flag<["-"], "disable-O0-optnone">, - HelpText<"Disable adding the optnone attribute to functions at O0">; def disable_red_zone : Flag<["-"], "disable-red-zone">, HelpText<"Do not emit code that uses the red zone.">; def dwarf_column_info : Flag<["-"], "dwarf-column-info">, @@ -200,12 +173,6 @@ def arange_sections : Flag<["-"], "arange_sections">, def dwarf_ext_refs : Flag<["-"], "dwarf-ext-refs">, HelpText<"Generate debug info with external references to clang modules" " or precompiled headers">; -def dwarf_explicit_import : Flag<["-"], "dwarf-explicit-import">, - HelpText<"Generate explicit import from anonymous namespace to containing" - " scope">; -def debug_forward_template_params : Flag<["-"], "debug-forward-template-params">, - HelpText<"Emit complete descriptions of template parameters in forward" - " declarations">; def fforbid_guard_variables : Flag<["-"], "fforbid-guard-variables">, HelpText<"Emit an error if a C++ static local initializer would need a guard variable">; def no_implicit_float : Flag<["-"], "no-implicit-float">, @@ -218,14 +185,9 @@ def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">, HelpText<"Emit a gcov coverage notes file when compiling.">; def femit_coverage_data: Flag<["-"], "femit-coverage-data">, HelpText<"Instrument the program to emit gcov coverage data when run.">; -def coverage_data_file : Separate<["-"], "coverage-data-file">, - HelpText<"Emit coverage data to this filename.">; -def coverage_data_file_EQ : Joined<["-"], "coverage-data-file=">, - Alias<coverage_data_file>; -def coverage_notes_file : Separate<["-"], "coverage-notes-file">, - HelpText<"Emit coverage notes to this filename.">; -def coverage_notes_file_EQ : Joined<["-"], "coverage-notes-file=">, - Alias<coverage_notes_file>; +def coverage_file : Separate<["-"], "coverage-file">, + HelpText<"Emit coverage data to this filename. The extension will be replaced.">; +def coverage_file_EQ : Joined<["-"], "coverage-file=">, Alias<coverage_file>; def coverage_cfg_checksum : Flag<["-"], "coverage-cfg-checksum">, HelpText<"Emit CFG checksum for functions in .gcno files.">; def coverage_no_function_names_in_data : Flag<["-"], "coverage-no-function-names-in-data">, @@ -244,12 +206,10 @@ def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, HelpText<"Turn off Type Based Alias Analysis">; def no_struct_path_tbaa : Flag<["-"], "no-struct-path-tbaa">, HelpText<"Turn off struct-path aware Type Based Alias Analysis">; -def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">, - HelpText<"Enable enhanced struct-path aware Type Based Alias Analysis">; def masm_verbose : Flag<["-"], "masm-verbose">, HelpText<"Generate verbose assembly output">; def mcode_model : Separate<["-"], "mcode-model">, - HelpText<"The code model to use">, Values<"small,kernel,medium,large">; + HelpText<"The code model to use">; def mdebug_pass : Separate<["-"], "mdebug-pass">, HelpText<"Enable additional debug output">; def mdisable_fp_elim : Flag<["-"], "mdisable-fp-elim">, @@ -263,12 +223,8 @@ def menable_no_nans : Flag<["-"], "menable-no-nans">, def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, HelpText<"Allow unsafe floating-point math optimizations which may decrease " "precision">; -def mreassociate : Flag<["-"], "mreassociate">, - HelpText<"Allow reassociation transformations for floating-point instructions">; def mfloat_abi : Separate<["-"], "mfloat-abi">, HelpText<"The float ABI to use">; -def mtp : Separate<["-"], "mtp">, - HelpText<"Mode for reading thread pointer">; def mlimit_float_precision : Separate<["-"], "mlimit-float-precision">, HelpText<"Limit float precision to the given value">; def split_stacks : Flag<["-"], "split-stacks">, @@ -292,10 +248,10 @@ def vectorize_loops : Flag<["-"], "vectorize-loops">, HelpText<"Run the Loop vectorization passes">; def vectorize_slp : Flag<["-"], "vectorize-slp">, HelpText<"Run the SLP vectorization passes">; +def vectorize_slp_aggressive : Flag<["-"], "vectorize-slp-aggressive">, + HelpText<"Run the BB vectorization passes">; def dependent_lib : Joined<["--"], "dependent-lib=">, HelpText<"Add dependent library">; -def linker_option : Joined<["--"], "linker-option=">, - HelpText<"Add linker option">; def fsanitize_coverage_type : Joined<["-"], "fsanitize-coverage-type=">, HelpText<"Sanitizer coverage type">; def fsanitize_coverage_indirect_calls @@ -307,54 +263,9 @@ def fsanitize_coverage_trace_bb def fsanitize_coverage_trace_cmp : Flag<["-"], "fsanitize-coverage-trace-cmp">, HelpText<"Enable cmp instruction tracing in sanitizer coverage">; -def fsanitize_coverage_trace_div - : Flag<["-"], "fsanitize-coverage-trace-div">, - HelpText<"Enable div instruction tracing in sanitizer coverage">; -def fsanitize_coverage_trace_gep - : Flag<["-"], "fsanitize-coverage-trace-gep">, - HelpText<"Enable gep instruction tracing in sanitizer coverage">; def fsanitize_coverage_8bit_counters : Flag<["-"], "fsanitize-coverage-8bit-counters">, HelpText<"Enable frequency counters in sanitizer coverage">; -def fsanitize_coverage_inline_8bit_counters - : Flag<["-"], "fsanitize-coverage-inline-8bit-counters">, - HelpText<"Enable inline 8-bit counters in sanitizer coverage">; -def fsanitize_coverage_pc_table - : Flag<["-"], "fsanitize-coverage-pc-table">, - HelpText<"Create a table of coverage-instrumented PCs">; -def fsanitize_coverage_trace_pc - : Flag<["-"], "fsanitize-coverage-trace-pc">, - HelpText<"Enable PC tracing in sanitizer coverage">; -def fsanitize_coverage_trace_pc_guard - : Flag<["-"], "fsanitize-coverage-trace-pc-guard">, - HelpText<"Enable PC tracing with guard in sanitizer coverage">; -def fsanitize_coverage_no_prune - : Flag<["-"], "fsanitize-coverage-no-prune">, - HelpText<"Disable coverage pruning (i.e. instrument all blocks/edges)">; -def fsanitize_coverage_stack_depth - : Flag<["-"], "fsanitize-coverage-stack-depth">, - HelpText<"Enable max stack depth tracing">; -def fprofile_instrument_EQ : Joined<["-"], "fprofile-instrument=">, - HelpText<"Enable PGO instrumentation. The accepted value is clang, llvm, " - "or none">, Values<"none,clang,llvm">; -def fprofile_instrument_path_EQ : Joined<["-"], "fprofile-instrument-path=">, - HelpText<"Generate instrumented code to collect execution counts into " - "<file> (overridden by LLVM_PROFILE_FILE env var)">; -def fprofile_instrument_use_path_EQ : - Joined<["-"], "fprofile-instrument-use-path=">, - HelpText<"Specify the profile path in PGO use compilation">; -def flto_visibility_public_std: - Flag<["-"], "flto-visibility-public-std">, - HelpText<"Use public LTO visibility for classes in std and stdext namespaces">; -def flto_unit: Flag<["-"], "flto-unit">, - HelpText<"Emit IR to support LTO unit features (CFI, whole program vtable opt)">; -def fno_lto_unit: Flag<["-"], "fno-lto-unit">; -def fthin_link_bitcode_EQ : Joined<["-"], "fthin-link-bitcode=">, - HelpText<"Write minimized bitcode to <file> for the ThinLTO thin link only">; -def fdebug_pass_manager : Flag<["-"], "fdebug-pass-manager">, - HelpText<"Prints debug information for the new pass manager">; -def fno_debug_pass_manager : Flag<["-"], "fno-debug-pass-manager">, - HelpText<"Disables debug printing for the new pass manager">; //===----------------------------------------------------------------------===// // Dependency Output Options @@ -380,9 +291,9 @@ def diagnostic_serialized_file : Separate<["-"], "serialize-diagnostic-file">, HelpText<"File for serializing diagnostics in a binary format">; def fdiagnostics_format : Separate<["-"], "fdiagnostics-format">, - HelpText<"Change diagnostic formatting to match IDE and command line tools">, Values<"clang,msvc,msvc-fallback,vi">; + HelpText<"Change diagnostic formatting to match IDE and command line tools">; def fdiagnostics_show_category : Separate<["-"], "fdiagnostics-show-category">, - HelpText<"Print diagnostic category">, Values<"none,id,name">; + HelpText<"Print diagnostic category">; def fno_diagnostics_use_presumed_location : Flag<["-"], "fno-diagnostics-use-presumed-location">, HelpText<"Ignore #line directives when displaying diagnostic locations">; def ftabstop : Separate<["-"], "ftabstop">, MetaVarName<"<N>">, @@ -397,17 +308,10 @@ def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">; def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">, HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">; -def fcaret_diagnostics_max_lines : - Separate<["-"], "fcaret-diagnostics-max-lines">, MetaVarName<"<N>">, - HelpText<"Set the maximum number of source lines to show in a caret diagnostic">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; -def verify_EQ : CommaJoined<["-"], "verify=">, - MetaVarName<"<prefixes>">, - HelpText<"Verify diagnostic output using comment directives that start with" - " prefixes in the comma-separated sequence <prefixes>">; def verify : Flag<["-"], "verify">, - HelpText<"Equivalent to -verify=expected">; + HelpText<"Verify diagnostic output using comment directives">; def verify_ignore_unexpected : Flag<["-"], "verify-ignore-unexpected">, HelpText<"Ignore unexpected diagnostic messages">; def verify_ignore_unexpected_EQ : CommaJoined<["-"], "verify-ignore-unexpected=">, @@ -443,14 +347,10 @@ def code_completion_patterns : Flag<["-"], "code-completion-patterns">, HelpText<"Include code patterns in code-completion results">; def no_code_completion_globals : Flag<["-"], "no-code-completion-globals">, HelpText<"Do not include global declarations in code-completion results.">; -def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level-decls">, - HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">; def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">, HelpText<"Include brief documentation comments in code-completion results.">; def disable_free : Flag<["-"], "disable-free">, HelpText<"Disable freeing of memory on exit">; -def discard_value_names : Flag<["-"], "discard-value-names">, - HelpText<"Discard value names in LLVM IR">; def load : Separate<["-"], "load">, MetaVarName<"<dsopath>">, HelpText<"Load the named plugin (dynamic shared object)">; def plugin : Separate<["-"], "plugin">, MetaVarName<"<name>">, @@ -469,6 +369,9 @@ def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">, HelpText<"Do not automatically generate or update the global module index">; def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">, HelpText<"Do not automatically import modules for error recovery">; +def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, + MetaVarName<"<name>">, + HelpText<"Specify the name of the module whose implementation file this is">; def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">, HelpText<"Use the current working directory as the home directory of " "module maps specified by -fmodule-map-file=<FILE>">; @@ -486,14 +389,6 @@ def fmodules_local_submodule_visibility : Flag<["-"], "fmodules-local-submodule-visibility">, HelpText<"Enforce name visibility rules across submodules of the same " "top-level module.">; -def fmodules_codegen : - Flag<["-"], "fmodules-codegen">, - HelpText<"Generate code for uses of this module that assumes an explicit " - "object file will be built for the module">; -def fmodules_debuginfo : - Flag<["-"], "fmodules-debuginfo">, - HelpText<"Generate debug info for types in an object file built from this " - "module and do not generate them elsewhere">; def fmodule_format_EQ : Joined<["-"], "fmodule-format=">, HelpText<"Select the container format for clang modules and PCH. " "Supported options are 'raw' and 'obj'.">; @@ -531,8 +426,6 @@ def ast_list : Flag<["-"], "ast-list">, HelpText<"Build ASTs and print the list of declaration node qualified names">; def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; -def ast_dump_all : Flag<["-"], "ast-dump-all">, - HelpText<"Build ASTs and then debug dump them, forcing deserialization">; def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, HelpText<"Build ASTs and then debug dump their name lookup tables">; def ast_view : Flag<["-"], "ast-view">, @@ -541,8 +434,6 @@ def print_decl_contexts : Flag<["-"], "print-decl-contexts">, HelpText<"Print DeclContexts and their Decls">; def emit_module : Flag<["-"], "emit-module">, HelpText<"Generate pre-compiled module file from a module map">; -def emit_module_interface : Flag<["-"], "emit-module-interface">, - HelpText<"Generate pre-compiled module file from a C++ module interface">; def emit_pth : Flag<["-"], "emit-pth">, HelpText<"Generate pre-tokenized header file">; def emit_pch : Flag<["-"], "emit-pch">, @@ -577,13 +468,8 @@ def arcmt_modify : Flag<["-"], "arcmt-modify">, def arcmt_migrate : Flag<["-"], "arcmt-migrate">, HelpText<"Apply modifications and produces temporary files that conform to ARC">; -def opt_record_file : Separate<["-"], "opt-record-file">, - HelpText<"File name to use for YAML optimization record output">; - def print_stats : Flag<["-"], "print-stats">, HelpText<"Print performance metrics and statistics">; -def stats_file : Joined<["-"], "stats-file=">, - HelpText<"Filename to write statistics to">; def fdump_record_layouts : Flag<["-"], "fdump-record-layouts">, HelpText<"Dump record layout information">; def fdump_record_layouts_simple : Flag<["-"], "fdump-record-layouts-simple">, @@ -599,16 +485,7 @@ def fixit_to_temp : Flag<["-"], "fixit-to-temporary">, def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; -def find_pch_source_EQ : Joined<["-"], "find-pch-source=">, - HelpText<"When building a pch, try to find the input file in include " - "directories, as if it had been included by the argument passed " - "to this flag.">; -def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, - HelpText<"Disable inclusion of timestamp in precompiled headers">; -def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">, - HelpText<"Aligned allocation/deallocation functions are unavailable">; - //===----------------------------------------------------------------------===// // Language Options //===----------------------------------------------------------------------===// @@ -624,10 +501,10 @@ def main_file_name : Separate<["-"], "main-file-name">, def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; -def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">, - HelpText<"Assume all functions with C linkage do not unwind">; -def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">, - HelpText<"Use split dwarf/Fission">; +def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, + HelpText<"Use SjLj style exceptions">; +def fnew_ms_eh: Flag<["-"], "fnew-ms-eh">, + HelpText<"Use the new IR representation for MS exceptions">; def split_dwarf_file : Separate<["-"], "split-dwarf-file">, HelpText<"File name to use for split dwarf debug info output">; def fno_wchar : Flag<["-"], "fno-wchar">, @@ -636,23 +513,21 @@ def fconstant_string_class : Separate<["-"], "fconstant-string-class">, MetaVarName<"<class name>">, HelpText<"Specify the class to use for constant Objective-C string objects.">; def fobjc_arc_cxxlib_EQ : Joined<["-"], "fobjc-arc-cxxlib=">, - HelpText<"Objective-C++ Automatic Reference Counting standard library kind">, Values<"libc++,libstdc++,none">; + HelpText<"Objective-C++ Automatic Reference Counting standard library kind">; def fobjc_runtime_has_weak : Flag<["-"], "fobjc-runtime-has-weak">, HelpText<"The target Objective-C runtime supports ARC weak operations">; def fobjc_dispatch_method_EQ : Joined<["-"], "fobjc-dispatch-method=">, - HelpText<"Objective-C dispatch method to use">, Values<"legacy,non-legacy,mixed">; + HelpText<"Objective-C dispatch method to use">; def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-default-synthesize-properties">, HelpText<"disable the default synthesis of Objective-C properties">; def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">, HelpText<"enable extended encoding of block type signature">; def pic_level : Separate<["-"], "pic-level">, HelpText<"Value for __PIC__">; -def pic_is_pie : Flag<["-"], "pic-is-pie">, - HelpText<"File is for a position independent executable">; +def pie_level : Separate<["-"], "pie-level">, + HelpText<"Value for __PIE__">; def fno_validate_pch : Flag<["-"], "fno-validate-pch">, HelpText<"Disable validation of precompiled headers">; -def fallow_pch_with_errors : Flag<["-"], "fallow-pch-with-compiler-errors">, - HelpText<"Accept a PCH file that was created with compiler errors">; def dump_deserialized_pch_decls : Flag<["-"], "dump-deserialized-decls">, HelpText<"Dump declarations that are deserialized from PCH, for testing">; def error_on_deserialized_pch_decl : Separate<["-"], "error-on-deserialized-decl">, @@ -709,28 +584,12 @@ def fno_rtti_data : Flag<["-"], "fno-rtti-data">, HelpText<"Control emission of RTTI data">; def fnative_half_type: Flag<["-"], "fnative-half-type">, HelpText<"Use the native half type for __fp16 instead of promoting to float">; -def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">, - HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">; def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">, HelpText<"Allow function arguments and returns of type half">; -def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">, - HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">; -def finclude_default_header : Flag<["-"], "finclude-default-header">, - HelpText<"Include the default header file for OpenCL">; -def fpreserve_vec3_type : Flag<["-"], "fpreserve-vec3-type">, - HelpText<"Preserve 3-component vector type">; -def fwchar_type_EQ : Joined<["-"], "fwchar-type=">, - HelpText<"Select underlying type for wchar_t">, Values<"char,short,int">; -def fsigned_wchar : Flag<["-"], "fsigned-wchar">, - HelpText<"Use a signed type for wchar_t">; -def fno_signed_wchar : Flag<["-"], "fno-signed-wchar">, - HelpText<"Use an unsigned type for wchar_t">; - -// FIXME: Remove these entirely once functionality/tests have been excised. -def fobjc_gc_only : Flag<["-"], "fobjc-gc-only">, Group<f_Group>, - HelpText<"Use GC exclusively for Objective-C related memory management">; -def fobjc_gc : Flag<["-"], "fobjc-gc">, Group<f_Group>, - HelpText<"Enable Objective-C garbage collection">; + +// C++ TSes. +def fcoroutines : Flag<["-"], "fcoroutines">, + HelpText<"Enable support for the C++ Coroutines TS">; //===----------------------------------------------------------------------===// // Header Search Options @@ -740,8 +599,6 @@ def nostdsysteminc : Flag<["-"], "nostdsysteminc">, HelpText<"Disable standard system #include directories">; def fdisable_module_hash : Flag<["-"], "fdisable-module-hash">, HelpText<"Disable the module hash">; -def fmodules_hash_content : Flag<["-"], "fmodules-hash-content">, - HelpText<"Enable hashing the content of a module file">; def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, MetaVarName<"<directory>">, HelpText<"Add directory to the C SYSTEM include search path">; def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">, @@ -782,8 +639,26 @@ def detailed_preprocessing_record : Flag<["-"], "detailed-preprocessing-record"> // OpenCL Options //===----------------------------------------------------------------------===// -def cl_ext_EQ : CommaJoined<["-"], "cl-ext=">, - HelpText<"OpenCL only. Enable or disable OpenCL extensions. The argument is a comma-separated sequence of one or more extension names, each prefixed by '+' or '-'.">; +def cl_opt_disable : Flag<["-"], "cl-opt-disable">, + HelpText<"OpenCL only. This option disables all optimizations. The default is optimizations are enabled.">; +def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, + HelpText<"OpenCL only. This option does nothing and is for compatibility with OpenCL 1.0">; +def cl_single_precision_constant : Flag<["-"], "cl-single-precision-constant">, + HelpText<"OpenCL only. Treat double precision floating-point constant as single precision constant.">; +def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, + HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">; +def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, + HelpText<"OpenCL only. Generate kernel argument metadata.">; +def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">, + HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">; +def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, + HelpText<"OpenCL only. Sets -cl-finite-math-only and -cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__">; +def cl_mad_enable : Flag<["-"], "cl-mad-enable">, + HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">; +def cl_std_EQ : Joined<["-"], "cl-std=">, + HelpText<"OpenCL language standard to compile for">; +def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, + HelpText<"OpenCL only. Allow denormals to be flushed to zero">; //===----------------------------------------------------------------------===// // CUDA Options @@ -791,12 +666,16 @@ def cl_ext_EQ : CommaJoined<["-"], "cl-ext=">, def fcuda_is_device : Flag<["-"], "fcuda-is-device">, HelpText<"Generate code for CUDA device">; +def fcuda_allow_host_calls_from_host_device : Flag<["-"], + "fcuda-allow-host-calls-from-host-device">, + HelpText<"Allow host device functions to call host functions">; +def fcuda_disable_target_call_checks : Flag<["-"], + "fcuda-disable-target-call-checks">, + HelpText<"Disable all cross-target (host, device, etc.) call checks in CUDA">; def fcuda_include_gpubinary : Separate<["-"], "fcuda-include-gpubinary">, HelpText<"Incorporate CUDA device-side binary into host object file.">; -def fcuda_allow_variadic_functions : Flag<["-"], "fcuda-allow-variadic-functions">, - HelpText<"Allow variadic functions in CUDA device code.">; -def fno_cuda_host_device_constexpr : Flag<["-"], "fno-cuda-host-device-constexpr">, - HelpText<"Don't treat unattributed constexpr functions as __host__ __device__.">; +def fcuda_target_overloads : Flag<["-"], "fcuda-target-overloads">, + HelpText<"Enable function overloads based on CUDA target attributes.">; //===----------------------------------------------------------------------===// // OpenMP Options @@ -804,7 +683,7 @@ def fno_cuda_host_device_constexpr : Flag<["-"], "fno-cuda-host-device-constexpr def fopenmp_is_device : Flag<["-"], "fopenmp-is-device">, HelpText<"Generate code only for an OpenMP target device.">; -def fopenmp_host_ir_file_path : Separate<["-"], "fopenmp-host-ir-file-path">, +def omp_host_ir_file_path : Separate<["-"], "omp-host-ir-file-path">, HelpText<"Path to the IR file produced by the frontend for the host.">; } // let Flags = [CC1Option] @@ -836,6 +715,4 @@ def show_inst : Flag<["-"], "show-inst">, def dwarf_debug_producer : Separate<["-"], "dwarf-debug-producer">, HelpText<"The string to embed in the Dwarf debug AT_producer record.">; -def defsym : Separate<["-"], "defsym">, - HelpText<"Define a value for a symbol">; } // let Flags = [CC1AsOption] diff --git a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def index bb91cf5f742..d9f6ab7f42d 100644 --- a/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def +++ b/gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def @@ -1,4 +1,4 @@ -//===--- CodeGenOptions.def - Code generation option database ----- C++ -*-===// +//===--- CodeGenOptions.def - Code generation option database ------ C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -29,15 +29,10 @@ CODEGENOPT(Name, Bits, Default) #endif CODEGENOPT(DisableIntegratedAS, 1, 0) ///< -no-integrated-as -ENUM_CODEGENOPT(CompressDebugSections, llvm::DebugCompressionType, 2, - llvm::DebugCompressionType::None) -CODEGENOPT(RelaxELFRelocations, 1, 0) ///< -Wa,--mrelax-relocations -CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. -CODEGENOPT(PreserveAsmComments, 1, 1) ///< -dA, -fno-preserve-as-comments. -CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) operator new +CODEGENOPT(CompressDebugSections, 1, 0) ///< -Wa,-compress-debug-sections CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink +CODEGENOPT(AsmVerbose , 1, 0) ///< -dA, -fverbose-asm. CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. -CODEGENOPT(Backchain , 1, 0) ///< -mbackchain CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files. CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files. @@ -48,59 +43,38 @@ CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled. CODEGENOPT(UniqueSectionNames, 1, 1) ///< Set for -funique-section-names. CODEGENOPT(DisableFPElim , 1, 0) ///< Set when -fomit-frame-pointer is enabled. CODEGENOPT(DisableFree , 1, 0) ///< Don't free memory. -CODEGENOPT(DiscardValueNames , 1, 0) ///< Discard Value Names from the IR (LLVMContext flag) CODEGENOPT(DisableGCov , 1, 0) ///< Don't run the GCov pass, for testing. +CODEGENOPT(DisableLLVMOpts , 1, 0) ///< Don't run any optimizations, for use in + ///< getting .bc files that correspond to the + ///< internal state before optimizations are + ///< done. CODEGENOPT(DisableLLVMPasses , 1, 0) ///< Don't run any LLVM IR passes to get ///< the pristine IR generated by the ///< frontend. -CODEGENOPT(DisableLifetimeMarkers, 1, 0) ///< Don't emit any lifetime markers -CODEGENOPT(DisableO0ImplyOptNone , 1, 0) ///< Don't annonate function with optnone at O0 -CODEGENOPT(ExperimentalNewPassManager, 1, 0) ///< Enables the new, experimental - ///< pass manager. -CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new - ///< pass manager. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what - ///< Decl* various IR entities came from. + ///< Decl* various IR entities came from. ///< Only useful when running CodeGen as a ///< subroutine. CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. -/// \brief Embed Bitcode mode (off/all/bitcode/marker). -ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) +/// \brief FP_CONTRACT mode (on/off/fast). +ENUM_CODEGENOPT(FPContractMode, FPContractModeKind, 2, FPC_On) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. CODEGENOPT(FunctionSections , 1, 0) ///< Set when -ffunction-sections is enabled. CODEGENOPT(InstrumentFunctions , 1, 0) ///< Set when -finstrument-functions is ///< enabled. -CODEGENOPT(InstrumentFunctionsAfterInlining , 1, 0) ///< Set when - ///< -finstrument-functions-after-inlining is enabled. -CODEGENOPT(InstrumentFunctionEntryBare , 1, 0) ///< Set when - ///< -finstrument-function-entry-bare is enabled. - -CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is - ///< enabled. - -///< Set when -fxray-always-emit-customevents is enabled. -CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) - -///< Set the minimum number of instructions in a function to determine selective -///< XRay instrumentation. -VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200) - CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. -CODEGENOPT(CallFEntry , 1, 0) ///< Set when -mfentry is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. -CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the - ///< compile step. -CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole - ///< program vtable opt). +CODEGENOPT(EmitFunctionSummary, 1, 0) ///< Set when -flto=thin is enabled on the + ///< compile step. CODEGENOPT(IncrementalLinkerCompatible, 1, 0) ///< Emit an object file which can ///< be used with an incremental ///< linker. @@ -117,28 +91,20 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero -CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated. -CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. +CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled. + ///< Disables use of the inline keyword. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. -CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero -CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss. /// \brief Method of Objective-C dispatch to use. -ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) +ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is ///< enabled. - -/// A version of Clang that we should attempt to be ABI-compatible with. -ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest) - VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. -/// \brief Choose profile instrumenation kind or no instrumentation. -ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone) -/// \brief Choose profile kind for PGO use compilation. -ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone) +CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate + ///< execution counts to use with PGO. CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to ///< enable code coverage analysis. CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping @@ -150,21 +116,14 @@ ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Defa CODEGENOPT(RelaxAll , 1, 0) ///< Relax all machine code instructions. CODEGENOPT(RelaxedAliasing , 1, 0) ///< Set when -fno-strict-aliasing is enabled. CODEGENOPT(StructPathTBAA , 1, 0) ///< Whether or not to use struct-path TBAA. -CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct-path TBAA. CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. -CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection - ///< in AddressSanitizer -CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping - ///< of globals in AddressSanitizer +CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero + ///< offset in AddressSanitizer. CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection ///< in MemorySanitizer CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI. -CODEGENOPT(SanitizeMinimalRuntime, 1, 0) ///< Use "_minimal" sanitizer runtime for - ///< diagnostics. -CODEGENOPT(SanitizeCfiICallGeneralizePointers, 1, 0) ///< Generalize pointer types in - ///< CFI icall function signatures CODEGENOPT(SanitizeCoverageType, 2, 0) ///< Type of sanitizer coverage ///< instrumentation. CODEGENOPT(SanitizeCoverageIndirectCalls, 1, 0) ///< Enable sanitizer coverage @@ -173,35 +132,22 @@ CODEGENOPT(SanitizeCoverageTraceBB, 1, 0) ///< Enable basic block tracing in ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverageTraceCmp, 1, 0) ///< Enable cmp instruction tracing ///< in sanitizer coverage. -CODEGENOPT(SanitizeCoverageTraceDiv, 1, 0) ///< Enable div instruction tracing - ///< in sanitizer coverage. -CODEGENOPT(SanitizeCoverageTraceGep, 1, 0) ///< Enable GEP instruction tracing - ///< in sanitizer coverage. CODEGENOPT(SanitizeCoverage8bitCounters, 1, 0) ///< Use 8-bit frequency counters ///< in sanitizer coverage. -CODEGENOPT(SanitizeCoverageTracePC, 1, 0) ///< Enable PC tracing - ///< in sanitizer coverage. -CODEGENOPT(SanitizeCoverageTracePCGuard, 1, 0) ///< Enable PC tracing with guard - ///< in sanitizer coverage. -CODEGENOPT(SanitizeCoverageInline8bitCounters, 1, 0) ///< Use inline 8bit counters. -CODEGENOPT(SanitizeCoveragePCTable, 1, 0) ///< Create a PC Table. -CODEGENOPT(SanitizeCoverageNoPrune, 1, 0) ///< Disable coverage pruning. -CODEGENOPT(SanitizeCoverageStackDepth, 1, 0) ///< Enable max stack depth tracing -CODEGENOPT(SanitizeStats , 1, 0) ///< Collect statistics for sanitizers. CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. CODEGENOPT(SoftFloat , 1, 0) ///< -soft-float. -CODEGENOPT(FineGrainedBitfieldAccesses, 1, 0) ///< Enable fine-grained bitfield accesses. CODEGENOPT(StrictEnums , 1, 0) ///< Optimize based on strict enum definition. CODEGENOPT(StrictVTablePointers, 1, 0) ///< Optimize based on the strict vtable pointers CODEGENOPT(TimePasses , 1, 0) ///< Set when -ftime-report is enabled. +CODEGENOPT(UnitAtATime , 1, 1) ///< Unused. For mirroring GCC optimization + ///< selection. CODEGENOPT(UnrollLoops , 1, 0) ///< Control whether loops are unrolled. CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled. -CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled. CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns. CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables. +CODEGENOPT(VectorizeBB , 1, 0) ///< Run basic block vectorizer. CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer. CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer. -CODEGENOPT(ProfileSampleAccurate, 1, 0) ///< Sample profile is accurate. /// Attempt to use register sized accesses to bit-fields in structures, when /// possible. @@ -214,7 +160,7 @@ CODEGENOPT(StackRealignment , 1, 0) ///< Control whether to force stack ///< realignment. CODEGENOPT(UseInitArray , 1, 0) ///< Control whether to use .init_array or ///< .ctors. -VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack +VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack ///< alignment, if not 0. VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack ///< probe size, even if 0. @@ -224,27 +170,12 @@ CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information CODEGENOPT(DebugTypeExtRefs, 1, 0) ///< Whether or not debug info should contain ///< external references to a PCH or module. -CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should - ///< contain explicit imports for +CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should + ///< contain explicit imports for ///< anonymous namespaces -CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF -CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the - ///< skeleton CU to allow for symbolication - ///< of inline stack frames without .dwo files. -CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete - ///< template parameter descriptions in - ///< forward declarations (versus just - ///< including them in the name). CODEGENOPT(EmitLLVMUseLists, 1, 0) ///< Control whether to serialize use-lists. -CODEGENOPT(WholeProgramVTables, 1, 0) ///< Whether to apply whole-program - /// vtable optimization. - -/// Whether to use public LTO visibility for entities in std and stdext -/// namespaces. This is enabled by clang-cl's /MT and /MTd flags. -CODEGENOPT(LTOVisibilityPublicStd, 1, 0) - /// The user specified number of registers to be used for integral arguments, /// or 0 if unspecified. VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) @@ -253,14 +184,10 @@ VALUE_CODEGENOPT(NumRegisterParameters, 32, 0) VALUE_CODEGENOPT(SSPBufferSize, 32, 0) /// The kind of generated debug info. -ENUM_CODEGENOPT(DebugInfo, codegenoptions::DebugInfoKind, 3, codegenoptions::NoDebugInfo) - -/// Whether to generate macro debug info. -CODEGENOPT(MacroDebugInfo, 1, 0) +ENUM_CODEGENOPT(DebugInfo, DebugInfoKind, 3, NoDebugInfo) /// Tune the debug info for this debugger. -ENUM_CODEGENOPT(DebuggerTuning, llvm::DebuggerKind, 2, - llvm::DebuggerKind::Default) +ENUM_CODEGENOPT(DebuggerTuning, DebuggerKind, 2, DebuggerKindDefault) /// Dwarf version. Version zero indicates to LLVM that no DWARF should be /// emitted. @@ -271,43 +198,14 @@ VALUE_CODEGENOPT(DwarfVersion, 3, 0) CODEGENOPT(EmitCodeView, 1, 0) /// The kind of inlining to perform. -ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NormalInlining) +ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining) // Vector functions library to use. -ENUM_CODEGENOPT(VecLib, VectorLibrary, 2, NoLibrary) +ENUM_CODEGENOPT(VecLib, VectorLibrary, 1, NoLibrary) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) -/// Number of path components to strip when emitting checks. (0 == full -/// filename) -VALUE_CODEGENOPT(EmitCheckPathComponentsToStrip, 32, 0) - -/// Whether to report the hotness of the code region for optimization remarks. -CODEGENOPT(DiagnosticsWithHotness, 1, 0) - -/// The minimum hotness value a diagnostic needs in order to be included in -/// optimization diagnostics. -VALUE_CODEGENOPT(DiagnosticsHotnessThreshold, 32, 0) - -/// Whether copy relocations support is available when building as PIE. -CODEGENOPT(PIECopyRelocations, 1, 0) - -/// Whether we should use the undefined behaviour optimization for control flow -/// paths that reach the end of a function without executing a required return. -CODEGENOPT(StrictReturn, 1, 1) - -/// Whether emit extra debug info for sample pgo profile collection. -CODEGENOPT(DebugInfoForProfiling, 1, 0) - -/// Whether 3-component vector type is preserved. -CODEGENOPT(PreserveVec3Type, 1, 0) - -/// Whether to emit .debug_gnu_pubnames section instead of .debug_pubnames. -CODEGENOPT(GnuPubnames, 1, 0) - -CODEGENOPT(NoPLT, 1, 0) - #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp index 38d7344572d..935985049c0 100644 --- a/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp +++ b/gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp @@ -14,7 +14,6 @@ #include "CGCall.h" #include "ABIInfo.h" -#include "CGBlocks.h" #include "CGCXXABI.h" #include "CGCleanup.h" #include "CodeGenFunction.h" @@ -26,12 +25,9 @@ #include "clang/Basic/TargetBuiltins.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/CGFunctionInfo.h" -#include "clang/CodeGen/SwiftCallingConv.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/ADT/StringExtras.h" -#include "llvm/Analysis/ValueTracking.h" #include "llvm/IR/Attributes.h" -#include "llvm/IR/CallingConv.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/InlineAsm.h" @@ -43,14 +39,13 @@ using namespace CodeGen; /***/ -unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { +static unsigned ClangCallConvToLLVMCallConv(CallingConv CC) { switch (CC) { default: return llvm::CallingConv::C; case CC_X86StdCall: return llvm::CallingConv::X86_StdCall; case CC_X86FastCall: return llvm::CallingConv::X86_FastCall; - case CC_X86RegCall: return llvm::CallingConv::X86_RegCall; case CC_X86ThisCall: return llvm::CallingConv::X86_ThisCall; - case CC_Win64: return llvm::CallingConv::Win64; + case CC_X86_64Win64: return llvm::CallingConv::X86_64_Win64; case CC_X86_64SysV: return llvm::CallingConv::X86_64_SysV; case CC_AAPCS: return llvm::CallingConv::ARM_AAPCS; case CC_AAPCS_VFP: return llvm::CallingConv::ARM_AAPCS_VFP; @@ -60,10 +55,7 @@ unsigned CodeGenTypes::ClangCallConvToLLVMCallConv(CallingConv CC) { // TODO: Add support for __vectorcall to LLVM. case CC_X86VectorCall: return llvm::CallingConv::X86_VectorCall; case CC_SpirFunction: return llvm::CallingConv::SPIR_FUNC; - case CC_OpenCLKernel: return CGM.getTargetCodeGenInfo().getOpenCLKernelCallingConv(); - case CC_PreserveMost: return llvm::CallingConv::PreserveMost; - case CC_PreserveAll: return llvm::CallingConv::PreserveAll; - case CC_Swift: return llvm::CallingConv::Swift; + case CC_SpirKernel: return llvm::CallingConv::SPIR_KERNEL; } } @@ -98,67 +90,32 @@ CodeGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> FTNP) { return arrangeLLVMFunctionInfo(FTNP->getReturnType().getUnqualifiedType(), /*instanceMethod=*/false, /*chainCall=*/false, None, - FTNP->getExtInfo(), {}, RequiredArgs(0)); + FTNP->getExtInfo(), RequiredArgs(0)); } -static void addExtParameterInfosForCall( - llvm::SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, - const FunctionProtoType *proto, - unsigned prefixArgs, - unsigned totalArgs) { - assert(proto->hasExtParameterInfos()); - assert(paramInfos.size() <= prefixArgs); - assert(proto->getNumParams() + prefixArgs <= totalArgs); - - paramInfos.reserve(totalArgs); - - // Add default infos for any prefix args that don't already have infos. - paramInfos.resize(prefixArgs); - - // Add infos for the prototype. - for (const auto &ParamInfo : proto->getExtParameterInfos()) { - paramInfos.push_back(ParamInfo); - // pass_object_size params have no parameter info. - if (ParamInfo.hasPassObjectSize()) - paramInfos.emplace_back(); - } - - assert(paramInfos.size() <= totalArgs && - "Did we forget to insert pass_object_size args?"); - // Add default infos for the variadic and/or suffix arguments. - paramInfos.resize(totalArgs); -} - -/// Adds the formal parameters in FPT to the given prefix. If any parameter in +/// Adds the formal paramaters in FPT to the given prefix. If any parameter in /// FPT has pass_object_size attrs, then we'll add parameters for those, too. static void appendParameterTypes(const CodeGenTypes &CGT, SmallVectorImpl<CanQualType> &prefix, - SmallVectorImpl<FunctionProtoType::ExtParameterInfo> ¶mInfos, - CanQual<FunctionProtoType> FPT) { - // Fast path: don't touch param info if we don't need to. - if (!FPT->hasExtParameterInfos()) { - assert(paramInfos.empty() && - "We have paramInfos, but the prototype doesn't?"); + const CanQual<FunctionProtoType> &FPT, + const FunctionDecl *FD) { + // Fast path: unknown target. + if (FD == nullptr) { prefix.append(FPT->param_type_begin(), FPT->param_type_end()); return; } - unsigned PrefixSize = prefix.size(); - // In the vast majority of cases, we'll have precisely FPT->getNumParams() + // In the vast majority cases, we'll have precisely FPT->getNumParams() // parameters; the only thing that can change this is the presence of // pass_object_size. So, we preallocate for the common case. prefix.reserve(prefix.size() + FPT->getNumParams()); - auto ExtInfos = FPT->getExtParameterInfos(); - assert(ExtInfos.size() == FPT->getNumParams()); + assert(FD->getNumParams() == FPT->getNumParams()); for (unsigned I = 0, E = FPT->getNumParams(); I != E; ++I) { prefix.push_back(FPT->getParamType(I)); - if (ExtInfos[I].hasPassObjectSize()) + if (FD->getParamDecl(I)->hasAttr<PassObjectSizeAttr>()) prefix.push_back(CGT.getContext().getSizeType()); } - - addExtParameterInfosForCall(paramInfos, FPT.getTypePtr(), PrefixSize, - prefix.size()); } /// Arrange the LLVM function layout for a value of the given function @@ -168,17 +125,13 @@ arrangeLLVMFunctionInfo(CodeGenTypes &CGT, bool instanceMethod, SmallVectorImpl<CanQualType> &prefix, CanQual<FunctionProtoType> FTP, const FunctionDecl *FD) { - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - RequiredArgs Required = - RequiredArgs::forPrototypePlus(FTP, prefix.size(), FD); + RequiredArgs required = RequiredArgs::forPrototypePlus(FTP, prefix.size()); // FIXME: Kill copy. - appendParameterTypes(CGT, prefix, paramInfos, FTP); + appendParameterTypes(CGT, prefix, FTP, FD); CanQualType resultType = FTP->getReturnType().getUnqualifiedType(); - return CGT.arrangeLLVMFunctionInfo(resultType, instanceMethod, /*chainCall=*/false, prefix, - FTP->getExtInfo(), paramInfos, - Required); + FTP->getExtInfo(), required); } /// Arrange the argument and result information for a value of the @@ -199,9 +152,6 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { if (D->hasAttr<FastCallAttr>()) return CC_X86FastCall; - if (D->hasAttr<RegCallAttr>()) - return CC_X86RegCall; - if (D->hasAttr<ThisCallAttr>()) return CC_X86ThisCall; @@ -218,17 +168,11 @@ static CallingConv getCallingConventionForDecl(const Decl *D, bool IsWindows) { return CC_IntelOclBicc; if (D->hasAttr<MSABIAttr>()) - return IsWindows ? CC_C : CC_Win64; + return IsWindows ? CC_C : CC_X86_64Win64; if (D->hasAttr<SysVABIAttr>()) return IsWindows ? CC_X86_64SysV : CC_C; - if (D->hasAttr<PreserveMostAttr>()) - return CC_PreserveMost; - - if (D->hasAttr<PreserveAllAttr>()) - return CC_PreserveAll; - return CC_C; } @@ -275,33 +219,16 @@ CodeGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *MD) { return arrangeFreeFunctionType(prototype, MD); } -bool CodeGenTypes::inheritingCtorHasParams( - const InheritedConstructor &Inherited, CXXCtorType Type) { - // Parameters are unnecessary if we're constructing a base class subobject - // and the inherited constructor lives in a virtual base. - return Type == Ctor_Complete || - !Inherited.getShadowDecl()->constructsVirtualBase() || - !Target.getCXXABI().hasConstructorVariants(); - } - const CGFunctionInfo & CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, StructorType Type) { SmallVector<CanQualType, 16> argTypes; - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; argTypes.push_back(GetThisType(Context, MD->getParent())); - bool PassParams = true; - GlobalDecl GD; if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) { GD = GlobalDecl(CD, toCXXCtorType(Type)); - - // A base class inheriting constructor doesn't get forwarded arguments - // needed to construct a virtual base (or base class thereof). - if (auto Inherited = CD->getInheritedConstructor()) - PassParams = inheritingCtorHasParams(Inherited, toCXXCtorType(Type)); } else { auto *DD = dyn_cast<CXXDestructorDecl>(MD); GD = GlobalDecl(DD, toCXXDtorType(Type)); @@ -310,24 +237,12 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, CanQual<FunctionProtoType> FTP = GetFormalType(MD); // Add the formal parameters. - if (PassParams) - appendParameterTypes(*this, argTypes, paramInfos, FTP); - - CGCXXABI::AddedStructorArgs AddedArgs = - TheCXXABI.buildStructorSignature(MD, Type, argTypes); - if (!paramInfos.empty()) { - // Note: prefix implies after the first param. - if (AddedArgs.Prefix) - paramInfos.insert(paramInfos.begin() + 1, AddedArgs.Prefix, - FunctionProtoType::ExtParameterInfo{}); - if (AddedArgs.Suffix) - paramInfos.append(AddedArgs.Suffix, - FunctionProtoType::ExtParameterInfo{}); - } + appendParameterTypes(*this, argTypes, FTP, MD); + + TheCXXABI.buildStructorSignature(MD, Type, argTypes); RequiredArgs required = - (PassParams && MD->isVariadic() ? RequiredArgs(argTypes.size()) - : RequiredArgs::All); + (MD->isVariadic() ? RequiredArgs(argTypes.size()) : RequiredArgs::All); FunctionType::ExtInfo extInfo = FTP->getExtInfo(); CanQualType resultType = TheCXXABI.HasThisReturn(GD) @@ -337,61 +252,22 @@ CodeGenTypes::arrangeCXXStructorDeclaration(const CXXMethodDecl *MD, : Context.VoidTy; return arrangeLLVMFunctionInfo(resultType, /*instanceMethod=*/true, /*chainCall=*/false, argTypes, extInfo, - paramInfos, required); -} - -static SmallVector<CanQualType, 16> -getArgTypesForCall(ASTContext &ctx, const CallArgList &args) { - SmallVector<CanQualType, 16> argTypes; - for (auto &arg : args) - argTypes.push_back(ctx.getCanonicalParamType(arg.Ty)); - return argTypes; -} - -static SmallVector<CanQualType, 16> -getArgTypesForDeclaration(ASTContext &ctx, const FunctionArgList &args) { - SmallVector<CanQualType, 16> argTypes; - for (auto &arg : args) - argTypes.push_back(ctx.getCanonicalParamType(arg->getType())); - return argTypes; -} - -static llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> -getExtParameterInfosForCall(const FunctionProtoType *proto, - unsigned prefixArgs, unsigned totalArgs) { - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> result; - if (proto->hasExtParameterInfos()) { - addExtParameterInfosForCall(result, proto, prefixArgs, totalArgs); - } - return result; + required); } /// Arrange a call to a C++ method, passing the given arguments. -/// -/// ExtraPrefixArgs is the number of ABI-specific args passed after the `this` -/// parameter. -/// ExtraSuffixArgs is the number of ABI-specific args passed at the end of -/// args. -/// PassProtoArgs indicates whether `args` has args for the parameters in the -/// given CXXConstructorDecl. const CGFunctionInfo & CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, const CXXConstructorDecl *D, CXXCtorType CtorKind, - unsigned ExtraPrefixArgs, - unsigned ExtraSuffixArgs, - bool PassProtoArgs) { + unsigned ExtraArgs) { // FIXME: Kill copy. SmallVector<CanQualType, 16> ArgTypes; for (const auto &Arg : args) ArgTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); - // +1 for implicit this, which should always be args[0]. - unsigned TotalPrefixArgs = 1 + ExtraPrefixArgs; - CanQual<FunctionProtoType> FPT = GetFormalType(D); - RequiredArgs Required = - RequiredArgs::forPrototypePlus(FPT, TotalPrefixArgs + ExtraSuffixArgs, D); + RequiredArgs Required = RequiredArgs::forPrototypePlus(FPT, 1 + ExtraArgs); GlobalDecl GD(D, CtorKind); CanQualType ResultType = TheCXXABI.HasThisReturn(GD) ? ArgTypes.front() @@ -400,17 +276,9 @@ CodeGenTypes::arrangeCXXConstructorCall(const CallArgList &args, : Context.VoidTy; FunctionType::ExtInfo Info = FPT->getExtInfo(); - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> ParamInfos; - // If the prototype args are elided, we should only have ABI-specific args, - // which never have param info. - if (PassProtoArgs && FPT->hasExtParameterInfos()) { - // ABI-specific suffix arguments are treated the same as variadic arguments. - addExtParameterInfosForCall(ParamInfos, FPT.getTypePtr(), TotalPrefixArgs, - ArgTypes.size()); - } return arrangeLLVMFunctionInfo(ResultType, /*instanceMethod=*/true, /*chainCall=*/false, ArgTypes, Info, - ParamInfos, Required); + Required); } /// Arrange the argument and result information for the declaration or @@ -427,13 +295,15 @@ CodeGenTypes::arrangeFunctionDeclaration(const FunctionDecl *FD) { // When declaring a function without a prototype, always use a // non-variadic type. - if (CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>()) { + if (isa<FunctionNoProtoType>(FTy)) { + CanQual<FunctionNoProtoType> noProto = FTy.getAs<FunctionNoProtoType>(); return arrangeLLVMFunctionInfo( noProto->getReturnType(), /*instanceMethod=*/false, - /*chainCall=*/false, None, noProto->getExtInfo(), {},RequiredArgs::All); + /*chainCall=*/false, None, noProto->getExtInfo(), RequiredArgs::All); } - return arrangeFreeFunctionType(FTy.castAs<FunctionProtoType>(), FD); + assert(isa<FunctionProtoType>(FTy)); + return arrangeFreeFunctionType(FTy.getAs<FunctionProtoType>(), FD); } /// Arrange the argument and result information for the declaration or @@ -455,15 +325,11 @@ const CGFunctionInfo & CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, QualType receiverType) { SmallVector<CanQualType, 16> argTys; - SmallVector<FunctionProtoType::ExtParameterInfo, 4> extParamInfos(2); argTys.push_back(Context.getCanonicalParamType(receiverType)); argTys.push_back(Context.getCanonicalParamType(Context.getObjCSelType())); // FIXME: Kill copy? - for (const auto *I : MD->parameters()) { + for (const auto *I : MD->params()) { argTys.push_back(Context.getCanonicalParamType(I->getType())); - auto extParamInfo = FunctionProtoType::ExtParameterInfo().withIsNoEscape( - I->hasAttr<NoEscapeAttr>()); - extParamInfos.push_back(extParamInfo); } FunctionType::ExtInfo einfo; @@ -479,18 +345,7 @@ CodeGenTypes::arrangeObjCMessageSendSignature(const ObjCMethodDecl *MD, return arrangeLLVMFunctionInfo( GetReturnType(MD->getReturnType()), /*instanceMethod=*/false, - /*chainCall=*/false, argTys, einfo, extParamInfos, required); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeUnprototypedObjCMessageSend(QualType returnType, - const CallArgList &args) { - auto argTypes = getArgTypesForCall(Context, args); - FunctionType::ExtInfo einfo; - - return arrangeLLVMFunctionInfo( - GetReturnType(returnType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, einfo, {}, RequiredArgs::All); + /*chainCall=*/false, argTys, einfo, required); } const CGFunctionInfo & @@ -519,7 +374,7 @@ CodeGenTypes::arrangeMSMemberPointerThunk(const CXXMethodDecl *MD) { CanQualType ArgTys[] = { GetThisType(Context, MD->getParent()) }; return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, ArgTys, - FTP->getExtInfo(), {}, RequiredArgs(1)); + FTP->getExtInfo(), RequiredArgs(1)); } const CGFunctionInfo & @@ -539,8 +394,7 @@ CodeGenTypes::arrangeMSCtorClosure(const CXXConstructorDecl *CD, /*IsVariadic=*/false, /*IsCXXMethod=*/true); return arrangeLLVMFunctionInfo(Context.VoidTy, /*instanceMethod=*/true, /*chainCall=*/false, ArgTys, - FunctionType::ExtInfo(CC), {}, - RequiredArgs::All); + FunctionType::ExtInfo(CC), RequiredArgs::All); } /// Arrange a call as unto a free function, except possibly with an @@ -554,8 +408,6 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, bool chainCall) { assert(args.size() >= numExtraRequiredArgs); - llvm::SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - // In most cases, there are no optional arguments. RequiredArgs required = RequiredArgs::All; @@ -565,10 +417,6 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, if (proto->isVariadic()) required = RequiredArgs(proto->getNumParams() + numExtraRequiredArgs); - if (proto->hasExtParameterInfos()) - addExtParameterInfosForCall(paramInfos, proto, numExtraRequiredArgs, - args.size()); - // If we don't have a prototype at all, but we're supposed to // explicitly use the variadic convention for unprototyped calls, // treat all of the arguments as required but preserve the nominal @@ -585,8 +433,7 @@ arrangeFreeFunctionLikeCall(CodeGenTypes &CGT, argTypes.push_back(CGT.getContext().getCanonicalParamType(arg.Ty)); return CGT.arrangeLLVMFunctionInfo(GetReturnType(fnType->getReturnType()), /*instanceMethod=*/false, chainCall, - argTypes, fnType->getExtInfo(), paramInfos, - required); + argTypes, fnType->getExtInfo(), required); } /// Figure out the rules for calling a function with the given formal @@ -601,7 +448,7 @@ CodeGenTypes::arrangeFreeFunctionCall(const CallArgList &args, chainCall ? 1 : 0, chainCall); } -/// A block function is essentially a free function with an +/// A block function call is essentially a free-function call with an /// extra implicit argument. const CGFunctionInfo & CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, @@ -611,110 +458,54 @@ CodeGenTypes::arrangeBlockFunctionCall(const CallArgList &args, } const CGFunctionInfo & -CodeGenTypes::arrangeBlockFunctionDeclaration(const FunctionProtoType *proto, - const FunctionArgList ¶ms) { - auto paramInfos = getExtParameterInfosForCall(proto, 1, params.size()); - auto argTypes = getArgTypesForDeclaration(Context, params); - - return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), - /*instanceMethod*/ false, /*chainCall*/ false, argTypes, - proto->getExtInfo(), paramInfos, - RequiredArgs::forPrototypePlus(proto, 1, nullptr)); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionCall(QualType resultType, - const CallArgList &args) { +CodeGenTypes::arrangeFreeFunctionCall(QualType resultType, + const CallArgList &args, + FunctionType::ExtInfo info, + RequiredArgs required) { // FIXME: Kill copy. SmallVector<CanQualType, 16> argTypes; for (const auto &Arg : args) argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); return arrangeLLVMFunctionInfo( GetReturnType(resultType), /*instanceMethod=*/false, - /*chainCall=*/false, argTypes, FunctionType::ExtInfo(), - /*paramInfos=*/ {}, RequiredArgs::All); + /*chainCall=*/false, argTypes, info, required); } +/// Arrange a call to a C++ method, passing the given arguments. const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionDeclaration(QualType resultType, - const FunctionArgList &args) { - auto argTypes = getArgTypesForDeclaration(Context, args); - - return arrangeLLVMFunctionInfo( - GetReturnType(resultType), /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); -} +CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, + const FunctionProtoType *FPT, + RequiredArgs required) { + // FIXME: Kill copy. + SmallVector<CanQualType, 16> argTypes; + for (const auto &Arg : args) + argTypes.push_back(Context.getCanonicalParamType(Arg.Ty)); -const CGFunctionInfo & -CodeGenTypes::arrangeBuiltinFunctionDeclaration(CanQualType resultType, - ArrayRef<CanQualType> argTypes) { + FunctionType::ExtInfo info = FPT->getExtInfo(); return arrangeLLVMFunctionInfo( - resultType, /*instanceMethod=*/false, /*chainCall=*/false, - argTypes, FunctionType::ExtInfo(), {}, RequiredArgs::All); + GetReturnType(FPT->getReturnType()), /*instanceMethod=*/true, + /*chainCall=*/false, argTypes, info, required); } -/// Arrange a call to a C++ method, passing the given arguments. -/// -/// numPrefixArgs is the number of ABI-specific prefix arguments we have. It -/// does not count `this`. -const CGFunctionInfo & -CodeGenTypes::arrangeCXXMethodCall(const CallArgList &args, - const FunctionProtoType *proto, - RequiredArgs required, - unsigned numPrefixArgs) { - assert(numPrefixArgs + 1 <= args.size() && - "Emitting a call with less args than the required prefix?"); - // Add one to account for `this`. It's a bit awkward here, but we don't count - // `this` in similar places elsewhere. - auto paramInfos = - getExtParameterInfosForCall(proto, numPrefixArgs + 1, args.size()); - +const CGFunctionInfo &CodeGenTypes::arrangeFreeFunctionDeclaration( + QualType resultType, const FunctionArgList &args, + const FunctionType::ExtInfo &info, bool isVariadic) { // FIXME: Kill copy. - auto argTypes = getArgTypesForCall(Context, args); + SmallVector<CanQualType, 16> argTypes; + for (auto Arg : args) + argTypes.push_back(Context.getCanonicalParamType(Arg->getType())); - FunctionType::ExtInfo info = proto->getExtInfo(); + RequiredArgs required = + (isVariadic ? RequiredArgs(args.size()) : RequiredArgs::All); return arrangeLLVMFunctionInfo( - GetReturnType(proto->getReturnType()), /*instanceMethod=*/true, - /*chainCall=*/false, argTypes, info, paramInfos, required); + GetReturnType(resultType), /*instanceMethod=*/false, + /*chainCall=*/false, argTypes, info, required); } const CGFunctionInfo &CodeGenTypes::arrangeNullaryFunction() { return arrangeLLVMFunctionInfo( getContext().VoidTy, /*instanceMethod=*/false, /*chainCall=*/false, - None, FunctionType::ExtInfo(), {}, RequiredArgs::All); -} - -const CGFunctionInfo & -CodeGenTypes::arrangeCall(const CGFunctionInfo &signature, - const CallArgList &args) { - assert(signature.arg_size() <= args.size()); - if (signature.arg_size() == args.size()) - return signature; - - SmallVector<FunctionProtoType::ExtParameterInfo, 16> paramInfos; - auto sigParamInfos = signature.getExtParameterInfos(); - if (!sigParamInfos.empty()) { - paramInfos.append(sigParamInfos.begin(), sigParamInfos.end()); - paramInfos.resize(args.size()); - } - - auto argTypes = getArgTypesForCall(Context, args); - - assert(signature.getRequiredArgs().allowsOptionalArgs()); - return arrangeLLVMFunctionInfo(signature.getReturnType(), - signature.isInstanceMethod(), - signature.isChainCall(), - argTypes, - signature.getExtInfo(), - paramInfos, - signature.getRequiredArgs()); -} - -namespace clang { -namespace CodeGen { -void computeSPIRKernelABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); -} + None, FunctionType::ExtInfo(), RequiredArgs::All); } /// Arrange the argument and result information for an abstract value @@ -726,42 +517,33 @@ CodeGenTypes::arrangeLLVMFunctionInfo(CanQualType resultType, bool chainCall, ArrayRef<CanQualType> argTypes, FunctionType::ExtInfo info, - ArrayRef<FunctionProtoType::ExtParameterInfo> paramInfos, RequiredArgs required) { assert(std::all_of(argTypes.begin(), argTypes.end(), - [](CanQualType T) { return T.isCanonicalAsParam(); })); + std::mem_fun_ref(&CanQualType::isCanonicalAsParam))); + + unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); // Lookup or create unique function info. llvm::FoldingSetNodeID ID; - CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, paramInfos, - required, resultType, argTypes); + CGFunctionInfo::Profile(ID, instanceMethod, chainCall, info, required, + resultType, argTypes); void *insertPos = nullptr; CGFunctionInfo *FI = FunctionInfos.FindNodeOrInsertPos(ID, insertPos); if (FI) return *FI; - unsigned CC = ClangCallConvToLLVMCallConv(info.getCC()); - // Construct the function info. We co-allocate the ArgInfos. FI = CGFunctionInfo::create(CC, instanceMethod, chainCall, info, - paramInfos, resultType, argTypes, required); + resultType, argTypes, required); FunctionInfos.InsertNode(FI, insertPos); bool inserted = FunctionsBeingProcessed.insert(FI).second; (void)inserted; assert(inserted && "Recursively being processed?"); - + // Compute ABI information. - if (CC == llvm::CallingConv::SPIR_KERNEL) { - // Force target independent argument handling for the host visible - // kernel functions. - computeSPIRKernelABIInfo(CGM, *FI); - } else if (info.getCC() == CC_Swift) { - swiftcall::computeABIInfo(CGM, *FI); - } else { - getABIInfo().computeInfo(*FI); - } + getABIInfo().computeInfo(*FI); // Loop over all of the computed argument and return value info. If any of // them are direct or extend without a specified coerce type, specify the @@ -784,16 +566,11 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, bool instanceMethod, bool chainCall, const FunctionType::ExtInfo &info, - ArrayRef<ExtParameterInfo> paramInfos, CanQualType resultType, ArrayRef<CanQualType> argTypes, RequiredArgs required) { - assert(paramInfos.empty() || paramInfos.size() == argTypes.size()); - - void *buffer = - operator new(totalSizeToAlloc<ArgInfo, ExtParameterInfo>( - argTypes.size() + 1, paramInfos.size())); - + void *buffer = operator new(sizeof(CGFunctionInfo) + + sizeof(ArgInfo) * (argTypes.size() + 1)); CGFunctionInfo *FI = new(buffer) CGFunctionInfo(); FI->CallingConvention = llvmCC; FI->EffectiveCallingConvention = llvmCC; @@ -802,19 +579,15 @@ CGFunctionInfo *CGFunctionInfo::create(unsigned llvmCC, FI->ChainCall = chainCall; FI->NoReturn = info.getNoReturn(); FI->ReturnsRetained = info.getProducesResult(); - FI->NoCallerSavedRegs = info.getNoCallerSavedRegs(); FI->Required = required; FI->HasRegParm = info.getHasRegParm(); FI->RegParm = info.getRegParm(); FI->ArgStruct = nullptr; FI->ArgStructAlign = 0; FI->NumArgs = argTypes.size(); - FI->HasExtParameterInfos = !paramInfos.empty(); FI->getArgsBuffer()[0].type = resultType; for (unsigned i = 0, e = argTypes.size(); i != e; ++i) FI->getArgsBuffer()[i + 1].type = argTypes[i]; - for (unsigned i = 0, e = paramInfos.size(); i != e; ++i) - FI->getExtParameterInfosBuffer()[i] = paramInfos[i]; return FI; } @@ -861,8 +634,7 @@ struct RecordExpansion : TypeExpansion { RecordExpansion(SmallVector<const CXXBaseSpecifier *, 1> &&Bases, SmallVector<const FieldDecl *, 1> &&Fields) - : TypeExpansion(TEK_Record), Bases(std::move(Bases)), - Fields(std::move(Fields)) {} + : TypeExpansion(TEK_Record), Bases(Bases), Fields(Fields) {} static bool classof(const TypeExpansion *TE) { return TE->Kind == TEK_Record; } @@ -1001,7 +773,7 @@ static void forConstantArrayExpansion(CodeGenFunction &CGF, } void CodeGenFunction::ExpandTypeFromArgs( - QualType Ty, LValue LV, SmallVectorImpl<llvm::Value *>::iterator &AI) { + QualType Ty, LValue LV, SmallVectorImpl<llvm::Argument *>::iterator &AI) { assert(LV.isSimple() && "Unexpected non-simple lvalue during struct expansion."); @@ -1026,7 +798,7 @@ void CodeGenFunction::ExpandTypeFromArgs( } for (auto FD : RExp->Fields) { // FIXME: What are the right qualifiers here? - LValue SubLV = EmitLValueForFieldInitialization(LV, FD); + LValue SubLV = EmitLValueForField(LV, FD); ExpandTypeFromArgs(FD->getType(), SubLV, AI); } } else if (isa<ComplexExpansion>(Exp.get())) { @@ -1227,15 +999,14 @@ static llvm::Value *CreateCoercedLoad(Address Src, llvm::Type *Ty, // // FIXME: Assert that we aren't truncating non-padding bits when have access // to that information. - Src = CGF.Builder.CreateBitCast(Src, - Ty->getPointerTo(Src.getAddressSpace())); + Src = CGF.Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(Ty)); return CGF.Builder.CreateLoad(Src); } // Otherwise do coercion through memory. This is stupid, but simple. Address Tmp = CreateTempAllocaForCoercion(CGF, Ty, Src.getAlignment()); - Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy); - Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.AllocaInt8PtrTy); + Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy); + Address SrcCasted = CGF.Builder.CreateBitCast(Src, CGF.Int8PtrTy); CGF.Builder.CreateMemCpy(Casted, SrcCasted, llvm::ConstantInt::get(CGF.IntPtrTy, SrcSize), false); @@ -1302,7 +1073,7 @@ static void CreateCoercedStore(llvm::Value *Src, // If store is legal, just bitcast the src pointer. if (SrcSize <= DstSize) { - Dst = CGF.Builder.CreateElementBitCast(Dst, SrcTy); + Dst = CGF.Builder.CreateBitCast(Dst, llvm::PointerType::getUnqual(SrcTy)); BuildAggStore(CGF, Src, Dst, DstIsVolatile); } else { // Otherwise do coercion through memory. This is stupid, but @@ -1316,8 +1087,8 @@ static void CreateCoercedStore(llvm::Value *Src, // to that information. Address Tmp = CreateTempAllocaForCoercion(CGF, SrcTy, Dst.getAlignment()); CGF.Builder.CreateStore(Src, Tmp); - Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.AllocaInt8PtrTy); - Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.AllocaInt8PtrTy); + Address Casted = CGF.Builder.CreateBitCast(Tmp, CGF.Int8PtrTy); + Address DstCasted = CGF.Builder.CreateBitCast(Dst, CGF.Int8PtrTy); CGF.Builder.CreateMemCpy(DstCasted, Casted, llvm::ConstantInt::get(CGF.IntPtrTy, DstSize), false); @@ -1449,13 +1220,11 @@ void ClangToLLVMArgMapping::construct(const ASTContext &Context, // ignore and inalloca doesn't have matching LLVM parameters. IRArgs.NumberOfArgs = 0; break; - case ABIArgInfo::CoerceAndExpand: - IRArgs.NumberOfArgs = AI.getCoerceAndExpandTypeSequence().size(); - break; - case ABIArgInfo::Expand: + case ABIArgInfo::Expand: { IRArgs.NumberOfArgs = getExpansionSize(ArgType, Context); break; } + } if (IRArgs.NumberOfArgs > 0) { IRArgs.FirstArgIndex = IRArgNo; @@ -1554,10 +1323,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { case ABIArgInfo::Ignore: resultType = llvm::Type::getVoidTy(getLLVMContext()); break; - - case ABIArgInfo::CoerceAndExpand: - resultType = retAI.getUnpaddedCoerceAndExpandType(); - break; } ClangToLLVMArgMapping IRFunctionArgs(getContext(), FI, true); @@ -1602,10 +1367,9 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { case ABIArgInfo::Indirect: { assert(NumIRArgs == 1); - // indirect arguments are always on the stack, which is alloca addr space. + // indirect arguments are always on the stack, which is addr space #0. llvm::Type *LTy = ConvertTypeForMem(it->type); - ArgTypes[FirstIRArg] = LTy->getPointerTo( - CGM.getDataLayout().getAllocaAddrSpace()); + ArgTypes[FirstIRArg] = LTy->getPointerTo(); break; } @@ -1626,15 +1390,6 @@ CodeGenTypes::GetFunctionType(const CGFunctionInfo &FI) { break; } - case ABIArgInfo::CoerceAndExpand: { - auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; - for (auto EltTy : ArgInfo.getCoerceAndExpandTypeSequence()) { - *ArgTypesIter++ = EltTy; - } - assert(ArgTypesIter == ArgTypes.begin() + FirstIRArg + NumIRArgs); - break; - } - case ABIArgInfo::Expand: auto ArgTypesIter = ArgTypes.begin() + FirstIRArg; getExpandedTypes(it->type, ArgTypesIter); @@ -1676,119 +1431,15 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx, FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); } -void CodeGenModule::ConstructDefaultFnAttrList(StringRef Name, bool HasOptnone, - bool AttrOnCallSite, - llvm::AttrBuilder &FuncAttrs) { - // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. - if (!HasOptnone) { - if (CodeGenOpts.OptimizeSize) - FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); - if (CodeGenOpts.OptimizeSize == 2) - FuncAttrs.addAttribute(llvm::Attribute::MinSize); - } - - if (CodeGenOpts.DisableRedZone) - FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); - if (CodeGenOpts.NoImplicitFloat) - FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); - - if (AttrOnCallSite) { - // Attributes that should go on the call site only. - if (!CodeGenOpts.SimplifyLibCalls || - CodeGenOpts.isNoBuiltinFunc(Name.data())) - FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); - if (!CodeGenOpts.TrapFuncName.empty()) - FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); - } else { - // Attributes that should go on the function, but not the call site. - if (!CodeGenOpts.DisableFPElim) { - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); - } else if (CodeGenOpts.OmitLeafFramePointer) { - FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } else { - FuncAttrs.addAttribute("no-frame-pointer-elim", "true"); - FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); - } - - FuncAttrs.addAttribute("less-precise-fpmad", - llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); - - if (!CodeGenOpts.FPDenormalMode.empty()) - FuncAttrs.addAttribute("denormal-fp-math", CodeGenOpts.FPDenormalMode); - - FuncAttrs.addAttribute("no-trapping-math", - llvm::toStringRef(CodeGenOpts.NoTrappingMath)); - - // TODO: Are these all needed? - // unsafe/inf/nan/nsz are handled by instruction-level FastMathFlags. - FuncAttrs.addAttribute("no-infs-fp-math", - llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); - FuncAttrs.addAttribute("no-nans-fp-math", - llvm::toStringRef(CodeGenOpts.NoNaNsFPMath)); - FuncAttrs.addAttribute("unsafe-fp-math", - llvm::toStringRef(CodeGenOpts.UnsafeFPMath)); - FuncAttrs.addAttribute("use-soft-float", - llvm::toStringRef(CodeGenOpts.SoftFloat)); - FuncAttrs.addAttribute("stack-protector-buffer-size", - llvm::utostr(CodeGenOpts.SSPBufferSize)); - FuncAttrs.addAttribute("no-signed-zeros-fp-math", - llvm::toStringRef(CodeGenOpts.NoSignedZeros)); - FuncAttrs.addAttribute( - "correctly-rounded-divide-sqrt-fp-math", - llvm::toStringRef(CodeGenOpts.CorrectlyRoundedDivSqrt)); - - // TODO: Reciprocal estimate codegen options should apply to instructions? - const std::vector<std::string> &Recips = CodeGenOpts.Reciprocals; - if (!Recips.empty()) - FuncAttrs.addAttribute("reciprocal-estimates", - llvm::join(Recips, ",")); - - if (!CodeGenOpts.PreferVectorWidth.empty() && - CodeGenOpts.PreferVectorWidth != "none") - FuncAttrs.addAttribute("prefer-vector-width", - CodeGenOpts.PreferVectorWidth); - - if (CodeGenOpts.StackRealignment) - FuncAttrs.addAttribute("stackrealign"); - if (CodeGenOpts.Backchain) - FuncAttrs.addAttribute("backchain"); - } - - if (getLangOpts().assumeFunctionsAreConvergent()) { - // Conservatively, mark all functions and calls in CUDA and OpenCL as - // convergent (meaning, they may call an intrinsically convergent op, such - // as __syncthreads() / barrier(), and so can't have certain optimizations - // applied around them). LLVM will remove this attribute where it safely - // can. - FuncAttrs.addAttribute(llvm::Attribute::Convergent); - } - - if (getLangOpts().CUDA && getLangOpts().CUDAIsDevice) { - // Exceptions aren't supported in CUDA device code. - FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); - - // Respect -fcuda-flush-denormals-to-zero. - if (getLangOpts().CUDADeviceFlushDenormalsToZero) - FuncAttrs.addAttribute("nvptx-f32ftz", "true"); - } -} - -void CodeGenModule::AddDefaultFnAttrs(llvm::Function &F) { - llvm::AttrBuilder FuncAttrs; - ConstructDefaultFnAttrList(F.getName(), - F.hasFnAttribute(llvm::Attribute::OptimizeNone), - /* AttrOnCallsite = */ false, FuncAttrs); - F.addAttributes(llvm::AttributeList::FunctionIndex, FuncAttrs); -} - void CodeGenModule::ConstructAttributeList( StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo, - llvm::AttributeList &AttrList, unsigned &CallingConv, bool AttrOnCallSite) { + AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) { llvm::AttrBuilder FuncAttrs; llvm::AttrBuilder RetAttrs; + bool HasOptnone = false; CallingConv = FI.getEffectiveCallingConvention(); + if (FI.isNoReturn()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); @@ -1799,7 +1450,6 @@ void CodeGenModule::ConstructAttributeList( const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); - bool HasOptnone = false; // FIXME: handle sseregparm someday... if (TargetDecl) { if (TargetDecl->hasAttr<ReturnsTwiceAttr>()) @@ -1808,12 +1458,8 @@ void CodeGenModule::ConstructAttributeList( FuncAttrs.addAttribute(llvm::Attribute::NoUnwind); if (TargetDecl->hasAttr<NoReturnAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoReturn); - if (TargetDecl->hasAttr<ColdAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::Cold); if (TargetDecl->hasAttr<NoDuplicateAttr>()) FuncAttrs.addAttribute(llvm::Attribute::NoDuplicate); - if (TargetDecl->hasAttr<ConvergentAttr>()) - FuncAttrs.addAttribute(llvm::Attribute::Convergent); if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { AddAttributesFromFunctionProtoType( @@ -1840,55 +1486,78 @@ void CodeGenModule::ConstructAttributeList( RetAttrs.addAttribute(llvm::Attribute::NoAlias); if (TargetDecl->hasAttr<ReturnsNonNullAttr>()) RetAttrs.addAttribute(llvm::Attribute::NonNull); - if (TargetDecl->hasAttr<AnyX86NoCallerSavedRegistersAttr>()) - FuncAttrs.addAttribute("no_caller_saved_registers"); HasOptnone = TargetDecl->hasAttr<OptimizeNoneAttr>(); - if (auto *AllocSize = TargetDecl->getAttr<AllocSizeAttr>()) { - Optional<unsigned> NumElemsParam; - // alloc_size args are base-1, 0 means not present. - if (unsigned N = AllocSize->getNumElemsParam()) - NumElemsParam = N - 1; - FuncAttrs.addAllocSizeAttr(AllocSize->getElemSizeParam() - 1, - NumElemsParam); - } } - ConstructDefaultFnAttrList(Name, HasOptnone, AttrOnCallSite, FuncAttrs); + // OptimizeNoneAttr takes precedence over -Os or -Oz. No warning needed. + if (!HasOptnone) { + if (CodeGenOpts.OptimizeSize) + FuncAttrs.addAttribute(llvm::Attribute::OptimizeForSize); + if (CodeGenOpts.OptimizeSize == 2) + FuncAttrs.addAttribute(llvm::Attribute::MinSize); + } + if (CodeGenOpts.DisableRedZone) + FuncAttrs.addAttribute(llvm::Attribute::NoRedZone); + if (CodeGenOpts.NoImplicitFloat) + FuncAttrs.addAttribute(llvm::Attribute::NoImplicitFloat); if (CodeGenOpts.EnableSegmentedStacks && !(TargetDecl && TargetDecl->hasAttr<NoSplitStackAttr>())) FuncAttrs.addAttribute("split-stack"); - // Add NonLazyBind attribute to function declarations when -fno-plt - // is used. - if (TargetDecl && CodeGenOpts.NoPLT) { - if (auto *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { - if (!Fn->isDefined() && !AttrOnCallSite) { - FuncAttrs.addAttribute(llvm::Attribute::NonLazyBind); - } + if (AttrOnCallSite) { + // Attributes that should go on the call site only. + if (!CodeGenOpts.SimplifyLibCalls || + CodeGenOpts.isNoBuiltinFunc(Name.data())) + FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin); + if (!CodeGenOpts.TrapFuncName.empty()) + FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName); + } else { + // Attributes that should go on the function, but not the call site. + if (!CodeGenOpts.DisableFPElim) { + FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); + } else if (CodeGenOpts.OmitLeafFramePointer) { + FuncAttrs.addAttribute("no-frame-pointer-elim", "false"); + FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); + } else { + FuncAttrs.addAttribute("no-frame-pointer-elim", "true"); + FuncAttrs.addAttribute("no-frame-pointer-elim-non-leaf"); } - } - if (!AttrOnCallSite) { bool DisableTailCalls = CodeGenOpts.DisableTailCalls || - (TargetDecl && (TargetDecl->hasAttr<DisableTailCallsAttr>() || - TargetDecl->hasAttr<AnyX86InterruptAttr>())); + (TargetDecl && TargetDecl->hasAttr<DisableTailCallsAttr>()); FuncAttrs.addAttribute("disable-tail-calls", llvm::toStringRef(DisableTailCalls)); + FuncAttrs.addAttribute("less-precise-fpmad", + llvm::toStringRef(CodeGenOpts.LessPreciseFPMAD)); + FuncAttrs.addAttribute("no-infs-fp-math", + llvm::toStringRef(CodeGenOpts.NoInfsFPMath)); + FuncAttrs.addAttribute("no-nans-fp-math", + llvm::toStringRef(CodeGenOpts.NoNaNsFPMath)); + FuncAttrs.addAttribute("unsafe-fp-math", + llvm::toStringRef(CodeGenOpts.UnsafeFPMath)); + FuncAttrs.addAttribute("use-soft-float", + llvm::toStringRef(CodeGenOpts.SoftFloat)); + FuncAttrs.addAttribute("stack-protector-buffer-size", + llvm::utostr(CodeGenOpts.SSPBufferSize)); + + if (CodeGenOpts.StackRealignment) + FuncAttrs.addAttribute("stackrealign"); + // Add target-cpu and target-features attributes to functions. If // we have a decl for the function and it has a target attribute then // parse that and add it to the feature set. StringRef TargetCPU = getTarget().getTargetOpts().CPU; - std::vector<std::string> Features; const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(TargetDecl); if (FD && FD->hasAttr<TargetAttr>()) { llvm::StringMap<bool> FeatureMap; getFunctionFeatureMap(FeatureMap, FD); // Produce the canonical string for this set of features. + std::vector<std::string> Features; for (llvm::StringMap<bool>::const_iterator it = FeatureMap.begin(), ie = FeatureMap.end(); it != ie; ++it) @@ -1900,22 +1569,28 @@ void CodeGenModule::ConstructAttributeList( // the function. const auto *TD = FD->getAttr<TargetAttr>(); TargetAttr::ParsedTargetAttr ParsedAttr = TD->parse(); - if (ParsedAttr.Architecture != "" && - getTarget().isValidCPUName(ParsedAttr.Architecture)) - TargetCPU = ParsedAttr.Architecture; + if (ParsedAttr.second != "") + TargetCPU = ParsedAttr.second; + if (TargetCPU != "") + FuncAttrs.addAttribute("target-cpu", TargetCPU); + if (!Features.empty()) { + std::sort(Features.begin(), Features.end()); + FuncAttrs.addAttribute( + "target-features", + llvm::join(Features.begin(), Features.end(), ",")); + } } else { // Otherwise just add the existing target cpu and target features to the // function. - Features = getTarget().getTargetOpts().Features; - } - - if (TargetCPU != "") - FuncAttrs.addAttribute("target-cpu", TargetCPU); - if (!Features.empty()) { - std::sort(Features.begin(), Features.end()); - FuncAttrs.addAttribute( - "target-features", - llvm::join(Features, ",")); + std::vector<std::string> &Features = getTarget().getTargetOpts().Features; + if (TargetCPU != "") + FuncAttrs.addAttribute("target-cpu", TargetCPU); + if (!Features.empty()) { + std::sort(Features.begin(), Features.end()); + FuncAttrs.addAttribute( + "target-features", + llvm::join(Features.begin(), Features.end(), ",")); + } } } @@ -1929,7 +1604,7 @@ void CodeGenModule::ConstructAttributeList( RetAttrs.addAttribute(llvm::Attribute::SExt); else if (RetTy->hasUnsignedIntegerRepresentation()) RetAttrs.addAttribute(llvm::Attribute::ZExt); - LLVM_FALLTHROUGH; + // FALL THROUGH case ABIArgInfo::Direct: if (RetAI.getInReg()) RetAttrs.addAttribute(llvm::Attribute::InReg); @@ -1945,9 +1620,6 @@ void CodeGenModule::ConstructAttributeList( break; } - case ABIArgInfo::CoerceAndExpand: - break; - case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } @@ -1961,26 +1633,28 @@ void CodeGenModule::ConstructAttributeList( RetAttrs.addAttribute(llvm::Attribute::NonNull); } - bool hasUsedSRet = false; - SmallVector<llvm::AttributeSet, 4> ArgAttrs(IRFunctionArgs.totalIRArgs()); + // Attach return attributes. + if (RetAttrs.hasAttributes()) { + PAL.push_back(llvm::AttributeSet::get( + getLLVMContext(), llvm::AttributeSet::ReturnIndex, RetAttrs)); + } // Attach attributes to sret. if (IRFunctionArgs.hasSRetArg()) { llvm::AttrBuilder SRETAttrs; SRETAttrs.addAttribute(llvm::Attribute::StructRet); - hasUsedSRet = true; if (RetAI.getInReg()) SRETAttrs.addAttribute(llvm::Attribute::InReg); - ArgAttrs[IRFunctionArgs.getSRetArgNo()] = - llvm::AttributeSet::get(getLLVMContext(), SRETAttrs); + PAL.push_back(llvm::AttributeSet::get( + getLLVMContext(), IRFunctionArgs.getSRetArgNo() + 1, SRETAttrs)); } // Attach attributes to inalloca argument. if (IRFunctionArgs.hasInallocaArg()) { llvm::AttrBuilder Attrs; Attrs.addAttribute(llvm::Attribute::InAlloca); - ArgAttrs[IRFunctionArgs.getInallocaArgNo()] = - llvm::AttributeSet::get(getLLVMContext(), Attrs); + PAL.push_back(llvm::AttributeSet::get( + getLLVMContext(), IRFunctionArgs.getInallocaArgNo() + 1, Attrs)); } unsigned ArgNo = 0; @@ -1993,12 +1667,10 @@ void CodeGenModule::ConstructAttributeList( // Add attribute for padding argument, if necessary. if (IRFunctionArgs.hasPaddingArg(ArgNo)) { - if (AI.getPaddingInReg()) { - ArgAttrs[IRFunctionArgs.getPaddingArgNo(ArgNo)] = - llvm::AttributeSet::get( - getLLVMContext(), - llvm::AttrBuilder().addAttribute(llvm::Attribute::InReg)); - } + if (AI.getPaddingInReg()) + PAL.push_back(llvm::AttributeSet::get( + getLLVMContext(), IRFunctionArgs.getPaddingArgNo(ArgNo) + 1, + llvm::Attribute::InReg)); } // 'restrict' -> 'noalias' is done in EmitFunctionProlog when we @@ -2014,7 +1686,7 @@ void CodeGenModule::ConstructAttributeList( else Attrs.addAttribute(llvm::Attribute::ZExt); } - LLVM_FALLTHROUGH; + // FALL THROUGH case ABIArgInfo::Direct: if (ArgNo == 0 && FI.isChainCall()) Attrs.addAttribute(llvm::Attribute::Nest); @@ -2055,8 +1727,7 @@ void CodeGenModule::ConstructAttributeList( } case ABIArgInfo::Ignore: case ABIArgInfo::Expand: - case ABIArgInfo::CoerceAndExpand: - break; + continue; case ABIArgInfo::InAlloca: // inalloca disables readnone and readonly. @@ -2074,57 +1745,21 @@ void CodeGenModule::ConstructAttributeList( Attrs.addAttribute(llvm::Attribute::NonNull); } - switch (FI.getExtParameterInfo(ArgNo).getABI()) { - case ParameterABI::Ordinary: - break; - - case ParameterABI::SwiftIndirectResult: { - // Add 'sret' if we haven't already used it for something, but - // only if the result is void. - if (!hasUsedSRet && RetTy->isVoidType()) { - Attrs.addAttribute(llvm::Attribute::StructRet); - hasUsedSRet = true; - } - - // Add 'noalias' in either case. - Attrs.addAttribute(llvm::Attribute::NoAlias); - - // Add 'dereferenceable' and 'alignment'. - auto PTy = ParamType->getPointeeType(); - if (!PTy->isIncompleteType() && PTy->isConstantSizeType()) { - auto info = getContext().getTypeInfoInChars(PTy); - Attrs.addDereferenceableAttr(info.first.getQuantity()); - Attrs.addAttribute(llvm::Attribute::getWithAlignment(getLLVMContext(), - info.second.getQuantity())); - } - break; - } - - case ParameterABI::SwiftErrorResult: - Attrs.addAttribute(llvm::Attribute::SwiftError); - break; - - case ParameterABI::SwiftContext: - Attrs.addAttribute(llvm::Attribute::SwiftSelf); - break; - } - - if (FI.getExtParameterInfo(ArgNo).isNoEscape()) - Attrs.addAttribute(llvm::Attribute::NoCapture); - if (Attrs.hasAttributes()) { unsigned FirstIRArg, NumIRArgs; std::tie(FirstIRArg, NumIRArgs) = IRFunctionArgs.getIRArgs(ArgNo); for (unsigned i = 0; i < NumIRArgs; i++) - ArgAttrs[FirstIRArg + i] = - llvm::AttributeSet::get(getLLVMContext(), Attrs); + PAL.push_back(llvm::AttributeSet::get(getLLVMContext(), + FirstIRArg + i + 1, Attrs)); } } assert(ArgNo == FI.arg_size()); - AttrList = llvm::AttributeList::get( - getLLVMContext(), llvm::AttributeSet::get(getLLVMContext(), FuncAttrs), - llvm::AttributeSet::get(getLLVMContext(), RetAttrs), ArgAttrs); + if (FuncAttrs.hasAttributes()) + PAL.push_back(llvm:: + AttributeSet::get(getLLVMContext(), + llvm::AttributeSet::FunctionIndex, + FuncAttrs)); } /// An argument came in as a promoted argument; demote it back to its @@ -2175,18 +1810,6 @@ static const NonNullAttr *getNonNullAttr(const Decl *FD, const ParmVarDecl *PVD, return nullptr; } -namespace { - struct CopyBackSwiftError final : EHScopeStack::Cleanup { - Address Temp; - Address Arg; - CopyBackSwiftError(Address temp, Address arg) : Temp(temp), Arg(arg) {} - void Emit(CodeGenFunction &CGF, Flags flags) override { - llvm::Value *errorValue = CGF.Builder.CreateLoad(Temp); - CGF.Builder.CreateStore(errorValue, Arg); - } - }; -} - void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::Function *Fn, const FunctionArgList &Args) { @@ -2212,7 +1835,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ClangToLLVMArgMapping IRFunctionArgs(CGM.getContext(), FI); // Flattened function arguments. - SmallVector<llvm::Value *, 16> FnArgs; + SmallVector<llvm::Argument *, 16> FnArgs; FnArgs.reserve(IRFunctionArgs.totalIRArgs()); for (auto &Arg : Fn->args()) { FnArgs.push_back(&Arg); @@ -2233,9 +1856,10 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // Name the struct return parameter. if (IRFunctionArgs.hasSRetArg()) { - auto AI = cast<llvm::Argument>(FnArgs[IRFunctionArgs.getSRetArgNo()]); + auto AI = FnArgs[IRFunctionArgs.getSRetArgNo()]; AI->setName("agg.result"); - AI->addAttr(llvm::Attribute::NoAlias); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), AI->getArgNo() + 1, + llvm::Attribute::NoAlias)); } // Track if we received the parameter as a pointer (indirect, byval, or @@ -2320,13 +1944,15 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, ArgI.getCoerceToType() == ConvertType(Ty) && ArgI.getDirectOffset() == 0) { assert(NumIRArgs == 1); - llvm::Value *V = FnArgs[FirstIRArg]; - auto AI = cast<llvm::Argument>(V); + auto AI = FnArgs[FirstIRArg]; + llvm::Value *V = AI; if (const ParmVarDecl *PVD = dyn_cast<ParmVarDecl>(Arg)) { if (getNonNullAttr(CurCodeDecl, PVD, PVD->getType(), PVD->getFunctionScopeIndex())) - AI->addAttr(llvm::Attribute::NonNull); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, + llvm::Attribute::NonNull)); QualType OTy = PVD->getOriginalType(); if (const auto *ArrTy = @@ -2343,9 +1969,12 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, llvm::AttrBuilder Attrs; Attrs.addDereferenceableAttr( getContext().getTypeSizeInChars(ETy).getQuantity()*ArrSize); - AI->addAttrs(Attrs); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, Attrs)); } else if (getContext().getTargetAddressSpace(ETy) == 0) { - AI->addAttr(llvm::Attribute::NonNull); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, + llvm::Attribute::NonNull)); } } } else if (const auto *ArrTy = @@ -2355,45 +1984,35 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // we know that it must be nonnull. if (ArrTy->getSizeModifier() == VariableArrayType::Static && !getContext().getTargetAddressSpace(ArrTy->getElementType())) - AI->addAttr(llvm::Attribute::NonNull); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, + llvm::Attribute::NonNull)); } const auto *AVAttr = PVD->getAttr<AlignValueAttr>(); if (!AVAttr) if (const auto *TOTy = dyn_cast<TypedefType>(OTy)) AVAttr = TOTy->getDecl()->getAttr<AlignValueAttr>(); - if (AVAttr) { + if (AVAttr) { llvm::Value *AlignmentValue = EmitScalarExpr(AVAttr->getAlignment()); llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(AlignmentValue); - unsigned Alignment = std::min((unsigned)AlignmentCI->getZExtValue(), - +llvm::Value::MaximumAlignment); - AI->addAttrs(llvm::AttrBuilder().addAlignmentAttr(Alignment)); + unsigned Alignment = + std::min((unsigned) AlignmentCI->getZExtValue(), + +llvm::Value::MaximumAlignment); + + llvm::AttrBuilder Attrs; + Attrs.addAlignmentAttr(Alignment); + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, Attrs)); } } if (Arg->getType().isRestrictQualified()) - AI->addAttr(llvm::Attribute::NoAlias); - - // LLVM expects swifterror parameters to be used in very restricted - // ways. Copy the value into a less-restricted temporary. - if (FI.getExtParameterInfo(ArgNo).getABI() - == ParameterABI::SwiftErrorResult) { - QualType pointeeTy = Ty->getPointeeType(); - assert(pointeeTy->isPointerType()); - Address temp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - Address arg = Address(V, getContext().getTypeAlignInChars(pointeeTy)); - llvm::Value *incomingErrorValue = Builder.CreateLoad(arg); - Builder.CreateStore(incomingErrorValue, temp); - V = temp.getPointer(); - - // Push a cleanup to copy the value back at the end of the function. - // The convention does not guarantee that the value will be written - // back if the function exits with an unwind exception. - EHStack.pushCleanup<CopyBackSwiftError>(NormalCleanup, temp, arg); - } + AI->addAttr(llvm::AttributeSet::get(getLLVMContext(), + AI->getArgNo() + 1, + llvm::Attribute::NoAlias)); // Ensure the argument is the correct type. if (V->getType() != ArgI.getCoerceToType()) @@ -2402,6 +2021,13 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, if (isPromoted) V = emitArgumentDemotion(*this, Arg, V); + if (const CXXMethodDecl *MD = + dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl)) { + if (MD->isVirtual() && Arg == CXXABIThisDecl) + V = CGM.getCXXABI(). + adjustThisParameterInVirtualFunctionPrologue(*this, CurGD, V); + } + // Because of merging of function types from multiple decls it is // possible for the type of an argument to not match the corresponding // type in the function type. Since we are codegening the callee @@ -2432,7 +2058,8 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, Address AddrToStoreInto = Address::invalid(); if (SrcSize <= DstSize) { - AddrToStoreInto = Builder.CreateElementBitCast(Ptr, STy); + AddrToStoreInto = + Builder.CreateBitCast(Ptr, llvm::PointerType::getUnqual(STy)); } else { AddrToStoreInto = CreateTempAlloca(STy, Alloca.getAlignment(), "coerce"); @@ -2473,29 +2100,6 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, break; } - case ABIArgInfo::CoerceAndExpand: { - // Reconstruct into a temporary. - Address alloca = CreateMemTemp(Ty, getContext().getDeclAlign(Arg)); - ArgVals.push_back(ParamValue::forIndirect(alloca)); - - auto coercionType = ArgI.getCoerceAndExpandType(); - alloca = Builder.CreateElementBitCast(alloca, coercionType); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - unsigned argIndex = FirstIRArg; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) - continue; - - auto eltAddr = Builder.CreateStructGEP(alloca, i, layout); - auto elt = FnArgs[argIndex++]; - Builder.CreateStore(elt, eltAddr); - } - assert(argIndex == FirstIRArg + NumIRArgs); - break; - } - case ABIArgInfo::Expand: { // If this structure was expanded into multiple arguments then // we need to create a temporary and reconstruct it from the @@ -2560,7 +2164,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF, // result is in a BasicBlock and is therefore an Instruction. llvm::Instruction *generator = cast<llvm::Instruction>(result); - SmallVector<llvm::Instruction *, 4> InstsToKill; + SmallVector<llvm::Instruction*,4> insnsToKill; // Look for: // %generator = bitcast %type1* %generator2 to %type2* @@ -2573,7 +2177,7 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF, if (generator->getNextNode() != bitcast) return nullptr; - InstsToKill.push_back(bitcast); + insnsToKill.push_back(bitcast); } // Look for: @@ -2606,26 +2210,27 @@ static llvm::Value *tryEmitFusedAutoreleaseOfResult(CodeGenFunction &CGF, assert(isa<llvm::CallInst>(prev)); assert(cast<llvm::CallInst>(prev)->getCalledValue() == CGF.CGM.getObjCEntrypoints().retainAutoreleasedReturnValueMarker); - InstsToKill.push_back(prev); + insnsToKill.push_back(prev); } } else { return nullptr; } result = call->getArgOperand(0); - InstsToKill.push_back(call); + insnsToKill.push_back(call); // Keep killing bitcasts, for sanity. Note that we no longer care // about precise ordering as long as there's exactly one use. while (llvm::BitCastInst *bitcast = dyn_cast<llvm::BitCastInst>(result)) { if (!bitcast->hasOneUse()) break; - InstsToKill.push_back(bitcast); + insnsToKill.push_back(bitcast); result = bitcast->getOperand(0); } // Delete all the unnecessary instructions, from latest to earliest. - for (auto *I : InstsToKill) - I->eraseFromParent(); + for (SmallVectorImpl<llvm::Instruction*>::iterator + i = insnsToKill.begin(), e = insnsToKill.end(); i != e; ++i) + (*i)->eraseFromParent(); // Do the fused retain/autorelease if we were asked to. if (doRetainAutorelease) @@ -2758,12 +2363,6 @@ static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) { void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, bool EmitRetDbgLoc, SourceLocation EndLoc) { - if (FI.isNoReturn()) { - // Noreturn functions don't return. - EmitUnreachable(EndLoc); - return; - } - if (CurCodeDecl && CurCodeDecl->hasAttr<NakedAttr>()) { // Naked functions don't have epilogues. Builder.CreateUnreachable(); @@ -2863,26 +2462,9 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, // In ARC, end functions that return a retainable type with a call // to objc_autoreleaseReturnValue. if (AutoreleaseResult) { -#ifndef NDEBUG - // Type::isObjCRetainabletype has to be called on a QualType that hasn't - // been stripped of the typedefs, so we cannot use RetTy here. Get the - // original return type of FunctionDecl, CurCodeDecl, and BlockDecl from - // CurCodeDecl or BlockInfo. - QualType RT; - - if (auto *FD = dyn_cast<FunctionDecl>(CurCodeDecl)) - RT = FD->getReturnType(); - else if (auto *MD = dyn_cast<ObjCMethodDecl>(CurCodeDecl)) - RT = MD->getReturnType(); - else if (isa<BlockDecl>(CurCodeDecl)) - RT = BlockInfo->BlockExpression->getFunctionType()->getReturnType(); - else - llvm_unreachable("Unexpected function/method type"); - assert(getLangOpts().ObjCAutoRefCount && !FI.isReturnsRetained() && - RT->isObjCRetainableType()); -#endif + RetTy->isObjCRetainableType()); RV = emitAutoreleaseOfResult(*this, RV); } @@ -2891,47 +2473,25 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, case ABIArgInfo::Ignore: break; - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = RetAI.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - // Load all of the coerced elements out into results. - llvm::SmallVector<llvm::Value*, 4> results; - Address addr = Builder.CreateElementBitCast(ReturnValue, coercionType); - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - auto coercedEltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(coercedEltType)) - continue; - - auto eltAddr = Builder.CreateStructGEP(addr, i, layout); - auto elt = Builder.CreateLoad(eltAddr); - results.push_back(elt); - } - - // If we have one result, it's the single direct result type. - if (results.size() == 1) { - RV = results[0]; - - // Otherwise, we need to make a first-class aggregate. - } else { - // Construct a return type that lacks padding elements. - llvm::Type *returnType = RetAI.getUnpaddedCoerceAndExpandType(); - - RV = llvm::UndefValue::get(returnType); - for (unsigned i = 0, e = results.size(); i != e; ++i) { - RV = Builder.CreateInsertValue(RV, results[i], i); - } - } - break; - } - case ABIArgInfo::Expand: llvm_unreachable("Invalid ABI kind for return argument"); } llvm::Instruction *Ret; if (RV) { - EmitReturnValueCheck(RV); + if (CurCodeDecl && SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) { + if (auto RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>()) { + SanitizerScope SanScope(this); + llvm::Value *Cond = Builder.CreateICmpNE( + RV, llvm::Constant::getNullValue(RV->getType())); + llvm::Constant *StaticData[] = { + EmitCheckSourceLocation(EndLoc), + EmitCheckSourceLocation(RetNNAttr->getLocation()), + }; + EmitCheck(std::make_pair(Cond, SanitizerKind::ReturnsNonnullAttribute), + "nonnull_return", StaticData, None); + } + } Ret = Builder.CreateRet(RV); } else { Ret = Builder.CreateRetVoid(); @@ -2941,65 +2501,6 @@ void CodeGenFunction::EmitFunctionEpilog(const CGFunctionInfo &FI, Ret->setDebugLoc(std::move(RetDbgLoc)); } -void CodeGenFunction::EmitReturnValueCheck(llvm::Value *RV) { - // A current decl may not be available when emitting vtable thunks. - if (!CurCodeDecl) - return; - - ReturnsNonNullAttr *RetNNAttr = nullptr; - if (SanOpts.has(SanitizerKind::ReturnsNonnullAttribute)) - RetNNAttr = CurCodeDecl->getAttr<ReturnsNonNullAttr>(); - - if (!RetNNAttr && !requiresReturnValueNullabilityCheck()) - return; - - // Prefer the returns_nonnull attribute if it's present. - SourceLocation AttrLoc; - SanitizerMask CheckKind; - SanitizerHandler Handler; - if (RetNNAttr) { - assert(!requiresReturnValueNullabilityCheck() && - "Cannot check nullability and the nonnull attribute"); - AttrLoc = RetNNAttr->getLocation(); - CheckKind = SanitizerKind::ReturnsNonnullAttribute; - Handler = SanitizerHandler::NonnullReturn; - } else { - if (auto *DD = dyn_cast<DeclaratorDecl>(CurCodeDecl)) - if (auto *TSI = DD->getTypeSourceInfo()) - if (auto FTL = TSI->getTypeLoc().castAs<FunctionTypeLoc>()) - AttrLoc = FTL.getReturnLoc().findNullabilityLoc(); - CheckKind = SanitizerKind::NullabilityReturn; - Handler = SanitizerHandler::NullabilityReturn; - } - - SanitizerScope SanScope(this); - - // Make sure the "return" source location is valid. If we're checking a - // nullability annotation, make sure the preconditions for the check are met. - llvm::BasicBlock *Check = createBasicBlock("nullcheck"); - llvm::BasicBlock *NoCheck = createBasicBlock("no.nullcheck"); - llvm::Value *SLocPtr = Builder.CreateLoad(ReturnLocation, "return.sloc.load"); - llvm::Value *CanNullCheck = Builder.CreateIsNotNull(SLocPtr); - if (requiresReturnValueNullabilityCheck()) - CanNullCheck = - Builder.CreateAnd(CanNullCheck, RetValNullabilityPrecondition); - Builder.CreateCondBr(CanNullCheck, Check, NoCheck); - EmitBlock(Check); - - // Now do the null check. - llvm::Value *Cond = Builder.CreateIsNotNull(RV); - llvm::Constant *StaticData[] = {EmitCheckSourceLocation(AttrLoc)}; - llvm::Value *DynamicData[] = {SLocPtr}; - EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, DynamicData); - - EmitBlock(NoCheck); - -#ifndef NDEBUG - // The return location should not be used after the check has been emitted. - ReturnLocation = Address::invalid(); -#endif -} - static bool isInAllocaArgument(CGCXXABI &ABI, QualType type) { const CXXRecordDecl *RD = type->getAsCXXRecordDecl(); return RD && ABI.getRecordArgABI(RD) == CGCXXABI::RAA_DirectInMemory; @@ -3010,13 +2511,13 @@ static AggValueSlot createPlaceholderSlot(CodeGenFunction &CGF, // FIXME: Generate IR in one pass, rather than going back and fixing up these // placeholders. llvm::Type *IRTy = CGF.ConvertTypeForMem(Ty); - llvm::Type *IRPtrTy = IRTy->getPointerTo(); - llvm::Value *Placeholder = llvm::UndefValue::get(IRPtrTy->getPointerTo()); + llvm::Value *Placeholder = + llvm::UndefValue::get(IRTy->getPointerTo()->getPointerTo()); + Placeholder = CGF.Builder.CreateDefaultAlignedLoad(Placeholder); // FIXME: When we generate this IR in one pass, we shouldn't need // this win32-specific alignment hack. CharUnits Align = CharUnits::fromQuantity(4); - Placeholder = CGF.Builder.CreateAlignedLoad(IRPtrTy, Placeholder, Align); return AggValueSlot::forAddr(Address(Placeholder, Align), Ty.getQualifiers(), @@ -3035,39 +2536,33 @@ void CodeGenFunction::EmitDelegateCallArg(CallArgList &args, QualType type = param->getType(); + // For the most part, we just need to load the alloca, except: + // 1) aggregate r-values are actually pointers to temporaries, and + // 2) references to non-scalars are pointers directly to the aggregate. + // I don't know why references to scalars are different here. + if (const ReferenceType *ref = type->getAs<ReferenceType>()) { + if (!hasScalarEvaluationKind(ref->getPointeeType())) + return args.add(RValue::getAggregate(local), type); + + // Locals which are references to scalars are represented + // with allocas holding the pointer. + return args.add(RValue::get(Builder.CreateLoad(local)), type); + } + assert(!isInAllocaArgument(CGM.getCXXABI(), type) && "cannot emit delegate call arguments for inalloca arguments!"); - // GetAddrOfLocalVar returns a pointer-to-pointer for references, - // but the argument needs to be the original pointer. - if (type->isReferenceType()) { - args.add(RValue::get(Builder.CreateLoad(local)), type); - - // In ARC, move out of consumed arguments so that the release cleanup - // entered by StartFunction doesn't cause an over-release. This isn't - // optimal -O0 code generation, but it should get cleaned up when - // optimization is enabled. This also assumes that delegate calls are - // performed exactly once for a set of arguments, but that should be safe. - } else if (getLangOpts().ObjCAutoRefCount && - param->hasAttr<NSConsumedAttr>() && - type->isObjCRetainableType()) { - llvm::Value *ptr = Builder.CreateLoad(local); - auto null = - llvm::ConstantPointerNull::get(cast<llvm::PointerType>(ptr->getType())); - Builder.CreateStore(null, local); - args.add(RValue::get(ptr), type); - - // For the most part, we just need to load the alloca, except that - // aggregate r-values are actually pointers to temporaries. - } else { - args.add(convertTempToRValue(local, type, loc), type); - } + args.add(convertTempToRValue(local, type, loc), type); } static bool isProvablyNull(llvm::Value *addr) { return isa<llvm::ConstantPointerNull>(addr); } +static bool isProvablyNonNull(llvm::Value *addr) { + return isa<llvm::AllocaInst>(addr); +} + /// Emit the actual writing-back of a writeback. static void emitWriteback(CodeGenFunction &CGF, const CallArgList::Writeback &writeback) { @@ -3080,8 +2575,7 @@ static void emitWriteback(CodeGenFunction &CGF, // If the argument wasn't provably non-null, we need to null check // before doing the store. - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); if (!provablyNonNull) { llvm::BasicBlock *writebackBB = CGF.createBasicBlock("icr.writeback"); contBB = CGF.createBasicBlock("icr.done"); @@ -3221,8 +2715,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, // If the address is *not* known to be non-null, we need to switch. llvm::Value *finalArgument; - bool provablyNonNull = llvm::isKnownNonZero(srcAddr.getPointer(), - CGF.CGM.getDataLayout()); + bool provablyNonNull = isProvablyNonNull(srcAddr.getPointer()); if (provablyNonNull) { finalArgument = temp.getPointer(); } else { @@ -3293,7 +2786,7 @@ static void emitWritebackArg(CodeGenFunction &CGF, CallArgList &args, } void CallArgList::allocateArgumentMemory(CodeGenFunction &CGF) { - assert(!StackBase); + assert(!StackBase && !StackCleanup.isValid()); // Save the stack. llvm::Function *F = CGF.CGM.getIntrinsic(llvm::Intrinsic::stacksave); @@ -3310,97 +2803,54 @@ void CallArgList::freeArgumentMemory(CodeGenFunction &CGF) const { void CodeGenFunction::EmitNonNullArgCheck(RValue RV, QualType ArgType, SourceLocation ArgLoc, - AbstractCallee AC, + const FunctionDecl *FD, unsigned ParmNum) { - if (!AC.getDecl() || !(SanOpts.has(SanitizerKind::NonnullAttribute) || - SanOpts.has(SanitizerKind::NullabilityArg))) + if (!SanOpts.has(SanitizerKind::NonnullAttribute) || !FD) return; - - // The param decl may be missing in a variadic function. - auto PVD = ParmNum < AC.getNumParams() ? AC.getParamDecl(ParmNum) : nullptr; + auto PVD = ParmNum < FD->getNumParams() ? FD->getParamDecl(ParmNum) : nullptr; unsigned ArgNo = PVD ? PVD->getFunctionScopeIndex() : ParmNum; - - // Prefer the nonnull attribute if it's present. - const NonNullAttr *NNAttr = nullptr; - if (SanOpts.has(SanitizerKind::NonnullAttribute)) - NNAttr = getNonNullAttr(AC.getDecl(), PVD, ArgType, ArgNo); - - bool CanCheckNullability = false; - if (SanOpts.has(SanitizerKind::NullabilityArg) && !NNAttr && PVD) { - auto Nullability = PVD->getType()->getNullability(getContext()); - CanCheckNullability = Nullability && - *Nullability == NullabilityKind::NonNull && - PVD->getTypeSourceInfo(); - } - - if (!NNAttr && !CanCheckNullability) + auto NNAttr = getNonNullAttr(FD, PVD, ArgType, ArgNo); + if (!NNAttr) return; - - SourceLocation AttrLoc; - SanitizerMask CheckKind; - SanitizerHandler Handler; - if (NNAttr) { - AttrLoc = NNAttr->getLocation(); - CheckKind = SanitizerKind::NonnullAttribute; - Handler = SanitizerHandler::NonnullArg; - } else { - AttrLoc = PVD->getTypeSourceInfo()->getTypeLoc().findNullabilityLoc(); - CheckKind = SanitizerKind::NullabilityArg; - Handler = SanitizerHandler::NullabilityArg; - } - SanitizerScope SanScope(this); assert(RV.isScalar()); llvm::Value *V = RV.getScalarVal(); llvm::Value *Cond = Builder.CreateICmpNE(V, llvm::Constant::getNullValue(V->getType())); llvm::Constant *StaticData[] = { - EmitCheckSourceLocation(ArgLoc), EmitCheckSourceLocation(AttrLoc), + EmitCheckSourceLocation(ArgLoc), + EmitCheckSourceLocation(NNAttr->getLocation()), llvm::ConstantInt::get(Int32Ty, ArgNo + 1), }; - EmitCheck(std::make_pair(Cond, CheckKind), Handler, StaticData, None); + EmitCheck(std::make_pair(Cond, SanitizerKind::NonnullAttribute), + "nonnull_arg", StaticData, None); } void CodeGenFunction::EmitCallArgs( CallArgList &Args, ArrayRef<QualType> ArgTypes, llvm::iterator_range<CallExpr::const_arg_iterator> ArgRange, - AbstractCallee AC, unsigned ParamsToSkip, EvaluationOrder Order) { + const FunctionDecl *CalleeDecl, unsigned ParamsToSkip) { assert((int)ArgTypes.size() == (ArgRange.end() - ArgRange.begin())); - // We *have* to evaluate arguments from right to left in the MS C++ ABI, - // because arguments are destroyed left to right in the callee. As a special - // case, there are certain language constructs that require left-to-right - // evaluation, and in those cases we consider the evaluation order requirement - // to trump the "destruction order is reverse construction order" guarantee. - bool LeftToRight = - CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee() - ? Order == EvaluationOrder::ForceLeftToRight - : Order != EvaluationOrder::ForceRightToLeft; - - auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg, - RValue EmittedArg) { - if (!AC.hasFunctionDecl() || I >= AC.getNumParams()) + auto MaybeEmitImplicitObjectSize = [&](unsigned I, const Expr *Arg) { + if (CalleeDecl == nullptr || I >= CalleeDecl->getNumParams()) return; - auto *PS = AC.getParamDecl(I)->getAttr<PassObjectSizeAttr>(); + auto *PS = CalleeDecl->getParamDecl(I)->getAttr<PassObjectSizeAttr>(); if (PS == nullptr) return; const auto &Context = getContext(); auto SizeTy = Context.getSizeType(); auto T = Builder.getIntNTy(Context.getTypeSize(SizeTy)); - assert(EmittedArg.getScalarVal() && "We emitted nothing for the arg?"); - llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T, - EmittedArg.getScalarVal()); + llvm::Value *V = evaluateOrEmitBuiltinObjectSize(Arg, PS->getType(), T); Args.add(RValue::get(V), SizeTy); - // If we're emitting args in reverse, be sure to do so with - // pass_object_size, as well. - if (!LeftToRight) - std::swap(Args.back(), *(&Args.back() - 1)); }; - // Insert a stack save if we're going to need any inalloca args. - bool HasInAllocaArgs = false; - if (CGM.getTarget().getCXXABI().isMicrosoft()) { + // We *have* to evaluate arguments from right to left in the MS C++ ABI, + // because arguments are destroyed left to right in the callee. + if (CGM.getTarget().getCXXABI().areArgsDestroyedLeftToRightInCallee()) { + // Insert a stack save if we're going to need any inalloca args. + bool HasInAllocaArgs = false; for (ArrayRef<QualType>::iterator I = ArgTypes.begin(), E = ArgTypes.end(); I != E && !HasInAllocaArgs; ++I) HasInAllocaArgs = isInAllocaArgument(CGM.getCXXABI(), *I); @@ -3408,41 +2858,30 @@ void CodeGenFunction::EmitCallArgs( assert(getTarget().getTriple().getArch() == llvm::Triple::x86); Args.allocateArgumentMemory(*this); } - } - // Evaluate each argument in the appropriate order. - size_t CallArgsStart = Args.size(); - for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { - unsigned Idx = LeftToRight ? I : E - I - 1; - CallExpr::const_arg_iterator Arg = ArgRange.begin() + Idx; - unsigned InitialArgSize = Args.size(); - // If *Arg is an ObjCIndirectCopyRestoreExpr, check that either the types of - // the argument and parameter match or the objc method is parameterized. - assert((!isa<ObjCIndirectCopyRestoreExpr>(*Arg) || - getContext().hasSameUnqualifiedType((*Arg)->getType(), - ArgTypes[Idx]) || - (isa<ObjCMethodDecl>(AC.getDecl()) && - isObjCMethodWithTypeParams(cast<ObjCMethodDecl>(AC.getDecl())))) && - "Argument and parameter types don't match"); - EmitCallArg(Args, *Arg, ArgTypes[Idx]); - // In particular, we depend on it being the last arg in Args, and the - // objectsize bits depend on there only being one arg if !LeftToRight. - assert(InitialArgSize + 1 == Args.size() && - "The code below depends on only adding one arg per EmitCallArg"); - (void)InitialArgSize; - RValue RVArg = Args.back().RV; - EmitNonNullArgCheck(RVArg, ArgTypes[Idx], (*Arg)->getExprLoc(), AC, - ParamsToSkip + Idx); - // @llvm.objectsize should never have side-effects and shouldn't need - // destruction/cleanups, so we can safely "emit" it after its arg, - // regardless of right-to-leftness - MaybeEmitImplicitObjectSize(Idx, *Arg, RVArg); - } + // Evaluate each argument. + size_t CallArgsStart = Args.size(); + for (int I = ArgTypes.size() - 1; I >= 0; --I) { + CallExpr::const_arg_iterator Arg = ArgRange.begin() + I; + EmitCallArg(Args, *Arg, ArgTypes[I]); + EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), + CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); + } - if (!LeftToRight) { // Un-reverse the arguments we just evaluated so they match up with the LLVM // IR function. std::reverse(Args.begin() + CallArgsStart, Args.end()); + return; + } + + for (unsigned I = 0, E = ArgTypes.size(); I != E; ++I) { + CallExpr::const_arg_iterator Arg = ArgRange.begin() + I; + assert(Arg != ArgRange.end()); + EmitCallArg(Args, *Arg, ArgTypes[I]); + EmitNonNullArgCheck(Args.back().RV, ArgTypes[I], (*Arg)->getExprLoc(), + CalleeDecl, ParamsToSkip + I); + MaybeEmitImplicitObjectSize(I, *Arg); } } @@ -3484,6 +2923,7 @@ void CodeGenFunction::EmitCallArg(CallArgList &args, const Expr *E, if (const ObjCIndirectCopyRestoreExpr *CRE = dyn_cast<ObjCIndirectCopyRestoreExpr>(E)) { assert(getLangOpts().ObjCAutoRefCount); + assert(getContext().hasSameType(E->getType(), type)); return emitWritebackArg(*this, args, CRE); } @@ -3606,13 +3046,24 @@ CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, return EmitRuntimeCall(callee, None, name); } +/// Emits a simple call (never an invoke) to the given runtime +/// function. +llvm::CallInst * +CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, + ArrayRef<llvm::Value*> args, + const llvm::Twine &name) { + llvm::CallInst *call = Builder.CreateCall(callee, args, name); + call->setCallingConv(getRuntimeCC()); + return call; +} + // Calls which may throw must have operand bundles indicating which funclet // they are nested within. static void -getBundlesForFunclet(llvm::Value *Callee, llvm::Instruction *CurrentFuncletPad, +getBundlesForFunclet(llvm::Value *Callee, + llvm::Instruction *CurrentFuncletPad, SmallVectorImpl<llvm::OperandBundleDef> &BundleList) { - // There is no need for a funclet operand bundle if we aren't inside a - // funclet. + // There is no need for a funclet operand bundle if we aren't inside a funclet. if (!CurrentFuncletPad) return; @@ -3624,19 +3075,6 @@ getBundlesForFunclet(llvm::Value *Callee, llvm::Instruction *CurrentFuncletPad, BundleList.emplace_back("funclet", CurrentFuncletPad); } -/// Emits a simple call (never an invoke) to the given runtime function. -llvm::CallInst * -CodeGenFunction::EmitRuntimeCall(llvm::Value *callee, - ArrayRef<llvm::Value*> args, - const llvm::Twine &name) { - SmallVector<llvm::OperandBundleDef, 1> BundleList; - getBundlesForFunclet(callee, CurrentFuncletPad, BundleList); - - llvm::CallInst *call = Builder.CreateCall(callee, args, BundleList, name); - call->setCallingConv(getRuntimeCC()); - return call; -} - /// Emits a call or invoke to the given noreturn runtime function. void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, ArrayRef<llvm::Value*> args) { @@ -3660,7 +3098,8 @@ void CodeGenFunction::EmitNoreturnRuntimeCallOrInvoke(llvm::Value *callee, } } -/// Emits a call or invoke instruction to the given nullary runtime function. +/// Emits a call or invoke instruction to the given nullary runtime +/// function. llvm::CallSite CodeGenFunction::EmitRuntimeCallOrInvoke(llvm::Value *callee, const Twine &name) { @@ -3684,16 +3123,13 @@ CodeGenFunction::EmitCallOrInvoke(llvm::Value *Callee, ArrayRef<llvm::Value *> Args, const Twine &Name) { llvm::BasicBlock *InvokeDest = getInvokeDest(); - SmallVector<llvm::OperandBundleDef, 1> BundleList; - getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList); llvm::Instruction *Inst; if (!InvokeDest) - Inst = Builder.CreateCall(Callee, Args, BundleList, Name); + Inst = Builder.CreateCall(Callee, Args, Name); else { llvm::BasicBlock *ContBB = createBasicBlock("invoke.cont"); - Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, BundleList, - Name); + Inst = Builder.CreateInvoke(Callee, ContBB, InvokeDest, Args, Name); EmitBlock(ContBB); } @@ -3721,37 +3157,33 @@ void CodeGenFunction::deferPlaceholderReplacement(llvm::Instruction *Old, } RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, - const CGCallee &Callee, + llvm::Value *Callee, ReturnValueSlot ReturnValue, const CallArgList &CallArgs, - llvm::Instruction **callOrInvoke, - SourceLocation Loc) { + CGCalleeInfo CalleeInfo, + llvm::Instruction **callOrInvoke) { // FIXME: We no longer need the types from CallArgs; lift up and simplify. - assert(Callee.isOrdinary()); - // Handle struct-return functions by passing a pointer to the // location that we would like to return into. QualType RetTy = CallInfo.getReturnType(); const ABIArgInfo &RetAI = CallInfo.getReturnInfo(); - llvm::FunctionType *IRFuncTy = Callee.getFunctionType(); - - // 1. Set up the arguments. + llvm::FunctionType *IRFuncTy = + cast<llvm::FunctionType>( + cast<llvm::PointerType>(Callee->getType())->getElementType()); // If we're using inalloca, insert the allocation after the stack save. // FIXME: Do this earlier rather than hacking it in here! Address ArgMemory = Address::invalid(); const llvm::StructLayout *ArgMemoryLayout = nullptr; if (llvm::StructType *ArgStruct = CallInfo.getArgStruct()) { - const llvm::DataLayout &DL = CGM.getDataLayout(); - ArgMemoryLayout = DL.getStructLayout(ArgStruct); + ArgMemoryLayout = CGM.getDataLayout().getStructLayout(ArgStruct); llvm::Instruction *IP = CallArgs.getStackBase(); llvm::AllocaInst *AI; if (IP) { IP = IP->getNextNode(); - AI = new llvm::AllocaInst(ArgStruct, DL.getAllocaAddrSpace(), - "argmem", IP); + AI = new llvm::AllocaInst(ArgStruct, "argmem", IP); } else { AI = CreateTempAlloca(ArgStruct, "argmem"); } @@ -3776,7 +3208,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // alloca to hold the result, unless one is given to us. Address SRetPtr = Address::invalid(); size_t UnusedReturnSize = 0; - if (RetAI.isIndirect() || RetAI.isInAlloca() || RetAI.isCoerceAndExpand()) { + if (RetAI.isIndirect() || RetAI.isInAlloca()) { if (!ReturnValue.isNull()) { SRetPtr = ReturnValue.getValue(); } else { @@ -3790,16 +3222,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } if (IRFunctionArgs.hasSRetArg()) { IRCallArgs[IRFunctionArgs.getSRetArgNo()] = SRetPtr.getPointer(); - } else if (RetAI.isInAlloca()) { + } else { Address Addr = createInAllocaStructGEP(RetAI.getInAllocaFieldIndex()); Builder.CreateStore(SRetPtr.getPointer(), Addr); } } - Address swiftErrorTemp = Address::invalid(); - Address swiftErrorArg = Address::invalid(); - - // Translate all of the arguments as necessary to match the IR lowering. assert(CallInfo.arg_size() == CallArgs.size() && "Mismatch between function signature & arguments."); unsigned ArgNo = 0; @@ -3850,8 +3278,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, assert(NumIRArgs == 1); if (RV.isScalar() || RV.isComplex()) { // Make a temporary alloca to pass the argument. - Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(), - "indirect-arg-temp", false); + Address Addr = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign()); IRCallArgs[FirstIRArg] = Addr.getPointer(); LValue argLV = MakeAddrLValue(Addr, I->Ty); @@ -3880,8 +3307,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, < Align.getQuantity()) || (ArgInfo.getIndirectByVal() && (RVAddrSpace != ArgAddrSpace))) { // Create an aligned temporary, and copy to it. - Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign(), - "byval-temp", false); + Address AI = CreateMemTemp(I->Ty, ArgInfo.getIndirectAlign()); IRCallArgs[FirstIRArg] = AI.getPointer(); EmitAggregateCopy(AI, Addr, I->Ty, RV.isVolatileQualified()); } else { @@ -3908,25 +3334,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, else V = Builder.CreateLoad(RV.getAggregateAddress()); - // Implement swifterror by copying into a new swifterror argument. - // We'll write back in the normal path out of the call. - if (CallInfo.getExtParameterInfo(ArgNo).getABI() - == ParameterABI::SwiftErrorResult) { - assert(!swiftErrorTemp.isValid() && "multiple swifterror args"); - - QualType pointeeTy = I->Ty->getPointeeType(); - swiftErrorArg = - Address(V, getContext().getTypeAlignInChars(pointeeTy)); - - swiftErrorTemp = - CreateMemTemp(pointeeTy, getPointerAlign(), "swifterror.temp"); - V = swiftErrorTemp.getPointer(); - cast<llvm::AllocaInst>(V)->setSwiftError(true); - - llvm::Value *errorValue = Builder.CreateLoad(swiftErrorArg); - Builder.CreateStore(errorValue, swiftErrorTemp); - } - // We might have to widen integers, but we should never truncate. if (ArgInfo.getCoerceToType() != V->getType() && V->getType()->isIntegerTy()) @@ -3937,7 +3344,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (FirstIRArg < IRFuncTy->getNumParams() && V->getType() != IRFuncTy->getParamType(FirstIRArg)) V = Builder.CreateBitCast(V, IRFuncTy->getParamType(FirstIRArg)); - IRCallArgs[FirstIRArg] = V; break; } @@ -3975,8 +3381,7 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, Builder.CreateMemCpy(TempAlloca, Src, SrcSize); Src = TempAlloca; } else { - Src = Builder.CreateBitCast(Src, - STy->getPointerTo(Src.getAddressSpace())); + Src = Builder.CreateBitCast(Src, llvm::PointerType::getUnqual(STy)); } auto SrcLayout = CGM.getDataLayout().getStructLayout(STy); @@ -3997,51 +3402,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, break; } - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = ArgInfo.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - llvm::Value *tempSize = nullptr; - Address addr = Address::invalid(); - if (RV.isAggregate()) { - addr = RV.getAggregateAddress(); - } else { - assert(RV.isScalar()); // complex should always just be direct - - llvm::Type *scalarType = RV.getScalarVal()->getType(); - auto scalarSize = CGM.getDataLayout().getTypeAllocSize(scalarType); - auto scalarAlign = CGM.getDataLayout().getPrefTypeAlignment(scalarType); - - tempSize = llvm::ConstantInt::get(CGM.Int64Ty, scalarSize); - - // Materialize to a temporary. - addr = CreateTempAlloca(RV.getScalarVal()->getType(), - CharUnits::fromQuantity(std::max(layout->getAlignment(), - scalarAlign))); - EmitLifetimeStart(scalarSize, addr.getPointer()); - - Builder.CreateStore(RV.getScalarVal(), addr); - } - - addr = Builder.CreateElementBitCast(addr, coercionType); - - unsigned IRArgPos = FirstIRArg; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; - Address eltAddr = Builder.CreateStructGEP(addr, i, layout); - llvm::Value *elt = Builder.CreateLoad(eltAddr); - IRCallArgs[IRArgPos++] = elt; - } - assert(IRArgPos == FirstIRArg + NumIRArgs); - - if (tempSize) { - EmitLifetimeEnd(tempSize, addr.getPointer()); - } - - break; - } - case ABIArgInfo::Expand: unsigned IRArgPos = FirstIRArg; ExpandTypeToArgs(I->Ty, RV, IRFuncTy, IRCallArgs, IRArgPos); @@ -4050,9 +3410,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, } } - llvm::Value *CalleePtr = Callee.getFunctionPointer(); - - // If we're using inalloca, set up that argument. if (ArgMemory.isValid()) { llvm::Value *Arg = ArgMemory.getPointer(); if (CallInfo.isVariadic()) { @@ -4060,9 +3417,10 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // end up with a variadic prototype and an inalloca call site. In such // cases, we can't do any parameter mismatch checks. Give up and bitcast // the callee. - unsigned CalleeAS = CalleePtr->getType()->getPointerAddressSpace(); - auto FnTy = getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS); - CalleePtr = Builder.CreateBitCast(CalleePtr, FnTy); + unsigned CalleeAS = + cast<llvm::PointerType>(Callee->getType())->getAddressSpace(); + Callee = Builder.CreateBitCast( + Callee, getTypes().GetFunctionType(CallInfo)->getPointerTo(CalleeAS)); } else { llvm::Type *LastParamTy = IRFuncTy->getParamType(IRFuncTy->getNumParams() - 1); @@ -4086,57 +3444,39 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, IRCallArgs[IRFunctionArgs.getInallocaArgNo()] = Arg; } - // 2. Prepare the function pointer. - - // If the callee is a bitcast of a non-variadic function to have a - // variadic function pointer type, check to see if we can remove the - // bitcast. This comes up with unprototyped functions. - // - // This makes the IR nicer, but more importantly it ensures that we - // can inline the function at -O0 if it is marked always_inline. - auto simplifyVariadicCallee = [](llvm::Value *Ptr) -> llvm::Value* { - llvm::FunctionType *CalleeFT = - cast<llvm::FunctionType>(Ptr->getType()->getPointerElementType()); - if (!CalleeFT->isVarArg()) - return Ptr; - - llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Ptr); - if (!CE || CE->getOpcode() != llvm::Instruction::BitCast) - return Ptr; - - llvm::Function *OrigFn = dyn_cast<llvm::Function>(CE->getOperand(0)); - if (!OrigFn) - return Ptr; - - llvm::FunctionType *OrigFT = OrigFn->getFunctionType(); - - // If the original type is variadic, or if any of the component types - // disagree, we cannot remove the cast. - if (OrigFT->isVarArg() || - OrigFT->getNumParams() != CalleeFT->getNumParams() || - OrigFT->getReturnType() != CalleeFT->getReturnType()) - return Ptr; - - for (unsigned i = 0, e = OrigFT->getNumParams(); i != e; ++i) - if (OrigFT->getParamType(i) != CalleeFT->getParamType(i)) - return Ptr; - - return OrigFn; - }; - CalleePtr = simplifyVariadicCallee(CalleePtr); - - // 3. Perform the actual call. - - // Deactivate any cleanups that we're supposed to do immediately before - // the call. if (!CallArgs.getCleanupsToDeactivate().empty()) deactivateArgCleanupsBeforeCall(*this, CallArgs); - // Assert that the arguments we computed match up. The IR verifier - // will catch this, but this is a common enough source of problems - // during IRGen changes that it's way better for debugging to catch - // it ourselves here. -#ifndef NDEBUG + // If the callee is a bitcast of a function to a varargs pointer to function + // type, check to see if we can remove the bitcast. This handles some cases + // with unprototyped functions. + if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(Callee)) + if (llvm::Function *CalleeF = dyn_cast<llvm::Function>(CE->getOperand(0))) { + llvm::PointerType *CurPT=cast<llvm::PointerType>(Callee->getType()); + llvm::FunctionType *CurFT = + cast<llvm::FunctionType>(CurPT->getElementType()); + llvm::FunctionType *ActualFT = CalleeF->getFunctionType(); + + if (CE->getOpcode() == llvm::Instruction::BitCast && + ActualFT->getReturnType() == CurFT->getReturnType() && + ActualFT->getNumParams() == CurFT->getNumParams() && + ActualFT->getNumParams() == IRCallArgs.size() && + (CurFT->isVarArg() || !ActualFT->isVarArg())) { + bool ArgsMatch = true; + for (unsigned i = 0, e = ActualFT->getNumParams(); i != e; ++i) + if (ActualFT->getParamType(i) != CurFT->getParamType(i)) { + ArgsMatch = false; + break; + } + + // Strip the cast if we can get away with it. This is a nice cleanup, + // but also allows us to inline the function at -O0 if it is marked + // always_inline. + if (ArgsMatch) + Callee = CalleeF; + } + } + assert(IRCallArgs.size() == IRFuncTy->getNumParams() || IRFuncTy->isVarArg()); for (unsigned i = 0; i < IRCallArgs.size(); ++i) { // Inalloca argument can have different type. @@ -4146,117 +3486,75 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, if (i < IRFuncTy->getNumParams()) assert(IRCallArgs[i]->getType() == IRFuncTy->getParamType(i)); } -#endif - // Compute the calling convention and attributes. unsigned CallingConv; - llvm::AttributeList Attrs; - CGM.ConstructAttributeList(CalleePtr->getName(), CallInfo, - Callee.getAbstractInfo(), Attrs, CallingConv, + CodeGen::AttributeListType AttributeList; + CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo, + AttributeList, CallingConv, /*AttrOnCallSite=*/true); + llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(), + AttributeList); - // Apply some call-site-specific attributes. - // TODO: work this into building the attribute set. - - // Apply always_inline to all calls within flatten functions. - // FIXME: should this really take priority over __try, below? - if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && - !(Callee.getAbstractInfo().getCalleeDecl() && - Callee.getAbstractInfo().getCalleeDecl()->hasAttr<NoInlineAttr>())) { - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::AlwaysInline); - } - - // Disable inlining inside SEH __try blocks. - if (isSEHTryScope()) { - Attrs = - Attrs.addAttribute(getLLVMContext(), llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoInline); - } - - // Decide whether to use a call or an invoke. bool CannotThrow; if (currentFunctionUsesSEHTry()) { - // SEH cares about asynchronous exceptions, so everything can "throw." + // SEH cares about asynchronous exceptions, everything can "throw." CannotThrow = false; } else if (isCleanupPadScope() && EHPersonality::get(*this).isMSVCXXPersonality()) { // The MSVC++ personality will implicitly terminate the program if an - // exception is thrown during a cleanup outside of a try/catch. - // We don't need to model anything in IR to get this behavior. + // exception is thrown. An unwind edge cannot be reached. CannotThrow = true; } else { - // Otherwise, nounwind call sites will never throw. - CannotThrow = Attrs.hasAttribute(llvm::AttributeList::FunctionIndex, + // Otherwise, nowunind callsites will never throw. + CannotThrow = Attrs.hasAttribute(llvm::AttributeSet::FunctionIndex, llvm::Attribute::NoUnwind); } llvm::BasicBlock *InvokeDest = CannotThrow ? nullptr : getInvokeDest(); SmallVector<llvm::OperandBundleDef, 1> BundleList; - getBundlesForFunclet(CalleePtr, CurrentFuncletPad, BundleList); + getBundlesForFunclet(Callee, CurrentFuncletPad, BundleList); - // Emit the actual call/invoke instruction. llvm::CallSite CS; if (!InvokeDest) { - CS = Builder.CreateCall(CalleePtr, IRCallArgs, BundleList); + CS = Builder.CreateCall(Callee, IRCallArgs, BundleList); } else { llvm::BasicBlock *Cont = createBasicBlock("invoke.cont"); - CS = Builder.CreateInvoke(CalleePtr, Cont, InvokeDest, IRCallArgs, + CS = Builder.CreateInvoke(Callee, Cont, InvokeDest, IRCallArgs, BundleList); EmitBlock(Cont); } - llvm::Instruction *CI = CS.getInstruction(); if (callOrInvoke) - *callOrInvoke = CI; + *callOrInvoke = CS.getInstruction(); - // Apply the attributes and calling convention. - CS.setAttributes(Attrs); - CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); - - // Apply various metadata. + if (CurCodeDecl && CurCodeDecl->hasAttr<FlattenAttr>() && + !CS.hasFnAttr(llvm::Attribute::NoInline)) + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::AlwaysInline); - if (!CI->getType()->isVoidTy()) - CI->setName("call"); + // Disable inlining inside SEH __try blocks. + if (isSEHTryScope()) + Attrs = + Attrs.addAttribute(getLLVMContext(), llvm::AttributeSet::FunctionIndex, + llvm::Attribute::NoInline); - // Insert instrumentation or attach profile metadata at indirect call sites. - // For more details, see the comment before the definition of - // IPVK_IndirectCallTarget in InstrProfData.inc. - if (!CS.getCalledFunction()) - PGO.valueProfile(Builder, llvm::IPVK_IndirectCallTarget, - CI, CalleePtr); + CS.setAttributes(Attrs); + CS.setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv)); // In ObjC ARC mode with no ObjC ARC exception safety, tell the ARC // optimizer it can aggressively ignore unwind edges. if (CGM.getLangOpts().ObjCAutoRefCount) - AddObjCARCExceptionMetadata(CI); - - // Suppress tail calls if requested. - if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); - if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) - Call->setTailCallKind(llvm::CallInst::TCK_NoTail); - } - - // 4. Finish the call. + AddObjCARCExceptionMetadata(CS.getInstruction()); // If the call doesn't return, finish the basic block and clear the - // insertion point; this allows the rest of IRGen to discard + // insertion point; this allows the rest of IRgen to discard // unreachable code. if (CS.doesNotReturn()) { if (UnusedReturnSize) EmitLifetimeEnd(llvm::ConstantInt::get(Int64Ty, UnusedReturnSize), SRetPtr.getPointer()); - // Strip away the noreturn attribute to better diagnose unreachable UB. - if (SanOpts.has(SanitizerKind::Unreachable)) { - if (auto *F = CS.getCalledFunction()) - F->removeFnAttr(llvm::Attribute::NoReturn); - CS.removeAttribute(llvm::AttributeList::FunctionIndex, - llvm::Attribute::NoReturn); - } - - EmitUnreachable(Loc); + Builder.CreateUnreachable(); Builder.ClearInsertionPoint(); // FIXME: For now, emit a dummy basic block because expr emitters in @@ -4268,14 +3566,12 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, return GetUndefRValue(RetTy); } - // Perform the swifterror writeback. - if (swiftErrorTemp.isValid()) { - llvm::Value *errorResult = Builder.CreateLoad(swiftErrorTemp); - Builder.CreateStore(errorResult, swiftErrorArg); - } + llvm::Instruction *CI = CS.getInstruction(); + if (Builder.isNamePreserving() && !CI->getType()->isVoidTy()) + CI->setName("call"); - // Emit any call-associated writebacks immediately. Arguably this - // should happen after any return-value munging. + // Emit any writebacks immediately. Arguably this should happen + // after any return-value munging. if (CallArgs.hasWritebacks()) emitWritebacks(*this, CallArgs); @@ -4283,35 +3579,14 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, // lexical order, so deactivate it and run it manually here. CallArgs.freeArgumentMemory(*this); - // Extract the return value. + if (llvm::CallInst *Call = dyn_cast<llvm::CallInst>(CI)) { + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + if (TargetDecl && TargetDecl->hasAttr<NotTailCalledAttr>()) + Call->setTailCallKind(llvm::CallInst::TCK_NoTail); + } + RValue Ret = [&] { switch (RetAI.getKind()) { - case ABIArgInfo::CoerceAndExpand: { - auto coercionType = RetAI.getCoerceAndExpandType(); - auto layout = CGM.getDataLayout().getStructLayout(coercionType); - - Address addr = SRetPtr; - addr = Builder.CreateElementBitCast(addr, coercionType); - - assert(CI->getType() == RetAI.getUnpaddedCoerceAndExpandType()); - bool requiresExtract = isa<llvm::StructType>(CI->getType()); - - unsigned unpaddedIndex = 0; - for (unsigned i = 0, e = coercionType->getNumElements(); i != e; ++i) { - llvm::Type *eltType = coercionType->getElementType(i); - if (ABIArgInfo::isPaddingForCoerceAndExpand(eltType)) continue; - Address eltAddr = Builder.CreateStructGEP(addr, i, layout); - llvm::Value *elt = CI; - if (requiresExtract) - elt = Builder.CreateExtractValue(elt, unpaddedIndex++); - else - assert(unpaddedIndex == 0); - Builder.CreateStore(elt, eltAddr); - } - // FALLTHROUGH - LLVM_FALLTHROUGH; - } - case ABIArgInfo::InAlloca: case ABIArgInfo::Indirect: { RValue ret = convertTempToRValue(SRetPtr, RetTy, SourceLocation()); @@ -4381,8 +3656,8 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm_unreachable("Unhandled ABIArgInfo::Kind"); } (); - // Emit the assume_aligned check on the return value. - const Decl *TargetDecl = Callee.getAbstractInfo().getCalleeDecl(); + const Decl *TargetDecl = CalleeInfo.getCalleeDecl(); + if (Ret.isScalar() && TargetDecl) { if (const auto *AA = TargetDecl->getAttr<AssumeAlignedAttr>()) { llvm::Value *OffsetValue = nullptr; @@ -4393,10 +3668,6 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, llvm::ConstantInt *AlignmentCI = cast<llvm::ConstantInt>(Alignment); EmitAlignmentAssumption(Ret.getScalarVal(), AlignmentCI->getZExtValue(), OffsetValue); - } else if (const auto *AA = TargetDecl->getAttr<AllocAlignAttr>()) { - llvm::Value *ParamVal = - CallArgs[AA->getParamIndex() - 1].RV.getScalarVal(); - EmitAlignmentAssumption(Ret.getScalarVal(), ParamVal); } } diff --git a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp index 6ce719aac67..237a4470409 100644 --- a/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp +++ b/gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp @@ -7,7 +7,6 @@ // //===----------------------------------------------------------------------===// -#include "clang/Frontend/CompilerInvocation.h" #include "TestModuleFileExtension.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/FileManager.h" @@ -16,11 +15,11 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Driver/Util.h" +#include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendDiagnostic.h" #include "clang/Frontend/LangStandard.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearchOptions.h" -#include "clang/Lex/PreprocessorOptions.h" #include "clang/Serialization/ASTReader.h" #include "clang/Serialization/ModuleFileExtension.h" #include "llvm/ADT/Hashing.h" @@ -34,7 +33,6 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" -#include "llvm/ProfileData/InstrProfReader.h" #include "llvm/Support/CodeGen.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" @@ -42,7 +40,6 @@ #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" #include "llvm/Target/TargetOptions.h" -#include "llvm/Support/ScopedPrinter.h" #include <atomic> #include <memory> #include <sys/stat.h> @@ -60,11 +57,12 @@ CompilerInvocationBase::CompilerInvocationBase() PreprocessorOpts(new PreprocessorOptions()) {} CompilerInvocationBase::CompilerInvocationBase(const CompilerInvocationBase &X) - : LangOpts(new LangOptions(*X.getLangOpts())), - TargetOpts(new TargetOptions(X.getTargetOpts())), - DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), - HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), - PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} + : RefCountedBase<CompilerInvocation>(), + LangOpts(new LangOptions(*X.getLangOpts())), + TargetOpts(new TargetOptions(X.getTargetOpts())), + DiagnosticOpts(new DiagnosticOptions(X.getDiagnosticOpts())), + HeaderSearchOpts(new HeaderSearchOptions(X.getHeaderSearchOpts())), + PreprocessorOpts(new PreprocessorOptions(X.getPreprocessorOpts())) {} CompilerInvocationBase::~CompilerInvocationBase() {} @@ -81,7 +79,7 @@ using namespace llvm::opt; static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { unsigned DefaultOpt = 0; - if (IK.getLanguage() == InputKind::OpenCL && !Args.hasArg(OPT_cl_opt_disable)) + if (IK == IK_OpenCL && !Args.hasArg(OPT_cl_opt_disable)) DefaultOpt = 2; if (Arg *A = Args.getLastArg(options::OPT_O_Group)) { @@ -97,9 +95,6 @@ static unsigned getOptimizationLevel(ArgList &Args, InputKind IK, if (S == "s" || S == "z" || S.empty()) return 2; - if (S == "g") - return 1; - return getLastArgIntValue(Args, OPT_O, DefaultOpt, Diags); } @@ -240,7 +235,6 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, } Opts.ShowCheckerHelp = Args.hasArg(OPT_analyzer_checker_help); - Opts.ShowEnabledCheckerList = Args.hasArg(OPT_analyzer_list_enabled_checkers); Opts.DisableAllChecks = Args.hasArg(OPT_analyzer_disable_all_checks); Opts.visualizeExplodedGraphWithGraphViz = @@ -330,17 +324,6 @@ static StringRef getCodeModel(ArgList &Args, DiagnosticsEngine &Diags) { return "default"; } -static StringRef getRelocModel(ArgList &Args, DiagnosticsEngine &Diags) { - if (Arg *A = Args.getLastArg(OPT_mrelocation_model)) { - StringRef Value = A->getValue(); - if (Value == "static" || Value == "pic" || Value == "ropi" || - Value == "rwpi" || Value == "ropi-rwpi" || Value == "dynamic-no-pic") - return Value; - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Value; - } - return "pic"; -} - /// \brief Create a new Regex instance out of the string value in \p RpassArg. /// It returns a pointer to the newly generated Regex instance. static std::shared_ptr<llvm::Regex> @@ -392,46 +375,6 @@ static void parseSanitizerKinds(StringRef FlagName, } } -// Set the profile kind for fprofile-instrument. -static void setPGOInstrumentor(CodeGenOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags) { - Arg *A = Args.getLastArg(OPT_fprofile_instrument_EQ); - if (A == nullptr) - return; - StringRef S = A->getValue(); - unsigned I = llvm::StringSwitch<unsigned>(S) - .Case("none", CodeGenOptions::ProfileNone) - .Case("clang", CodeGenOptions::ProfileClangInstr) - .Case("llvm", CodeGenOptions::ProfileIRInstr) - .Default(~0U); - if (I == ~0U) { - Diags.Report(diag::err_drv_invalid_pgo_instrumentor) << A->getAsString(Args) - << S; - return; - } - CodeGenOptions::ProfileInstrKind Instrumentor = - static_cast<CodeGenOptions::ProfileInstrKind>(I); - Opts.setProfileInstr(Instrumentor); -} - -// Set the profile kind using fprofile-instrument-use-path. -static void setPGOUseInstrumentor(CodeGenOptions &Opts, - const Twine &ProfileName) { - auto ReaderOrErr = llvm::IndexedInstrProfReader::create(ProfileName); - // In error, return silently and let Clang PGOUse report the error message. - if (auto E = ReaderOrErr.takeError()) { - llvm::consumeError(std::move(E)); - Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); - return; - } - std::unique_ptr<llvm::IndexedInstrProfReader> PGOReader = - std::move(ReaderOrErr.get()); - if (PGOReader->isIRLevelProfile()) - Opts.setProfileUse(CodeGenOptions::ProfileIRInstr); - else - Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); -} - static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags, const TargetOptions &TargetOpts) { @@ -451,41 +394,19 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } Opts.OptimizationLevel = OptimizationLevel; - // At O0 we want to fully disable inlining outside of cases marked with - // 'alwaysinline' that are required for correctness. - Opts.setInlining((Opts.OptimizationLevel == 0) - ? CodeGenOptions::OnlyAlwaysInlining - : CodeGenOptions::NormalInlining); - // Explicit inlining flags can disable some or all inlining even at - // optimization levels above zero. - if (Arg *InlineArg = Args.getLastArg( - options::OPT_finline_functions, options::OPT_finline_hint_functions, - options::OPT_fno_inline_functions, options::OPT_fno_inline)) { - if (Opts.OptimizationLevel > 0) { - const Option &InlineOpt = InlineArg->getOption(); - if (InlineOpt.matches(options::OPT_finline_functions)) - Opts.setInlining(CodeGenOptions::NormalInlining); - else if (InlineOpt.matches(options::OPT_finline_hint_functions)) - Opts.setInlining(CodeGenOptions::OnlyHintInlining); - else - Opts.setInlining(CodeGenOptions::OnlyAlwaysInlining); - } - } - - Opts.ExperimentalNewPassManager = Args.hasFlag( - OPT_fexperimental_new_pass_manager, OPT_fno_experimental_new_pass_manager, - /* Default */ false); - - Opts.DebugPassManager = - Args.hasFlag(OPT_fdebug_pass_manager, OPT_fno_debug_pass_manager, - /* Default */ false); + // We must always run at least the always inlining pass. + Opts.setInlining( + (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining + : CodeGenOptions::OnlyAlwaysInlining); + // -fno-inline-functions overrides OptimizationLevel > 1. + Opts.NoInline = Args.hasArg(OPT_fno_inline); + Opts.setInlining(Args.hasArg(OPT_fno_inline_functions) ? + CodeGenOptions::OnlyAlwaysInlining : Opts.getInlining()); if (Arg *A = Args.getLastArg(OPT_fveclib)) { StringRef Name = A->getValue(); if (Name == "Accelerate") Opts.setVecLib(CodeGenOptions::Accelerate); - else if (Name == "SVML") - Opts.setVecLib(CodeGenOptions::SVML); else if (Name == "none") Opts.setVecLib(CodeGenOptions::NoLibrary); else @@ -495,40 +416,34 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, if (Arg *A = Args.getLastArg(OPT_debug_info_kind_EQ)) { unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) - .Case("line-tables-only", codegenoptions::DebugLineTablesOnly) - .Case("limited", codegenoptions::LimitedDebugInfo) - .Case("standalone", codegenoptions::FullDebugInfo) + .Case("line-tables-only", CodeGenOptions::DebugLineTablesOnly) + .Case("limited", CodeGenOptions::LimitedDebugInfo) + .Case("standalone", CodeGenOptions::FullDebugInfo) .Default(~0U); if (Val == ~0U) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); else - Opts.setDebugInfo(static_cast<codegenoptions::DebugInfoKind>(Val)); + Opts.setDebugInfo(static_cast<CodeGenOptions::DebugInfoKind>(Val)); } if (Arg *A = Args.getLastArg(OPT_debugger_tuning_EQ)) { unsigned Val = llvm::StringSwitch<unsigned>(A->getValue()) - .Case("gdb", unsigned(llvm::DebuggerKind::GDB)) - .Case("lldb", unsigned(llvm::DebuggerKind::LLDB)) - .Case("sce", unsigned(llvm::DebuggerKind::SCE)) + .Case("gdb", CodeGenOptions::DebuggerKindGDB) + .Case("lldb", CodeGenOptions::DebuggerKindLLDB) + .Case("sce", CodeGenOptions::DebuggerKindSCE) .Default(~0U); if (Val == ~0U) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); else - Opts.setDebuggerTuning(static_cast<llvm::DebuggerKind>(Val)); + Opts.setDebuggerTuning(static_cast<CodeGenOptions::DebuggerKind>(Val)); } Opts.DwarfVersion = getLastArgIntValue(Args, OPT_dwarf_version_EQ, 0, Diags); Opts.DebugColumnInfo = Args.hasArg(OPT_dwarf_column_info); Opts.EmitCodeView = Args.hasArg(OPT_gcodeview); - Opts.MacroDebugInfo = Args.hasArg(OPT_debug_info_macro); - Opts.WholeProgramVTables = Args.hasArg(OPT_fwhole_program_vtables); - Opts.LTOVisibilityPublicStd = Args.hasArg(OPT_flto_visibility_public_std); - Opts.EnableSplitDwarf = Args.hasArg(OPT_enable_split_dwarf); Opts.SplitDwarfFile = Args.getLastArgValue(OPT_split_dwarf_file); - Opts.SplitDwarfInlining = !Args.hasArg(OPT_fno_split_dwarf_inlining); Opts.DebugTypeExtRefs = Args.hasArg(OPT_dwarf_ext_refs); - Opts.DebugExplicitImport = Args.hasArg(OPT_dwarf_explicit_import); - Opts.DebugFwdTemplateParams = Args.hasArg(OPT_debug_forward_template_params); + Opts.DebugExplicitImport = Triple.isPS4CPU(); for (const auto &Arg : Args.getAllArgValues(OPT_fdebug_prefix_map_EQ)) Opts.DebugPrefixMap.insert(StringRef(Arg).split('=')); @@ -537,20 +452,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.getLastArg(OPT_emit_llvm_uselists, OPT_no_emit_llvm_uselists)) Opts.EmitLLVMUseLists = A->getOption().getID() == OPT_emit_llvm_uselists; + Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns); Opts.DisableLLVMPasses = Args.hasArg(OPT_disable_llvm_passes); - Opts.DisableLifetimeMarkers = Args.hasArg(OPT_disable_lifetimemarkers); - Opts.DisableO0ImplyOptNone = Args.hasArg(OPT_disable_O0_optnone); Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone); Opts.ForbidGuardVariables = Args.hasArg(OPT_fforbid_guard_variables); Opts.UseRegisterSizedBitfieldAccess = Args.hasArg( OPT_fuse_register_sized_bitfield_access); Opts.RelaxedAliasing = Args.hasArg(OPT_relaxed_aliasing); Opts.StructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa); - Opts.NewStructPathTBAA = !Args.hasArg(OPT_no_struct_path_tbaa) && - Args.hasArg(OPT_new_struct_path_tbaa); - Opts.FineGrainedBitfieldAccesses = - Args.hasFlag(OPT_ffine_grained_bitfield_accesses, - OPT_fno_fine_grained_bitfield_accesses, false); Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags); Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants); Opts.NoCommon = Args.hasArg(OPT_fno_common); @@ -562,57 +471,20 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.UnrollLoops = Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops, - (Opts.OptimizationLevel > 1)); + (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize)); Opts.RerollLoops = Args.hasArg(OPT_freroll_loops); Opts.DisableIntegratedAS = Args.hasArg(OPT_fno_integrated_as); Opts.Autolink = !Args.hasArg(OPT_fno_autolink); Opts.SampleProfileFile = Args.getLastArgValue(OPT_fprofile_sample_use_EQ); - Opts.DebugInfoForProfiling = Args.hasFlag( - OPT_fdebug_info_for_profiling, OPT_fno_debug_info_for_profiling, false); - Opts.GnuPubnames = Args.hasArg(OPT_ggnu_pubnames); - - setPGOInstrumentor(Opts, Args, Diags); - Opts.InstrProfileOutput = - Args.getLastArgValue(OPT_fprofile_instrument_path_EQ); - Opts.ProfileInstrumentUsePath = - Args.getLastArgValue(OPT_fprofile_instrument_use_path_EQ); - if (!Opts.ProfileInstrumentUsePath.empty()) - setPGOUseInstrumentor(Opts, Opts.ProfileInstrumentUsePath); - - if (Arg *A = Args.getLastArg(OPT_fclang_abi_compat_EQ)) { - Opts.setClangABICompat(CodeGenOptions::ClangABI::Latest); - - StringRef Ver = A->getValue(); - std::pair<StringRef, StringRef> VerParts = Ver.split('.'); - unsigned Major, Minor = 0; - - // Check the version number is valid: either 3.x (0 <= x <= 9) or - // y or y.0 (4 <= y <= current version). - if (!VerParts.first.startswith("0") && - !VerParts.first.getAsInteger(10, Major) && - 3 <= Major && Major <= CLANG_VERSION_MAJOR && - (Major == 3 ? VerParts.second.size() == 1 && - !VerParts.second.getAsInteger(10, Minor) - : VerParts.first.size() == Ver.size() || - VerParts.second == "0")) { - // Got a valid version number. - if (Major == 3 && Minor <= 8) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver3_8); - else if (Major <= 4) - Opts.setClangABICompat(CodeGenOptions::ClangABI::Ver4); - } else if (Ver != "latest") { - Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); - } - } - + Opts.ProfileInstrGenerate = Args.hasArg(OPT_fprofile_instr_generate) || + Args.hasArg(OPT_fprofile_instr_generate_EQ); + Opts.InstrProfileOutput = Args.getLastArgValue(OPT_fprofile_instr_generate_EQ); + Opts.InstrProfileInput = Args.getLastArgValue(OPT_fprofile_instr_use_EQ); Opts.CoverageMapping = Args.hasFlag(OPT_fcoverage_mapping, OPT_fno_coverage_mapping, false); Opts.DumpCoverageMapping = Args.hasArg(OPT_dump_coverage_mapping); Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose); - Opts.PreserveAsmComments = !Args.hasArg(OPT_fno_preserve_as_comments); - Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.ObjCAutoRefCountExceptions = Args.hasArg(OPT_fobjc_arc_exceptions); Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit); Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases); @@ -621,12 +493,23 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.DisableFPElim = (Args.hasArg(OPT_mdisable_fp_elim) || Args.hasArg(OPT_pg)); Opts.DisableFree = Args.hasArg(OPT_disable_free); - Opts.DiscardValueNames = Args.hasArg(OPT_discard_value_names); Opts.DisableTailCalls = Args.hasArg(OPT_mdisable_tail_calls); Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi); - Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) || - Args.hasArg(OPT_cl_unsafe_math_optimizations) || - Args.hasArg(OPT_cl_fast_relaxed_math); + if (Arg *A = Args.getLastArg(OPT_meabi)) { + StringRef Value = A->getValue(); + llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value) + .Case("default", llvm::EABI::Default) + .Case("4", llvm::EABI::EABI4) + .Case("5", llvm::EABI::EABI5) + .Case("gnu", llvm::EABI::GNU) + .Default(llvm::EABI::Unknown); + if (EABIVersion == llvm::EABI::Unknown) + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) + << Value; + else + Opts.EABIVersion = Value; + } + Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable); Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision); Opts.NoInfsFPMath = (Args.hasArg(OPT_menable_no_infinities) || Args.hasArg(OPT_cl_finite_math_only) || @@ -635,17 +518,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_finite_math_only) || Args.hasArg(OPT_cl_fast_relaxed_math)); - Opts.NoSignedZeros = (Args.hasArg(OPT_fno_signed_zeros) || - Args.hasArg(OPT_cl_no_signed_zeros) || - Args.hasArg(OPT_cl_unsafe_math_optimizations) || - Args.hasArg(OPT_cl_fast_relaxed_math)); - Opts.Reassociate = Args.hasArg(OPT_mreassociate); - Opts.FlushDenorm = Args.hasArg(OPT_cl_denorms_are_zero); - Opts.CorrectlyRoundedDivSqrt = - Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt); - Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); + Opts.NoSignedZeros = Args.hasArg(OPT_fno_signed_zeros); Opts.ReciprocalMath = Args.hasArg(OPT_freciprocal_math); - Opts.NoTrappingMath = Args.hasArg(OPT_fno_trapping_math); Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss); Opts.BackendOptions = Args.getAllArgValues(OPT_backend_option); Opts.NumRegisterParameters = getLastArgIntValue(Args, OPT_mregparm, 0, Diags); @@ -655,21 +529,17 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.RelaxAll = Args.hasArg(OPT_mrelax_all); Opts.IncrementalLinkerCompatible = Args.hasArg(OPT_mincremental_linker_compatible); - Opts.PIECopyRelocations = - Args.hasArg(OPT_mpie_copy_relocations); - Opts.NoPLT = Args.hasArg(OPT_fno_plt); Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer); Opts.SaveTempLabels = Args.hasArg(OPT_msave_temp_labels); Opts.NoDwarfDirectoryAsm = Args.hasArg(OPT_fno_dwarf_directory_asm); Opts.SoftFloat = Args.hasArg(OPT_msoft_float); Opts.StrictEnums = Args.hasArg(OPT_fstrict_enums); - Opts.StrictReturn = !Args.hasArg(OPT_fno_strict_return); Opts.StrictVTablePointers = Args.hasArg(OPT_fstrict_vtable_pointers); Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) || Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); Opts.UnwindTables = Args.hasArg(OPT_munwind_tables); - Opts.RelocationModel = getRelocModel(Args, Diags); + Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic"); Opts.ThreadModel = Args.getLastArgValue(OPT_mthread_model, "posix"); if (Opts.ThreadModel != "posix" && Opts.ThreadModel != "single") Diags.Report(diag::err_drv_invalid_value) @@ -687,35 +557,22 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.MergeFunctions = Args.hasArg(OPT_fmerge_functions); - Opts.NoUseJumpTables = Args.hasArg(OPT_fno_jump_tables); - - Opts.ProfileSampleAccurate = Args.hasArg(OPT_fprofile_sample_accurate); - Opts.PrepareForLTO = Args.hasArg(OPT_flto, OPT_flto_EQ); - Opts.EmitSummaryIndex = false; - if (Arg *A = Args.getLastArg(OPT_flto_EQ)) { - StringRef S = A->getValue(); - if (S == "thin") - Opts.EmitSummaryIndex = true; - else if (S != "full") - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << S; - } - Opts.LTOUnit = Args.hasFlag(OPT_flto_unit, OPT_fno_lto_unit, false); + const Arg *A = Args.getLastArg(OPT_flto, OPT_flto_EQ); + Opts.EmitFunctionSummary = A && A->containsValue("thin"); if (Arg *A = Args.getLastArg(OPT_fthinlto_index_EQ)) { - if (IK.getLanguage() != InputKind::LLVM_IR) + if (IK != IK_LLVM_IR) Diags.Report(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-x ir"; Opts.ThinLTOIndexFile = Args.getLastArgValue(OPT_fthinlto_index_EQ); } - Opts.ThinLinkBitcodeFile = Args.getLastArgValue(OPT_fthin_link_bitcode_EQ); Opts.MSVolatile = Args.hasArg(OPT_fms_volatile); + Opts.VectorizeBB = Args.hasArg(OPT_vectorize_slp_aggressive); Opts.VectorizeLoop = Args.hasArg(OPT_vectorize_loops); Opts.VectorizeSLP = Args.hasArg(OPT_vectorize_slp); - Opts.PreferVectorWidth = Args.getLastArgValue(OPT_mprefer_vector_width_EQ); - Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name); Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier); @@ -723,8 +580,7 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.EmitGcovArcs = Args.hasArg(OPT_femit_coverage_data); Opts.EmitGcovNotes = Args.hasArg(OPT_femit_coverage_notes); if (Opts.EmitGcovArcs || Opts.EmitGcovNotes) { - Opts.CoverageDataFile = Args.getLastArgValue(OPT_coverage_data_file); - Opts.CoverageNotesFile = Args.getLastArgValue(OPT_coverage_notes_file); + Opts.CoverageFile = Args.getLastArgValue(OPT_coverage_file); Opts.CoverageExtraChecksum = Args.hasArg(OPT_coverage_cfg_checksum); Opts.CoverageNoFunctionNamesInData = Args.hasArg(OPT_coverage_no_function_names_in_data); @@ -741,89 +597,18 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } } - // Handle -fembed-bitcode option. - if (Arg *A = Args.getLastArg(OPT_fembed_bitcode_EQ)) { - StringRef Name = A->getValue(); - unsigned Model = llvm::StringSwitch<unsigned>(Name) - .Case("off", CodeGenOptions::Embed_Off) - .Case("all", CodeGenOptions::Embed_All) - .Case("bitcode", CodeGenOptions::Embed_Bitcode) - .Case("marker", CodeGenOptions::Embed_Marker) - .Default(~0U); - if (Model == ~0U) { - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name; - Success = false; - } else - Opts.setEmbedBitcode( - static_cast<CodeGenOptions::EmbedBitcodeKind>(Model)); - } - // FIXME: For backend options that are not yet recorded as function - // attributes in the IR, keep track of them so we can embed them in a - // separate data section and use them when building the bitcode. - if (Opts.getEmbedBitcode() == CodeGenOptions::Embed_All) { - for (const auto &A : Args) { - // Do not encode output and input. - if (A->getOption().getID() == options::OPT_o || - A->getOption().getID() == options::OPT_INPUT || - A->getOption().getID() == options::OPT_x || - A->getOption().getID() == options::OPT_fembed_bitcode || - (A->getOption().getGroup().isValid() && - A->getOption().getGroup().getID() == options::OPT_W_Group)) - continue; - ArgStringList ASL; - A->render(Args, ASL); - for (const auto &arg : ASL) { - StringRef ArgStr(arg); - Opts.CmdArgs.insert(Opts.CmdArgs.end(), ArgStr.begin(), ArgStr.end()); - // using \00 to seperate each commandline options. - Opts.CmdArgs.push_back('\0'); - } - } - } - Opts.PreserveVec3Type = Args.hasArg(OPT_fpreserve_vec3_type); Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions); - Opts.InstrumentFunctionsAfterInlining = - Args.hasArg(OPT_finstrument_functions_after_inlining); - Opts.InstrumentFunctionEntryBare = - Args.hasArg(OPT_finstrument_function_entry_bare); - Opts.XRayInstrumentFunctions = Args.hasArg(OPT_fxray_instrument); - Opts.XRayAlwaysEmitCustomEvents = - Args.hasArg(OPT_fxray_always_emit_customevents); - Opts.XRayInstructionThreshold = - getLastArgIntValue(Args, OPT_fxray_instruction_threshold_EQ, 200, Diags); Opts.InstrumentForProfiling = Args.hasArg(OPT_pg); - Opts.CallFEntry = Args.hasArg(OPT_mfentry); Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info); - - if (const Arg *A = Args.getLastArg(OPT_compress_debug_sections, - OPT_compress_debug_sections_EQ)) { - if (A->getOption().getID() == OPT_compress_debug_sections) { - // TODO: be more clever about the compression type auto-detection - Opts.setCompressDebugSections(llvm::DebugCompressionType::GNU); - } else { - auto DCT = llvm::StringSwitch<llvm::DebugCompressionType>(A->getValue()) - .Case("none", llvm::DebugCompressionType::None) - .Case("zlib", llvm::DebugCompressionType::Z) - .Case("zlib-gnu", llvm::DebugCompressionType::GNU) - .Default(llvm::DebugCompressionType::None); - Opts.setCompressDebugSections(DCT); - } - } - - Opts.RelaxELFRelocations = Args.hasArg(OPT_mrelax_relocations); + Opts.CompressDebugSections = Args.hasArg(OPT_compress_debug_sections); Opts.DebugCompilationDir = Args.getLastArgValue(OPT_fdebug_compilation_dir); for (auto A : Args.filtered(OPT_mlink_bitcode_file, OPT_mlink_cuda_bitcode)) { - CodeGenOptions::BitcodeFileToLink F; - F.Filename = A->getValue(); - if (A->getOption().matches(OPT_mlink_cuda_bitcode)) { - F.LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded; - // When linking CUDA bitcode, propagate function attributes so that - // e.g. libdevice gets fast-math attrs if we're building with fast-math. - F.PropagateAttrs = true; - F.Internalize = true; - } - Opts.LinkBitcodeFiles.push_back(F); + unsigned LinkFlags = llvm::Linker::Flags::None; + if (A->getOption().matches(OPT_mlink_cuda_bitcode)) + LinkFlags = llvm::Linker::Flags::LinkOnlyNeeded | + llvm::Linker::Flags::InternalizeLinkedSymbols; + Opts.LinkBitcodeFiles.push_back(std::make_pair(LinkFlags, A->getValue())); } Opts.SanitizeCoverageType = getLastArgIntValue(Args, OPT_fsanitize_coverage_type, 0, Diags); @@ -831,37 +616,13 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_fsanitize_coverage_indirect_calls); Opts.SanitizeCoverageTraceBB = Args.hasArg(OPT_fsanitize_coverage_trace_bb); Opts.SanitizeCoverageTraceCmp = Args.hasArg(OPT_fsanitize_coverage_trace_cmp); - Opts.SanitizeCoverageTraceDiv = Args.hasArg(OPT_fsanitize_coverage_trace_div); - Opts.SanitizeCoverageTraceGep = Args.hasArg(OPT_fsanitize_coverage_trace_gep); Opts.SanitizeCoverage8bitCounters = Args.hasArg(OPT_fsanitize_coverage_8bit_counters); - Opts.SanitizeCoverageTracePC = Args.hasArg(OPT_fsanitize_coverage_trace_pc); - Opts.SanitizeCoverageTracePCGuard = - Args.hasArg(OPT_fsanitize_coverage_trace_pc_guard); - Opts.SanitizeCoverageNoPrune = Args.hasArg(OPT_fsanitize_coverage_no_prune); - Opts.SanitizeCoverageInline8bitCounters = - Args.hasArg(OPT_fsanitize_coverage_inline_8bit_counters); - Opts.SanitizeCoveragePCTable = Args.hasArg(OPT_fsanitize_coverage_pc_table); - Opts.SanitizeCoverageStackDepth = - Args.hasArg(OPT_fsanitize_coverage_stack_depth); Opts.SanitizeMemoryTrackOrigins = getLastArgIntValue(Args, OPT_fsanitize_memory_track_origins_EQ, 0, Diags); Opts.SanitizeMemoryUseAfterDtor = - Args.hasFlag(OPT_fsanitize_memory_use_after_dtor, - OPT_fno_sanitize_memory_use_after_dtor, - false); - Opts.SanitizeMinimalRuntime = Args.hasArg(OPT_fsanitize_minimal_runtime); + Args.hasArg(OPT_fsanitize_memory_use_after_dtor); Opts.SanitizeCfiCrossDso = Args.hasArg(OPT_fsanitize_cfi_cross_dso); - Opts.SanitizeCfiICallGeneralizePointers = - Args.hasArg(OPT_fsanitize_cfi_icall_generalize_pointers); - Opts.SanitizeStats = Args.hasArg(OPT_fsanitize_stats); - if (Arg *A = Args.getLastArg(OPT_fsanitize_address_use_after_scope, - OPT_fno_sanitize_address_use_after_scope)) { - Opts.SanitizeAddressUseAfterScope = - A->getOption().getID() == OPT_fsanitize_address_use_after_scope; - } - Opts.SanitizeAddressGlobalsDeadStripping = - Args.hasArg(OPT_fsanitize_address_globals_dead_stripping); Opts.SSPBufferSize = getLastArgIntValue(Args, OPT_stack_protector_buffer_size, 8, Diags); Opts.StackRealignment = Args.hasArg(OPT_mstackrealign); @@ -914,14 +675,14 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } } - if (Arg *A = Args.getLastArg(OPT_fdenormal_fp_math_EQ)) { + if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { StringRef Val = A->getValue(); - if (Val == "ieee") - Opts.FPDenormalMode = "ieee"; - else if (Val == "preserve-sign") - Opts.FPDenormalMode = "preserve-sign"; - else if (Val == "positive-zero") - Opts.FPDenormalMode = "positive-zero"; + if (Val == "fast") + Opts.setFPContractMode(CodeGenOptions::FPC_Fast); + else if (Val == "on") + Opts.setFPContractMode(CodeGenOptions::FPC_On); + else if (Val == "off") + Opts.setFPContractMode(CodeGenOptions::FPC_Off); else Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; } @@ -936,13 +697,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, } Opts.DependentLibraries = Args.getAllArgValues(OPT_dependent_lib); - Opts.LinkerOptions = Args.getAllArgValues(OPT_linker_option); bool NeedLocTracking = false; - Opts.OptRecordFile = Args.getLastArgValue(OPT_opt_record_file); - if (!Opts.OptRecordFile.empty()) - NeedLocTracking = true; - if (Arg *A = Args.getLastArg(OPT_Rpass_EQ)) { Opts.OptimizationRemarkPattern = GenerateOptimizationRemarkRegex(Diags, Args, A); @@ -961,32 +717,16 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, NeedLocTracking = true; } - Opts.DiagnosticsWithHotness = - Args.hasArg(options::OPT_fdiagnostics_show_hotness); - bool UsingSampleProfile = !Opts.SampleProfileFile.empty(); - bool UsingProfile = UsingSampleProfile || - (Opts.getProfileUse() != CodeGenOptions::ProfileNone); - - if (Opts.DiagnosticsWithHotness && !UsingProfile) - Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) - << "-fdiagnostics-show-hotness"; - - Opts.DiagnosticsHotnessThreshold = getLastArgUInt64Value( - Args, options::OPT_fdiagnostics_hotness_threshold_EQ, 0); - if (Opts.DiagnosticsHotnessThreshold > 0 && !UsingProfile) - Diags.Report(diag::warn_drv_diagnostics_hotness_requires_pgo) - << "-fdiagnostics-hotness-threshold="; - // If the user requested to use a sample profile for PGO, then the // backend will need to track source location information so the profile // can be incorporated into the IR. - if (UsingSampleProfile) + if (!Opts.SampleProfileFile.empty()) NeedLocTracking = true; // If the user requested a flag that requires source locations available in // the backend, make sure that the backend tracks source location information. - if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo) - Opts.setDebugInfo(codegenoptions::LocTrackingOnly); + if (NeedLocTracking && Opts.getDebugInfo() == CodeGenOptions::NoDebugInfo) + Opts.setDebugInfo(CodeGenOptions::LocTrackingOnly); Opts.RewriteMapFiles = Args.getAllArgValues(OPT_frewrite_map_file); @@ -1002,11 +742,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, Opts.CudaGpuBinaryFileNames = Args.getAllArgValues(OPT_fcuda_include_gpubinary); - Opts.Backchain = Args.hasArg(OPT_mbackchain); - - Opts.EmitCheckPathComponentsToStrip = getLastArgIntValue( - Args, OPT_fsanitize_undefined_strip_path_components_EQ, 0, Diags); - return Success; } @@ -1031,70 +766,13 @@ static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts, // They won't be discovered by the regular preprocessor, so // we let make / ninja to know about this implicit dependency. Opts.ExtraDeps = Args.getAllArgValues(OPT_fdepfile_entry); - // Only the -fmodule-file=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { - StringRef Val = A->getValue(); - if (Val.find('=') == StringRef::npos) - Opts.ExtraDeps.push_back(Val); - } -} - -static bool parseShowColorsArgs(const ArgList &Args, bool DefaultColor) { - // Color diagnostics default to auto ("on" if terminal supports) in the driver - // but default to off in cc1, needing an explicit OPT_fdiagnostics_color. - // Support both clang's -f[no-]color-diagnostics and gcc's - // -f[no-]diagnostics-colors[=never|always|auto]. - enum { - Colors_On, - Colors_Off, - Colors_Auto - } ShowColors = DefaultColor ? Colors_Auto : Colors_Off; - for (Arg *A : Args) { - const Option &O = A->getOption(); - if (O.matches(options::OPT_fcolor_diagnostics) || - O.matches(options::OPT_fdiagnostics_color)) { - ShowColors = Colors_On; - } else if (O.matches(options::OPT_fno_color_diagnostics) || - O.matches(options::OPT_fno_diagnostics_color)) { - ShowColors = Colors_Off; - } else if (O.matches(options::OPT_fdiagnostics_color_EQ)) { - StringRef Value(A->getValue()); - if (Value == "always") - ShowColors = Colors_On; - else if (Value == "never") - ShowColors = Colors_Off; - else if (Value == "auto") - ShowColors = Colors_Auto; - } - } - return ShowColors == Colors_On || - (ShowColors == Colors_Auto && - llvm::sys::Process::StandardErrHasColors()); -} - -static bool checkVerifyPrefixes(const std::vector<std::string> &VerifyPrefixes, - DiagnosticsEngine *Diags) { - bool Success = true; - for (const auto &Prefix : VerifyPrefixes) { - // Every prefix must start with a letter and contain only alphanumeric - // characters, hyphens, and underscores. - auto BadChar = std::find_if(Prefix.begin(), Prefix.end(), - [](char C){return !isAlphanumeric(C) - && C != '-' && C != '_';}); - if (BadChar != Prefix.end() || !isLetter(Prefix[0])) { - Success = false; - if (Diags) { - Diags->Report(diag::err_drv_invalid_value) << "-verify=" << Prefix; - Diags->Report(diag::note_drv_verify_prefix_spelling); - } - } - } - return Success; + auto ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); + Opts.ExtraDeps.insert(Opts.ExtraDeps.end(), ModuleFiles.begin(), + ModuleFiles.end()); } bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, - DiagnosticsEngine *Diags, - bool DefaultDiagColor, bool DefaultShowOpt) { + DiagnosticsEngine *Diags) { using namespace options; bool Success = true; @@ -1107,16 +785,13 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.Pedantic = Args.hasArg(OPT_pedantic); Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors); Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics); - Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor); + Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics); Opts.ShowColumn = Args.hasFlag(OPT_fshow_column, OPT_fno_show_column, /*Default=*/true); Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info); Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location); - Opts.AbsolutePath = Args.hasArg(OPT_fdiagnostics_absolute_paths); - Opts.ShowOptionNames = - Args.hasFlag(OPT_fdiagnostics_show_option, - OPT_fno_diagnostics_show_option, DefaultShowOpt); + Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option); llvm::sys::Process::UseANSIEscapeCodes(Args.hasArg(OPT_fansi_escape_codes)); @@ -1179,18 +854,7 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info); Opts.ShowParseableFixits = Args.hasArg(OPT_fdiagnostics_parseable_fixits); Opts.ShowPresumedLoc = !Args.hasArg(OPT_fno_diagnostics_use_presumed_location); - Opts.VerifyDiagnostics = Args.hasArg(OPT_verify) || Args.hasArg(OPT_verify_EQ); - Opts.VerifyPrefixes = Args.getAllArgValues(OPT_verify_EQ); - if (Args.hasArg(OPT_verify)) - Opts.VerifyPrefixes.push_back("expected"); - // Keep VerifyPrefixes in its original order for the sake of diagnostics, and - // then sort it to prepare for fast lookup using std::binary_search. - if (!checkVerifyPrefixes(Opts.VerifyPrefixes, Diags)) { - Opts.VerifyDiagnostics = false; - Success = false; - } - else - std::sort(Opts.VerifyPrefixes.begin(), Opts.VerifyPrefixes.end()); + Opts.VerifyDiagnostics = Args.hasArg(OPT_verify); DiagnosticLevelMask DiagMask = DiagnosticLevelMask::None; Success &= parseDiagnosticLevelMask("-verify-ignore-unexpected=", Args.getAllArgValues(OPT_verify_ignore_unexpected_EQ), @@ -1213,9 +877,6 @@ bool clang::ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args, Opts.SpellCheckingLimit = getLastArgIntValue( Args, OPT_fspell_checking_limit, DiagnosticOptions::DefaultSpellCheckingLimit, Diags); - Opts.SnippetLineLimit = getLastArgIntValue( - Args, OPT_fcaret_diagnostics_max_lines, - DiagnosticOptions::DefaultSnippetLineLimit, Diags); Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop, DiagnosticOptions::DefaultTabStop, Diags); if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) { @@ -1260,8 +921,7 @@ static bool parseTestModuleFileExtensionArg(StringRef Arg, } static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags, - bool &IsHeaderFile) { + DiagnosticsEngine &Diags) { using namespace options; Opts.ProgramAction = frontend::ParseSyntaxOnly; if (const Arg *A = Args.getLastArg(OPT_Action_Group)) { @@ -1271,7 +931,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, case OPT_ast_list: Opts.ProgramAction = frontend::ASTDeclList; break; case OPT_ast_dump: - case OPT_ast_dump_all: case OPT_ast_dump_lookups: Opts.ProgramAction = frontend::ASTDump; break; case OPT_ast_print: @@ -1303,8 +962,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.ProgramAction = frontend::FixIt; break; case OPT_emit_module: Opts.ProgramAction = frontend::GenerateModule; break; - case OPT_emit_module_interface: - Opts.ProgramAction = frontend::GenerateModuleInterface; break; case OPT_emit_pch: Opts.ProgramAction = frontend::GeneratePCH; break; case OPT_emit_pth: @@ -1342,10 +999,18 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.Plugins.emplace_back(A->getValue(0)); Opts.ProgramAction = frontend::PluginAction; Opts.ActionName = A->getValue(); + + for (const Arg *AA : Args.filtered(OPT_plugin_arg)) + if (AA->getValue(0) == Opts.ActionName) + Opts.PluginArgs.emplace_back(AA->getValue(1)); } + Opts.AddPluginActions = Args.getAllArgValues(OPT_add_plugin); - for (const Arg *AA : Args.filtered(OPT_plugin_arg)) - Opts.PluginArgs[AA->getValue(0)].emplace_back(AA->getValue(1)); + Opts.AddPluginArgs.resize(Opts.AddPluginActions.size()); + for (int i = 0, e = Opts.AddPluginActions.size(); i != e; ++i) + for (const Arg *A : Args.filtered(OPT_plugin_arg)) + if (A->getValue(0) == Opts.AddPluginActions[i]) + Opts.AddPluginArgs[i].emplace_back(A->getValue(1)); for (const std::string &Arg : Args.getAllArgValues(OPT_ftest_module_file_extension_EQ)) { @@ -1363,8 +1028,8 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, // Add the testing module file extension. Opts.ModuleFileExtensions.push_back( - std::make_shared<TestModuleFileExtension>( - BlockName, MajorVersion, MinorVersion, Hashed, UserInfo)); + new TestModuleFileExtension(BlockName, MajorVersion, MinorVersion, + Hashed, UserInfo)); } if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) { @@ -1390,21 +1055,14 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Opts.FixAndRecompile = Args.hasArg(OPT_fixit_recompile); Opts.FixToTemporaries = Args.hasArg(OPT_fixit_to_temp); Opts.ASTDumpDecls = Args.hasArg(OPT_ast_dump); - Opts.ASTDumpAll = Args.hasArg(OPT_ast_dump_all); Opts.ASTDumpFilter = Args.getLastArgValue(OPT_ast_dump_filter); Opts.ASTDumpLookups = Args.hasArg(OPT_ast_dump_lookups); Opts.UseGlobalModuleIndex = !Args.hasArg(OPT_fno_modules_global_index); Opts.GenerateGlobalModuleIndex = Opts.UseGlobalModuleIndex; Opts.ModuleMapFiles = Args.getAllArgValues(OPT_fmodule_map_file); - // Only the -fmodule-file=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { - StringRef Val = A->getValue(); - if (Val.find('=') == StringRef::npos) - Opts.ModuleFiles.push_back(Val); - } + Opts.ModuleFiles = Args.getAllArgValues(OPT_fmodule_file); Opts.ModulesEmbedFiles = Args.getAllArgValues(OPT_fmodules_embed_file_EQ); Opts.ModulesEmbedAllFiles = Args.hasArg(OPT_fmodules_embed_all_files); - Opts.IncludeTimestamps = !Args.hasArg(OPT_fno_pch_timestamp); Opts.CodeCompleteOpts.IncludeMacros = Args.hasArg(OPT_code_completion_macros); @@ -1412,8 +1070,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = Args.hasArg(OPT_code_completion_patterns); Opts.CodeCompleteOpts.IncludeGlobals = !Args.hasArg(OPT_no_code_completion_globals); - Opts.CodeCompleteOpts.IncludeNamespaceLevelDecls - = !Args.hasArg(OPT_no_code_completion_ns_level_decls); Opts.CodeCompleteOpts.IncludeBriefComments = Args.hasArg(OPT_code_completion_brief_comments); @@ -1421,8 +1077,6 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, = Args.getLastArgValue(OPT_foverride_record_layout_EQ); Opts.AuxTriple = llvm::Triple::normalize(Args.getLastArgValue(OPT_aux_triple)); - Opts.FindPchSource = Args.getLastArgValue(OPT_find_pch_source_EQ); - Opts.StatsFile = Args.getLastArgValue(OPT_stats_file); if (const Arg *A = Args.getLastArg(OPT_arcmt_check, OPT_arcmt_modify, @@ -1486,54 +1140,34 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, << "ARC migration" << "ObjC migration"; } - InputKind DashX(InputKind::Unknown); + InputKind DashX = IK_None; if (const Arg *A = Args.getLastArg(OPT_x)) { - StringRef XValue = A->getValue(); - - // Parse suffixes: '<lang>(-header|[-module-map][-cpp-output])'. - // FIXME: Supporting '<lang>-header-cpp-output' would be useful. - bool Preprocessed = XValue.consume_back("-cpp-output"); - bool ModuleMap = XValue.consume_back("-module-map"); - IsHeaderFile = - !Preprocessed && !ModuleMap && XValue.consume_back("-header"); - - // Principal languages. - DashX = llvm::StringSwitch<InputKind>(XValue) - .Case("c", InputKind::C) - .Case("cl", InputKind::OpenCL) - .Case("cuda", InputKind::CUDA) - .Case("c++", InputKind::CXX) - .Case("objective-c", InputKind::ObjC) - .Case("objective-c++", InputKind::ObjCXX) - .Case("renderscript", InputKind::RenderScript) - .Default(InputKind::Unknown); - - // "objc[++]-cpp-output" is an acceptable synonym for - // "objective-c[++]-cpp-output". - if (DashX.isUnknown() && Preprocessed && !IsHeaderFile && !ModuleMap) - DashX = llvm::StringSwitch<InputKind>(XValue) - .Case("objc", InputKind::ObjC) - .Case("objc++", InputKind::ObjCXX) - .Default(InputKind::Unknown); - - // Some special cases cannot be combined with suffixes. - if (DashX.isUnknown() && !Preprocessed && !ModuleMap && !IsHeaderFile) - DashX = llvm::StringSwitch<InputKind>(XValue) - .Case("cpp-output", InputKind(InputKind::C).getPreprocessed()) - .Case("assembler-with-cpp", InputKind::Asm) - .Cases("ast", "pcm", - InputKind(InputKind::Unknown, InputKind::Precompiled)) - .Case("ir", InputKind::LLVM_IR) - .Default(InputKind::Unknown); - - if (DashX.isUnknown()) + DashX = llvm::StringSwitch<InputKind>(A->getValue()) + .Case("c", IK_C) + .Case("cl", IK_OpenCL) + .Case("cuda", IK_CUDA) + .Case("c++", IK_CXX) + .Case("objective-c", IK_ObjC) + .Case("objective-c++", IK_ObjCXX) + .Case("cpp-output", IK_PreprocessedC) + .Case("assembler-with-cpp", IK_Asm) + .Case("c++-cpp-output", IK_PreprocessedCXX) + .Case("cuda-cpp-output", IK_PreprocessedCuda) + .Case("objective-c-cpp-output", IK_PreprocessedObjC) + .Case("objc-cpp-output", IK_PreprocessedObjC) + .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX) + .Case("objc++-cpp-output", IK_PreprocessedObjCXX) + .Case("c-header", IK_C) + .Case("cl-header", IK_OpenCL) + .Case("objective-c-header", IK_ObjC) + .Case("c++-header", IK_CXX) + .Case("objective-c++-header", IK_ObjCXX) + .Cases("ast", "pcm", IK_AST) + .Case("ir", IK_LLVM_IR) + .Default(IK_None); + if (DashX == IK_None) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); - - if (Preprocessed) - DashX = DashX.getPreprocessed(); - if (ModuleMap) - DashX = DashX.withFormat(InputKind::ModuleMap); } // '-' is the default input if none is given. @@ -1543,22 +1177,13 @@ static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args, Inputs.push_back("-"); for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { InputKind IK = DashX; - if (IK.isUnknown()) { + if (IK == IK_None) { IK = FrontendOptions::getInputKindForExtension( StringRef(Inputs[i]).rsplit('.').second); - // FIXME: Warn on this? - if (IK.isUnknown()) - IK = InputKind::C; // FIXME: Remove this hack. if (i == 0) DashX = IK; } - - // The -emit-module action implicitly takes a module map. - if (Opts.ProgramAction == frontend::GenerateModule && - IK.getFormat() == InputKind::Source) - IK = IK.withFormat(InputKind::ModuleMap); - Opts.Inputs.emplace_back(std::move(Inputs[i]), IK); } @@ -1583,8 +1208,7 @@ std::string CompilerInvocation::GetResourcesPath(const char *Argv0, return P.str(); } -static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, - const std::string &WorkingDir) { +static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) { using namespace options; Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/"); Opts.Verbose = Args.hasArg(OPT_v); @@ -1594,31 +1218,9 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, if (const Arg *A = Args.getLastArg(OPT_stdlib_EQ)) Opts.UseLibcxx = (strcmp(A->getValue(), "libc++") == 0); Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir); - - // Canonicalize -fmodules-cache-path before storing it. - SmallString<128> P(Args.getLastArgValue(OPT_fmodules_cache_path)); - if (!(P.empty() || llvm::sys::path::is_absolute(P))) { - if (WorkingDir.empty()) - llvm::sys::fs::make_absolute(P); - else - llvm::sys::fs::make_absolute(WorkingDir, P); - } - llvm::sys::path::remove_dots(P); - Opts.ModuleCachePath = P.str(); - + Opts.ModuleCachePath = Args.getLastArgValue(OPT_fmodules_cache_path); Opts.ModuleUserBuildPath = Args.getLastArgValue(OPT_fmodules_user_build_path); - // Only the -fmodule-file=<name>=<file> form. - for (const Arg *A : Args.filtered(OPT_fmodule_file)) { - StringRef Val = A->getValue(); - if (Val.find('=') != StringRef::npos) - Opts.PrebuiltModuleFiles.insert(Val.split('=')); - } - for (const Arg *A : Args.filtered(OPT_fprebuilt_module_path)) - Opts.AddPrebuiltModulePath(A->getValue()); Opts.DisableModuleHash = Args.hasArg(OPT_fdisable_module_hash); - Opts.ModulesHashContent = Args.hasArg(OPT_fmodules_hash_content); - Opts.ModulesValidateDiagnosticOptions = - !Args.hasArg(OPT_fmodules_disable_diagnostic_validation); Opts.ImplicitModuleMaps = Args.hasArg(OPT_fimplicit_module_maps); Opts.ModuleMapFileHomeIsCwd = Args.hasArg(OPT_fmodule_map_file_home_is_cwd); Opts.ModuleCachePruneInterval = @@ -1636,14 +1238,11 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, for (const Arg *A : Args.filtered(OPT_fmodules_ignore_macro)) { StringRef MacroDef = A->getValue(); - Opts.ModulesIgnoreMacros.insert( - llvm::CachedHashString(MacroDef.split('=').first)); + Opts.ModulesIgnoreMacros.insert(MacroDef.split('=').first); } // Add -I..., -F..., and -index-header-map options in order. bool IsIndexHeaderMap = false; - bool IsSysrootSpecified = - Args.hasArg(OPT__sysroot_EQ) || Args.hasArg(OPT_isysroot); for (const Arg *A : Args.filtered(OPT_I, OPT_F, OPT_index_header_map)) { if (A->getOption().matches(OPT_index_header_map)) { // -index-header-map applies to the next -I or -F. @@ -1654,18 +1253,8 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, frontend::IncludeDirGroup Group = IsIndexHeaderMap ? frontend::IndexHeaderMap : frontend::Angled; - bool IsFramework = A->getOption().matches(OPT_F); - std::string Path = A->getValue(); - - if (IsSysrootSpecified && !IsFramework && A->getValue()[0] == '=') { - SmallString<32> Buffer; - llvm::sys::path::append(Buffer, Opts.Sysroot, - llvm::StringRef(A->getValue()).substr(1)); - Path = Buffer.str(); - } - - Opts.AddPath(Path, Group, IsFramework, - /*IgnoreSysroot*/ true); + Opts.AddPath(A->getValue(), Group, + /*IsFramework=*/A->getOption().matches(OPT_F), true); IsIndexHeaderMap = false; } @@ -1690,9 +1279,6 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, !A->getOption().matches(OPT_iwithsysroot)); for (const Arg *A : Args.filtered(OPT_iframework)) Opts.AddPath(A->getValue(), frontend::System, true, true); - for (const Arg *A : Args.filtered(OPT_iframeworkwithsysroot)) - Opts.AddPath(A->getValue(), frontend::System, /*IsFramework=*/true, - /*IgnoreSysRoot=*/false); // Add the paths for the various language specific isystem flags. for (const Arg *A : Args.filtered(OPT_c_isystem)) @@ -1724,51 +1310,45 @@ static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args, } void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, - const llvm::Triple &T, - PreprocessorOptions &PPOpts, LangStandard::Kind LangStd) { // Set some properties which depend solely on the input kind; it would be nice // to move these to the language standard, and have the driver resolve the // input kind + language standard. - // - // FIXME: Perhaps a better model would be for a single source file to have - // multiple language standards (C / C++ std, ObjC std, OpenCL std, OpenMP std) - // simultaneously active? - if (IK.getLanguage() == InputKind::Asm) { + if (IK == IK_Asm) { Opts.AsmPreprocessor = 1; - } else if (IK.isObjectiveC()) { + } else if (IK == IK_ObjC || + IK == IK_ObjCXX || + IK == IK_PreprocessedObjC || + IK == IK_PreprocessedObjCXX) { Opts.ObjC1 = Opts.ObjC2 = 1; } if (LangStd == LangStandard::lang_unspecified) { // Based on the base language, pick one. - switch (IK.getLanguage()) { - case InputKind::Unknown: - case InputKind::LLVM_IR: + switch (IK) { + case IK_None: + case IK_AST: + case IK_LLVM_IR: llvm_unreachable("Invalid input kind!"); - case InputKind::OpenCL: - LangStd = LangStandard::lang_opencl10; + case IK_OpenCL: + LangStd = LangStandard::lang_opencl; break; - case InputKind::CUDA: + case IK_CUDA: + case IK_PreprocessedCuda: LangStd = LangStandard::lang_cuda; break; - case InputKind::Asm: - case InputKind::C: - // The PS4 uses C99 as the default C standard. - if (T.isPS4()) - LangStd = LangStandard::lang_gnu99; - else - LangStd = LangStandard::lang_gnu11; - break; - case InputKind::ObjC: + case IK_Asm: + case IK_C: + case IK_PreprocessedC: + case IK_ObjC: + case IK_PreprocessedObjC: LangStd = LangStandard::lang_gnu11; break; - case InputKind::CXX: - case InputKind::ObjCXX: - LangStd = LangStandard::lang_gnucxx14; - break; - case InputKind::RenderScript: - LangStd = LangStandard::lang_c99; + case IK_CXX: + case IK_PreprocessedCXX: + case IK_ObjCXX: + case IK_PreprocessedObjCXX: + LangStd = LangStandard::lang_gnucxx98; break; } } @@ -1777,21 +1357,19 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.LineComment = Std.hasLineComments(); Opts.C99 = Std.isC99(); Opts.C11 = Std.isC11(); - Opts.C17 = Std.isC17(); Opts.CPlusPlus = Std.isCPlusPlus(); Opts.CPlusPlus11 = Std.isCPlusPlus11(); Opts.CPlusPlus14 = Std.isCPlusPlus14(); - Opts.CPlusPlus17 = Std.isCPlusPlus17(); - Opts.CPlusPlus2a = Std.isCPlusPlus2a(); + Opts.CPlusPlus1z = Std.isCPlusPlus1z(); Opts.Digraphs = Std.hasDigraphs(); Opts.GNUMode = Std.isGNUMode(); - Opts.GNUInline = !Opts.C99 && !Opts.CPlusPlus; + Opts.GNUInline = Std.isC89(); Opts.HexFloats = Std.hasHexFloats(); Opts.ImplicitInt = Std.hasImplicitInt(); // Set OpenCL Version. - Opts.OpenCL = Std.isOpenCL(); - if (LangStd == LangStandard::lang_opencl10) + Opts.OpenCL = LangStd == LangStandard::lang_opencl || IK == IK_OpenCL; + if (LangStd == LangStandard::lang_opencl) Opts.OpenCLVersion = 100; else if (LangStd == LangStandard::lang_opencl11) Opts.OpenCLVersion = 110; @@ -1804,26 +1382,14 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, if (Opts.OpenCL) { Opts.AltiVec = 0; Opts.ZVector = 0; + Opts.CXXOperatorNames = 1; Opts.LaxVectorConversions = 0; - Opts.setDefaultFPContractMode(LangOptions::FPC_On); + Opts.DefaultFPContract = 1; Opts.NativeHalfType = 1; - Opts.NativeHalfArgsAndReturns = 1; - // Include default header file for OpenCL. - if (Opts.IncludeDefaultHeader) { - PPOpts.Includes.push_back("opencl-c.h"); - } } - Opts.CUDA = IK.getLanguage() == InputKind::CUDA; - if (Opts.CUDA) - // Set default FP_CONTRACT to FAST. - Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); - - Opts.RenderScript = IK.getLanguage() == InputKind::RenderScript; - if (Opts.RenderScript) { - Opts.NativeHalfType = 1; - Opts.NativeHalfArgsAndReturns = 1; - } + Opts.CUDA = IK == IK_CUDA || IK == IK_PreprocessedCuda || + LangStd == LangStandard::lang_cuda; // OpenCL and C++ both have bool, true, false keywords. Opts.Bool = Opts.OpenCL || Opts.CPlusPlus; @@ -1837,8 +1403,6 @@ void CompilerInvocation::setLangDefaults(LangOptions &Opts, InputKind IK, Opts.GNUKeywords = Opts.GNUMode; Opts.CXXOperatorNames = Opts.CPlusPlus; - Opts.AlignedAllocation = Opts.CPlusPlus17; - Opts.DollarIdents = !Opts.AsmPreprocessor; } @@ -1860,117 +1424,53 @@ static Visibility parseVisibility(Arg *arg, ArgList &args, return DefaultVisibility; } -/// Check if input file kind and language standard are compatible. -static bool IsInputCompatibleWithStandard(InputKind IK, - const LangStandard &S) { - switch (IK.getLanguage()) { - case InputKind::Unknown: - case InputKind::LLVM_IR: - llvm_unreachable("should not parse language flags for this input"); - - case InputKind::C: - case InputKind::ObjC: - case InputKind::RenderScript: - return S.getLanguage() == InputKind::C; - - case InputKind::OpenCL: - return S.getLanguage() == InputKind::OpenCL; - - case InputKind::CXX: - case InputKind::ObjCXX: - return S.getLanguage() == InputKind::CXX; - - case InputKind::CUDA: - // FIXME: What -std= values should be permitted for CUDA compilations? - return S.getLanguage() == InputKind::CUDA || - S.getLanguage() == InputKind::CXX; - - case InputKind::Asm: - // Accept (and ignore) all -std= values. - // FIXME: The -std= value is not ignored; it affects the tokenization - // and preprocessing rules if we're preprocessing this asm input. - return true; - } - - llvm_unreachable("unexpected input language"); -} - -/// Get language name for given input kind. -static const StringRef GetInputKindName(InputKind IK) { - switch (IK.getLanguage()) { - case InputKind::C: - return "C"; - case InputKind::ObjC: - return "Objective-C"; - case InputKind::CXX: - return "C++"; - case InputKind::ObjCXX: - return "Objective-C++"; - case InputKind::OpenCL: - return "OpenCL"; - case InputKind::CUDA: - return "CUDA"; - case InputKind::RenderScript: - return "RenderScript"; - - case InputKind::Asm: - return "Asm"; - case InputKind::LLVM_IR: - return "LLVM IR"; - - case InputKind::Unknown: - break; - } - llvm_unreachable("unknown input language"); -} - static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, - const TargetOptions &TargetOpts, - PreprocessorOptions &PPOpts, DiagnosticsEngine &Diags) { // FIXME: Cleanup per-file based stuff. LangStandard::Kind LangStd = LangStandard::lang_unspecified; if (const Arg *A = Args.getLastArg(OPT_std_EQ)) { LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) -#define LANGSTANDARD(id, name, lang, desc, features) \ +#define LANGSTANDARD(id, name, desc, features) \ .Case(name, LangStandard::lang_##id) -#define LANGSTANDARD_ALIAS(id, alias) \ - .Case(alias, LangStandard::lang_##id) #include "clang/Frontend/LangStandards.def" .Default(LangStandard::lang_unspecified); - if (LangStd == LangStandard::lang_unspecified) { + if (LangStd == LangStandard::lang_unspecified) Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << A->getValue(); - // Report supported standards with short description. - for (unsigned KindValue = 0; - KindValue != LangStandard::lang_unspecified; - ++KindValue) { - const LangStandard &Std = LangStandard::getLangStandardForKind( - static_cast<LangStandard::Kind>(KindValue)); - if (IsInputCompatibleWithStandard(IK, Std)) { - auto Diag = Diags.Report(diag::note_drv_use_standard); - Diag << Std.getName() << Std.getDescription(); - unsigned NumAliases = 0; -#define LANGSTANDARD(id, name, lang, desc, features) -#define LANGSTANDARD_ALIAS(id, alias) \ - if (KindValue == LangStandard::lang_##id) ++NumAliases; -#define LANGSTANDARD_ALIAS_DEPR(id, alias) -#include "clang/Frontend/LangStandards.def" - Diag << NumAliases; -#define LANGSTANDARD(id, name, lang, desc, features) -#define LANGSTANDARD_ALIAS(id, alias) \ - if (KindValue == LangStandard::lang_##id) Diag << alias; -#define LANGSTANDARD_ALIAS_DEPR(id, alias) -#include "clang/Frontend/LangStandards.def" - } - } - } else { + else { // Valid standard, check to make sure language and standard are // compatible. const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd); - if (!IsInputCompatibleWithStandard(IK, Std)) { - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getAsString(Args) << GetInputKindName(IK); + switch (IK) { + case IK_C: + case IK_ObjC: + case IK_PreprocessedC: + case IK_PreprocessedObjC: + if (!(Std.isC89() || Std.isC99())) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "C/ObjC"; + break; + case IK_CXX: + case IK_ObjCXX: + case IK_PreprocessedCXX: + case IK_PreprocessedObjCXX: + if (!Std.isCPlusPlus()) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "C++/ObjC++"; + break; + case IK_OpenCL: + if (!Std.isC99()) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "OpenCL"; + break; + case IK_CUDA: + case IK_PreprocessedCuda: + if (!Std.isCPlusPlus()) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "CUDA"; + break; + default: + break; } } } @@ -1979,37 +1479,22 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Override the -std option in this case. if (const Arg *A = Args.getLastArg(OPT_cl_std_EQ)) { LangStandard::Kind OpenCLLangStd - = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) - .Cases("cl", "CL", LangStandard::lang_opencl10) - .Cases("cl1.1", "CL1.1", LangStandard::lang_opencl11) - .Cases("cl1.2", "CL1.2", LangStandard::lang_opencl12) - .Cases("cl2.0", "CL2.0", LangStandard::lang_opencl20) - .Default(LangStandard::lang_unspecified); + = llvm::StringSwitch<LangStandard::Kind>(A->getValue()) + .Case("CL", LangStandard::lang_opencl) + .Case("CL1.1", LangStandard::lang_opencl11) + .Case("CL1.2", LangStandard::lang_opencl12) + .Case("CL2.0", LangStandard::lang_opencl20) + .Default(LangStandard::lang_unspecified); if (OpenCLLangStd == LangStandard::lang_unspecified) { Diags.Report(diag::err_drv_invalid_value) - << A->getAsString(Args) << A->getValue(); + << A->getAsString(Args) << A->getValue(); } else LangStd = OpenCLLangStd; } - Opts.IncludeDefaultHeader = Args.hasArg(OPT_finclude_default_header); - - llvm::Triple T(TargetOpts.Triple); - CompilerInvocation::setLangDefaults(Opts, IK, T, PPOpts, LangStd); - - // -cl-strict-aliasing needs to emit diagnostic in the case where CL > 1.0. - // This option should be deprecated for CL > 1.0 because - // this option was added for compatibility with OpenCL 1.0. - if (Args.getLastArg(OPT_cl_strict_aliasing) - && Opts.OpenCLVersion > 100) { - std::string VerSpec = llvm::to_string(Opts.OpenCLVersion / 100) + - std::string(".") + - llvm::to_string((Opts.OpenCLVersion % 100) / 10); - Diags.Report(diag::warn_option_invalid_ocl_version) - << VerSpec << Args.getLastArg(OPT_cl_strict_aliasing)->getAsString(Args); - } + CompilerInvocation::setLangDefaults(Opts, IK, LangStd); // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension // keywords. This behavior is provided by GCC's poorly named '-fasm' flag, @@ -2025,17 +1510,14 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fcuda_is_device)) Opts.CUDAIsDevice = 1; - if (Args.hasArg(OPT_fcuda_allow_variadic_functions)) - Opts.CUDAAllowVariadicFunctions = 1; + if (Args.hasArg(OPT_fcuda_allow_host_calls_from_host_device)) + Opts.CUDAAllowHostCallsFromHostDevice = 1; - if (Args.hasArg(OPT_fno_cuda_host_device_constexpr)) - Opts.CUDAHostDeviceConstexpr = 0; + if (Args.hasArg(OPT_fcuda_disable_target_call_checks)) + Opts.CUDADisableTargetCallChecks = 1; - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_flush_denormals_to_zero)) - Opts.CUDADeviceFlushDenormalsToZero = 1; - - if (Opts.CUDAIsDevice && Args.hasArg(OPT_fcuda_approx_transcendentals)) - Opts.CUDADeviceApproxTranscendentals = 1; + if (Args.hasArg(OPT_fcuda_target_overloads)) + Opts.CUDATargetOverloads = 1; if (Opts.ObjC1) { if (Arg *arg = Args.getLastArg(OPT_fobjc_runtime_EQ)) { @@ -2089,8 +1571,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fgnu89_inline)) { if (Opts.CPlusPlus) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << "-fgnu89-inline" << GetInputKindName(IK); + Diags.Report(diag::err_drv_argument_not_allowed_with) << "-fgnu89-inline" + << "C++/ObjC++"; else Opts.GNUInline = 1; } @@ -2107,6 +1589,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, if (Args.hasArg(OPT_fno_constant_cfstrings)) Opts.NoConstantCFStrings = 1; + if (Args.hasArg(OPT_faltivec)) + Opts.AltiVec = 1; + if (Args.hasArg(OPT_fzvector)) Opts.ZVector = 1; @@ -2156,7 +1641,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs // is specified, or -std is set to a conforming mode. // Trigraphs are disabled by default in c++1z onwards. - Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus17; + Opts.Trigraphs = !Opts.GNUMode && !Opts.MSVCCompat && !Opts.CPlusPlus1z; Opts.Trigraphs = Args.hasFlag(OPT_ftrigraphs, OPT_fno_trigraphs, Opts.Trigraphs); @@ -2176,42 +1661,20 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.Exceptions = Args.hasArg(OPT_fexceptions); Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); - - // Handle exception personalities - Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, - options::OPT_fseh_exceptions, - options::OPT_fdwarf_exceptions); - if (A) { - const Option &Opt = A->getOption(); - Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); - Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); - Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); - } - - Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); + Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); - Opts.RTTI = Opts.CPlusPlus && !Args.hasArg(OPT_fno_rtti); + Opts.RTTI = !Args.hasArg(OPT_fno_rtti); Opts.RTTIData = Opts.RTTI && !Args.hasArg(OPT_fno_rtti_data); - Opts.Blocks = Args.hasArg(OPT_fblocks) || (Opts.OpenCL - && Opts.OpenCLVersion >= 200); + Opts.Blocks = Args.hasArg(OPT_fblocks); Opts.BlocksRuntimeOptional = Args.hasArg(OPT_fblocks_runtime_optional); - Opts.CoroutinesTS = Args.hasArg(OPT_fcoroutines_ts); - - // Enable [[]] attributes in C++11 by default. - Opts.DoubleSquareBracketAttributes = - Args.hasFlag(OPT_fdouble_square_bracket_attributes, - OPT_fno_double_square_bracket_attributes, Opts.CPlusPlus11); - - Opts.ModulesTS = Args.hasArg(OPT_fmodules_ts); - Opts.Modules = Args.hasArg(OPT_fmodules) || Opts.ModulesTS; + Opts.Coroutines = Args.hasArg(OPT_fcoroutines); + Opts.Modules = Args.hasArg(OPT_fmodules); Opts.ModulesStrictDeclUse = Args.hasArg(OPT_fmodules_strict_decluse); Opts.ModulesDeclUse = Args.hasArg(OPT_fmodules_decluse) || Opts.ModulesStrictDeclUse; Opts.ModulesLocalVisibility = - Args.hasArg(OPT_fmodules_local_submodule_visibility) || Opts.ModulesTS; - Opts.ModulesCodegen = Args.hasArg(OPT_fmodules_codegen); - Opts.ModulesDebugInfo = Args.hasArg(OPT_fmodules_debuginfo); + Args.hasArg(OPT_fmodules_local_submodule_visibility); Opts.ModulesSearchAll = Opts.Modules && !Args.hasArg(OPT_fno_modules_search_all) && Args.hasArg(OPT_fmodules_search_all); @@ -2219,45 +1682,22 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ImplicitModules = !Args.hasArg(OPT_fno_implicit_modules); Opts.CharIsSigned = Opts.OpenCL || !Args.hasArg(OPT_fno_signed_char); Opts.WChar = Opts.CPlusPlus && !Args.hasArg(OPT_fno_wchar); - if (const Arg *A = Args.getLastArg(OPT_fwchar_type_EQ)) { - Opts.WCharSize = llvm::StringSwitch<unsigned>(A->getValue()) - .Case("char", 1) - .Case("short", 2) - .Case("int", 4) - .Default(0); - if (Opts.WCharSize == 0) - Diags.Report(diag::err_fe_invalid_wchar_type) << A->getValue(); - } - Opts.WCharIsSigned = Args.hasFlag(OPT_fsigned_wchar, OPT_fno_signed_wchar, true); + Opts.ShortWChar = Args.hasFlag(OPT_fshort_wchar, OPT_fno_short_wchar, false); Opts.ShortEnums = Args.hasArg(OPT_fshort_enums); Opts.Freestanding = Args.hasArg(OPT_ffreestanding); Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding; if (!Opts.NoBuiltin) getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs); Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin); - Opts.RelaxedTemplateTemplateArgs = - Args.hasArg(OPT_frelaxed_template_template_args); + Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new); Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation); - Opts.AlignedAllocation = - Args.hasFlag(OPT_faligned_allocation, OPT_fno_aligned_allocation, - Opts.AlignedAllocation); - Opts.AlignedAllocationUnavailable = - Opts.AlignedAllocation && Args.hasArg(OPT_aligned_alloc_unavailable); - Opts.NewAlignOverride = - getLastArgIntValue(Args, OPT_fnew_alignment_EQ, 0, Diags); - if (Opts.NewAlignOverride && !llvm::isPowerOf2_32(Opts.NewAlignOverride)) { - Arg *A = Args.getLastArg(OPT_fnew_alignment_EQ); - Diags.Report(diag::err_fe_invalid_alignment) << A->getAsString(Args) - << A->getValue(); - Opts.NewAlignOverride = 0; - } Opts.ConceptsTS = Args.hasArg(OPT_fconcepts_ts); Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions); Opts.AccessControl = !Args.hasArg(OPT_fno_access_control); Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors); Opts.MathErrno = !Opts.OpenCL && Args.hasArg(OPT_fmath_errno); Opts.InstantiationDepth = - getLastArgIntValue(Args, OPT_ftemplate_depth, 1024, Diags); + getLastArgIntValue(Args, OPT_ftemplate_depth, 256, Diags); Opts.ArrowDepth = getLastArgIntValue(Args, OPT_foperator_arrow_depth, 256, Diags); Opts.ConstexprCallDepth = @@ -2278,9 +1718,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls); Opts.PackStruct = getLastArgIntValue(Args, OPT_fpack_struct_EQ, 0, Diags); Opts.MaxTypeAlign = getLastArgIntValue(Args, OPT_fmax_type_align_EQ, 0, Diags); - Opts.AlignDouble = Args.hasArg(OPT_malign_double); Opts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); - Opts.PIE = Args.hasArg(OPT_pic_is_pie); + Opts.PIELevel = getLastArgIntValue(Args, OPT_pie_level, 0, Diags); Opts.Static = Args.hasArg(OPT_static_define); Opts.DumpRecordLayoutsSimple = Args.hasArg(OPT_fdump_record_layouts_simple); Opts.DumpRecordLayouts = Opts.DumpRecordLayoutsSimple @@ -2290,6 +1729,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align); Opts.SinglePrecisionConstants = Args.hasArg(OPT_cl_single_precision_constant); Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math); + Opts.MRTD = Args.hasArg(OPT_mrtd); Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat); Opts.FakeAddressSpaceMap = Args.hasArg(OPT_ffake_address_space_map); Opts.ParseUnknownAnytype = Args.hasArg(OPT_funknown_anytype); @@ -2297,30 +1737,39 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.DebuggerCastResultToId = Args.hasArg(OPT_fdebugger_cast_result_to_id); Opts.DebuggerObjCLiteral = Args.hasArg(OPT_fdebugger_objc_literal); Opts.ApplePragmaPack = Args.hasArg(OPT_fapple_pragma_pack); - Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name_EQ); + Opts.CurrentModule = Args.getLastArgValue(OPT_fmodule_name); Opts.AppExt = Args.hasArg(OPT_fapplication_extension); + Opts.ImplementationOfModule = + Args.getLastArgValue(OPT_fmodule_implementation_of); Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end()); Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type); - Opts.NativeHalfArgsAndReturns |= Args.hasArg(OPT_fnative_half_arguments_and_returns); - // Enable HalfArgsAndReturns if present in Args or if NativeHalfArgsAndReturns - // is enabled. - Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns) - | Opts.NativeHalfArgsAndReturns; + Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns); Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); // __declspec is enabled by default for the PS4 by the driver, and also // enabled for Microsoft Extensions or Borland Extensions, here. // // FIXME: __declspec is also currently enabled for CUDA, but isn't really a - // CUDA extension. However, it is required for supporting - // __clang_cuda_builtin_vars.h, which uses __declspec(property). Once that has - // been rewritten in terms of something more generic, remove the Opts.CUDA - // term here. + // CUDA extension, however it is required for supporting cuda_builtin_vars.h, + // which uses __declspec(property). Once that has been rewritten in terms of + // something more generic, remove the Opts.CUDA term here. Opts.DeclSpecKeyword = Args.hasFlag(OPT_fdeclspec, OPT_fno_declspec, (Opts.MicrosoftExt || Opts.Borland || Opts.CUDA)); + if (!Opts.CurrentModule.empty() && !Opts.ImplementationOfModule.empty() && + Opts.CurrentModule != Opts.ImplementationOfModule) { + Diags.Report(diag::err_conflicting_module_names) + << Opts.CurrentModule << Opts.ImplementationOfModule; + } + + // For now, we only support local submodule visibility in C++ (because we + // heavily depend on the ODR for merging redefinitions). + if (Opts.ModulesLocalVisibility && !Opts.CPlusPlus) + Diags.Report(diag::err_drv_argument_not_allowed_with) + << "-fmodules-local-submodule-visibility" << "C"; + if (Arg *A = Args.getLastArg(OPT_faddress_space_map_mangling_EQ)) { switch (llvm::StringSwitch<unsigned>(A->getValue()) .Case("target", LangOptions::ASMM_Target) @@ -2361,105 +1810,20 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.setMSPointerToMemberRepresentationMethod(InheritanceModel); } - // Check for MS default calling conventions being specified. - if (Arg *A = Args.getLastArg(OPT_fdefault_calling_conv_EQ)) { - LangOptions::DefaultCallingConvention DefaultCC = - llvm::StringSwitch<LangOptions::DefaultCallingConvention>(A->getValue()) - .Case("cdecl", LangOptions::DCC_CDecl) - .Case("fastcall", LangOptions::DCC_FastCall) - .Case("stdcall", LangOptions::DCC_StdCall) - .Case("vectorcall", LangOptions::DCC_VectorCall) - .Case("regcall", LangOptions::DCC_RegCall) - .Default(LangOptions::DCC_None); - if (DefaultCC == LangOptions::DCC_None) - Diags.Report(diag::err_drv_invalid_value) - << "-fdefault-calling-conv=" << A->getValue(); - - llvm::Triple T(TargetOpts.Triple); - llvm::Triple::ArchType Arch = T.getArch(); - bool emitError = (DefaultCC == LangOptions::DCC_FastCall || - DefaultCC == LangOptions::DCC_StdCall) && - Arch != llvm::Triple::x86; - emitError |= (DefaultCC == LangOptions::DCC_VectorCall || - DefaultCC == LangOptions::DCC_RegCall) && - !(Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64); - if (emitError) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getSpelling() << T.getTriple(); - else - Opts.setDefaultCallingConv(DefaultCC); - } - - // -mrtd option - if (Arg *A = Args.getLastArg(OPT_mrtd)) { - if (Opts.getDefaultCallingConv() != LangOptions::DCC_None) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getSpelling() << "-fdefault-calling-conv"; - else { - llvm::Triple T(TargetOpts.Triple); - if (T.getArch() != llvm::Triple::x86) - Diags.Report(diag::err_drv_argument_not_allowed_with) - << A->getSpelling() << T.getTriple(); - else - Opts.setDefaultCallingConv(LangOptions::DCC_StdCall); - } - } - // Check if -fopenmp is specified. - Opts.OpenMP = Args.hasArg(options::OPT_fopenmp) ? 1 : 0; - // Check if -fopenmp-simd is specified. - Opts.OpenMPSimd = !Opts.OpenMP && Args.hasFlag(options::OPT_fopenmp_simd, - options::OPT_fno_openmp_simd, - /*Default=*/false); + Opts.OpenMP = Args.hasArg(options::OPT_fopenmp); Opts.OpenMPUseTLS = Opts.OpenMP && !Args.hasArg(options::OPT_fnoopenmp_use_tls); Opts.OpenMPIsDevice = Opts.OpenMP && Args.hasArg(options::OPT_fopenmp_is_device); - if (Opts.OpenMP || Opts.OpenMPSimd) { - if (int Version = - getLastArgIntValue(Args, OPT_fopenmp_version_EQ, - Opts.OpenMPSimd ? 45 : Opts.OpenMP, Diags)) - Opts.OpenMP = Version; - else if (Opts.OpenMPSimd) - Opts.OpenMP = 45; - // Provide diagnostic when a given target is not expected to be an OpenMP - // device or host. - if (!Opts.OpenMPIsDevice) { - switch (T.getArch()) { - default: - break; - // Add unsupported host targets here: - case llvm::Triple::nvptx: - case llvm::Triple::nvptx64: - Diags.Report(clang::diag::err_drv_omp_host_target_not_supported) - << TargetOpts.Triple; - break; - } - } - } - - // Set the flag to prevent the implementation from emitting device exception - // handling code for those requiring so. - if (Opts.OpenMPIsDevice && T.isNVPTX()) { - Opts.Exceptions = 0; - Opts.CXXExceptions = 0; - } - // Get the OpenMP target triples if any. - if (Arg *A = Args.getLastArg(options::OPT_fopenmp_targets_EQ)) { + if (Arg *A = Args.getLastArg(options::OPT_omptargets_EQ)) { for (unsigned i = 0; i < A->getNumValues(); ++i) { llvm::Triple TT(A->getValue(i)); - if (TT.getArch() == llvm::Triple::UnknownArch || - !(TT.getArch() == llvm::Triple::ppc || - TT.getArch() == llvm::Triple::ppc64 || - TT.getArch() == llvm::Triple::ppc64le || - TT.getArch() == llvm::Triple::nvptx || - TT.getArch() == llvm::Triple::nvptx64 || - TT.getArch() == llvm::Triple::x86 || - TT.getArch() == llvm::Triple::x86_64)) + if (TT.getArch() == llvm::Triple::UnknownArch) Diags.Report(clang::diag::err_drv_invalid_omp_target) << A->getValue(i); else Opts.OMPTargetTriples.push_back(TT); @@ -2468,7 +1832,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // Get OpenMP host file path if any and report if a non existent file is // found - if (Arg *A = Args.getLastArg(options::OPT_fopenmp_host_ir_file_path)) { + if (Arg *A = Args.getLastArg(options::OPT_omp_host_ir_file_path)) { Opts.OMPHostIRFile = A->getValue(); if (!llvm::sys::fs::exists(Opts.OMPHostIRFile)) Diags.Report(clang::diag::err_drv_omp_host_ir_file_not_found) @@ -2489,12 +1853,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, // This is the __NO_INLINE__ define, which just depends on things like the // optimization level and -fno-inline, not actually whether the backend has // inlining enabled. - Opts.NoInlineDefine = !Opts.Optimize; - if (Arg *InlineArg = Args.getLastArg( - options::OPT_finline_functions, options::OPT_finline_hint_functions, - options::OPT_fno_inline_functions, options::OPT_fno_inline)) - if (InlineArg->getOption().matches(options::OPT_fno_inline)) - Opts.NoInlineDefine = true; + Opts.NoInlineDefine = !Opt || Args.hasArg(OPT_fno_inline); Opts.FastMath = Args.hasArg(OPT_ffast_math) || Args.hasArg(OPT_cl_fast_relaxed_math); @@ -2505,18 +1864,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Args.hasArg(OPT_cl_unsafe_math_optimizations) || Args.hasArg(OPT_cl_fast_relaxed_math); - if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { - StringRef Val = A->getValue(); - if (Val == "fast") - Opts.setDefaultFPContractMode(LangOptions::FPC_Fast); - else if (Val == "on") - Opts.setDefaultFPContractMode(LangOptions::FPC_On); - else if (Val == "off") - Opts.setDefaultFPContractMode(LangOptions::FPC_Off); - else - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; - } - Opts.RetainCommentsFromSystemHeaders = Args.hasArg(OPT_fretain_comments_from_system_headers); @@ -2539,71 +1886,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.SanitizeAddressFieldPadding = getLastArgIntValue(Args, OPT_fsanitize_address_field_padding, 0, Diags); Opts.SanitizerBlacklistFiles = Args.getAllArgValues(OPT_fsanitize_blacklist); - - // -fxray-instrument - Opts.XRayInstrument = - Args.hasFlag(OPT_fxray_instrument, OPT_fnoxray_instrument, false); - - // -fxray-always-emit-customevents - Opts.XRayAlwaysEmitCustomEvents = - Args.hasFlag(OPT_fxray_always_emit_customevents, - OPT_fnoxray_always_emit_customevents, false); - - // -fxray-{always,never}-instrument= filenames. - Opts.XRayAlwaysInstrumentFiles = - Args.getAllArgValues(OPT_fxray_always_instrument); - Opts.XRayNeverInstrumentFiles = - Args.getAllArgValues(OPT_fxray_never_instrument); - - // -fallow-editor-placeholders - Opts.AllowEditorPlaceholders = Args.hasArg(OPT_fallow_editor_placeholders); -} - -static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) { - switch (Action) { - case frontend::ASTDeclList: - case frontend::ASTDump: - case frontend::ASTPrint: - case frontend::ASTView: - case frontend::EmitAssembly: - case frontend::EmitBC: - case frontend::EmitHTML: - case frontend::EmitLLVM: - case frontend::EmitLLVMOnly: - case frontend::EmitCodeGenOnly: - case frontend::EmitObj: - case frontend::FixIt: - case frontend::GenerateModule: - case frontend::GenerateModuleInterface: - case frontend::GeneratePCH: - case frontend::GeneratePTH: - case frontend::ParseSyntaxOnly: - case frontend::ModuleFileInfo: - case frontend::VerifyPCH: - case frontend::PluginAction: - case frontend::PrintDeclContext: - case frontend::RewriteObjC: - case frontend::RewriteTest: - case frontend::RunAnalysis: - case frontend::MigrateSource: - return false; - - case frontend::DumpRawTokens: - case frontend::DumpTokens: - case frontend::InitOnly: - case frontend::PrintPreamble: - case frontend::PrintPreprocessedInput: - case frontend::RewriteMacros: - case frontend::RunPreprocessorOnly: - return true; - } - llvm_unreachable("invalid frontend action"); } static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, FileManager &FileMgr, - DiagnosticsEngine &Diags, - frontend::ActionKind Action) { + DiagnosticsEngine &Diags) { using namespace options; Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch); Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth); @@ -2614,7 +1901,6 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, Opts.UsePredefines = !Args.hasArg(OPT_undef); Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record); Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch); - Opts.AllowPCHWithCompilerErrors = Args.hasArg(OPT_fallow_pch_with_errors); Opts.DumpDeserializedPCHDecls = Args.hasArg(OPT_dump_deserialized_pch_decls); for (const Arg *A : Args.filtered(OPT_error_on_deserialized_pch_decl)) @@ -2653,6 +1939,10 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, for (const Arg *A : Args.filtered(OPT_chain_include)) Opts.ChainedIncludes.emplace_back(A->getValue()); + // Include 'altivec.h' if -faltivec option present + if (Args.hasArg(OPT_faltivec)) + Opts.Includes.emplace_back("altivec.h"); + for (const Arg *A : Args.filtered(OPT_remap_file)) { std::pair<StringRef, StringRef> Split = StringRef(A->getValue()).split(';'); @@ -2676,12 +1966,6 @@ static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args, else Opts.ObjCXXARCStandardLibrary = (ObjCXXARCStandardLibraryKind)Library; } - - // Always avoid lexing editor placeholders when we're just running the - // preprocessor as we never want to emit the - // "editor placeholder in source file" error in PP only mode. - if (isStrictlyPreprocessorAction(Action)) - Opts.LexEditorPlaceholders = false; } static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, @@ -2689,48 +1973,65 @@ static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts, frontend::ActionKind Action) { using namespace options; - if (isStrictlyPreprocessorAction(Action)) - Opts.ShowCPP = !Args.hasArg(OPT_dM); - else + switch (Action) { + case frontend::ASTDeclList: + case frontend::ASTDump: + case frontend::ASTPrint: + case frontend::ASTView: + case frontend::EmitAssembly: + case frontend::EmitBC: + case frontend::EmitHTML: + case frontend::EmitLLVM: + case frontend::EmitLLVMOnly: + case frontend::EmitCodeGenOnly: + case frontend::EmitObj: + case frontend::FixIt: + case frontend::GenerateModule: + case frontend::GeneratePCH: + case frontend::GeneratePTH: + case frontend::ParseSyntaxOnly: + case frontend::ModuleFileInfo: + case frontend::VerifyPCH: + case frontend::PluginAction: + case frontend::PrintDeclContext: + case frontend::RewriteObjC: + case frontend::RewriteTest: + case frontend::RunAnalysis: + case frontend::MigrateSource: Opts.ShowCPP = 0; + break; + + case frontend::DumpRawTokens: + case frontend::DumpTokens: + case frontend::InitOnly: + case frontend::PrintPreamble: + case frontend::PrintPreprocessedInput: + case frontend::RewriteMacros: + case frontend::RunPreprocessorOnly: + Opts.ShowCPP = !Args.hasArg(OPT_dM); + break; + } Opts.ShowComments = Args.hasArg(OPT_C); Opts.ShowLineMarkers = !Args.hasArg(OPT_P); Opts.ShowMacroComments = Args.hasArg(OPT_CC); Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD); - Opts.ShowIncludeDirectives = Args.hasArg(OPT_dI); Opts.RewriteIncludes = Args.hasArg(OPT_frewrite_includes); - Opts.RewriteImports = Args.hasArg(OPT_frewrite_imports); Opts.UseLineDirectives = Args.hasArg(OPT_fuse_line_directives); } -static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args, - DiagnosticsEngine &Diags) { +static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) { using namespace options; Opts.ABI = Args.getLastArgValue(OPT_target_abi); - if (Arg *A = Args.getLastArg(OPT_meabi)) { - StringRef Value = A->getValue(); - llvm::EABI EABIVersion = llvm::StringSwitch<llvm::EABI>(Value) - .Case("default", llvm::EABI::Default) - .Case("4", llvm::EABI::EABI4) - .Case("5", llvm::EABI::EABI5) - .Case("gnu", llvm::EABI::GNU) - .Default(llvm::EABI::Unknown); - if (EABIVersion == llvm::EABI::Unknown) - Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) - << Value; - else - Opts.EABIVersion = EABIVersion; - } Opts.CPU = Args.getLastArgValue(OPT_target_cpu); Opts.FPMath = Args.getLastArgValue(OPT_mfpmath); Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature); Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version); Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); + Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ); // Use the default target triple if unspecified. if (Opts.Triple.empty()) Opts.Triple = llvm::sys::getDefaultTargetTriple(); - Opts.OpenCLExtensionsAsWritten = Args.getAllArgValues(OPT_cl_ext_EQ); } bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, @@ -2740,13 +2041,12 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, bool Success = true; // Parse the arguments. - std::unique_ptr<OptTable> Opts = createDriverOptTable(); + std::unique_ptr<OptTable> Opts(createDriverOptTable()); const unsigned IncludedFlagsBitmask = options::CC1Option; unsigned MissingArgIndex, MissingArgCount; InputArgList Args = Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex, MissingArgCount, IncludedFlagsBitmask); - LangOptions &LangOpts = *Res.getLangOpts(); // Check for missing argument error. if (MissingArgCount) { @@ -2764,83 +2064,91 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, Success &= ParseAnalyzerArgs(*Res.getAnalyzerOpts(), Args, Diags); Success &= ParseMigratorArgs(Res.getMigratorOpts(), Args); ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), Args); - Success &= - ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags, - false /*DefaultDiagColor*/, false /*DefaultShowOpt*/); - ParseCommentArgs(LangOpts.CommentOpts, Args); + Success &= ParseDiagnosticArgs(Res.getDiagnosticOpts(), Args, &Diags); + ParseCommentArgs(Res.getLangOpts()->CommentOpts, Args); ParseFileSystemArgs(Res.getFileSystemOpts(), Args); // FIXME: We shouldn't have to pass the DashX option around here - InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags, - LangOpts.IsHeaderFile); - ParseTargetArgs(Res.getTargetOpts(), Args, Diags); + InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), Args, Diags); + ParseTargetArgs(Res.getTargetOpts(), Args); Success &= ParseCodeGenArgs(Res.getCodeGenOpts(), Args, DashX, Diags, Res.getTargetOpts()); - ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args, - Res.getFileSystemOpts().WorkingDir); - if (DashX.getFormat() == InputKind::Precompiled || - DashX.getLanguage() == InputKind::LLVM_IR) { + ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), Args); + if (DashX == IK_AST || DashX == IK_LLVM_IR) { // ObjCAAutoRefCount and Sanitize LangOpts are used to setup the // PassManager in BackendUtil.cpp. They need to be initializd no matter // what the input type is. if (Args.hasArg(OPT_fobjc_arc)) - LangOpts.ObjCAutoRefCount = 1; - // PIClevel and PIELevel are needed during code generation and this should be - // set regardless of the input type. - LangOpts.PICLevel = getLastArgIntValue(Args, OPT_pic_level, 0, Diags); - LangOpts.PIE = Args.hasArg(OPT_pic_is_pie); + Res.getLangOpts()->ObjCAutoRefCount = 1; parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), - Diags, LangOpts.Sanitize); + Diags, Res.getLangOpts()->Sanitize); } else { // Other LangOpts are only initialzed when the input is not AST or LLVM IR. - // FIXME: Should we really be calling this for an InputKind::Asm input? - ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(), - Res.getPreprocessorOpts(), Diags); + ParseLangArgs(*Res.getLangOpts(), Args, DashX, Diags); if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC) - LangOpts.ObjCExceptions = 1; - } - - if (LangOpts.CUDA) { - // During CUDA device-side compilation, the aux triple is the - // triple used for host compilation. - if (LangOpts.CUDAIsDevice) - Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; + Res.getLangOpts()->ObjCExceptions = 1; } - - // Set the triple of the host for OpenMP device compile. - if (LangOpts.OpenMPIsDevice) - Res.getTargetOpts().HostTriple = Res.getFrontendOpts().AuxTriple; - - // FIXME: Override value name discarding when asan or msan is used because the - // backend passes depend on the name of the alloca in order to print out - // names. - Res.getCodeGenOpts().DiscardValueNames &= - !LangOpts.Sanitize.has(SanitizerKind::Address) && - !LangOpts.Sanitize.has(SanitizerKind::Memory); - // FIXME: ParsePreprocessorArgs uses the FileManager to read the contents of // PCH file and find the original header name. Remove the need to do that in // ParsePreprocessorArgs and remove the FileManager // parameters from the function and the "FileManager.h" #include. FileManager FileMgr(Res.getFileSystemOpts()); - ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags, - Res.getFrontendOpts().ProgramAction); + ParsePreprocessorArgs(Res.getPreprocessorOpts(), Args, FileMgr, Diags); ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), Args, Res.getFrontendOpts().ProgramAction); + return Success; +} - // Turn on -Wspir-compat for SPIR target. - llvm::Triple T(Res.getTargetOpts().Triple); - auto Arch = T.getArch(); - if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) { - Res.getDiagnosticOpts().Warnings.push_back("spir-compat"); - } +namespace { + + class ModuleSignature { + SmallVector<uint64_t, 16> Data; + unsigned CurBit; + uint64_t CurValue; + + public: + ModuleSignature() : CurBit(0), CurValue(0) { } + + void add(uint64_t Value, unsigned Bits); + void add(StringRef Value); + void flush(); + + llvm::APInt getAsInteger() const; + }; +} - // If sanitizer is enabled, disable OPT_ffine_grained_bitfield_accesses. - if (Res.getCodeGenOpts().FineGrainedBitfieldAccesses && - !Res.getLangOpts()->Sanitize.empty()) { - Res.getCodeGenOpts().FineGrainedBitfieldAccesses = false; - Diags.Report(diag::warn_drv_fine_grained_bitfield_accesses_ignored); +void ModuleSignature::add(uint64_t Value, unsigned int NumBits) { + CurValue |= Value << CurBit; + if (CurBit + NumBits < 64) { + CurBit += NumBits; + return; } - return Success; + + // Add the current word. + Data.push_back(CurValue); + + if (CurBit) + CurValue = Value >> (64-CurBit); + else + CurValue = 0; + CurBit = (CurBit+NumBits) & 63; +} + +void ModuleSignature::flush() { + if (CurBit == 0) + return; + + Data.push_back(CurValue); + CurBit = 0; + CurValue = 0; +} + +void ModuleSignature::add(StringRef Value) { + for (auto &c : Value) + add(c, 8); +} + +llvm::APInt ModuleSignature::getAsInteger() const { + return llvm::APInt(Data.size() * 64, Data); } std::string CompilerInvocation::getModuleHash() const { @@ -2887,8 +2195,7 @@ std::string CompilerInvocation::getModuleHash() const { if (!hsOpts.ModulesIgnoreMacros.empty()) { // Check whether we're ignoring this macro. StringRef MacroDef = I->first; - if (hsOpts.ModulesIgnoreMacros.count( - llvm::CachedHashString(MacroDef.split('=').first))) + if (hsOpts.ModulesIgnoreMacros.count(MacroDef.split('=').first)) continue; } @@ -2902,8 +2209,7 @@ std::string CompilerInvocation::getModuleHash() const { hsOpts.UseBuiltinIncludes, hsOpts.UseStandardSystemIncludes, hsOpts.UseStandardCXXIncludes, - hsOpts.UseLibcxx, - hsOpts.ModulesValidateDiagnosticOptions); + hsOpts.UseLibcxx); code = hash_combine(code, hsOpts.ResourceDir); // Extend the signature with the user build path. @@ -2911,16 +2217,32 @@ std::string CompilerInvocation::getModuleHash() const { // Extend the signature with the module file extensions. const FrontendOptions &frontendOpts = getFrontendOpts(); - for (const auto &ext : frontendOpts.ModuleFileExtensions) { + for (auto ext : frontendOpts.ModuleFileExtensions) { code = ext->hashExtension(code); } - // Extend the signature with the enabled sanitizers, if at least one is - // enabled. Sanitizers which cannot affect AST generation aren't hashed. - SanitizerSet SanHash = LangOpts->Sanitize; - SanHash.clear(getPPTransparentSanitizers()); - if (!SanHash.empty()) - code = hash_combine(code, SanHash.Mask); + // Darwin-specific hack: if we have a sysroot, use the contents and + // modification time of + // $sysroot/System/Library/CoreServices/SystemVersion.plist + // as part of the module hash. + if (!hsOpts.Sysroot.empty()) { + SmallString<128> systemVersionFile; + systemVersionFile += hsOpts.Sysroot; + llvm::sys::path::append(systemVersionFile, "System"); + llvm::sys::path::append(systemVersionFile, "Library"); + llvm::sys::path::append(systemVersionFile, "CoreServices"); + llvm::sys::path::append(systemVersionFile, "SystemVersion.plist"); + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> buffer = + llvm::MemoryBuffer::getFile(systemVersionFile); + if (buffer) { + code = hash_combine(code, buffer.get()->getBuffer()); + + struct stat statBuf; + if (stat(systemVersionFile.c_str(), &statBuf) == 0) + code = hash_combine(code, statBuf.st_mtime); + } + } return llvm::APInt(64, code).toString(36, /*Signed=*/false); } @@ -2973,29 +2295,22 @@ void BuryPointer(const void *Ptr) { IntrusiveRefCntPtr<vfs::FileSystem> createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags) { - return createVFSFromCompilerInvocation(CI, Diags, vfs::getRealFileSystem()); -} - -IntrusiveRefCntPtr<vfs::FileSystem> -createVFSFromCompilerInvocation(const CompilerInvocation &CI, - DiagnosticsEngine &Diags, - IntrusiveRefCntPtr<vfs::FileSystem> BaseFS) { if (CI.getHeaderSearchOpts().VFSOverlayFiles.empty()) - return BaseFS; + return vfs::getRealFileSystem(); - IntrusiveRefCntPtr<vfs::OverlayFileSystem> Overlay( - new vfs::OverlayFileSystem(BaseFS)); + IntrusiveRefCntPtr<vfs::OverlayFileSystem> + Overlay(new vfs::OverlayFileSystem(vfs::getRealFileSystem())); // earlier vfs files are on the bottom for (const std::string &File : CI.getHeaderSearchOpts().VFSOverlayFiles) { llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Buffer = - BaseFS->getBufferForFile(File); + llvm::MemoryBuffer::getFile(File); if (!Buffer) { Diags.Report(diag::err_missing_vfs_overlay_file) << File; return IntrusiveRefCntPtr<vfs::FileSystem>(); } - IntrusiveRefCntPtr<vfs::FileSystem> FS = vfs::getVFSFromYAML( - std::move(Buffer.get()), /*DiagHandler*/ nullptr, File); + IntrusiveRefCntPtr<vfs::FileSystem> FS = + vfs::getVFSFromYAML(std::move(Buffer.get()), /*DiagHandler*/ nullptr); if (!FS.get()) { Diags.Report(diag::err_invalid_vfs_overlay) << File; return IntrusiveRefCntPtr<vfs::FileSystem>(); |