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 160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h" 170b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 180b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 190b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h" 200b57cec5SDimitry Andric #include "llvm/CodeGen/CallingConvLower.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunction.h" 22*8bcb0991SDimitry Andric #include "llvm/IR/Function.h" 230b57cec5SDimitry Andric #include "llvm/MC/MCLinkerOptimizationHint.h" 240b57cec5SDimitry Andric #include <cassert> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric namespace llvm { 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric class MachineInstr; 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric /// AArch64FunctionInfo - This class is derived from MachineFunctionInfo and 310b57cec5SDimitry Andric /// contains private AArch64-specific information for each MachineFunction. 320b57cec5SDimitry Andric class AArch64FunctionInfo final : public MachineFunctionInfo { 330b57cec5SDimitry Andric /// Number of bytes of arguments this function has on the stack. If the callee 340b57cec5SDimitry Andric /// is expected to restore the argument stack this should be a multiple of 16, 350b57cec5SDimitry Andric /// all usable during a tail call. 360b57cec5SDimitry Andric /// 370b57cec5SDimitry Andric /// The alternative would forbid tail call optimisation in some cases: if we 380b57cec5SDimitry Andric /// want to transfer control from a function with 8-bytes of stack-argument 390b57cec5SDimitry Andric /// space to a function with 16-bytes then misalignment of this value would 400b57cec5SDimitry Andric /// make a stack adjustment necessary, which could not be undone by the 410b57cec5SDimitry Andric /// callee. 420b57cec5SDimitry Andric unsigned BytesInStackArgArea = 0; 430b57cec5SDimitry Andric 440b57cec5SDimitry Andric /// The number of bytes to restore to deallocate space for incoming 450b57cec5SDimitry Andric /// arguments. Canonically 0 in the C calling convention, but non-zero when 460b57cec5SDimitry Andric /// callee is expected to pop the args. 470b57cec5SDimitry Andric unsigned ArgumentStackToRestore = 0; 480b57cec5SDimitry Andric 490b57cec5SDimitry Andric /// HasStackFrame - True if this function has a stack frame. Set by 500b57cec5SDimitry Andric /// determineCalleeSaves(). 510b57cec5SDimitry Andric bool HasStackFrame = false; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric /// Amount of stack frame size, not including callee-saved registers. 540b57cec5SDimitry Andric unsigned LocalStackSize; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric /// Amount of stack frame size used for saving callee-saved registers. 570b57cec5SDimitry Andric unsigned CalleeSavedStackSize; 580b57cec5SDimitry Andric 590b57cec5SDimitry Andric /// Number of TLS accesses using the special (combinable) 600b57cec5SDimitry Andric /// _TLS_MODULE_BASE_ symbol. 610b57cec5SDimitry Andric unsigned NumLocalDynamicTLSAccesses = 0; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed on the 640b57cec5SDimitry Andric /// stack. 650b57cec5SDimitry Andric int VarArgsStackIndex = 0; 660b57cec5SDimitry Andric 670b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 680b57cec5SDimitry Andric /// general purpose registers. 690b57cec5SDimitry Andric int VarArgsGPRIndex = 0; 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in general purpose 720b57cec5SDimitry Andric /// registers. 730b57cec5SDimitry Andric unsigned VarArgsGPRSize = 0; 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric /// FrameIndex for start of varargs area for arguments passed in 760b57cec5SDimitry Andric /// floating-point registers. 770b57cec5SDimitry Andric int VarArgsFPRIndex = 0; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric /// Size of the varargs area for arguments passed in floating-point 800b57cec5SDimitry Andric /// registers. 810b57cec5SDimitry Andric unsigned VarArgsFPRSize = 0; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric /// True if this function has a subset of CSRs that is handled explicitly via 840b57cec5SDimitry Andric /// copies. 850b57cec5SDimitry Andric bool IsSplitCSR = false; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric /// True when the stack gets realigned dynamically because the size of stack 880b57cec5SDimitry Andric /// frame is unknown at compile time. e.g., in case of VLAs. 890b57cec5SDimitry Andric bool StackRealigned = false; 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric /// True when the callee-save stack area has unused gaps that may be used for 920b57cec5SDimitry Andric /// other stack allocations. 930b57cec5SDimitry Andric bool CalleeSaveStackHasFreeSpace = false; 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric /// SRetReturnReg - sret lowering includes returning the value of the 960b57cec5SDimitry Andric /// returned struct in a register. This field holds the virtual register into 970b57cec5SDimitry Andric /// which the sret argument is passed. 980b57cec5SDimitry Andric unsigned SRetReturnReg = 0; 99*8bcb0991SDimitry Andric /// SVE stack size (for predicates and data vectors) are maintained here 100*8bcb0991SDimitry Andric /// rather than in FrameInfo, as the placement and Stack IDs are target 101*8bcb0991SDimitry Andric /// specific. 102*8bcb0991SDimitry Andric uint64_t StackSizeSVE = 0; 103*8bcb0991SDimitry Andric 104*8bcb0991SDimitry Andric /// HasCalculatedStackSizeSVE indicates whether StackSizeSVE is valid. 105*8bcb0991SDimitry Andric bool HasCalculatedStackSizeSVE = false; 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric /// Has a value when it is known whether or not the function uses a 1080b57cec5SDimitry Andric /// redzone, and no value otherwise. 1090b57cec5SDimitry Andric /// Initialized during frame lowering, unless the function has the noredzone 1100b57cec5SDimitry Andric /// attribute, in which case it is set to false at construction. 1110b57cec5SDimitry Andric Optional<bool> HasRedZone; 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric /// ForwardedMustTailRegParms - A list of virtual and physical registers 1140b57cec5SDimitry Andric /// that must be forwarded to every musttail call. 1150b57cec5SDimitry Andric SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric // Offset from SP-at-entry to the tagged base pointer. 1180b57cec5SDimitry Andric // Tagged base pointer is set up to point to the first (lowest address) tagged 1190b57cec5SDimitry Andric // stack slot. 1200b57cec5SDimitry Andric unsigned TaggedBasePointerOffset; 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric public: 1230b57cec5SDimitry Andric AArch64FunctionInfo() = default; 1240b57cec5SDimitry Andric 1250b57cec5SDimitry Andric explicit AArch64FunctionInfo(MachineFunction &MF) { 1260b57cec5SDimitry Andric (void)MF; 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // If we already know that the function doesn't have a redzone, set 1290b57cec5SDimitry Andric // HasRedZone here. 1300b57cec5SDimitry Andric if (MF.getFunction().hasFnAttribute(Attribute::NoRedZone)) 1310b57cec5SDimitry Andric HasRedZone = false; 1320b57cec5SDimitry Andric } 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric unsigned getBytesInStackArgArea() const { return BytesInStackArgArea; } 1350b57cec5SDimitry Andric void setBytesInStackArgArea(unsigned bytes) { BytesInStackArgArea = bytes; } 1360b57cec5SDimitry Andric 1370b57cec5SDimitry Andric unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; } 1380b57cec5SDimitry Andric void setArgumentStackToRestore(unsigned bytes) { 1390b57cec5SDimitry Andric ArgumentStackToRestore = bytes; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric 142*8bcb0991SDimitry Andric bool hasCalculatedStackSizeSVE() const { return HasCalculatedStackSizeSVE; } 143*8bcb0991SDimitry Andric 144*8bcb0991SDimitry Andric void setStackSizeSVE(uint64_t S) { 145*8bcb0991SDimitry Andric HasCalculatedStackSizeSVE = true; 146*8bcb0991SDimitry Andric StackSizeSVE = S; 147*8bcb0991SDimitry Andric } 148*8bcb0991SDimitry Andric 149*8bcb0991SDimitry Andric uint64_t getStackSizeSVE() const { return StackSizeSVE; } 150*8bcb0991SDimitry Andric 1510b57cec5SDimitry Andric bool hasStackFrame() const { return HasStackFrame; } 1520b57cec5SDimitry Andric void setHasStackFrame(bool s) { HasStackFrame = s; } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric bool isStackRealigned() const { return StackRealigned; } 1550b57cec5SDimitry Andric void setStackRealigned(bool s) { StackRealigned = s; } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric bool hasCalleeSaveStackFreeSpace() const { 1580b57cec5SDimitry Andric return CalleeSaveStackHasFreeSpace; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric void setCalleeSaveStackHasFreeSpace(bool s) { 1610b57cec5SDimitry Andric CalleeSaveStackHasFreeSpace = s; 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric 1640b57cec5SDimitry Andric bool isSplitCSR() const { return IsSplitCSR; } 1650b57cec5SDimitry Andric void setIsSplitCSR(bool s) { IsSplitCSR = s; } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric void setLocalStackSize(unsigned Size) { LocalStackSize = Size; } 1680b57cec5SDimitry Andric unsigned getLocalStackSize() const { return LocalStackSize; } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric void setCalleeSavedStackSize(unsigned Size) { CalleeSavedStackSize = Size; } 1710b57cec5SDimitry Andric unsigned getCalleeSavedStackSize() const { return CalleeSavedStackSize; } 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamicTLSAccesses; } 1740b57cec5SDimitry Andric unsigned getNumLocalDynamicTLSAccesses() const { 1750b57cec5SDimitry Andric return NumLocalDynamicTLSAccesses; 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric 1780b57cec5SDimitry Andric Optional<bool> hasRedZone() const { return HasRedZone; } 1790b57cec5SDimitry Andric void setHasRedZone(bool s) { HasRedZone = s; } 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric int getVarArgsStackIndex() const { return VarArgsStackIndex; } 1820b57cec5SDimitry Andric void setVarArgsStackIndex(int Index) { VarArgsStackIndex = Index; } 1830b57cec5SDimitry Andric 1840b57cec5SDimitry Andric int getVarArgsGPRIndex() const { return VarArgsGPRIndex; } 1850b57cec5SDimitry Andric void setVarArgsGPRIndex(int Index) { VarArgsGPRIndex = Index; } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric unsigned getVarArgsGPRSize() const { return VarArgsGPRSize; } 1880b57cec5SDimitry Andric void setVarArgsGPRSize(unsigned Size) { VarArgsGPRSize = Size; } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric int getVarArgsFPRIndex() const { return VarArgsFPRIndex; } 1910b57cec5SDimitry Andric void setVarArgsFPRIndex(int Index) { VarArgsFPRIndex = Index; } 1920b57cec5SDimitry Andric 1930b57cec5SDimitry Andric unsigned getVarArgsFPRSize() const { return VarArgsFPRSize; } 1940b57cec5SDimitry Andric void setVarArgsFPRSize(unsigned Size) { VarArgsFPRSize = Size; } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric unsigned getSRetReturnReg() const { return SRetReturnReg; } 1970b57cec5SDimitry Andric void setSRetReturnReg(unsigned Reg) { SRetReturnReg = Reg; } 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric unsigned getJumpTableEntrySize(int Idx) const { 2000b57cec5SDimitry Andric auto It = JumpTableEntryInfo.find(Idx); 2010b57cec5SDimitry Andric if (It != JumpTableEntryInfo.end()) 2020b57cec5SDimitry Andric return It->second.first; 2030b57cec5SDimitry Andric return 4; 2040b57cec5SDimitry Andric } 2050b57cec5SDimitry Andric MCSymbol *getJumpTableEntryPCRelSymbol(int Idx) const { 2060b57cec5SDimitry Andric return JumpTableEntryInfo.find(Idx)->second.second; 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric void setJumpTableEntryInfo(int Idx, unsigned Size, MCSymbol *PCRelSym) { 2090b57cec5SDimitry Andric JumpTableEntryInfo[Idx] = std::make_pair(Size, PCRelSym); 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric 2120b57cec5SDimitry Andric using SetOfInstructions = SmallPtrSet<const MachineInstr *, 16>; 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric const SetOfInstructions &getLOHRelated() const { return LOHRelated; } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric // Shortcuts for LOH related types. 2170b57cec5SDimitry Andric class MILOHDirective { 2180b57cec5SDimitry Andric MCLOHType Kind; 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric /// Arguments of this directive. Order matters. 2210b57cec5SDimitry Andric SmallVector<const MachineInstr *, 3> Args; 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric public: 2240b57cec5SDimitry Andric using LOHArgs = ArrayRef<const MachineInstr *>; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric MILOHDirective(MCLOHType Kind, LOHArgs Args) 2270b57cec5SDimitry Andric : Kind(Kind), Args(Args.begin(), Args.end()) { 2280b57cec5SDimitry Andric assert(isValidMCLOHType(Kind) && "Invalid LOH directive type!"); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric MCLOHType getKind() const { return Kind; } 2320b57cec5SDimitry Andric LOHArgs getArgs() const { return Args; } 2330b57cec5SDimitry Andric }; 2340b57cec5SDimitry Andric 2350b57cec5SDimitry Andric using MILOHArgs = MILOHDirective::LOHArgs; 2360b57cec5SDimitry Andric using MILOHContainer = SmallVector<MILOHDirective, 32>; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric const MILOHContainer &getLOHContainer() const { return LOHContainerSet; } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric /// Add a LOH directive of this @p Kind and this @p Args. 2410b57cec5SDimitry Andric void addLOHDirective(MCLOHType Kind, MILOHArgs Args) { 2420b57cec5SDimitry Andric LOHContainerSet.push_back(MILOHDirective(Kind, Args)); 2430b57cec5SDimitry Andric LOHRelated.insert(Args.begin(), Args.end()); 2440b57cec5SDimitry Andric } 2450b57cec5SDimitry Andric 2460b57cec5SDimitry Andric SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() { 2470b57cec5SDimitry Andric return ForwardedMustTailRegParms; 2480b57cec5SDimitry Andric } 2490b57cec5SDimitry Andric 2500b57cec5SDimitry Andric unsigned getTaggedBasePointerOffset() const { 2510b57cec5SDimitry Andric return TaggedBasePointerOffset; 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric void setTaggedBasePointerOffset(unsigned Offset) { 2540b57cec5SDimitry Andric TaggedBasePointerOffset = Offset; 2550b57cec5SDimitry Andric } 2560b57cec5SDimitry Andric 2570b57cec5SDimitry Andric private: 2580b57cec5SDimitry Andric // Hold the lists of LOHs. 2590b57cec5SDimitry Andric MILOHContainer LOHContainerSet; 2600b57cec5SDimitry Andric SetOfInstructions LOHRelated; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric DenseMap<int, std::pair<unsigned, MCSymbol *>> JumpTableEntryInfo; 2630b57cec5SDimitry Andric }; 2640b57cec5SDimitry Andric 2650b57cec5SDimitry Andric } // end namespace llvm 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AARCH64_AARCH64MACHINEFUNCTIONINFO_H 268