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