summaryrefslogtreecommitdiff
path: root/gnu/llvm
diff options
context:
space:
mode:
authorPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:47:02 +0000
committerPascal Stumpf <pascal@cvs.openbsd.org>2016-09-03 22:47:02 +0000
commitc198ad09c18f3e76b43e376fbbc31e99e65a9137 (patch)
tree6520b546e1f252bad861cf5a29390bd3ecaf650a /gnu/llvm
parent42036bd5b84978c8bf5307aaac934c90fac325ac (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.h233
-rw-r--r--gnu/llvm/include/llvm/CodeGen/Passes.h498
-rw-r--r--gnu/llvm/include/llvm/InitializePasses.h368
-rw-r--r--gnu/llvm/lib/CodeGen/CMakeLists.txt87
-rw-r--r--gnu/llvm/lib/CodeGen/PrologEpilogInserter.cpp836
-rw-r--r--gnu/llvm/lib/Target/X86/X86FrameLowering.cpp1123
-rw-r--r--gnu/llvm/lib/Target/X86/X86FrameLowering.h82
-rw-r--r--gnu/llvm/lib/Target/X86/X86InstrCompiler.td653
-rw-r--r--gnu/llvm/tools/clang/include/clang/Driver/CC1Options.td245
-rw-r--r--gnu/llvm/tools/clang/include/clang/Frontend/CodeGenOptions.def160
-rw-r--r--gnu/llvm/tools/clang/lib/CodeGen/CGCall.cpp1539
-rw-r--r--gnu/llvm/tools/clang/lib/Frontend/CompilerInvocation.cpp1443
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> &paramInfos,
- 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> &paramInfos,
- 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 &params) {
- 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>();