xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86MachineFunctionInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===-- X86MachineFunctionInfo.h - X86 machine function info ----*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file declares X86-specific per-machine-function information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_X86_X86MACHINEFUNCTIONINFO_H
14 #define LLVM_LIB_TARGET_X86_X86MACHINEFUNCTIONINFO_H
15 
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/CodeGen/CallingConvLower.h"
19 #include "llvm/CodeGen/MIRYamlMapping.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/Support/YAMLTraits.h"
22 #include <set>
23 
24 namespace llvm {
25 
26 enum AMXProgModelEnum { None = 0, DirectReg = 1, ManagedRA = 2 };
27 
28 class X86MachineFunctionInfo;
29 
30 namespace yaml {
31 template <> struct ScalarEnumerationTraits<AMXProgModelEnum> {
32   static void enumeration(IO &YamlIO, AMXProgModelEnum &Value) {
33     YamlIO.enumCase(Value, "None", AMXProgModelEnum::None);
34     YamlIO.enumCase(Value, "DirectReg", AMXProgModelEnum::DirectReg);
35     YamlIO.enumCase(Value, "ManagedRA", AMXProgModelEnum::ManagedRA);
36   }
37 };
38 
39 struct X86MachineFunctionInfo final : public yaml::MachineFunctionInfo {
40   AMXProgModelEnum AMXProgModel;
41 
42   X86MachineFunctionInfo() = default;
43   X86MachineFunctionInfo(const llvm::X86MachineFunctionInfo &MFI);
44 
45   void mappingImpl(yaml::IO &YamlIO) override;
46   ~X86MachineFunctionInfo() = default;
47 };
48 
49 template <> struct MappingTraits<X86MachineFunctionInfo> {
50   static void mapping(IO &YamlIO, X86MachineFunctionInfo &MFI) {
51     YamlIO.mapOptional("amxProgModel", MFI.AMXProgModel);
52   }
53 };
54 } // end namespace yaml
55 
56 /// X86MachineFunctionInfo - This class is derived from MachineFunction and
57 /// contains private X86 target-specific information for each MachineFunction.
58 class X86MachineFunctionInfo : public MachineFunctionInfo {
59   virtual void anchor();
60 
61   /// ForceFramePointer - True if the function is required to use of frame
62   /// pointer for reasons other than it containing dynamic allocation or
63   /// that FP eliminatation is turned off. For example, Cygwin main function
64   /// contains stack pointer re-alignment code which requires FP.
65   bool ForceFramePointer = false;
66 
67   /// RestoreBasePointerOffset - Non-zero if the function has base pointer
68   /// and makes call to llvm.eh.sjlj.setjmp. When non-zero, the value is a
69   /// displacement from the frame pointer to a slot where the base pointer
70   /// is stashed.
71   signed char RestoreBasePointerOffset = 0;
72 
73   /// WinEHXMMSlotInfo - Slot information of XMM registers in the stack frame
74   /// in bytes.
75   DenseMap<int, unsigned> WinEHXMMSlotInfo;
76 
77   /// CalleeSavedFrameSize - Size of the callee-saved register portion of the
78   /// stack frame in bytes.
79   unsigned CalleeSavedFrameSize = 0;
80 
81   /// BytesToPopOnReturn - Number of bytes function pops on return (in addition
82   /// to the space used by the return address).
83   /// Used on windows platform for stdcall & fastcall name decoration
84   unsigned BytesToPopOnReturn = 0;
85 
86   /// ReturnAddrIndex - FrameIndex for return slot.
87   int ReturnAddrIndex = 0;
88 
89   /// FrameIndex for return slot.
90   int FrameAddrIndex = 0;
91 
92   /// TailCallReturnAddrDelta - The number of bytes by which return address
93   /// stack slot is moved as the result of tail call optimization.
94   int TailCallReturnAddrDelta = 0;
95 
96   /// SRetReturnReg - Some subtargets require that sret lowering includes
97   /// returning the value of the returned struct in a register. This field
98   /// holds the virtual register into which the sret argument is passed.
99   Register SRetReturnReg;
100 
101   /// GlobalBaseReg - keeps track of the virtual register initialized for
102   /// use as the global base register. This is used for PIC in some PIC
103   /// relocation models.
104   Register GlobalBaseReg;
105 
106   /// VarArgsFrameIndex - FrameIndex for start of varargs area.
107   int VarArgsFrameIndex = 0;
108   /// RegSaveFrameIndex - X86-64 vararg func register save area.
109   int RegSaveFrameIndex = 0;
110   /// VarArgsGPOffset - X86-64 vararg func int reg offset.
111   unsigned VarArgsGPOffset = 0;
112   /// VarArgsFPOffset - X86-64 vararg func fp reg offset.
113   unsigned VarArgsFPOffset = 0;
114   /// ArgumentStackSize - The number of bytes on stack consumed by the arguments
115   /// being passed on the stack.
116   unsigned ArgumentStackSize = 0;
117   /// NumLocalDynamics - Number of local-dynamic TLS accesses.
118   unsigned NumLocalDynamics = 0;
119   /// HasPushSequences - Keeps track of whether this function uses sequences
120   /// of pushes to pass function parameters.
121   bool HasPushSequences = false;
122 
123   /// True if the function recovers from an SEH exception, and therefore needs
124   /// to spill and restore the frame pointer.
125   bool HasSEHFramePtrSave = false;
126 
127   /// The frame index of a stack object containing the original frame pointer
128   /// used to address arguments in a function using a base pointer.
129   int SEHFramePtrSaveIndex = 0;
130 
131   /// The AMX programing model used in the function.
132   AMXProgModelEnum AMXProgModel = AMXProgModelEnum::None;
133 
134   /// True if this function has a subset of CSRs that is handled explicitly via
135   /// copies.
136   bool IsSplitCSR = false;
137 
138   /// True if this function uses the red zone.
139   bool UsesRedZone = false;
140 
141   /// True if this function has DYN_ALLOCA instructions.
142   bool HasDynAlloca = false;
143 
144   /// True if this function has any preallocated calls.
145   bool HasPreallocatedCall = false;
146 
147   /// Whether this function has an extended frame record [Ctx, RBP, Return
148   /// addr]. If so, bit 60 of the in-memory frame pointer will be 1 to enable
149   /// other tools to detect the extended record.
150   bool HasSwiftAsyncContext = false;
151 
152   /// Ajust stack for push2/pop2
153   bool PadForPush2Pop2 = false;
154 
155   /// Candidate registers for push2/pop2
156   std::set<Register> CandidatesForPush2Pop2;
157 
158   /// True if this function has CFI directives that adjust the CFA.
159   /// This is used to determine if we should direct the debugger to use
160   /// the CFA instead of the stack pointer.
161   bool HasCFIAdjustCfa = false;
162 
163   MachineInstr *StackPtrSaveMI = nullptr;
164 
165   std::optional<int> SwiftAsyncContextFrameIdx;
166 
167   // Preallocated fields are only used during isel.
168   // FIXME: Can we find somewhere else to store these?
169   DenseMap<const Value *, size_t> PreallocatedIds;
170   SmallVector<size_t, 0> PreallocatedStackSizes;
171   SmallVector<SmallVector<size_t, 4>, 0> PreallocatedArgOffsets;
172 
173 private:
174   /// ForwardedMustTailRegParms - A list of virtual and physical registers
175   /// that must be forwarded to every musttail call.
176   SmallVector<ForwardedRegister, 1> ForwardedMustTailRegParms;
177 
178 public:
179   X86MachineFunctionInfo() = default;
180   X86MachineFunctionInfo(const Function &F, const TargetSubtargetInfo *STI) {}
181 
182   X86MachineFunctionInfo(const X86MachineFunctionInfo &) = default;
183 
184   MachineFunctionInfo *
185   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
186         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
187       const override;
188 
189   void initializeBaseYamlFields(const yaml::X86MachineFunctionInfo &YamlMFI);
190 
191   bool getForceFramePointer() const { return ForceFramePointer;}
192   void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
193 
194   bool getHasPushSequences() const { return HasPushSequences; }
195   void setHasPushSequences(bool HasPush) { HasPushSequences = HasPush; }
196 
197   bool getRestoreBasePointer() const { return RestoreBasePointerOffset!=0; }
198   void setRestoreBasePointer(const MachineFunction *MF);
199   void setRestoreBasePointer(unsigned CalleeSavedFrameSize) {
200     RestoreBasePointerOffset = -CalleeSavedFrameSize;
201   }
202   int getRestoreBasePointerOffset() const {return RestoreBasePointerOffset; }
203 
204   DenseMap<int, unsigned>& getWinEHXMMSlotInfo() { return WinEHXMMSlotInfo; }
205   const DenseMap<int, unsigned>& getWinEHXMMSlotInfo() const {
206     return WinEHXMMSlotInfo; }
207 
208   unsigned getCalleeSavedFrameSize() const {
209     return CalleeSavedFrameSize + 8 * padForPush2Pop2();
210   }
211   void setCalleeSavedFrameSize(unsigned bytes) { CalleeSavedFrameSize = bytes; }
212 
213   unsigned getBytesToPopOnReturn() const { return BytesToPopOnReturn; }
214   void setBytesToPopOnReturn (unsigned bytes) { BytesToPopOnReturn = bytes;}
215 
216   int getRAIndex() const { return ReturnAddrIndex; }
217   void setRAIndex(int Index) { ReturnAddrIndex = Index; }
218 
219   int getFAIndex() const { return FrameAddrIndex; }
220   void setFAIndex(int Index) { FrameAddrIndex = Index; }
221 
222   int getTCReturnAddrDelta() const { return TailCallReturnAddrDelta; }
223   void setTCReturnAddrDelta(int delta) {TailCallReturnAddrDelta = delta;}
224 
225   Register getSRetReturnReg() const { return SRetReturnReg; }
226   void setSRetReturnReg(Register Reg) { SRetReturnReg = Reg; }
227 
228   Register getGlobalBaseReg() const { return GlobalBaseReg; }
229   void setGlobalBaseReg(Register Reg) { GlobalBaseReg = Reg; }
230 
231   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
232   void setVarArgsFrameIndex(int Idx) { VarArgsFrameIndex = Idx; }
233 
234   int getRegSaveFrameIndex() const { return RegSaveFrameIndex; }
235   void setRegSaveFrameIndex(int Idx) { RegSaveFrameIndex = Idx; }
236 
237   unsigned getVarArgsGPOffset() const { return VarArgsGPOffset; }
238   void setVarArgsGPOffset(unsigned Offset) { VarArgsGPOffset = Offset; }
239 
240   unsigned getVarArgsFPOffset() const { return VarArgsFPOffset; }
241   void setVarArgsFPOffset(unsigned Offset) { VarArgsFPOffset = Offset; }
242 
243   unsigned getArgumentStackSize() const { return ArgumentStackSize; }
244   void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
245 
246   unsigned getNumLocalDynamicTLSAccesses() const { return NumLocalDynamics; }
247   void incNumLocalDynamicTLSAccesses() { ++NumLocalDynamics; }
248 
249   bool getHasSEHFramePtrSave() const { return HasSEHFramePtrSave; }
250   void setHasSEHFramePtrSave(bool V) { HasSEHFramePtrSave = V; }
251 
252   int getSEHFramePtrSaveIndex() const { return SEHFramePtrSaveIndex; }
253   void setSEHFramePtrSaveIndex(int Index) { SEHFramePtrSaveIndex = Index; }
254 
255   AMXProgModelEnum getAMXProgModel() const { return AMXProgModel; }
256   void setAMXProgModel(AMXProgModelEnum Model) {
257     assert((AMXProgModel == AMXProgModelEnum::None || AMXProgModel == Model) &&
258            "mixed model is not supported");
259     AMXProgModel = Model;
260   }
261 
262   SmallVectorImpl<ForwardedRegister> &getForwardedMustTailRegParms() {
263     return ForwardedMustTailRegParms;
264   }
265 
266   bool isSplitCSR() const { return IsSplitCSR; }
267   void setIsSplitCSR(bool s) { IsSplitCSR = s; }
268 
269   bool getUsesRedZone() const { return UsesRedZone; }
270   void setUsesRedZone(bool V) { UsesRedZone = V; }
271 
272   bool hasDynAlloca() const { return HasDynAlloca; }
273   void setHasDynAlloca(bool v) { HasDynAlloca = v; }
274 
275   bool hasPreallocatedCall() const { return HasPreallocatedCall; }
276   void setHasPreallocatedCall(bool v) { HasPreallocatedCall = v; }
277 
278   bool hasSwiftAsyncContext() const { return HasSwiftAsyncContext; }
279   void setHasSwiftAsyncContext(bool v) { HasSwiftAsyncContext = v; }
280 
281   bool padForPush2Pop2() const { return PadForPush2Pop2; }
282   void setPadForPush2Pop2(bool V) { PadForPush2Pop2 = V; }
283 
284   bool isCandidateForPush2Pop2(Register Reg) const {
285     return CandidatesForPush2Pop2.find(Reg) != CandidatesForPush2Pop2.end();
286   }
287   void addCandidateForPush2Pop2(Register Reg) {
288     CandidatesForPush2Pop2.insert(Reg);
289   }
290   size_t getNumCandidatesForPush2Pop2() const {
291     return CandidatesForPush2Pop2.size();
292   }
293 
294   bool hasCFIAdjustCfa() const { return HasCFIAdjustCfa; }
295   void setHasCFIAdjustCfa(bool v) { HasCFIAdjustCfa = v; }
296 
297   void setStackPtrSaveMI(MachineInstr *MI) { StackPtrSaveMI = MI; }
298   MachineInstr *getStackPtrSaveMI() const { return StackPtrSaveMI; }
299 
300   std::optional<int> getSwiftAsyncContextFrameIdx() const {
301     return SwiftAsyncContextFrameIdx;
302   }
303   void setSwiftAsyncContextFrameIdx(int v) { SwiftAsyncContextFrameIdx = v; }
304 
305   size_t getPreallocatedIdForCallSite(const Value *CS) {
306     auto Insert = PreallocatedIds.insert({CS, PreallocatedIds.size()});
307     if (Insert.second) {
308       PreallocatedStackSizes.push_back(0);
309       PreallocatedArgOffsets.emplace_back();
310     }
311     return Insert.first->second;
312   }
313 
314   void setPreallocatedStackSize(size_t Id, size_t StackSize) {
315     PreallocatedStackSizes[Id] = StackSize;
316   }
317 
318   size_t getPreallocatedStackSize(const size_t Id) {
319     assert(PreallocatedStackSizes[Id] != 0 && "stack size not set");
320     return PreallocatedStackSizes[Id];
321   }
322 
323   void setPreallocatedArgOffsets(size_t Id, ArrayRef<size_t> AO) {
324     PreallocatedArgOffsets[Id].assign(AO.begin(), AO.end());
325   }
326 
327   ArrayRef<size_t> getPreallocatedArgOffsets(const size_t Id) {
328     assert(!PreallocatedArgOffsets[Id].empty() && "arg offsets not set");
329     return PreallocatedArgOffsets[Id];
330   }
331 };
332 
333 } // End llvm namespace
334 
335 #endif
336