Home | History | Annotate | Line # | Download | only in AArch64
      1 //=- AArch64MachineFunctionInfo.h - AArch64 machine function info -*- C++ -*-=//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file declares AArch64-specific per-machine-function information.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H
     14 #define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H
     15 
     16 #include "llvm/ADT/ArrayRef.h"
     17 #include "llvm/ADT/Optional.h"
     18 #include "llvm/ADT/SmallPtrSet.h"
     19 #include "llvm/ADT/SmallVector.h"
     20 #include "llvm/CodeGen/CallingConvLower.h"
     21 #include "llvm/CodeGen/MIRYamlMapping.h"
     22 #include "llvm/CodeGen/MachineFunction.h"
     23 #include "llvm/IR/Function.h"
     24 #include "llvm/MC/MCLinkerOptimizationHint.h"
     25 #include <cassert>
     26 
     27 namespace llvm {
     28 
     29 namespace yaml {
     30 struct AArch64FunctionInfo;
     31 } // end namespace yaml
     32 
     33 class MachineInstr;
     34 
     35 /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and
     36 /// contains private AArch64-specific information for each MachineFunction.
     37 class AArch64FunctionInfo final : public MachineFunctionInfo {
     38   /// Backreference to the machine function.
     39   MachineFunction &MF;
     40 
     41   /// Number of bytes of arguments this function has on the stack. If the callee
     42   /// is expected to restore the argument stack this should be a multiple of 16,
     43   /// all usable during a tail call.
     44   ///
     45   /// The alternative would forbid tail call optimisation in some cases: if we
     46   /// want to transfer control from a function with 8-bytes of stack-argument
     47   /// space to a function with 16-bytes then misalignment of this value would
     48   /// make a stack adjustment necessary, which could not be undone by the
     49   /// callee.
     50   unsigned BytesInStackArgArea = 0;
     51 
     52   /// The number of bytes to restore to deallocate space for incoming
     53   /// arguments. Canonically 0 in the C calling convention, but non-zero when
     54   /// callee is expected to pop the args.
     55   unsigned ArgumentStackToRestore = 0;
     56 
     57   /// Space just below incoming stack pointer reserved for arguments being
     58   /// passed on the stack during a tail call. This will be the difference
     59   /// between the largest tail call argument space needed in this function and
     60   /// what's already available by reusing space of incoming arguments.
     61   unsigned TailCallReservedStack = 0;
     62 
     63   /// HasStackFrame - True if this function has a stack frame. Set by
     64   /// determineCalleeSaves().
     65   bool HasStackFrame = false;
     66 
     67   /// Amount of stack frame size, not including callee-saved registers.
     68   uint64_t LocalStackSize = 0;
     69 
     70   /// The start and end frame indices for the SVE callee saves.
     71   int MinSVECSFrameIndex = 0;
     72   int MaxSVECSFrameIndex = 0;
     73 
     74   /// Amount of stack frame size used for saving callee-saved registers.
     75   unsigned CalleeSavedStackSize = 0;
     76   unsigned SVECalleeSavedStackSize = 0;
     77   bool HasCalleeSavedStackSize = false;
     78 
     79   /// Number of TLS accesses using the special (combinable)
     80   /// _TLS_MODULE_BASE_ symbol.
     81   unsigned NumLocalDynamicTLSAccesses = 0;
     82 
     83   /// FrameIndex for start of varargs area for arguments passed on the
     84   /// stack.
     85   int VarArgsStackIndex = 0;
     86 
     87   /// FrameIndex for start of varargs area for arguments passed in
     88   /// general purpose registers.
     89   int VarArgsGPRIndex = 0;
     90 
     91   /// Size of the varargs area for arguments passed in general purpose
     92   /// registers.
     93   unsigned VarArgsGPRSize = 0;
     94 
     95   /// FrameIndex for start of varargs area for arguments passed in
     96   /// floating-point registers.
     97   int VarArgsFPRIndex = 0;
     98 
     99   /// Size of the varargs area for arguments passed in floating-point
    100   /// registers.
    101   unsigned VarArgsFPRSize = 0;
    102 
    103   /// True if this function has a subset of CSRs that is handled explicitly via
    104   /// copies.
    105   bool IsSplitCSR = false;
    106 
    107   /// True when the stack gets realigned dynamically because the size of stack
    108   /// frame is unknown at compile time. e.g., in case of VLAs.
    109   bool StackRealigned = false;
    110 
    111   /// True when the callee-save stack area has unused gaps that may be used for
    112   /// other stack allocations.
    113   bool CalleeSaveStackHasFreeSpace = false;
    114 
    115   /// SRetReturnReg - sret lowering includes returning the value of the
    116   /// returned struct in a register. This field holds the virtual register into
    117   /// which the sret argument is passed.
    118   unsigned SRetReturnReg = 0;
    119   /// SVE stack size (for predicates and data vectors) are maintained here
    120   /// rather than in FrameInfo, as the placement and Stack IDs are target
    121   /// specific.
    122   uint64_t StackSizeSVE = 0;
    123 
    124   /// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid.
    125   bool HasCalculatedStackSizeSVE = false;
    126 
    127   /// Has a value when it is known whether or not the function uses a
    128   /// redzone, and no value otherwise.
    129   /// Initialized during frame lowering, unless the function has the noredzone
    130   /// attribute, in which case it is set to false at construction.
    131   Optional<bool> HasRedZone;
    132 
    133   /// ForwardedMustTailRegParms - A list of virtual and physical registers
    134   /// that must be forwarded to every musttail call.
    135   SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms;
    136 
    137   /// FrameIndex for the tagged base pointer.
    138   Optional<int> TaggedBasePointerIndex;
    139 
    140   /// Offset from SP-at-entry to the tagged base pointer.
    141   /// Tagged base pointer is set up to point to the first (lowest address)
    142   /// tagged stack slot.
    143   unsigned TaggedBasePointerOffset;
    144 
    145   /// OutliningStyle denotes, if a function was outined, how it was outlined,
    146   /// e.g. Tail Call, Thunk, or Function if none apply.
    147   Optional<std::string> OutliningStyle;
    148 
    149   // Offset from SP-after-callee-saved-spills (i.e. SP-at-entry minus
    150   // CalleeSavedStackSize) to the address of the frame record.
    151   int CalleeSaveBaseToFrameRecordOffset = 0;
    152 
    153   /// SignReturnAddress is true if PAC-RET is enabled for the function with
    154   /// defaults being sign non-leaf functions only, with the B key.
    155   bool SignReturnAddress = false;
    156 
    157   /// SignReturnAddressAll modifies the default PAC-RET mode to signing leaf
    158   /// functions as well.
    159   bool SignReturnAddressAll = false;
    160 
    161   /// SignWithBKey modifies the default PAC-RET mode to signing with the B key.
    162   bool SignWithBKey = false;
    163 
    164   /// BranchTargetEnforcement enables placing BTI instructions at potential
    165   /// indirect branch destinations.
    166   bool BranchTargetEnforcement = false;
    167 
    168   /// Whether this function has an extended frame record [Ctx, FP, LR]. If so,
    169   /// bit 60 of the in-memory FP will be 1 to enable other tools to detect the
    170   /// extended record.
    171   bool HasSwiftAsyncContext = false;
    172 
    173   /// The stack slot where the Swift asynchronous context is stored.
    174   int SwiftAsyncContextFrameIdx = std::numeric_limits<int>::max();
    175 
    176 public:
    177   explicit AArch64FunctionInfo(MachineFunction &MF);
    178 
    179   void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI);
    180 
    181   unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; }
    182   void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; }
    183 
    184   unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; }
    185   void setArgumentStackToRestore(unsigned bytes) {
    186     ArgumentStackToRestore = bytes;
    187   }
    188 
    189   unsigned getTailCallReservedStack() const { return TailCallReservedStack; }
    190   void setTailCallReservedStack(unsigned bytes) {
    191     TailCallReservedStack = bytes;
    192   }
    193 
    194   bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; }
    195 
    196   void setStackSizeSVE(uint64_t S) {
    197     HasCalculatedStackSizeSVE = true;
    198     StackSizeSVE = S;
    199   }
    200 
    201   uint64_t getStackSizeSVE() const { return StackSizeSVE; }
    202 
    203   bool hasStackFrame() const { return HasStackFrame; }
    204   void setHasStackFrame(bool s) { HasStackFrame = s; }
    205 
    206   bool isStackRealigned() const { return StackRealigned; }
    207   void setStackRealigned(bool s) { StackRealigned = s; }
    208 
    209   bool hasCalleeSaveStackFreeSpace() const {
    210     return CalleeSaveStackHasFreeSpace;
    211   }
    212   void setCalleeSaveStackHasFreeSpace(bool s) {
    213     CalleeSaveStackHasFreeSpace = s;
    214   }
    215   bool isSplitCSR() const { return IsSplitCSR; }
    216   void setIsSplitCSR(bool s) { IsSplitCSR = s; }
    217 
    218   void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; }
    219   uint64_t getLocalStackSize() const { return LocalStackSize; }
    220 
    221   void setOutliningStyle(std::string Style) { OutliningStyle = Style; }
    222   Optional<std::string> getOutliningStyle() const { return OutliningStyle; }
    223 
    224   void setCalleeSavedStackSize(unsigned Size) {
    225     CalleeSavedStackSize = Size;
    226     HasCalleeSavedStackSize = true;
    227   }
    228 
    229   // When CalleeSavedStackSize has not been set (for example when
    230   // some MachineIR pass is run in isolation), then recalculate
    231   // the CalleeSavedStackSize directly from the CalleeSavedInfo.
    232   // Note: This information can only be recalculated after PEI
    233   // has assigned offsets to the callee save objects.
    234   unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const {
    235     bool ValidateCalleeSavedStackSize = false;
    236 
    237 #ifndef NDEBUG
    238     // Make sure the calculated size derived from the CalleeSavedInfo
    239     // equals the cached size that was calculated elsewhere (e.g. in
    240     // determineCalleeSaves).
    241     ValidateCalleeSavedStackSize = HasCalleeSavedStackSize;
    242 #endif
    243 
    244     if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) {
    245       assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated");
    246       if (MFI.getCalleeSavedInfo().empty())
    247         return 0;
    248 
    249       int64_t MinOffset = std::numeric_limits<int64_t>::max();
    250       int64_t MaxOffset = std::numeric_limits<int64_t>::min();
    251       for (const auto &Info : MFI.getCalleeSavedInfo()) {
    252         int FrameIdx = Info.getFrameIdx();
    253         if (MFI.getStackID(FrameIdx) != TargetStackID::Default)
    254           continue;
    255         int64_t Offset = MFI.getObjectOffset(FrameIdx);
    256         int64_t ObjSize = MFI.getObjectSize(FrameIdx);
    257         MinOffset = std::min<int64_t>(Offset, MinOffset);
    258         MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset);
    259       }
    260 
    261       if (SwiftAsyncContextFrameIdx != std::numeric_limits<int>::max()) {
    262         int64_t Offset = MFI.getObjectOffset(getSwiftAsyncContextFrameIdx());
    263         int64_t ObjSize = MFI.getObjectSize(getSwiftAsyncContextFrameIdx());
    264         MinOffset = std::min<int64_t>(Offset, MinOffset);
    265         MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset);
    266       }
    267 
    268       unsigned Size = alignTo(MaxOffset - MinOffset, 16);
    269       assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) &&
    270              "Invalid size calculated for callee saves");
    271       return Size;
    272     }
    273 
    274     return getCalleeSavedStackSize();
    275   }
    276 
    277   unsigned getCalleeSavedStackSize() const {
    278     assert(HasCalleeSavedStackSize &&
    279            "CalleeSavedStackSize has not been calculated");
    280     return CalleeSavedStackSize;
    281   }
    282 
    283   // Saves the CalleeSavedStackSize for SVE vectors in 'scalable bytes'
    284   void setSVECalleeSavedStackSize(unsigned Size) {
    285     SVECalleeSavedStackSize = Size;
    286   }
    287   unsigned getSVECalleeSavedStackSize() const {
    288     return SVECalleeSavedStackSize;
    289   }
    290 
    291   void setMinMaxSVECSFrameIndex(int Min, int Max) {
    292     MinSVECSFrameIndex = Min;
    293     MaxSVECSFrameIndex = Max;
    294   }
    295 
    296   int getMinSVECSFrameIndex() const { return MinSVECSFrameIndex; }
    297   int getMaxSVECSFrameIndex() const { return MaxSVECSFrameIndex; }
    298 
    299   void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; }
    300   unsigned getNumLocalDynamicTLSAccesses() const {
    301     return NumLocalDynamicTLSAccesses;
    302   }
    303 
    304   Optional<bool> hasRedZone() const { return HasRedZone; }
    305   void setHasRedZone(bool s) { HasRedZone = s; }
    306 
    307   int getVarArgsStackIndex() const { return VarArgsStackIndex; }
    308   void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; }
    309 
    310   int getVarArgsGPRIndex() const { return VarArgsGPRIndex; }
    311   void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; }
    312 
    313   unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; }
    314   void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; }
    315 
    316   int getVarArgsFPRIndex() const { return VarArgsFPRIndex; }
    317   void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; }
    318 
    319   unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; }
    320   void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; }
    321 
    322   unsigned getSRetReturnReg() const { return SRetReturnReg; }
    323   void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; }
    324 
    325   unsigned getJumpTableEntrySize(int Idx) const {
    326     return JumpTableEntryInfo[Idx].first;
    327   }
    328   MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const {
    329     return JumpTableEntryInfo[Idx].second;
    330   }
    331   void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) {
    332     if ((unsigned)Idx >= JumpTableEntryInfo.size())
    333       JumpTableEntryInfo.resize(Idx+1);
    334     JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym);
    335   }
    336 
    337   using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>;
    338 
    339   const SetOfInstructions &getLOHRelated() const { return LOHRelated; }
    340 
    341   // Shortcuts for LOH related types.
    342   class MILOHDirective {
    343     MCLOHType Kind;
    344 
    345     /// Arguments of this directive. Order matters.
    346     SmallVector<const MachineInstr *, 3> Args;
    347 
    348   public:
    349     using LOHArgs = ArrayRef<const MachineInstr *>;
    350 
    351     MILOHDirective(MCLOHType Kind, LOHArgs Args)
    352         : Kind(Kind), Args(Args.begin(), Args.end()) {
    353       assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!");
    354     }
    355 
    356     MCLOHType getKind() const { return Kind; }
    357     LOHArgs getArgs() const { return Args; }
    358   };
    359 
    360   using MILOHArgs = MILOHDirective::LOHArgs;
    361   using MILOHContainer = SmallVector<MILOHDirective, 32>;
    362 
    363   const MILOHContainer &getLOHContainer() const { return LOHContainerSet; }
    364 
    365   /// Add a LOH directive of this @p Kind and this @p Args.
    366   void addLOHDirective(MCLOHType Kind, MILOHArgs Args) {
    367     LOHContainerSet.push_back(MILOHDirective(Kind, Args));
    368     LOHRelated.insert(Args.begin(), Args.end());
    369   }
    370 
    371   SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() {
    372     return ForwardedMustTailRegParms;
    373   }
    374 
    375   Optional<int> getTaggedBasePointerIndex() const {
    376     return TaggedBasePointerIndex;
    377   }
    378   void setTaggedBasePointerIndex(int Index) { TaggedBasePointerIndex = Index; }
    379 
    380   unsigned getTaggedBasePointerOffset() const {
    381     return TaggedBasePointerOffset;
    382   }
    383   void setTaggedBasePointerOffset(unsigned Offset) {
    384     TaggedBasePointerOffset = Offset;
    385   }
    386 
    387   int getCalleeSaveBaseToFrameRecordOffset() const {
    388     return CalleeSaveBaseToFrameRecordOffset;
    389   }
    390   void setCalleeSaveBaseToFrameRecordOffset(int Offset) {
    391     CalleeSaveBaseToFrameRecordOffset = Offset;
    392   }
    393 
    394   bool shouldSignReturnAddress() const;
    395   bool shouldSignReturnAddress(bool SpillsLR) const;
    396 
    397   bool shouldSignWithBKey() const { return SignWithBKey; }
    398 
    399   bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
    400 
    401   void setHasSwiftAsyncContext(bool HasContext) {
    402     HasSwiftAsyncContext = HasContext;
    403   }
    404   bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; }
    405 
    406   void setSwiftAsyncContextFrameIdx(int FI) {
    407     SwiftAsyncContextFrameIdx = FI;
    408   }
    409   int getSwiftAsyncContextFrameIdx() const { return SwiftAsyncContextFrameIdx; }
    410 
    411 private:
    412   // Hold the lists of LOHs.
    413   MILOHContainer LOHContainerSet;
    414   SetOfInstructions LOHRelated;
    415 
    416   SmallVector<std::pair<unsigned, MCSymbol *>, 2> JumpTableEntryInfo;
    417 };
    418 
    419 namespace yaml {
    420 struct AArch64FunctionInfo final : public yaml::MachineFunctionInfo {
    421   Optional<bool> HasRedZone;
    422 
    423   AArch64FunctionInfo() = default;
    424   AArch64FunctionInfo(const llvm::AArch64FunctionInfo &MFI);
    425 
    426   void mappingImpl(yaml::IO &YamlIO) override;
    427   ~AArch64FunctionInfo() = default;
    428 };
    429 
    430 template <> struct MappingTraits<AArch64FunctionInfo> {
    431   static void mapping(IO &YamlIO, AArch64FunctionInfo &MFI) {
    432     YamlIO.mapOptional("hasRedZone", MFI.HasRedZone);
    433   }
    434 };
    435 
    436 } // end namespace yaml
    437 
    438 } // end namespace llvm
    439 
    440 #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H
    441