xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64MachineFunctionInfo.h (revision 0b57cec536236d46e3dba9bd041533462f33dbb7)
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