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/MachineFunction.h" 22 #include "llvm/CodeGen/TargetFrameLowering.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/MC/MCLinkerOptimizationHint.h" 25 #include <cassert> 26 27 namespace llvm { 28 29 class MachineInstr; 30 31 /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and 32 /// contains private AArch64-specific information for each MachineFunction. 33 class AArch64FunctionInfo final : public MachineFunctionInfo { 34 /// Number of bytes of arguments this function has on the stack. If the callee 35 /// is expected to restore the argument stack this should be a multiple of 16, 36 /// all usable during a tail call. 37 /// 38 /// The alternative would forbid tail call optimisation in some cases: if we 39 /// want to transfer control from a function with 8-bytes of stack-argument 40 /// space to a function with 16-bytes then misalignment of this value would 41 /// make a stack adjustment necessary, which could not be undone by the 42 /// callee. 43 unsigned BytesInStackArgArea = 0; 44 45 /// The number of bytes to restore to deallocate space for incoming 46 /// arguments. Canonically 0 in the C calling convention, but non-zero when 47 /// callee is expected to pop the args. 48 unsigned ArgumentStackToRestore = 0; 49 50 /// HasStackFrame - True if this function has a stack frame. Set by 51 /// determineCalleeSaves(). 52 bool HasStackFrame = false; 53 54 /// Amount of stack frame size, not including callee-saved registers. 55 uint64_t LocalStackSize = 0; 56 57 /// The start and end frame indices for the SVE callee saves. 58 int MinSVECSFrameIndex = 0; 59 int MaxSVECSFrameIndex = 0; 60 61 /// Amount of stack frame size used for saving callee-saved registers. 62 unsigned CalleeSavedStackSize = 0; 63 unsigned SVECalleeSavedStackSize = 0; 64 bool HasCalleeSavedStackSize = false; 65 66 /// Number of TLS accesses using the special (combinable) 67 /// _TLS_MODULE_BASE_ symbol. 68 unsigned NumLocalDynamicTLSAccesses = 0; 69 70 /// FrameIndex for start of varargs area for arguments passed on the 71 /// stack. 72 int VarArgsStackIndex = 0; 73 74 /// FrameIndex for start of varargs area for arguments passed in 75 /// general purpose registers. 76 int VarArgsGPRIndex = 0; 77 78 /// Size of the varargs area for arguments passed in general purpose 79 /// registers. 80 unsigned VarArgsGPRSize = 0; 81 82 /// FrameIndex for start of varargs area for arguments passed in 83 /// floating-point registers. 84 int VarArgsFPRIndex = 0; 85 86 /// Size of the varargs area for arguments passed in floating-point 87 /// registers. 88 unsigned VarArgsFPRSize = 0; 89 90 /// True if this function has a subset of CSRs that is handled explicitly via 91 /// copies. 92 bool IsSplitCSR = false; 93 94 /// True when the stack gets realigned dynamically because the size of stack 95 /// frame is unknown at compile time. e.g., in case of VLAs. 96 bool StackRealigned = false; 97 98 /// True when the callee-save stack area has unused gaps that may be used for 99 /// other stack allocations. 100 bool CalleeSaveStackHasFreeSpace = false; 101 102 /// SRetReturnReg - sret lowering includes returning the value of the 103 /// returned struct in a register. This field holds the virtual register into 104 /// which the sret argument is passed. 105 unsigned SRetReturnReg = 0; 106 /// SVE stack size (for predicates and data vectors) are maintained here 107 /// rather than in FrameInfo, as the placement and Stack IDs are target 108 /// specific. 109 uint64_t StackSizeSVE = 0; 110 111 /// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid. 112 bool HasCalculatedStackSizeSVE = false; 113 114 /// Has a value when it is known whether or not the function uses a 115 /// redzone, and no value otherwise. 116 /// Initialized during frame lowering, unless the function has the noredzone 117 /// attribute, in which case it is set to false at construction. 118 Optional<bool> HasRedZone; 119 120 /// ForwardedMustTailRegParms - A list of virtual and physical registers 121 /// that must be forwarded to every musttail call. 122 SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms; 123 124 // Offset from SP-at-entry to the tagged base pointer. 125 // Tagged base pointer is set up to point to the first (lowest address) tagged 126 // stack slot. 127 unsigned TaggedBasePointerOffset = 0; 128 129 public: 130 AArch64FunctionInfo() = default; 131 AArch64FunctionInfo(MachineFunction & MF)132 explicit AArch64FunctionInfo(MachineFunction &MF) { 133 (void)MF; 134 135 // If we already know that the function doesn't have a redzone, set 136 // HasRedZone here. 137 if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) 138 HasRedZone = false; 139 } 140 getBytesInStackArgArea()141 unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } setBytesInStackArgArea(unsigned bytes)142 void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } 143 getArgumentStackToRestore()144 unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; } setArgumentStackToRestore(unsigned bytes)145 void setArgumentStackToRestore(unsigned bytes) { 146 ArgumentStackToRestore = bytes; 147 } 148 hasCalculatedStackSizeSVE()149 bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; } 150 setStackSizeSVE(uint64_t S)151 void setStackSizeSVE(uint64_t S) { 152 HasCalculatedStackSizeSVE = true; 153 StackSizeSVE = S; 154 } 155 getStackSizeSVE()156 uint64_t getStackSizeSVE() const { return StackSizeSVE; } 157 hasStackFrame()158 bool hasStackFrame() const { return HasStackFrame; } setHasStackFrame(bool s)159 void setHasStackFrame(bool s) { HasStackFrame = s; } 160 isStackRealigned()161 bool isStackRealigned() const { return StackRealigned; } setStackRealigned(bool s)162 void setStackRealigned(bool s) { StackRealigned = s; } 163 hasCalleeSaveStackFreeSpace()164 bool hasCalleeSaveStackFreeSpace() const { 165 return CalleeSaveStackHasFreeSpace; 166 } setCalleeSaveStackHasFreeSpace(bool s)167 void setCalleeSaveStackHasFreeSpace(bool s) { 168 CalleeSaveStackHasFreeSpace = s; 169 } isSplitCSR()170 bool isSplitCSR() const { return IsSplitCSR; } setIsSplitCSR(bool s)171 void setIsSplitCSR(bool s) { IsSplitCSR = s; } 172 setLocalStackSize(uint64_t Size)173 void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; } getLocalStackSize()174 uint64_t getLocalStackSize() const { return LocalStackSize; } 175 setCalleeSavedStackSize(unsigned Size)176 void setCalleeSavedStackSize(unsigned Size) { 177 CalleeSavedStackSize = Size; 178 HasCalleeSavedStackSize = true; 179 } 180 181 // When CalleeSavedStackSize has not been set (for example when 182 // some MachineIR pass is run in isolation), then recalculate 183 // the CalleeSavedStackSize directly from the CalleeSavedInfo. 184 // Note: This information can only be recalculated after PEI 185 // has assigned offsets to the callee save objects. getCalleeSavedStackSize(const MachineFrameInfo & MFI)186 unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const { 187 bool ValidateCalleeSavedStackSize = false; 188 189 #ifndef NDEBUG 190 // Make sure the calculated size derived from the CalleeSavedInfo 191 // equals the cached size that was calculated elsewhere (e.g. in 192 // determineCalleeSaves). 193 ValidateCalleeSavedStackSize = HasCalleeSavedStackSize; 194 #endif 195 196 if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) { 197 assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated"); 198 if (MFI.getCalleeSavedInfo().empty()) 199 return 0; 200 201 int64_t MinOffset = std::numeric_limits<int64_t>::max(); 202 int64_t MaxOffset = std::numeric_limits<int64_t>::min(); 203 for (const auto &Info : MFI.getCalleeSavedInfo()) { 204 int FrameIdx = Info.getFrameIdx(); 205 if (MFI.getStackID(FrameIdx) != TargetStackID::Default) 206 continue; 207 int64_t Offset = MFI.getObjectOffset(FrameIdx); 208 int64_t ObjSize = MFI.getObjectSize(FrameIdx); 209 MinOffset = std::min<int64_t>(Offset, MinOffset); 210 MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset); 211 } 212 213 unsigned Size = alignTo(MaxOffset - MinOffset, 16); 214 assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) && 215 "Invalid size calculated for callee saves"); 216 return Size; 217 } 218 219 return getCalleeSavedStackSize(); 220 } 221 getCalleeSavedStackSize()222 unsigned getCalleeSavedStackSize() const { 223 assert(HasCalleeSavedStackSize && 224 "CalleeSavedStackSize has not been calculated"); 225 return CalleeSavedStackSize; 226 } 227 228 // Saves the CalleeSavedStackSize for SVE vectors in 'scalable bytes' setSVECalleeSavedStackSize(unsigned Size)229 void setSVECalleeSavedStackSize(unsigned Size) { 230 SVECalleeSavedStackSize = Size; 231 } getSVECalleeSavedStackSize()232 unsigned getSVECalleeSavedStackSize() const { 233 return SVECalleeSavedStackSize; 234 } 235 setMinMaxSVECSFrameIndex(int Min,int Max)236 void setMinMaxSVECSFrameIndex(int Min, int Max) { 237 MinSVECSFrameIndex = Min; 238 MaxSVECSFrameIndex = Max; 239 } 240 getMinSVECSFrameIndex()241 int getMinSVECSFrameIndex() const { return MinSVECSFrameIndex; } getMaxSVECSFrameIndex()242 int getMaxSVECSFrameIndex() const { return MaxSVECSFrameIndex; } 243 incNumLocalDynamicTLSAccesses()244 void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; } getNumLocalDynamicTLSAccesses()245 unsigned getNumLocalDynamicTLSAccesses() const { 246 return NumLocalDynamicTLSAccesses; 247 } 248 hasRedZone()249 Optional<bool> hasRedZone() const { return HasRedZone; } setHasRedZone(bool s)250 void setHasRedZone(bool s) { HasRedZone = s; } 251 getVarArgsStackIndex()252 int getVarArgsStackIndex() const { return VarArgsStackIndex; } setVarArgsStackIndex(int Index)253 void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; } 254 getVarArgsGPRIndex()255 int getVarArgsGPRIndex() const { return VarArgsGPRIndex; } setVarArgsGPRIndex(int Index)256 void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; } 257 getVarArgsGPRSize()258 unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; } setVarArgsGPRSize(unsigned Size)259 void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; } 260 getVarArgsFPRIndex()261 int getVarArgsFPRIndex() const { return VarArgsFPRIndex; } setVarArgsFPRIndex(int Index)262 void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; } 263 getVarArgsFPRSize()264 unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; } setVarArgsFPRSize(unsigned Size)265 void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; } 266 getSRetReturnReg()267 unsigned getSRetReturnReg() const { return SRetReturnReg; } setSRetReturnReg(unsigned Reg)268 void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } 269 getJumpTableEntrySize(int Idx)270 unsigned getJumpTableEntrySize(int Idx) const { 271 auto It = JumpTableEntryInfo.find(Idx); 272 if (It != JumpTableEntryInfo.end()) 273 return It->second.first; 274 return 4; 275 } getJumpTableEntryPCRelSymbol(int Idx)276 MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const { 277 return JumpTableEntryInfo.find(Idx)->second.second; 278 } setJumpTableEntryInfo(int Idx,unsigned Size,MCSymbol * PCRelSym)279 void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) { 280 JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym); 281 } 282 283 using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>; 284 getLOHRelated()285 const SetOfInstructions &getLOHRelated() const { return LOHRelated; } 286 287 // Shortcuts for LOH related types. 288 class MILOHDirective { 289 MCLOHType Kind; 290 291 /// Arguments of this directive. Order matters. 292 SmallVector<const MachineInstr *, 3> Args; 293 294 public: 295 using LOHArgs = ArrayRef<const MachineInstr *>; 296 MILOHDirective(MCLOHType Kind,LOHArgs Args)297 MILOHDirective(MCLOHType Kind, LOHArgs Args) 298 : Kind(Kind), Args(Args.begin(), Args.end()) { 299 assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 300 } 301 getKind()302 MCLOHType getKind() const { return Kind; } getArgs()303 LOHArgs getArgs() const { return Args; } 304 }; 305 306 using MILOHArgs = MILOHDirective::LOHArgs; 307 using MILOHContainer = SmallVector<MILOHDirective, 32>; 308 getLOHContainer()309 const MILOHContainer &getLOHContainer() const { return LOHContainerSet; } 310 311 /// Add a LOH directive of this @p Kind and this @p Args. addLOHDirective(MCLOHType Kind,MILOHArgs Args)312 void addLOHDirective(MCLOHType Kind, MILOHArgs Args) { 313 LOHContainerSet.push_back(MILOHDirective(Kind, Args)); 314 LOHRelated.insert(Args.begin(), Args.end()); 315 } 316 getForwardedMustTailRegParms()317 SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() { 318 return ForwardedMustTailRegParms; 319 } 320 getTaggedBasePointerOffset()321 unsigned getTaggedBasePointerOffset() const { 322 return TaggedBasePointerOffset; 323 } setTaggedBasePointerOffset(unsigned Offset)324 void setTaggedBasePointerOffset(unsigned Offset) { 325 TaggedBasePointerOffset = Offset; 326 } 327 328 private: 329 // Hold the lists of LOHs. 330 MILOHContainer LOHContainerSet; 331 SetOfInstructions LOHRelated; 332 333 DenseMap<int, std::pair<unsigned, MCSymbol *>> JumpTableEntryInfo; 334 }; 335 336 } // end namespace llvm 337 338 #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 339