1296417Sdim//=- AArch64MachineFunctionInfo.h - AArch64 machine function info -*- C++ -*-=// 2249259Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6249259Sdim// 7249259Sdim//===----------------------------------------------------------------------===// 8249259Sdim// 9249259Sdim// This file declares AArch64-specific per-machine-function information. 10249259Sdim// 11249259Sdim//===----------------------------------------------------------------------===// 12249259Sdim 13280031Sdim#ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 14280031Sdim#define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 15249259Sdim 16314564Sdim#include "llvm/ADT/ArrayRef.h" 17341825Sdim#include "llvm/ADT/Optional.h" 18276479Sdim#include "llvm/ADT/SmallPtrSet.h" 19276479Sdim#include "llvm/ADT/SmallVector.h" 20344779Sdim#include "llvm/CodeGen/CallingConvLower.h" 21249259Sdim#include "llvm/CodeGen/MachineFunction.h" 22360784Sdim#include "llvm/CodeGen/TargetFrameLowering.h" 23360784Sdim#include "llvm/IR/Function.h" 24276479Sdim#include "llvm/MC/MCLinkerOptimizationHint.h" 25314564Sdim#include <cassert> 26249259Sdim 27249259Sdimnamespace llvm { 28249259Sdim 29327952Sdimclass MachineInstr; 30327952Sdim 31276479Sdim/// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and 32276479Sdim/// contains private AArch64-specific information for each MachineFunction. 33314564Sdimclass AArch64FunctionInfo final : public MachineFunctionInfo { 34249259Sdim /// Number of bytes of arguments this function has on the stack. If the callee 35249259Sdim /// is expected to restore the argument stack this should be a multiple of 16, 36249259Sdim /// all usable during a tail call. 37249259Sdim /// 38249259Sdim /// The alternative would forbid tail call optimisation in some cases: if we 39249259Sdim /// want to transfer control from a function with 8-bytes of stack-argument 40249259Sdim /// space to a function with 16-bytes then misalignment of this value would 41249259Sdim /// make a stack adjustment necessary, which could not be undone by the 42249259Sdim /// callee. 43314564Sdim unsigned BytesInStackArgArea = 0; 44249259Sdim 45249259Sdim /// The number of bytes to restore to deallocate space for incoming 46249259Sdim /// arguments. Canonically 0 in the C calling convention, but non-zero when 47249259Sdim /// callee is expected to pop the args. 48314564Sdim unsigned ArgumentStackToRestore = 0; 49249259Sdim 50276479Sdim /// HasStackFrame - True if this function has a stack frame. Set by 51296417Sdim /// determineCalleeSaves(). 52314564Sdim bool HasStackFrame = false; 53249259Sdim 54341825Sdim /// Amount of stack frame size, not including callee-saved registers. 55360784Sdim uint64_t LocalStackSize = 0; 56249259Sdim 57360784Sdim /// The start and end frame indices for the SVE callee saves. 58360784Sdim int MinSVECSFrameIndex = 0; 59360784Sdim int MaxSVECSFrameIndex = 0; 60360784Sdim 61341825Sdim /// Amount of stack frame size used for saving callee-saved registers. 62360784Sdim unsigned CalleeSavedStackSize = 0; 63360784Sdim unsigned SVECalleeSavedStackSize = 0; 64360784Sdim bool HasCalleeSavedStackSize = false; 65309124Sdim 66341825Sdim /// Number of TLS accesses using the special (combinable) 67276479Sdim /// _TLS_MODULE_BASE_ symbol. 68314564Sdim unsigned NumLocalDynamicTLSAccesses = 0; 69249259Sdim 70341825Sdim /// FrameIndex for start of varargs area for arguments passed on the 71276479Sdim /// stack. 72314564Sdim int VarArgsStackIndex = 0; 73249259Sdim 74341825Sdim /// FrameIndex for start of varargs area for arguments passed in 75276479Sdim /// general purpose registers. 76314564Sdim int VarArgsGPRIndex = 0; 77249259Sdim 78341825Sdim /// Size of the varargs area for arguments passed in general purpose 79276479Sdim /// registers. 80314564Sdim unsigned VarArgsGPRSize = 0; 81249259Sdim 82341825Sdim /// FrameIndex for start of varargs area for arguments passed in 83276479Sdim /// floating-point registers. 84314564Sdim int VarArgsFPRIndex = 0; 85249259Sdim 86341825Sdim /// Size of the varargs area for arguments passed in floating-point 87276479Sdim /// registers. 88314564Sdim unsigned VarArgsFPRSize = 0; 89249259Sdim 90296417Sdim /// True if this function has a subset of CSRs that is handled explicitly via 91296417Sdim /// copies. 92314564Sdim bool IsSplitCSR = false; 93296417Sdim 94309124Sdim /// True when the stack gets realigned dynamically because the size of stack 95309124Sdim /// frame is unknown at compile time. e.g., in case of VLAs. 96314564Sdim bool StackRealigned = false; 97309124Sdim 98309124Sdim /// True when the callee-save stack area has unused gaps that may be used for 99309124Sdim /// other stack allocations. 100314564Sdim bool CalleeSaveStackHasFreeSpace = false; 101309124Sdim 102353358Sdim /// SRetReturnReg - sret lowering includes returning the value of the 103353358Sdim /// returned struct in a register. This field holds the virtual register into 104353358Sdim /// which the sret argument is passed. 105353358Sdim unsigned SRetReturnReg = 0; 106360784Sdim /// SVE stack size (for predicates and data vectors) are maintained here 107360784Sdim /// rather than in FrameInfo, as the placement and Stack IDs are target 108360784Sdim /// specific. 109360784Sdim uint64_t StackSizeSVE = 0; 110353358Sdim 111360784Sdim /// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid. 112360784Sdim bool HasCalculatedStackSizeSVE = false; 113360784Sdim 114341825Sdim /// Has a value when it is known whether or not the function uses a 115341825Sdim /// redzone, and no value otherwise. 116341825Sdim /// Initialized during frame lowering, unless the function has the noredzone 117341825Sdim /// attribute, in which case it is set to false at construction. 118341825Sdim Optional<bool> HasRedZone; 119341825Sdim 120344779Sdim /// ForwardedMustTailRegParms - A list of virtual and physical registers 121344779Sdim /// that must be forwarded to every musttail call. 122344779Sdim SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms; 123353358Sdim 124353358Sdim // Offset from SP-at-entry to the tagged base pointer. 125353358Sdim // Tagged base pointer is set up to point to the first (lowest address) tagged 126353358Sdim // stack slot. 127360784Sdim unsigned TaggedBasePointerOffset = 0; 128353358Sdim 129249259Sdimpublic: 130314564Sdim AArch64FunctionInfo() = default; 131249259Sdim 132314564Sdim explicit AArch64FunctionInfo(MachineFunction &MF) { 133276479Sdim (void)MF; 134341825Sdim 135341825Sdim // If we already know that the function doesn't have a redzone, set 136341825Sdim // HasRedZone here. 137341825Sdim if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) 138341825Sdim HasRedZone = false; 139276479Sdim } 140249259Sdim 141249259Sdim unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } 142276479Sdim void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } 143249259Sdim 144249259Sdim unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; } 145249259Sdim void setArgumentStackToRestore(unsigned bytes) { 146249259Sdim ArgumentStackToRestore = bytes; 147249259Sdim } 148249259Sdim 149360784Sdim bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; } 150360784Sdim 151360784Sdim void setStackSizeSVE(uint64_t S) { 152360784Sdim HasCalculatedStackSizeSVE = true; 153360784Sdim StackSizeSVE = S; 154360784Sdim } 155360784Sdim 156360784Sdim uint64_t getStackSizeSVE() const { return StackSizeSVE; } 157360784Sdim 158276479Sdim bool hasStackFrame() const { return HasStackFrame; } 159276479Sdim void setHasStackFrame(bool s) { HasStackFrame = s; } 160249259Sdim 161309124Sdim bool isStackRealigned() const { return StackRealigned; } 162309124Sdim void setStackRealigned(bool s) { StackRealigned = s; } 163309124Sdim 164309124Sdim bool hasCalleeSaveStackFreeSpace() const { 165309124Sdim return CalleeSaveStackHasFreeSpace; 166309124Sdim } 167309124Sdim void setCalleeSaveStackHasFreeSpace(bool s) { 168309124Sdim CalleeSaveStackHasFreeSpace = s; 169309124Sdim } 170296417Sdim bool isSplitCSR() const { return IsSplitCSR; } 171296417Sdim void setIsSplitCSR(bool s) { IsSplitCSR = s; } 172296417Sdim 173360784Sdim void setLocalStackSize(uint64_t Size) { LocalStackSize = Size; } 174360784Sdim uint64_t getLocalStackSize() const { return LocalStackSize; } 175249259Sdim 176360784Sdim void setCalleeSavedStackSize(unsigned Size) { 177360784Sdim CalleeSavedStackSize = Size; 178360784Sdim HasCalleeSavedStackSize = true; 179360784Sdim } 180309124Sdim 181360784Sdim // When CalleeSavedStackSize has not been set (for example when 182360784Sdim // some MachineIR pass is run in isolation), then recalculate 183360784Sdim // the CalleeSavedStackSize directly from the CalleeSavedInfo. 184360784Sdim // Note: This information can only be recalculated after PEI 185360784Sdim // has assigned offsets to the callee save objects. 186360784Sdim unsigned getCalleeSavedStackSize(const MachineFrameInfo &MFI) const { 187360784Sdim bool ValidateCalleeSavedStackSize = false; 188360784Sdim 189360784Sdim#ifndef NDEBUG 190360784Sdim // Make sure the calculated size derived from the CalleeSavedInfo 191360784Sdim // equals the cached size that was calculated elsewhere (e.g. in 192360784Sdim // determineCalleeSaves). 193360784Sdim ValidateCalleeSavedStackSize = HasCalleeSavedStackSize; 194360784Sdim#endif 195360784Sdim 196360784Sdim if (!HasCalleeSavedStackSize || ValidateCalleeSavedStackSize) { 197360784Sdim assert(MFI.isCalleeSavedInfoValid() && "CalleeSavedInfo not calculated"); 198360784Sdim if (MFI.getCalleeSavedInfo().empty()) 199360784Sdim return 0; 200360784Sdim 201360784Sdim int64_t MinOffset = std::numeric_limits<int64_t>::max(); 202360784Sdim int64_t MaxOffset = std::numeric_limits<int64_t>::min(); 203360784Sdim for (const auto &Info : MFI.getCalleeSavedInfo()) { 204360784Sdim int FrameIdx = Info.getFrameIdx(); 205360784Sdim if (MFI.getStackID(FrameIdx) != TargetStackID::Default) 206360784Sdim continue; 207360784Sdim int64_t Offset = MFI.getObjectOffset(FrameIdx); 208360784Sdim int64_t ObjSize = MFI.getObjectSize(FrameIdx); 209360784Sdim MinOffset = std::min<int64_t>(Offset, MinOffset); 210360784Sdim MaxOffset = std::max<int64_t>(Offset + ObjSize, MaxOffset); 211360784Sdim } 212360784Sdim 213360784Sdim unsigned Size = alignTo(MaxOffset - MinOffset, 16); 214360784Sdim assert((!HasCalleeSavedStackSize || getCalleeSavedStackSize() == Size) && 215360784Sdim "Invalid size calculated for callee saves"); 216360784Sdim return Size; 217360784Sdim } 218360784Sdim 219360784Sdim return getCalleeSavedStackSize(); 220360784Sdim } 221360784Sdim 222360784Sdim unsigned getCalleeSavedStackSize() const { 223360784Sdim assert(HasCalleeSavedStackSize && 224360784Sdim "CalleeSavedStackSize has not been calculated"); 225360784Sdim return CalleeSavedStackSize; 226360784Sdim } 227360784Sdim 228360784Sdim // Saves the CalleeSavedStackSize for SVE vectors in 'scalable bytes' 229360784Sdim void setSVECalleeSavedStackSize(unsigned Size) { 230360784Sdim SVECalleeSavedStackSize = Size; 231360784Sdim } 232360784Sdim unsigned getSVECalleeSavedStackSize() const { 233360784Sdim return SVECalleeSavedStackSize; 234360784Sdim } 235360784Sdim 236360784Sdim void setMinMaxSVECSFrameIndex(int Min, int Max) { 237360784Sdim MinSVECSFrameIndex = Min; 238360784Sdim MaxSVECSFrameIndex = Max; 239360784Sdim } 240360784Sdim 241360784Sdim int getMinSVECSFrameIndex() const { return MinSVECSFrameIndex; } 242360784Sdim int getMaxSVECSFrameIndex() const { return MaxSVECSFrameIndex; } 243360784Sdim 244276479Sdim void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; } 245276479Sdim unsigned getNumLocalDynamicTLSAccesses() const { 246276479Sdim return NumLocalDynamicTLSAccesses; 247276479Sdim } 248249259Sdim 249341825Sdim Optional<bool> hasRedZone() const { return HasRedZone; } 250341825Sdim void setHasRedZone(bool s) { HasRedZone = s; } 251341825Sdim 252276479Sdim int getVarArgsStackIndex() const { return VarArgsStackIndex; } 253276479Sdim void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; } 254249259Sdim 255276479Sdim int getVarArgsGPRIndex() const { return VarArgsGPRIndex; } 256276479Sdim void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; } 257249259Sdim 258276479Sdim unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; } 259276479Sdim void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; } 260249259Sdim 261276479Sdim int getVarArgsFPRIndex() const { return VarArgsFPRIndex; } 262276479Sdim void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; } 263249259Sdim 264276479Sdim unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; } 265276479Sdim void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; } 266249259Sdim 267353358Sdim unsigned getSRetReturnReg() const { return SRetReturnReg; } 268353358Sdim void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } 269353358Sdim 270344779Sdim unsigned getJumpTableEntrySize(int Idx) const { 271344779Sdim auto It = JumpTableEntryInfo.find(Idx); 272344779Sdim if (It != JumpTableEntryInfo.end()) 273344779Sdim return It->second.first; 274344779Sdim return 4; 275344779Sdim } 276344779Sdim MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const { 277344779Sdim return JumpTableEntryInfo.find(Idx)->second.second; 278344779Sdim } 279344779Sdim void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) { 280344779Sdim JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym); 281344779Sdim } 282344779Sdim 283327952Sdim using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>; 284276479Sdim 285276479Sdim const SetOfInstructions &getLOHRelated() const { return LOHRelated; } 286276479Sdim 287276479Sdim // Shortcuts for LOH related types. 288276479Sdim class MILOHDirective { 289276479Sdim MCLOHType Kind; 290276479Sdim 291276479Sdim /// Arguments of this directive. Order matters. 292276479Sdim SmallVector<const MachineInstr *, 3> Args; 293276479Sdim 294276479Sdim public: 295327952Sdim using LOHArgs = ArrayRef<const MachineInstr *>; 296276479Sdim 297309124Sdim MILOHDirective(MCLOHType Kind, LOHArgs Args) 298276479Sdim : Kind(Kind), Args(Args.begin(), Args.end()) { 299276479Sdim assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 300276479Sdim } 301276479Sdim 302276479Sdim MCLOHType getKind() const { return Kind; } 303309124Sdim LOHArgs getArgs() const { return Args; } 304276479Sdim }; 305276479Sdim 306327952Sdim using MILOHArgs = MILOHDirective::LOHArgs; 307327952Sdim using MILOHContainer = SmallVector<MILOHDirective, 32>; 308276479Sdim 309276479Sdim const MILOHContainer &getLOHContainer() const { return LOHContainerSet; } 310276479Sdim 311276479Sdim /// Add a LOH directive of this @p Kind and this @p Args. 312309124Sdim void addLOHDirective(MCLOHType Kind, MILOHArgs Args) { 313276479Sdim LOHContainerSet.push_back(MILOHDirective(Kind, Args)); 314276479Sdim LOHRelated.insert(Args.begin(), Args.end()); 315276479Sdim } 316276479Sdim 317344779Sdim SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() { 318344779Sdim return ForwardedMustTailRegParms; 319344779Sdim } 320344779Sdim 321353358Sdim unsigned getTaggedBasePointerOffset() const { 322353358Sdim return TaggedBasePointerOffset; 323353358Sdim } 324353358Sdim void setTaggedBasePointerOffset(unsigned Offset) { 325353358Sdim TaggedBasePointerOffset = Offset; 326353358Sdim } 327353358Sdim 328276479Sdimprivate: 329276479Sdim // Hold the lists of LOHs. 330276479Sdim MILOHContainer LOHContainerSet; 331276479Sdim SetOfInstructions LOHRelated; 332344779Sdim 333344779Sdim DenseMap<int, std::pair<unsigned, MCSymbol *>> JumpTableEntryInfo; 334249259Sdim}; 335249259Sdim 336314564Sdim} // end namespace llvm 337314564Sdim 338314564Sdim#endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 339