1*0b57cec5SDimitry Andric //=- AArch64MachineFunctionInfo.h - AArch64 machine function info -*- C++ -*-=// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file declares AArch64-specific per-machine-function information. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 14*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 17*0b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 19*0b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 20*0b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 21*0b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 22*0b57cec5SDimitry Andric #include "llvm/MC/MCLinkerOptimizationHint.h" 23*0b57cec5SDimitry Andric #include <cassert> 24*0b57cec5SDimitry Andric 25*0b57cec5SDimitry Andric namespace llvm { 26*0b57cec5SDimitry Andric 27*0b57cec5SDimitry Andric class MachineInstr; 28*0b57cec5SDimitry Andric 29*0b57cec5SDimitry Andric /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and 30*0b57cec5SDimitry Andric /// contains private AArch64-specific information for each MachineFunction. 31*0b57cec5SDimitry Andric class AArch64FunctionInfo final : public MachineFunctionInfo { 32*0b57cec5SDimitry Andric /// Number of bytes of arguments this function has on the stack. If the callee 33*0b57cec5SDimitry Andric /// is expected to restore the argument stack this should be a multiple of 16, 34*0b57cec5SDimitry Andric /// all usable during a tail call. 35*0b57cec5SDimitry Andric /// 36*0b57cec5SDimitry Andric /// The alternative would forbid tail call optimisation in some cases: if we 37*0b57cec5SDimitry Andric /// want to transfer control from a function with 8-bytes of stack-argument 38*0b57cec5SDimitry Andric /// space to a function with 16-bytes then misalignment of this value would 39*0b57cec5SDimitry Andric /// make a stack adjustment necessary, which could not be undone by the 40*0b57cec5SDimitry Andric /// callee. 41*0b57cec5SDimitry Andric unsigned BytesInStackArgArea = 0; 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric /// The number of bytes to restore to deallocate space for incoming 44*0b57cec5SDimitry Andric /// arguments. Canonically 0 in the C calling convention, but non-zero when 45*0b57cec5SDimitry Andric /// callee is expected to pop the args. 46*0b57cec5SDimitry Andric unsigned ArgumentStackToRestore = 0; 47*0b57cec5SDimitry Andric 48*0b57cec5SDimitry Andric /// HasStackFrame - True if this function has a stack frame. Set by 49*0b57cec5SDimitry Andric /// determineCalleeSaves(). 50*0b57cec5SDimitry Andric bool HasStackFrame = false; 51*0b57cec5SDimitry Andric 52*0b57cec5SDimitry Andric /// Amount of stack frame size, not including callee-saved registers. 53*0b57cec5SDimitry Andric unsigned LocalStackSize; 54*0b57cec5SDimitry Andric 55*0b57cec5SDimitry Andric /// Amount of stack frame size used for saving callee-saved registers. 56*0b57cec5SDimitry Andric unsigned CalleeSavedStackSize; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric /// Number of TLS accesses using the special (combinable) 59*0b57cec5SDimitry Andric /// _TLS_MODULE_BASE_ symbol. 60*0b57cec5SDimitry Andric unsigned NumLocalDynamicTLSAccesses = 0; 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed on the 63*0b57cec5SDimitry Andric /// stack. 64*0b57cec5SDimitry Andric int VarArgsStackIndex = 0; 65*0b57cec5SDimitry Andric 66*0b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 67*0b57cec5SDimitry Andric /// general purpose registers. 68*0b57cec5SDimitry Andric int VarArgsGPRIndex = 0; 69*0b57cec5SDimitry Andric 70*0b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in general purpose 71*0b57cec5SDimitry Andric /// registers. 72*0b57cec5SDimitry Andric unsigned VarArgsGPRSize = 0; 73*0b57cec5SDimitry Andric 74*0b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 75*0b57cec5SDimitry Andric /// floating-point registers. 76*0b57cec5SDimitry Andric int VarArgsFPRIndex = 0; 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in floating-point 79*0b57cec5SDimitry Andric /// registers. 80*0b57cec5SDimitry Andric unsigned VarArgsFPRSize = 0; 81*0b57cec5SDimitry Andric 82*0b57cec5SDimitry Andric /// True if this function has a subset of CSRs that is handled explicitly via 83*0b57cec5SDimitry Andric /// copies. 84*0b57cec5SDimitry Andric bool IsSplitCSR = false; 85*0b57cec5SDimitry Andric 86*0b57cec5SDimitry Andric /// True when the stack gets realigned dynamically because the size of stack 87*0b57cec5SDimitry Andric /// frame is unknown at compile time. e.g., in case of VLAs. 88*0b57cec5SDimitry Andric bool StackRealigned = false; 89*0b57cec5SDimitry Andric 90*0b57cec5SDimitry Andric /// True when the callee-save stack area has unused gaps that may be used for 91*0b57cec5SDimitry Andric /// other stack allocations. 92*0b57cec5SDimitry Andric bool CalleeSaveStackHasFreeSpace = false; 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric /// SRetReturnReg - sret lowering includes returning the value of the 95*0b57cec5SDimitry Andric /// returned struct in a register. This field holds the virtual register into 96*0b57cec5SDimitry Andric /// which the sret argument is passed. 97*0b57cec5SDimitry Andric unsigned SRetReturnReg = 0; 98*0b57cec5SDimitry Andric 99*0b57cec5SDimitry Andric /// Has a value when it is known whether or not the function uses a 100*0b57cec5SDimitry Andric /// redzone, and no value otherwise. 101*0b57cec5SDimitry Andric /// Initialized during frame lowering, unless the function has the noredzone 102*0b57cec5SDimitry Andric /// attribute, in which case it is set to false at construction. 103*0b57cec5SDimitry Andric Optional<bool> HasRedZone; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric /// ForwardedMustTailRegParms - A list of virtual and physical registers 106*0b57cec5SDimitry Andric /// that must be forwarded to every musttail call. 107*0b57cec5SDimitry Andric SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms; 108*0b57cec5SDimitry Andric 109*0b57cec5SDimitry Andric // Offset from SP-at-entry to the tagged base pointer. 110*0b57cec5SDimitry Andric // Tagged base pointer is set up to point to the first (lowest address) tagged 111*0b57cec5SDimitry Andric // stack slot. 112*0b57cec5SDimitry Andric unsigned TaggedBasePointerOffset; 113*0b57cec5SDimitry Andric 114*0b57cec5SDimitry Andric public: 115*0b57cec5SDimitry Andric AArch64FunctionInfo() = default; 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric explicit AArch64FunctionInfo(MachineFunction &MF) { 118*0b57cec5SDimitry Andric (void)MF; 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric // If we already know that the function doesn't have a redzone, set 121*0b57cec5SDimitry Andric // HasRedZone here. 122*0b57cec5SDimitry Andric if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) 123*0b57cec5SDimitry Andric HasRedZone = false; 124*0b57cec5SDimitry Andric } 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } 127*0b57cec5SDimitry Andric void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } 128*0b57cec5SDimitry Andric 129*0b57cec5SDimitry Andric unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; } 130*0b57cec5SDimitry Andric void setArgumentStackToRestore(unsigned bytes) { 131*0b57cec5SDimitry Andric ArgumentStackToRestore = bytes; 132*0b57cec5SDimitry Andric } 133*0b57cec5SDimitry Andric 134*0b57cec5SDimitry Andric bool hasStackFrame() const { return HasStackFrame; } 135*0b57cec5SDimitry Andric void setHasStackFrame(bool s) { HasStackFrame = s; } 136*0b57cec5SDimitry Andric 137*0b57cec5SDimitry Andric bool isStackRealigned() const { return StackRealigned; } 138*0b57cec5SDimitry Andric void setStackRealigned(bool s) { StackRealigned = s; } 139*0b57cec5SDimitry Andric 140*0b57cec5SDimitry Andric bool hasCalleeSaveStackFreeSpace() const { 141*0b57cec5SDimitry Andric return CalleeSaveStackHasFreeSpace; 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric void setCalleeSaveStackHasFreeSpace(bool s) { 144*0b57cec5SDimitry Andric CalleeSaveStackHasFreeSpace = s; 145*0b57cec5SDimitry Andric } 146*0b57cec5SDimitry Andric 147*0b57cec5SDimitry Andric bool isSplitCSR() const { return IsSplitCSR; } 148*0b57cec5SDimitry Andric void setIsSplitCSR(bool s) { IsSplitCSR = s; } 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric void setLocalStackSize(unsigned Size) { LocalStackSize = Size; } 151*0b57cec5SDimitry Andric unsigned getLocalStackSize() const { return LocalStackSize; } 152*0b57cec5SDimitry Andric 153*0b57cec5SDimitry Andric void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; } 154*0b57cec5SDimitry Andric unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; } 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; } 157*0b57cec5SDimitry Andric unsigned getNumLocalDynamicTLSAccesses() const { 158*0b57cec5SDimitry Andric return NumLocalDynamicTLSAccesses; 159*0b57cec5SDimitry Andric } 160*0b57cec5SDimitry Andric 161*0b57cec5SDimitry Andric Optional<bool> hasRedZone() const { return HasRedZone; } 162*0b57cec5SDimitry Andric void setHasRedZone(bool s) { HasRedZone = s; } 163*0b57cec5SDimitry Andric 164*0b57cec5SDimitry Andric int getVarArgsStackIndex() const { return VarArgsStackIndex; } 165*0b57cec5SDimitry Andric void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; } 166*0b57cec5SDimitry Andric 167*0b57cec5SDimitry Andric int getVarArgsGPRIndex() const { return VarArgsGPRIndex; } 168*0b57cec5SDimitry Andric void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; } 169*0b57cec5SDimitry Andric 170*0b57cec5SDimitry Andric unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; } 171*0b57cec5SDimitry Andric void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; } 172*0b57cec5SDimitry Andric 173*0b57cec5SDimitry Andric int getVarArgsFPRIndex() const { return VarArgsFPRIndex; } 174*0b57cec5SDimitry Andric void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; } 175*0b57cec5SDimitry Andric 176*0b57cec5SDimitry Andric unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; } 177*0b57cec5SDimitry Andric void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; } 178*0b57cec5SDimitry Andric 179*0b57cec5SDimitry Andric unsigned getSRetReturnReg() const { return SRetReturnReg; } 180*0b57cec5SDimitry Andric void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } 181*0b57cec5SDimitry Andric 182*0b57cec5SDimitry Andric unsigned getJumpTableEntrySize(int Idx) const { 183*0b57cec5SDimitry Andric auto It = JumpTableEntryInfo.find(Idx); 184*0b57cec5SDimitry Andric if (It != JumpTableEntryInfo.end()) 185*0b57cec5SDimitry Andric return It->second.first; 186*0b57cec5SDimitry Andric return 4; 187*0b57cec5SDimitry Andric } 188*0b57cec5SDimitry Andric MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const { 189*0b57cec5SDimitry Andric return JumpTableEntryInfo.find(Idx)->second.second; 190*0b57cec5SDimitry Andric } 191*0b57cec5SDimitry Andric void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) { 192*0b57cec5SDimitry Andric JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym); 193*0b57cec5SDimitry Andric } 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>; 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric const SetOfInstructions &getLOHRelated() const { return LOHRelated; } 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric // Shortcuts for LOH related types. 200*0b57cec5SDimitry Andric class MILOHDirective { 201*0b57cec5SDimitry Andric MCLOHType Kind; 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric /// Arguments of this directive. Order matters. 204*0b57cec5SDimitry Andric SmallVector<const MachineInstr *, 3> Args; 205*0b57cec5SDimitry Andric 206*0b57cec5SDimitry Andric public: 207*0b57cec5SDimitry Andric using LOHArgs = ArrayRef<const MachineInstr *>; 208*0b57cec5SDimitry Andric 209*0b57cec5SDimitry Andric MILOHDirective(MCLOHType Kind, LOHArgs Args) 210*0b57cec5SDimitry Andric : Kind(Kind), Args(Args.begin(), Args.end()) { 211*0b57cec5SDimitry Andric assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 212*0b57cec5SDimitry Andric } 213*0b57cec5SDimitry Andric 214*0b57cec5SDimitry Andric MCLOHType getKind() const { return Kind; } 215*0b57cec5SDimitry Andric LOHArgs getArgs() const { return Args; } 216*0b57cec5SDimitry Andric }; 217*0b57cec5SDimitry Andric 218*0b57cec5SDimitry Andric using MILOHArgs = MILOHDirective::LOHArgs; 219*0b57cec5SDimitry Andric using MILOHContainer = SmallVector<MILOHDirective, 32>; 220*0b57cec5SDimitry Andric 221*0b57cec5SDimitry Andric const MILOHContainer &getLOHContainer() const { return LOHContainerSet; } 222*0b57cec5SDimitry Andric 223*0b57cec5SDimitry Andric /// Add a LOH directive of this @p Kind and this @p Args. 224*0b57cec5SDimitry Andric void addLOHDirective(MCLOHType Kind, MILOHArgs Args) { 225*0b57cec5SDimitry Andric LOHContainerSet.push_back(MILOHDirective(Kind, Args)); 226*0b57cec5SDimitry Andric LOHRelated.insert(Args.begin(), Args.end()); 227*0b57cec5SDimitry Andric } 228*0b57cec5SDimitry Andric 229*0b57cec5SDimitry Andric SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() { 230*0b57cec5SDimitry Andric return ForwardedMustTailRegParms; 231*0b57cec5SDimitry Andric } 232*0b57cec5SDimitry Andric 233*0b57cec5SDimitry Andric unsigned getTaggedBasePointerOffset() const { 234*0b57cec5SDimitry Andric return TaggedBasePointerOffset; 235*0b57cec5SDimitry Andric } 236*0b57cec5SDimitry Andric void setTaggedBasePointerOffset(unsigned Offset) { 237*0b57cec5SDimitry Andric TaggedBasePointerOffset = Offset; 238*0b57cec5SDimitry Andric } 239*0b57cec5SDimitry Andric 240*0b57cec5SDimitry Andric private: 241*0b57cec5SDimitry Andric // Hold the lists of LOHs. 242*0b57cec5SDimitry Andric MILOHContainer LOHContainerSet; 243*0b57cec5SDimitry Andric SetOfInstructions LOHRelated; 244*0b57cec5SDimitry Andric 245*0b57cec5SDimitry Andric DenseMap<int, std::pair<unsigned, MCSymbol *>> JumpTableEntryInfo; 246*0b57cec5SDimitry Andric }; 247*0b57cec5SDimitry Andric 248*0b57cec5SDimitry Andric } // end namespace llvm 249*0b57cec5SDimitry Andric 250*0b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 251