xref: /llvm-project/llvm/lib/Target/ARM/ARMMachineFunctionInfo.h (revision d37554b69b414ee00eacfd35eaa2e051b1ade2d7)
1 //===-- ARMMachineFunctionInfo.h - ARM 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 ARM-specific per-machine-function information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
14 #define LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
15 
16 #include "llvm/ADT/DenseMap.h"
17 #include "llvm/ADT/SmallPtrSet.h"
18 #include "llvm/CodeGen/MIRYamlMapping.h"
19 #include "llvm/CodeGen/MachineFunction.h"
20 #include "llvm/IR/GlobalVariable.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include <utility>
23 
24 namespace llvm {
25 
26 namespace yaml {
27 struct ARMFunctionInfo;
28 } // end namespace yaml
29 
30 class ARMSubtarget;
31 
32 /// ARMFunctionInfo - This class is derived from MachineFunctionInfo and
33 /// contains private ARM-specific information for each MachineFunction.
34 class ARMFunctionInfo : public MachineFunctionInfo {
35   virtual void anchor();
36 
37   /// isThumb - True if this function is compiled under Thumb mode.
38   /// Used to initialized Align, so must precede it.
39   bool isThumb = false;
40 
41   /// hasThumb2 - True if the target architecture supports Thumb2. Do not use
42   /// to determine if function is compiled under Thumb mode, for that use
43   /// 'isThumb'.
44   bool hasThumb2 = false;
45 
46   /// ArgsRegSaveSize - Size of the register save area for vararg functions or
47   /// those making guaranteed tail calls that need more stack argument space
48   /// than is provided by this functions incoming parameters.
49   ///
50   unsigned ArgRegsSaveSize = 0;
51 
52   /// ReturnRegsCount - Number of registers used up in the return.
53   unsigned ReturnRegsCount = 0;
54 
55   /// HasStackFrame - True if this function has a stack frame. Set by
56   /// determineCalleeSaves().
57   bool HasStackFrame = false;
58 
59   /// RestoreSPFromFP - True if epilogue should restore SP from FP. Set by
60   /// emitPrologue.
61   bool RestoreSPFromFP = false;
62 
63   /// LRSpilled - True if the LR register has been for spilled for
64   /// any reason, so it's legal to emit an ARM::tBfar (i.e. "bl").
65   bool LRSpilled = false;
66 
67   /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
68   /// spill stack offset.
69   unsigned FramePtrSpillOffset = 0;
70 
71   /// GPRCS1Offset, GPRCS2Offset, DPRCSOffset - Starting offset of callee saved
72   /// register spills areas. For Mac OS X:
73   ///
74   /// GPR callee-saved (1) : r4, r5, r6, r7, lr
75   /// --------------------------------------------
76   /// GPR callee-saved (2) : r8, r10, r11
77   /// --------------------------------------------
78   /// DPR callee-saved : d8 - d15
79   ///
80   /// Also see AlignedDPRCSRegs below. Not all D-regs need to go in area 3.
81   /// Some may be spilled after the stack has been realigned.
82   unsigned GPRCS1Offset = 0;
83   unsigned GPRCS2Offset = 0;
84   unsigned DPRCS1Offset = 0;
85 
86   /// GPRCS1Size, GPRCS2Size, DPRCSSize - Sizes of callee saved register spills
87   /// areas.
88   unsigned FPCXTSaveSize = 0;
89   unsigned FRSaveSize = 0;
90   unsigned GPRCS1Size = 0;
91   unsigned GPRCS2Size = 0;
92   unsigned DPRCSAlignGapSize = 0;
93   unsigned DPRCS1Size = 0;
94   unsigned GPRCS3Size = 0;
95 
96   /// NumAlignedDPRCS2Regs - The number of callee-saved DPRs that are saved in
97   /// the aligned portion of the stack frame.  This is always a contiguous
98   /// sequence of D-registers starting from d8.
99   ///
100   /// We do not keep track of the frame indices used for these registers - they
101   /// behave like any other frame index in the aligned stack frame.  These
102   /// registers also aren't included in DPRCSSize above.
103   unsigned NumAlignedDPRCS2Regs = 0;
104 
105   unsigned PICLabelUId = 0;
106 
107   /// VarArgsFrameIndex - FrameIndex for start of varargs area.
108   int VarArgsFrameIndex = 0;
109 
110   /// HasITBlocks - True if IT blocks have been inserted.
111   bool HasITBlocks = false;
112 
113   // Security Extensions
114   bool IsCmseNSEntry;
115   bool IsCmseNSCall;
116 
117   /// CPEClones - Track constant pool entries clones created by Constant Island
118   /// pass.
119   DenseMap<unsigned, unsigned> CPEClones;
120 
121   /// ArgumentStackSize - amount of bytes on stack consumed by the arguments
122   /// being passed on the stack
123   unsigned ArgumentStackSize = 0;
124 
125   /// ArgumentStackToRestore - amount of bytes on stack consumed that we must
126   /// restore on return.
127   unsigned ArgumentStackToRestore = 0;
128 
129   /// CoalescedWeights - mapping of basic blocks to the rolling counter of
130   /// coalesced weights.
131   DenseMap<const MachineBasicBlock*, unsigned> CoalescedWeights;
132 
133   /// True if this function has a subset of CSRs that is handled explicitly via
134   /// copies.
135   bool IsSplitCSR = false;
136 
137   /// Globals that have had their storage promoted into the constant pool.
138   SmallPtrSet<const GlobalVariable*,2> PromotedGlobals;
139 
140   /// The amount the literal pool has been increasedby due to promoted globals.
141   int PromotedGlobalsIncrease = 0;
142 
143   /// True if r0 will be preserved by a call to this function (e.g. C++
144   /// con/destructors).
145   bool PreservesR0 = false;
146 
147   /// True if the function should sign its return address.
148   bool SignReturnAddress = false;
149 
150   /// True if the fucntion should sign its return address, even if LR is not
151   /// saved.
152   bool SignReturnAddressAll = false;
153 
154   /// True if BTI instructions should be placed at potential indirect jump
155   /// destinations.
156   bool BranchTargetEnforcement = false;
157 
158 public:
159   ARMFunctionInfo() = default;
160 
161   explicit ARMFunctionInfo(const Function &F, const ARMSubtarget *STI);
162 
163   MachineFunctionInfo *
164   clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
165         const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
166       const override;
167 
168   bool isThumbFunction() const { return isThumb; }
169   bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
170   bool isThumb2Function() const { return isThumb && hasThumb2; }
171 
172   bool isCmseNSEntryFunction() const { return IsCmseNSEntry; }
173   bool isCmseNSCallFunction() const { return IsCmseNSCall; }
174 
175   unsigned getArgRegsSaveSize() const { return ArgRegsSaveSize; }
176   void setArgRegsSaveSize(unsigned s) { ArgRegsSaveSize = s; }
177 
178   unsigned getReturnRegsCount() const { return ReturnRegsCount; }
179   void setReturnRegsCount(unsigned s) { ReturnRegsCount = s; }
180 
181   bool hasStackFrame() const { return HasStackFrame; }
182   void setHasStackFrame(bool s) { HasStackFrame = s; }
183 
184   bool shouldRestoreSPFromFP() const { return RestoreSPFromFP; }
185   void setShouldRestoreSPFromFP(bool s) { RestoreSPFromFP = s; }
186 
187   bool isLRSpilled() const { return LRSpilled; }
188   void setLRIsSpilled(bool s) { LRSpilled = s; }
189 
190   unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
191   void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
192 
193   unsigned getNumAlignedDPRCS2Regs() const { return NumAlignedDPRCS2Regs; }
194   void setNumAlignedDPRCS2Regs(unsigned n) { NumAlignedDPRCS2Regs = n; }
195 
196   unsigned getGPRCalleeSavedArea1Offset() const { return GPRCS1Offset; }
197   unsigned getGPRCalleeSavedArea2Offset() const { return GPRCS2Offset; }
198   unsigned getDPRCalleeSavedArea1Offset() const { return DPRCS1Offset; }
199 
200   void setGPRCalleeSavedArea1Offset(unsigned o) { GPRCS1Offset = o; }
201   void setGPRCalleeSavedArea2Offset(unsigned o) { GPRCS2Offset = o; }
202   void setDPRCalleeSavedArea1Offset(unsigned o) { DPRCS1Offset = o; }
203 
204   unsigned getFPCXTSaveAreaSize() const       { return FPCXTSaveSize; }
205   unsigned getFrameRecordSavedAreaSize() const { return FRSaveSize; }
206   unsigned getGPRCalleeSavedArea1Size() const { return GPRCS1Size; }
207   unsigned getGPRCalleeSavedArea2Size() const { return GPRCS2Size; }
208   unsigned getDPRCalleeSavedGapSize() const   { return DPRCSAlignGapSize; }
209   unsigned getDPRCalleeSavedArea1Size() const { return DPRCS1Size; }
210   unsigned getGPRCalleeSavedArea3Size() const { return GPRCS3Size; }
211 
212   void setFPCXTSaveAreaSize(unsigned s)       { FPCXTSaveSize = s; }
213   void setFrameRecordSavedAreaSize(unsigned s) { FRSaveSize = s; }
214   void setGPRCalleeSavedArea1Size(unsigned s) { GPRCS1Size = s; }
215   void setGPRCalleeSavedArea2Size(unsigned s) { GPRCS2Size = s; }
216   void setDPRCalleeSavedGapSize(unsigned s)   { DPRCSAlignGapSize = s; }
217   void setDPRCalleeSavedArea1Size(unsigned s) { DPRCS1Size = s; }
218   void setGPRCalleeSavedArea3Size(unsigned s) { GPRCS3Size = s; }
219 
220   unsigned getArgumentStackSize() const { return ArgumentStackSize; }
221   void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
222 
223   unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; }
224   void setArgumentStackToRestore(unsigned v) { ArgumentStackToRestore = v; }
225 
226   void initPICLabelUId(unsigned UId) {
227     PICLabelUId = UId;
228   }
229 
230   unsigned getNumPICLabels() const {
231     return PICLabelUId;
232   }
233 
234   unsigned createPICLabelUId() {
235     return PICLabelUId++;
236   }
237 
238   int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
239   void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
240 
241   bool hasITBlocks() const { return HasITBlocks; }
242   void setHasITBlocks(bool h) { HasITBlocks = h; }
243 
244   bool isSplitCSR() const { return IsSplitCSR; }
245   void setIsSplitCSR(bool s) { IsSplitCSR = s; }
246 
247   void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
248     if (!CPEClones.insert(std::make_pair(CPCloneIdx, CPIdx)).second)
249       llvm_unreachable("Duplicate entries!");
250   }
251 
252   unsigned getOriginalCPIdx(unsigned CloneIdx) const {
253     DenseMap<unsigned, unsigned>::const_iterator I = CPEClones.find(CloneIdx);
254     if (I != CPEClones.end())
255       return I->second;
256     else
257       return -1U;
258   }
259 
260   DenseMap<const MachineBasicBlock *, unsigned>::iterator
261   getCoalescedWeight(MachineBasicBlock *MBB) {
262     return CoalescedWeights.try_emplace(MBB, 0).first;
263   }
264 
265   /// Indicate to the backend that \c GV has had its storage changed to inside
266   /// a constant pool. This means it no longer needs to be emitted as a
267   /// global variable.
268   void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV) {
269     PromotedGlobals.insert(GV);
270   }
271   SmallPtrSet<const GlobalVariable*, 2>& getGlobalsPromotedToConstantPool() {
272     return PromotedGlobals;
273   }
274   int getPromotedConstpoolIncrease() const {
275     return PromotedGlobalsIncrease;
276   }
277   void setPromotedConstpoolIncrease(int Sz) {
278     PromotedGlobalsIncrease = Sz;
279   }
280 
281   DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;
282   DenseMap<unsigned, unsigned> EHPrologueOffsetInRegs;
283 
284   void setPreservesR0() { PreservesR0 = true; }
285   bool getPreservesR0() const { return PreservesR0; }
286 
287   bool shouldSignReturnAddress() const {
288     return shouldSignReturnAddress(LRSpilled);
289   }
290 
291   bool shouldSignReturnAddress(bool SpillsLR) const {
292     if (!SignReturnAddress)
293       return false;
294     if (SignReturnAddressAll)
295       return true;
296     return SpillsLR;
297   }
298 
299   bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
300 
301   void initializeBaseYamlFields(const yaml::ARMFunctionInfo &YamlMFI);
302 };
303 
304 namespace yaml {
305 struct ARMFunctionInfo final : public yaml::MachineFunctionInfo {
306   bool LRSpilled;
307 
308   ARMFunctionInfo() = default;
309   ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI);
310 
311   void mappingImpl(yaml::IO &YamlIO) override;
312   ~ARMFunctionInfo() = default;
313 };
314 
315 template <> struct MappingTraits<ARMFunctionInfo> {
316   static void mapping(IO &YamlIO, ARMFunctionInfo &MFI) {
317     YamlIO.mapOptional("isLRSpilled", MFI.LRSpilled);
318   }
319 };
320 
321 } // end namespace yaml
322 
323 } // end namespace llvm
324 
325 #endif // LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
326