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