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
23namespace llvm {
24
25namespace yaml {
26struct ARMFunctionInfo;
27} // end namespace yaml
28
29class ARMSubtarget;
30
31/// ARMFunctionInfo - This class is derived from MachineFunctionInfo and
32/// contains private ARM-specific information for each MachineFunction.
33class ARMFunctionInfo : public MachineFunctionInfo {
34 virtual void anchor();
35
36 /// isThumb - True if this function is compiled under Thumb mode.
37 /// Used to initialized Align, so must precede it.
38 bool isThumb = false;
39
40 /// hasThumb2 - True if the target architecture supports Thumb2. Do not use
41 /// to determine if function is compiled under Thumb mode, for that use
42 /// 'isThumb'.
43 bool hasThumb2 = false;
44
45 /// ArgsRegSaveSize - Size of the register save area for vararg functions or
46 /// those making guaranteed tail calls that need more stack argument space
47 /// than is provided by this functions incoming parameters.
48 ///
49 unsigned ArgRegsSaveSize = 0;
50
51 /// ReturnRegsCount - Number of registers used up in the return.
52 unsigned ReturnRegsCount = 0;
53
54 /// HasStackFrame - True if this function has a stack frame. Set by
55 /// determineCalleeSaves().
56 bool HasStackFrame = false;
57
58 /// RestoreSPFromFP - True if epilogue should restore SP from FP. Set by
59 /// emitPrologue.
60 bool RestoreSPFromFP = false;
61
62 /// LRSpilled - True if the LR register has been for spilled for
63 /// any reason, so it's legal to emit an ARM::tBfar (i.e. "bl").
64 bool LRSpilled = false;
65
66 /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
67 /// spill stack offset.
68 unsigned FramePtrSpillOffset = 0;
69
70 /// GPRCS1Offset, GPRCS2Offset, DPRCSOffset - Starting offset of callee saved
71 /// register spills areas. For Mac OS X:
72 ///
73 /// GPR callee-saved (1) : r4, r5, r6, r7, lr
74 /// --------------------------------------------
75 /// GPR callee-saved (2) : r8, r10, r11
76 /// --------------------------------------------
77 /// DPR callee-saved : d8 - d15
78 ///
79 /// Also see AlignedDPRCSRegs below. Not all D-regs need to go in area 3.
80 /// Some may be spilled after the stack has been realigned.
81 unsigned GPRCS1Offset = 0;
82 unsigned GPRCS2Offset = 0;
83 unsigned DPRCS1Offset = 0;
84
85 /// GPRCS1Size, GPRCS2Size, DPRCSSize - Sizes of callee saved register spills
86 /// areas.
87 unsigned FPCXTSaveSize = 0;
88 unsigned FRSaveSize = 0;
89 unsigned GPRCS1Size = 0;
90 unsigned GPRCS2Size = 0;
91 unsigned FPStatusSize = 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 /// The result of EstimateFunctionSizeInBytes, if that was run during frame
159 /// lowering. Used to check later that the estimate was conservative.
160 std::optional<unsigned> EstimatedFunctionSizeInBytes;
161
162public:
163 ARMFunctionInfo() = default;
164
165 explicit ARMFunctionInfo(const Function &F, const ARMSubtarget *STI);
166
167 MachineFunctionInfo *
168 clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
169 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
170 const override;
171
172 bool isThumbFunction() const { return isThumb; }
173 bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
174 bool isThumb2Function() const { return isThumb && hasThumb2; }
175
176 bool isCmseNSEntryFunction() const { return IsCmseNSEntry; }
177 bool isCmseNSCallFunction() const { return IsCmseNSCall; }
178
179 unsigned getArgRegsSaveSize() const { return ArgRegsSaveSize; }
180 void setArgRegsSaveSize(unsigned s) { ArgRegsSaveSize = s; }
181
182 unsigned getReturnRegsCount() const { return ReturnRegsCount; }
183 void setReturnRegsCount(unsigned s) { ReturnRegsCount = s; }
184
185 bool hasStackFrame() const { return HasStackFrame; }
186 void setHasStackFrame(bool s) { HasStackFrame = s; }
187
188 bool shouldRestoreSPFromFP() const { return RestoreSPFromFP; }
189 void setShouldRestoreSPFromFP(bool s) { RestoreSPFromFP = s; }
190
191 bool isLRSpilled() const { return LRSpilled; }
192 void setLRIsSpilled(bool s) { LRSpilled = s; }
193
194 unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
195 void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
196
197 unsigned getNumAlignedDPRCS2Regs() const { return NumAlignedDPRCS2Regs; }
198 void setNumAlignedDPRCS2Regs(unsigned n) { NumAlignedDPRCS2Regs = n; }
199
200 unsigned getGPRCalleeSavedArea1Offset() const { return GPRCS1Offset; }
201 unsigned getGPRCalleeSavedArea2Offset() const { return GPRCS2Offset; }
202 unsigned getDPRCalleeSavedArea1Offset() const { return DPRCS1Offset; }
203
204 void setGPRCalleeSavedArea1Offset(unsigned o) { GPRCS1Offset = o; }
205 void setGPRCalleeSavedArea2Offset(unsigned o) { GPRCS2Offset = o; }
206 void setDPRCalleeSavedArea1Offset(unsigned o) { DPRCS1Offset = o; }
207
208 unsigned getFPCXTSaveAreaSize() const { return FPCXTSaveSize; }
209 unsigned getFrameRecordSavedAreaSize() const { return FRSaveSize; }
210 unsigned getGPRCalleeSavedArea1Size() const { return GPRCS1Size; }
211 unsigned getGPRCalleeSavedArea2Size() const { return GPRCS2Size; }
212 unsigned getFPStatusSavesSize() const { return FPStatusSize; }
213 unsigned getDPRCalleeSavedGapSize() const { return DPRCSAlignGapSize; }
214 unsigned getDPRCalleeSavedArea1Size() const { return DPRCS1Size; }
215 unsigned getGPRCalleeSavedArea3Size() const { return GPRCS3Size; }
216
217 void setFPCXTSaveAreaSize(unsigned s) { FPCXTSaveSize = s; }
218 void setFrameRecordSavedAreaSize(unsigned s) { FRSaveSize = s; }
219 void setGPRCalleeSavedArea1Size(unsigned s) { GPRCS1Size = s; }
220 void setGPRCalleeSavedArea2Size(unsigned s) { GPRCS2Size = s; }
221 void setFPStatusSavesSize(unsigned s) { FPStatusSize = s; }
222 void setDPRCalleeSavedGapSize(unsigned s) { DPRCSAlignGapSize = s; }
223 void setDPRCalleeSavedArea1Size(unsigned s) { DPRCS1Size = s; }
224 void setGPRCalleeSavedArea3Size(unsigned s) { GPRCS3Size = s; }
225
226 unsigned getArgumentStackSize() const { return ArgumentStackSize; }
227 void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
228
229 unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; }
230 void setArgumentStackToRestore(unsigned v) { ArgumentStackToRestore = v; }
231
232 std::optional<unsigned> getEstimatedFunctionSizeInBytes() const {
233 return EstimatedFunctionSizeInBytes;
234 }
235 void setEstimatedFunctionSizeInBytes(unsigned v) {
236 EstimatedFunctionSizeInBytes = v;
237 }
238
239 void initPICLabelUId(unsigned UId) {
240 PICLabelUId = UId;
241 }
242
243 unsigned getNumPICLabels() const {
244 return PICLabelUId;
245 }
246
247 unsigned createPICLabelUId() {
248 return PICLabelUId++;
249 }
250
251 int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
252 void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
253
254 bool hasITBlocks() const { return HasITBlocks; }
255 void setHasITBlocks(bool h) { HasITBlocks = h; }
256
257 bool isSplitCSR() const { return IsSplitCSR; }
258 void setIsSplitCSR(bool s) { IsSplitCSR = s; }
259
260 void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
261 if (!CPEClones.insert(KV: std::make_pair(x&: CPCloneIdx, y&: CPIdx)).second)
262 llvm_unreachable("Duplicate entries!");
263 }
264
265 unsigned getOriginalCPIdx(unsigned CloneIdx) const {
266 auto I = CPEClones.find(Val: CloneIdx);
267 if (I != CPEClones.end())
268 return I->second;
269 else
270 return -1U;
271 }
272
273 DenseMap<const MachineBasicBlock *, unsigned>::iterator
274 getCoalescedWeight(MachineBasicBlock *MBB) {
275 return CoalescedWeights.try_emplace(Key: MBB, Args: 0).first;
276 }
277
278 /// Indicate to the backend that \c GV has had its storage changed to inside
279 /// a constant pool. This means it no longer needs to be emitted as a
280 /// global variable.
281 void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV) {
282 PromotedGlobals.insert(Ptr: GV);
283 }
284 SmallPtrSet<const GlobalVariable*, 2>& getGlobalsPromotedToConstantPool() {
285 return PromotedGlobals;
286 }
287 int getPromotedConstpoolIncrease() const {
288 return PromotedGlobalsIncrease;
289 }
290 void setPromotedConstpoolIncrease(int Sz) {
291 PromotedGlobalsIncrease = Sz;
292 }
293
294 DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;
295 DenseMap<unsigned, unsigned> EHPrologueOffsetInRegs;
296
297 void setPreservesR0() { PreservesR0 = true; }
298 bool getPreservesR0() const { return PreservesR0; }
299
300 bool shouldSignReturnAddress() const {
301 return shouldSignReturnAddress(SpillsLR: LRSpilled);
302 }
303
304 bool shouldSignReturnAddress(bool SpillsLR) const {
305 if (!SignReturnAddress)
306 return false;
307 if (SignReturnAddressAll)
308 return true;
309 return SpillsLR;
310 }
311
312 bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
313
314 void initializeBaseYamlFields(const yaml::ARMFunctionInfo &YamlMFI);
315};
316
317namespace yaml {
318struct ARMFunctionInfo final : public yaml::MachineFunctionInfo {
319 bool LRSpilled;
320
321 ARMFunctionInfo() = default;
322 ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI);
323
324 void mappingImpl(yaml::IO &YamlIO) override;
325 ~ARMFunctionInfo() override = default;
326};
327
328template <> struct MappingTraits<ARMFunctionInfo> {
329 static void mapping(IO &YamlIO, ARMFunctionInfo &MFI) {
330 YamlIO.mapOptional(Key: "isLRSpilled", Val&: MFI.LRSpilled);
331 }
332};
333
334} // end namespace yaml
335
336} // end namespace llvm
337
338#endif // LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
339