10b57cec5SDimitry Andric //=- AArch64MachineFunctionInfo.h - AArch64 machine function info -*- C++ -*-=// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file declares AArch64-specific per-machine-function information. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 150b57cec5SDimitry Andric 16*0fca6ea1SDimitry Andric #include "AArch64Subtarget.h" 170b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 215ffd83dbSDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h" 2281ad6265SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 248bcb0991SDimitry Andric #include "llvm/IR/Function.h" 250b57cec5SDimitry Andric #include "llvm/MC/MCLinkerOptimizationHint.h" 26cb14a3feSDimitry Andric #include "llvm/MC/MCSymbol.h" 270b57cec5SDimitry Andric #include <cassert> 28bdd1243dSDimitry Andric #include <optional> 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric namespace llvm { 310b57cec5SDimitry Andric 325ffd83dbSDimitry Andric namespace yaml { 335ffd83dbSDimitry Andric struct AArch64FunctionInfo; 345ffd83dbSDimitry Andric } // end namespace yaml 355ffd83dbSDimitry Andric 36bdd1243dSDimitry Andric class AArch64Subtarget; 370b57cec5SDimitry Andric class MachineInstr; 380b57cec5SDimitry Andric 39*0fca6ea1SDimitry Andric struct TPIDR2Object { 40*0fca6ea1SDimitry Andric int FrameIndex = std::numeric_limits<int>::max(); 41*0fca6ea1SDimitry Andric unsigned Uses = 0; 42*0fca6ea1SDimitry Andric }; 43*0fca6ea1SDimitry Andric 440b57cec5SDimitry Andric /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and 450b57cec5SDimitry Andric /// contains private AArch64-specific information for each MachineFunction. 460b57cec5SDimitry Andric class AArch64FunctionInfo final : public MachineFunctionInfo { 470b57cec5SDimitry Andric /// Number of bytes of arguments this function has on the stack. If the callee 480b57cec5SDimitry Andric /// is expected to restore the argument stack this should be a multiple of 16, 490b57cec5SDimitry Andric /// all usable during a tail call. 500b57cec5SDimitry Andric /// 510b57cec5SDimitry Andric /// The alternative would forbid tail call optimisation in some cases: if we 520b57cec5SDimitry Andric /// want to transfer control from a function with 8-bytes of stack-argument 530b57cec5SDimitry Andric /// space to a function with 16-bytes then misalignment of this value would 540b57cec5SDimitry Andric /// make a stack adjustment necessary, which could not be undone by the 550b57cec5SDimitry Andric /// callee. 560b57cec5SDimitry Andric unsigned BytesInStackArgArea = 0; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric /// The number of bytes to restore to deallocate space for incoming 590b57cec5SDimitry Andric /// arguments. Canonically 0 in the C calling convention, but non-zero when 600b57cec5SDimitry Andric /// callee is expected to pop the args. 610b57cec5SDimitry Andric unsigned ArgumentStackToRestore = 0; 620b57cec5SDimitry Andric 63fe6060f1SDimitry Andric /// Space just below incoming stack pointer reserved for arguments being 64fe6060f1SDimitry Andric /// passed on the stack during a tail call. This will be the difference 65fe6060f1SDimitry Andric /// between the largest tail call argument space needed in this function and 66fe6060f1SDimitry Andric /// what's already available by reusing space of incoming arguments. 67fe6060f1SDimitry Andric unsigned TailCallReservedStack = 0; 68fe6060f1SDimitry Andric 690b57cec5SDimitry Andric /// HasStackFrame - True if this function has a stack frame. Set by 700b57cec5SDimitry Andric /// determineCalleeSaves(). 710b57cec5SDimitry Andric bool HasStackFrame = false; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric /// Amount of stack frame size, not including callee-saved registers. 74480093f4SDimitry Andric uint64_t LocalStackSize = 0; 75480093f4SDimitry Andric 76480093f4SDimitry Andric /// The start and end frame indices for the SVE callee saves. 77480093f4SDimitry Andric int MinSVECSFrameIndex = 0; 78480093f4SDimitry Andric int MaxSVECSFrameIndex = 0; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric /// Amount of stack frame size used for saving callee-saved registers. 81480093f4SDimitry Andric unsigned CalleeSavedStackSize = 0; 82480093f4SDimitry Andric unsigned SVECalleeSavedStackSize = 0; 83480093f4SDimitry Andric bool HasCalleeSavedStackSize = false; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric /// Number of TLS accesses using the special (combinable) 860b57cec5SDimitry Andric /// _TLS_MODULE_BASE_ symbol. 870b57cec5SDimitry Andric unsigned NumLocalDynamicTLSAccesses = 0; 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed on the 900b57cec5SDimitry Andric /// stack. 910b57cec5SDimitry Andric int VarArgsStackIndex = 0; 920b57cec5SDimitry Andric 93bdd1243dSDimitry Andric /// Offset of start of varargs area for arguments passed on the stack. 94bdd1243dSDimitry Andric unsigned VarArgsStackOffset = 0; 95bdd1243dSDimitry Andric 960b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 970b57cec5SDimitry Andric /// general purpose registers. 980b57cec5SDimitry Andric int VarArgsGPRIndex = 0; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in general purpose 1010b57cec5SDimitry Andric /// registers. 1020b57cec5SDimitry Andric unsigned VarArgsGPRSize = 0; 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 1050b57cec5SDimitry Andric /// floating-point registers. 1060b57cec5SDimitry Andric int VarArgsFPRIndex = 0; 1070b57cec5SDimitry Andric 1080b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in floating-point 1090b57cec5SDimitry Andric /// registers. 1100b57cec5SDimitry Andric unsigned VarArgsFPRSize = 0; 1110b57cec5SDimitry Andric 112*0fca6ea1SDimitry Andric /// The stack slots used to add space between FPR and GPR accesses when using 113*0fca6ea1SDimitry Andric /// hazard padding. StackHazardCSRSlotIndex is added between GPR and FPR CSRs. 114*0fca6ea1SDimitry Andric /// StackHazardSlotIndex is added between (sorted) stack objects. 115*0fca6ea1SDimitry Andric int StackHazardSlotIndex = std::numeric_limits<int>::max(); 116*0fca6ea1SDimitry Andric int StackHazardCSRSlotIndex = std::numeric_limits<int>::max(); 117*0fca6ea1SDimitry Andric 1180b57cec5SDimitry Andric /// True if this function has a subset of CSRs that is handled explicitly via 1190b57cec5SDimitry Andric /// copies. 1200b57cec5SDimitry Andric bool IsSplitCSR = false; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric /// True when the stack gets realigned dynamically because the size of stack 1230b57cec5SDimitry Andric /// frame is unknown at compile time. e.g., in case of VLAs. 1240b57cec5SDimitry Andric bool StackRealigned = false; 1250b57cec5SDimitry Andric 1260b57cec5SDimitry Andric /// True when the callee-save stack area has unused gaps that may be used for 1270b57cec5SDimitry Andric /// other stack allocations. 1280b57cec5SDimitry Andric bool CalleeSaveStackHasFreeSpace = false; 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric /// SRetReturnReg - sret lowering includes returning the value of the 1310b57cec5SDimitry Andric /// returned struct in a register. This field holds the virtual register into 1320b57cec5SDimitry Andric /// which the sret argument is passed. 13381ad6265SDimitry Andric Register SRetReturnReg; 13481ad6265SDimitry Andric 1358bcb0991SDimitry Andric /// SVE stack size (for predicates and data vectors) are maintained here 1368bcb0991SDimitry Andric /// rather than in FrameInfo, as the placement and Stack IDs are target 1378bcb0991SDimitry Andric /// specific. 1388bcb0991SDimitry Andric uint64_t StackSizeSVE = 0; 1398bcb0991SDimitry Andric 1408bcb0991SDimitry Andric /// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid. 1418bcb0991SDimitry Andric bool HasCalculatedStackSizeSVE = false; 1420b57cec5SDimitry Andric 1430b57cec5SDimitry Andric /// Has a value when it is known whether or not the function uses a 1440b57cec5SDimitry Andric /// redzone, and no value otherwise. 1450b57cec5SDimitry Andric /// Initialized during frame lowering, unless the function has the noredzone 1460b57cec5SDimitry Andric /// attribute, in which case it is set to false at construction. 147bdd1243dSDimitry Andric std::optional<bool> HasRedZone; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric /// ForwardedMustTailRegParms - A list of virtual and physical registers 1500b57cec5SDimitry Andric /// that must be forwarded to every musttail call. 1510b57cec5SDimitry Andric SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms; 1520b57cec5SDimitry Andric 153e8d8bef9SDimitry Andric /// FrameIndex for the tagged base pointer. 154bdd1243dSDimitry Andric std::optional<int> TaggedBasePointerIndex; 155e8d8bef9SDimitry Andric 156e8d8bef9SDimitry Andric /// Offset from SP-at-entry to the tagged base pointer. 157e8d8bef9SDimitry Andric /// Tagged base pointer is set up to point to the first (lowest address) 158e8d8bef9SDimitry Andric /// tagged stack slot. 159e8d8bef9SDimitry Andric unsigned TaggedBasePointerOffset; 1600b57cec5SDimitry Andric 1615ffd83dbSDimitry Andric /// OutliningStyle denotes, if a function was outined, how it was outlined, 1625ffd83dbSDimitry Andric /// e.g. Tail Call, Thunk, or Function if none apply. 163bdd1243dSDimitry Andric std::optional<std::string> OutliningStyle; 1645ffd83dbSDimitry Andric 165e8d8bef9SDimitry Andric // Offset from SP-after-callee-saved-spills (i.e. SP-at-entry minus 166e8d8bef9SDimitry Andric // CalleeSavedStackSize) to the address of the frame record. 167e8d8bef9SDimitry Andric int CalleeSaveBaseToFrameRecordOffset = 0; 168e8d8bef9SDimitry Andric 169e8d8bef9SDimitry Andric /// SignReturnAddress is true if PAC-RET is enabled for the function with 170e8d8bef9SDimitry Andric /// defaults being sign non-leaf functions only, with the B key. 171e8d8bef9SDimitry Andric bool SignReturnAddress = false; 172e8d8bef9SDimitry Andric 173e8d8bef9SDimitry Andric /// SignReturnAddressAll modifies the default PAC-RET mode to signing leaf 174e8d8bef9SDimitry Andric /// functions as well. 175e8d8bef9SDimitry Andric bool SignReturnAddressAll = false; 176e8d8bef9SDimitry Andric 177e8d8bef9SDimitry Andric /// SignWithBKey modifies the default PAC-RET mode to signing with the B key. 178e8d8bef9SDimitry Andric bool SignWithBKey = false; 179e8d8bef9SDimitry Andric 180cb14a3feSDimitry Andric /// SigningInstrOffset captures the offset of the PAC-RET signing instruction 181cb14a3feSDimitry Andric /// within the prologue, so it can be re-used for authentication in the 182cb14a3feSDimitry Andric /// epilogue when using PC as a second salt (FEAT_PAuth_LR) 183cb14a3feSDimitry Andric MCSymbol *SignInstrLabel = nullptr; 184cb14a3feSDimitry Andric 185e8d8bef9SDimitry Andric /// BranchTargetEnforcement enables placing BTI instructions at potential 186e8d8bef9SDimitry Andric /// indirect branch destinations. 187e8d8bef9SDimitry Andric bool BranchTargetEnforcement = false; 188e8d8bef9SDimitry Andric 189cb14a3feSDimitry Andric /// Indicates that SP signing should be diversified with PC as-per PAuthLR. 190cb14a3feSDimitry Andric /// This is set by -mbranch-protection and will emit NOP instructions unless 191cb14a3feSDimitry Andric /// the subtarget feature +pauthlr is also used (in which case non-NOP 192cb14a3feSDimitry Andric /// instructions are emitted). 193cb14a3feSDimitry Andric bool BranchProtectionPAuthLR = false; 194cb14a3feSDimitry Andric 195fe6060f1SDimitry Andric /// Whether this function has an extended frame record [Ctx, FP, LR]. If so, 196fe6060f1SDimitry Andric /// bit 60 of the in-memory FP will be 1 to enable other tools to detect the 197fe6060f1SDimitry Andric /// extended record. 198fe6060f1SDimitry Andric bool HasSwiftAsyncContext = false; 199fe6060f1SDimitry Andric 200fe6060f1SDimitry Andric /// The stack slot where the Swift asynchronous context is stored. 201fe6060f1SDimitry Andric int SwiftAsyncContextFrameIdx = std::numeric_limits<int>::max(); 202fe6060f1SDimitry Andric 20381ad6265SDimitry Andric bool IsMTETagged = false; 20481ad6265SDimitry Andric 20581ad6265SDimitry Andric /// The function has Scalable Vector or Scalable Predicate register argument 20681ad6265SDimitry Andric /// or return type 20781ad6265SDimitry Andric bool IsSVECC = false; 20881ad6265SDimitry Andric 209bdd1243dSDimitry Andric /// The frame-index for the TPIDR2 object used for lazy saves. 210*0fca6ea1SDimitry Andric TPIDR2Object TPIDR2; 211bdd1243dSDimitry Andric 2125f757f3fSDimitry Andric /// Whether this function changes streaming mode within the function. 2135f757f3fSDimitry Andric bool HasStreamingModeChanges = false; 214bdd1243dSDimitry Andric 21581ad6265SDimitry Andric /// True if the function need unwind information. 216bdd1243dSDimitry Andric mutable std::optional<bool> NeedsDwarfUnwindInfo; 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric /// True if the function need asynchronous unwind information. 219bdd1243dSDimitry Andric mutable std::optional<bool> NeedsAsyncDwarfUnwindInfo; 22081ad6265SDimitry Andric 2215f757f3fSDimitry Andric int64_t StackProbeSize = 0; 2225f757f3fSDimitry Andric 2237a6dacacSDimitry Andric // Holds a register containing pstate.sm. This is set 2247a6dacacSDimitry Andric // on function entry to record the initial pstate of a function. 2257a6dacacSDimitry Andric Register PStateSMReg = MCRegister::NoRegister; 2267a6dacacSDimitry Andric 227*0fca6ea1SDimitry Andric // Has the PNReg used to build PTRUE instruction. 228*0fca6ea1SDimitry Andric // The PTRUE is used for the LD/ST of ZReg pairs in save and restore. 229*0fca6ea1SDimitry Andric unsigned PredicateRegForFillSpill = 0; 230*0fca6ea1SDimitry Andric 231*0fca6ea1SDimitry Andric // The stack slots where VG values are stored to. 232*0fca6ea1SDimitry Andric int64_t VGIdx = std::numeric_limits<int>::max(); 233*0fca6ea1SDimitry Andric int64_t StreamingVGIdx = std::numeric_limits<int>::max(); 234*0fca6ea1SDimitry Andric 2350b57cec5SDimitry Andric public: 236bdd1243dSDimitry Andric AArch64FunctionInfo(const Function &F, const AArch64Subtarget *STI); 2370b57cec5SDimitry Andric 23881ad6265SDimitry Andric MachineFunctionInfo * 23981ad6265SDimitry Andric clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, 24081ad6265SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 24181ad6265SDimitry Andric const override; 24281ad6265SDimitry Andric 243*0fca6ea1SDimitry Andric void setPredicateRegForFillSpill(unsigned Reg) { 244*0fca6ea1SDimitry Andric PredicateRegForFillSpill = Reg; 245*0fca6ea1SDimitry Andric } 246*0fca6ea1SDimitry Andric unsigned getPredicateRegForFillSpill() const { 247*0fca6ea1SDimitry Andric return PredicateRegForFillSpill; 248*0fca6ea1SDimitry Andric } 249*0fca6ea1SDimitry Andric 2507a6dacacSDimitry Andric Register getPStateSMReg() const { return PStateSMReg; }; 2517a6dacacSDimitry Andric void setPStateSMReg(Register Reg) { PStateSMReg = Reg; }; 2527a6dacacSDimitry Andric 253*0fca6ea1SDimitry Andric int64_t getVGIdx() const { return VGIdx; }; 254*0fca6ea1SDimitry Andric void setVGIdx(unsigned Idx) { VGIdx = Idx; }; 255*0fca6ea1SDimitry Andric 256*0fca6ea1SDimitry Andric int64_t getStreamingVGIdx() const { return StreamingVGIdx; }; 257*0fca6ea1SDimitry Andric void setStreamingVGIdx(unsigned FrameIdx) { StreamingVGIdx = FrameIdx; }; 258*0fca6ea1SDimitry Andric 25981ad6265SDimitry Andric bool isSVECC() const { return IsSVECC; }; 26081ad6265SDimitry Andric void setIsSVECC(bool s) { IsSVECC = s; }; 26181ad6265SDimitry Andric 262*0fca6ea1SDimitry Andric TPIDR2Object &getTPIDR2Obj() { return TPIDR2; } 263bdd1243dSDimitry Andric 2645ffd83dbSDimitry Andric void initializeBaseYamlFields(const yaml::AArch64FunctionInfo &YamlMFI); 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } 2670b57cec5SDimitry Andric void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } 2680b57cec5SDimitry Andric 2690b57cec5SDimitry Andric unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; } 2700b57cec5SDimitry Andric void setArgumentStackToRestore(unsigned bytes) { 2710b57cec5SDimitry Andric ArgumentStackToRestore = bytes; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric 274fe6060f1SDimitry Andric unsigned getTailCallReservedStack() const { return TailCallReservedStack; } 275fe6060f1SDimitry Andric void setTailCallReservedStack(unsigned bytes) { 276fe6060f1SDimitry Andric TailCallReservedStack = bytes; 277fe6060f1SDimitry Andric } 278fe6060f1SDimitry Andric 2798bcb0991SDimitry Andric bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; } 2808bcb0991SDimitry Andric 2818bcb0991SDimitry Andric void setStackSizeSVE(uint64_t S) { 2828bcb0991SDimitry Andric HasCalculatedStackSizeSVE = true; 2838bcb0991SDimitry Andric StackSizeSVE = S; 2848bcb0991SDimitry Andric } 2858bcb0991SDimitry Andric 2868bcb0991SDimitry Andric uint64_t getStackSizeSVE() const { return StackSizeSVE; } 2878bcb0991SDimitry Andric 2880b57cec5SDimitry Andric bool hasStackFrame() const { return HasStackFrame; } 2890b57cec5SDimitry Andric void setHasStackFrame(bool s) { HasStackFrame = s; } 2900b57cec5SDimitry Andric 2910b57cec5SDimitry Andric bool isStackRealigned() const { return StackRealigned; } 2920b57cec5SDimitry Andric void setStackRealigned(bool s) { StackRealigned = s; } 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric bool hasCalleeSaveStackFreeSpace() const { 2950b57cec5SDimitry Andric return CalleeSaveStackHasFreeSpace; 2960b57cec5SDimitry Andric } 2970b57cec5SDimitry Andric void setCalleeSaveStackHasFreeSpace(bool s) { 2980b57cec5SDimitry Andric CalleeSaveStackHasFreeSpace = s; 2990b57cec5SDimitry Andric } 3000b57cec5SDimitry Andric bool isSplitCSR() const { return IsSplitCSR; } 3010b57cec5SDimitry Andric void setIsSplitCSR(bool s) { IsSplitCSR = s; } 3020b57cec5SDimitry Andric 303480093f4SDimitry Andric void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; } 304480093f4SDimitry Andric uint64_t getLocalStackSize() const { return LocalStackSize; } 3050b57cec5SDimitry Andric 3065ffd83dbSDimitry Andric void setOutliningStyle(std::string Style) { OutliningStyle = Style; } 307bdd1243dSDimitry Andric std::optional<std::string> getOutliningStyle() const { 308bdd1243dSDimitry Andric return OutliningStyle; 309bdd1243dSDimitry Andric } 3105ffd83dbSDimitry Andric 311480093f4SDimitry Andric void setCalleeSavedStackSize(unsigned Size) { 312480093f4SDimitry Andric CalleeSavedStackSize = Size; 313480093f4SDimitry Andric HasCalleeSavedStackSize = true; 314480093f4SDimitry Andric } 315480093f4SDimitry Andric 316480093f4SDimitry Andric // When CalleeSavedStackSize has not been set (for example when 317480093f4SDimitry Andric // some MachineIR pass is run in isolation), then recalculate 318480093f4SDimitry Andric // the CalleeSavedStackSize directly from the CalleeSavedInfo. 319480093f4SDimitry Andric // Note: This information can only be recalculated after PEI 320480093f4SDimitry Andric // has assigned offsets to the callee save objects. 321480093f4SDimitry Andric unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const { 322480093f4SDimitry Andric bool ValidateCalleeSavedStackSize = false; 323480093f4SDimitry Andric 324480093f4SDimitry Andric #ifndef NDEBUG 325480093f4SDimitry Andric // Make sure the calculated size derived from the CalleeSavedInfo 326480093f4SDimitry Andric // equals the cached size that was calculated elsewhere (e.g. in 327480093f4SDimitry Andric // determineCalleeSaves). 328480093f4SDimitry Andric ValidateCalleeSavedStackSize = HasCalleeSavedStackSize; 329480093f4SDimitry Andric #endif 330480093f4SDimitry Andric 331480093f4SDimitry Andric if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) { 332480093f4SDimitry Andric assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated"); 333480093f4SDimitry Andric if (MFI.getCalleeSavedInfo().empty()) 334480093f4SDimitry Andric return 0; 335480093f4SDimitry Andric 336480093f4SDimitry Andric int64_t MinOffset = std::numeric_limits<int64_t>::max(); 337480093f4SDimitry Andric int64_t MaxOffset = std::numeric_limits<int64_t>::min(); 338480093f4SDimitry Andric for (const auto &Info : MFI.getCalleeSavedInfo()) { 339480093f4SDimitry Andric int FrameIdx = Info.getFrameIdx(); 340480093f4SDimitry Andric if (MFI.getStackID(FrameIdx) != TargetStackID::Default) 341480093f4SDimitry Andric continue; 342480093f4SDimitry Andric int64_t Offset = MFI.getObjectOffset(FrameIdx); 343480093f4SDimitry Andric int64_t ObjSize = MFI.getObjectSize(FrameIdx); 344480093f4SDimitry Andric MinOffset = std::min<int64_t>(Offset, MinOffset); 345480093f4SDimitry Andric MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset); 346480093f4SDimitry Andric } 347480093f4SDimitry Andric 348fe6060f1SDimitry Andric if (SwiftAsyncContextFrameIdx != std::numeric_limits<int>::max()) { 349fe6060f1SDimitry Andric int64_t Offset = MFI.getObjectOffset(getSwiftAsyncContextFrameIdx()); 350fe6060f1SDimitry Andric int64_t ObjSize = MFI.getObjectSize(getSwiftAsyncContextFrameIdx()); 351fe6060f1SDimitry Andric MinOffset = std::min<int64_t>(Offset, MinOffset); 352fe6060f1SDimitry Andric MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset); 353fe6060f1SDimitry Andric } 354fe6060f1SDimitry Andric 355*0fca6ea1SDimitry Andric if (StackHazardCSRSlotIndex != std::numeric_limits<int>::max()) { 356*0fca6ea1SDimitry Andric int64_t Offset = MFI.getObjectOffset(StackHazardCSRSlotIndex); 357*0fca6ea1SDimitry Andric int64_t ObjSize = MFI.getObjectSize(StackHazardCSRSlotIndex); 358*0fca6ea1SDimitry Andric MinOffset = std::min<int64_t>(Offset, MinOffset); 359*0fca6ea1SDimitry Andric MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset); 360*0fca6ea1SDimitry Andric } 361*0fca6ea1SDimitry Andric 362480093f4SDimitry Andric unsigned Size = alignTo(MaxOffset - MinOffset, 16); 363480093f4SDimitry Andric assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) && 364480093f4SDimitry Andric "Invalid size calculated for callee saves"); 365480093f4SDimitry Andric return Size; 366480093f4SDimitry Andric } 367480093f4SDimitry Andric 368480093f4SDimitry Andric return getCalleeSavedStackSize(); 369480093f4SDimitry Andric } 370480093f4SDimitry Andric 371480093f4SDimitry Andric unsigned getCalleeSavedStackSize() const { 372480093f4SDimitry Andric assert(HasCalleeSavedStackSize && 373480093f4SDimitry Andric "CalleeSavedStackSize has not been calculated"); 374480093f4SDimitry Andric return CalleeSavedStackSize; 375480093f4SDimitry Andric } 376480093f4SDimitry Andric 377480093f4SDimitry Andric // Saves the CalleeSavedStackSize for SVE vectors in 'scalable bytes' 378480093f4SDimitry Andric void setSVECalleeSavedStackSize(unsigned Size) { 379480093f4SDimitry Andric SVECalleeSavedStackSize = Size; 380480093f4SDimitry Andric } 381480093f4SDimitry Andric unsigned getSVECalleeSavedStackSize() const { 382480093f4SDimitry Andric return SVECalleeSavedStackSize; 383480093f4SDimitry Andric } 384480093f4SDimitry Andric 385480093f4SDimitry Andric void setMinMaxSVECSFrameIndex(int Min, int Max) { 386480093f4SDimitry Andric MinSVECSFrameIndex = Min; 387480093f4SDimitry Andric MaxSVECSFrameIndex = Max; 388480093f4SDimitry Andric } 389480093f4SDimitry Andric 390480093f4SDimitry Andric int getMinSVECSFrameIndex() const { return MinSVECSFrameIndex; } 391480093f4SDimitry Andric int getMaxSVECSFrameIndex() const { return MaxSVECSFrameIndex; } 3920b57cec5SDimitry Andric 3930b57cec5SDimitry Andric void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; } 3940b57cec5SDimitry Andric unsigned getNumLocalDynamicTLSAccesses() const { 3950b57cec5SDimitry Andric return NumLocalDynamicTLSAccesses; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 398bdd1243dSDimitry Andric std::optional<bool> hasRedZone() const { return HasRedZone; } 3990b57cec5SDimitry Andric void setHasRedZone(bool s) { HasRedZone = s; } 4000b57cec5SDimitry Andric 4010b57cec5SDimitry Andric int getVarArgsStackIndex() const { return VarArgsStackIndex; } 4020b57cec5SDimitry Andric void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; } 4030b57cec5SDimitry Andric 404bdd1243dSDimitry Andric unsigned getVarArgsStackOffset() const { return VarArgsStackOffset; } 405bdd1243dSDimitry Andric void setVarArgsStackOffset(unsigned Offset) { VarArgsStackOffset = Offset; } 406bdd1243dSDimitry Andric 4070b57cec5SDimitry Andric int getVarArgsGPRIndex() const { return VarArgsGPRIndex; } 4080b57cec5SDimitry Andric void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; } 4090b57cec5SDimitry Andric 4100b57cec5SDimitry Andric unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; } 4110b57cec5SDimitry Andric void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; } 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric int getVarArgsFPRIndex() const { return VarArgsFPRIndex; } 4140b57cec5SDimitry Andric void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; } 4170b57cec5SDimitry Andric void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; } 4180b57cec5SDimitry Andric 419*0fca6ea1SDimitry Andric bool hasStackHazardSlotIndex() const { 420*0fca6ea1SDimitry Andric return StackHazardSlotIndex != std::numeric_limits<int>::max(); 421*0fca6ea1SDimitry Andric } 422*0fca6ea1SDimitry Andric int getStackHazardSlotIndex() const { return StackHazardSlotIndex; } 423*0fca6ea1SDimitry Andric void setStackHazardSlotIndex(int Index) { 424*0fca6ea1SDimitry Andric assert(StackHazardSlotIndex == std::numeric_limits<int>::max()); 425*0fca6ea1SDimitry Andric StackHazardSlotIndex = Index; 426*0fca6ea1SDimitry Andric } 427*0fca6ea1SDimitry Andric int getStackHazardCSRSlotIndex() const { return StackHazardCSRSlotIndex; } 428*0fca6ea1SDimitry Andric void setStackHazardCSRSlotIndex(int Index) { 429*0fca6ea1SDimitry Andric assert(StackHazardCSRSlotIndex == std::numeric_limits<int>::max()); 430*0fca6ea1SDimitry Andric StackHazardCSRSlotIndex = Index; 431*0fca6ea1SDimitry Andric } 432*0fca6ea1SDimitry Andric 4330b57cec5SDimitry Andric unsigned getSRetReturnReg() const { return SRetReturnReg; } 4340b57cec5SDimitry Andric void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } 4350b57cec5SDimitry Andric 4360b57cec5SDimitry Andric unsigned getJumpTableEntrySize(int Idx) const { 437e8d8bef9SDimitry Andric return JumpTableEntryInfo[Idx].first; 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const { 440e8d8bef9SDimitry Andric return JumpTableEntryInfo[Idx].second; 4410b57cec5SDimitry Andric } 4420b57cec5SDimitry Andric void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) { 443e8d8bef9SDimitry Andric if ((unsigned)Idx >= JumpTableEntryInfo.size()) 444e8d8bef9SDimitry Andric JumpTableEntryInfo.resize(Idx+1); 4450b57cec5SDimitry Andric JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym); 4460b57cec5SDimitry Andric } 4470b57cec5SDimitry Andric 4480b57cec5SDimitry Andric using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>; 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric const SetOfInstructions &getLOHRelated() const { return LOHRelated; } 4510b57cec5SDimitry Andric 4520b57cec5SDimitry Andric // Shortcuts for LOH related types. 4530b57cec5SDimitry Andric class MILOHDirective { 4540b57cec5SDimitry Andric MCLOHType Kind; 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric /// Arguments of this directive. Order matters. 4570b57cec5SDimitry Andric SmallVector<const MachineInstr *, 3> Args; 4580b57cec5SDimitry Andric 4590b57cec5SDimitry Andric public: 4600b57cec5SDimitry Andric using LOHArgs = ArrayRef<const MachineInstr *>; 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric MILOHDirective(MCLOHType Kind, LOHArgs Args) 4630b57cec5SDimitry Andric : Kind(Kind), Args(Args.begin(), Args.end()) { 4640b57cec5SDimitry Andric assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 4650b57cec5SDimitry Andric } 4660b57cec5SDimitry Andric 4670b57cec5SDimitry Andric MCLOHType getKind() const { return Kind; } 4680b57cec5SDimitry Andric LOHArgs getArgs() const { return Args; } 4690b57cec5SDimitry Andric }; 4700b57cec5SDimitry Andric 4710b57cec5SDimitry Andric using MILOHArgs = MILOHDirective::LOHArgs; 4720b57cec5SDimitry Andric using MILOHContainer = SmallVector<MILOHDirective, 32>; 4730b57cec5SDimitry Andric 4740b57cec5SDimitry Andric const MILOHContainer &getLOHContainer() const { return LOHContainerSet; } 4750b57cec5SDimitry Andric 4760b57cec5SDimitry Andric /// Add a LOH directive of this @p Kind and this @p Args. 4770b57cec5SDimitry Andric void addLOHDirective(MCLOHType Kind, MILOHArgs Args) { 4780b57cec5SDimitry Andric LOHContainerSet.push_back(MILOHDirective(Kind, Args)); 4790b57cec5SDimitry Andric LOHRelated.insert(Args.begin(), Args.end()); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() { 4830b57cec5SDimitry Andric return ForwardedMustTailRegParms; 4840b57cec5SDimitry Andric } 4850b57cec5SDimitry Andric 486bdd1243dSDimitry Andric std::optional<int> getTaggedBasePointerIndex() const { 487e8d8bef9SDimitry Andric return TaggedBasePointerIndex; 488e8d8bef9SDimitry Andric } 489e8d8bef9SDimitry Andric void setTaggedBasePointerIndex(int Index) { TaggedBasePointerIndex = Index; } 490e8d8bef9SDimitry Andric 4910b57cec5SDimitry Andric unsigned getTaggedBasePointerOffset() const { 4920b57cec5SDimitry Andric return TaggedBasePointerOffset; 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric void setTaggedBasePointerOffset(unsigned Offset) { 4950b57cec5SDimitry Andric TaggedBasePointerOffset = Offset; 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric 498e8d8bef9SDimitry Andric int getCalleeSaveBaseToFrameRecordOffset() const { 499e8d8bef9SDimitry Andric return CalleeSaveBaseToFrameRecordOffset; 500e8d8bef9SDimitry Andric } 501e8d8bef9SDimitry Andric void setCalleeSaveBaseToFrameRecordOffset(int Offset) { 502e8d8bef9SDimitry Andric CalleeSaveBaseToFrameRecordOffset = Offset; 503e8d8bef9SDimitry Andric } 504e8d8bef9SDimitry Andric 505bdd1243dSDimitry Andric bool shouldSignReturnAddress(const MachineFunction &MF) const; 506e8d8bef9SDimitry Andric bool shouldSignReturnAddress(bool SpillsLR) const; 507e8d8bef9SDimitry Andric 5085f757f3fSDimitry Andric bool needsShadowCallStackPrologueEpilogue(MachineFunction &MF) const; 5095f757f3fSDimitry Andric 510e8d8bef9SDimitry Andric bool shouldSignWithBKey() const { return SignWithBKey; } 511cb14a3feSDimitry Andric 512cb14a3feSDimitry Andric MCSymbol *getSigningInstrLabel() const { return SignInstrLabel; } 513cb14a3feSDimitry Andric void setSigningInstrLabel(MCSymbol *Label) { SignInstrLabel = Label; } 514cb14a3feSDimitry Andric 51581ad6265SDimitry Andric bool isMTETagged() const { return IsMTETagged; } 516e8d8bef9SDimitry Andric 517e8d8bef9SDimitry Andric bool branchTargetEnforcement() const { return BranchTargetEnforcement; } 518e8d8bef9SDimitry Andric 519cb14a3feSDimitry Andric bool branchProtectionPAuthLR() const { return BranchProtectionPAuthLR; } 520cb14a3feSDimitry Andric 521fe6060f1SDimitry Andric void setHasSwiftAsyncContext(bool HasContext) { 522fe6060f1SDimitry Andric HasSwiftAsyncContext = HasContext; 523fe6060f1SDimitry Andric } 524fe6060f1SDimitry Andric bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; } 525fe6060f1SDimitry Andric 526fe6060f1SDimitry Andric void setSwiftAsyncContextFrameIdx(int FI) { 527fe6060f1SDimitry Andric SwiftAsyncContextFrameIdx = FI; 528fe6060f1SDimitry Andric } 529fe6060f1SDimitry Andric int getSwiftAsyncContextFrameIdx() const { return SwiftAsyncContextFrameIdx; } 530fe6060f1SDimitry Andric 531bdd1243dSDimitry Andric bool needsDwarfUnwindInfo(const MachineFunction &MF) const; 532bdd1243dSDimitry Andric bool needsAsyncDwarfUnwindInfo(const MachineFunction &MF) const; 53381ad6265SDimitry Andric 5345f757f3fSDimitry Andric bool hasStreamingModeChanges() const { return HasStreamingModeChanges; } 5355f757f3fSDimitry Andric void setHasStreamingModeChanges(bool HasChanges) { 5365f757f3fSDimitry Andric HasStreamingModeChanges = HasChanges; 5375f757f3fSDimitry Andric } 5385f757f3fSDimitry Andric 5395f757f3fSDimitry Andric bool hasStackProbing() const { return StackProbeSize != 0; } 5405f757f3fSDimitry Andric 5415f757f3fSDimitry Andric int64_t getStackProbeSize() const { return StackProbeSize; } 5425f757f3fSDimitry Andric 5430b57cec5SDimitry Andric private: 5440b57cec5SDimitry Andric // Hold the lists of LOHs. 5450b57cec5SDimitry Andric MILOHContainer LOHContainerSet; 5460b57cec5SDimitry Andric SetOfInstructions LOHRelated; 5470b57cec5SDimitry Andric 548e8d8bef9SDimitry Andric SmallVector<std::pair<unsigned, MCSymbol *>, 2> JumpTableEntryInfo; 5490b57cec5SDimitry Andric }; 5500b57cec5SDimitry Andric 5515ffd83dbSDimitry Andric namespace yaml { 5525ffd83dbSDimitry Andric struct AArch64FunctionInfo final : public yaml::MachineFunctionInfo { 553bdd1243dSDimitry Andric std::optional<bool> HasRedZone; 5545ffd83dbSDimitry Andric 5555ffd83dbSDimitry Andric AArch64FunctionInfo() = default; 5565ffd83dbSDimitry Andric AArch64FunctionInfo(const llvm::AArch64FunctionInfo &MFI); 5575ffd83dbSDimitry Andric 5585ffd83dbSDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 5595ffd83dbSDimitry Andric ~AArch64FunctionInfo() = default; 5605ffd83dbSDimitry Andric }; 5615ffd83dbSDimitry Andric 5625ffd83dbSDimitry Andric template <> struct MappingTraits<AArch64FunctionInfo> { 5635ffd83dbSDimitry Andric static void mapping(IO &YamlIO, AArch64FunctionInfo &MFI) { 5645ffd83dbSDimitry Andric YamlIO.mapOptional("hasRedZone", MFI.HasRedZone); 5655ffd83dbSDimitry Andric } 5665ffd83dbSDimitry Andric }; 5675ffd83dbSDimitry Andric 5685ffd83dbSDimitry Andric } // end namespace yaml 5695ffd83dbSDimitry Andric 5700b57cec5SDimitry Andric } // end namespace llvm 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 573