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
24namespace llvm {
25
26namespace yaml {
27struct ARMFunctionInfo;
28} // end namespace yaml
29
30class ARMSubtarget;
31
32/// ARMFunctionInfo - This class is derived from MachineFunctionInfo and
33/// contains private ARM-specific information for each MachineFunction.
34class 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 DPRCSOffset = 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 DPRCSSize = 0;
94
95 /// NumAlignedDPRCS2Regs - The number of callee-saved DPRs that are saved in
96 /// the aligned portion of the stack frame. This is always a contiguous
97 /// sequence of D-registers starting from d8.
98 ///
99 /// We do not keep track of the frame indices used for these registers - they
100 /// behave like any other frame index in the aligned stack frame. These
101 /// registers also aren't included in DPRCSSize above.
102 unsigned NumAlignedDPRCS2Regs = 0;
103
104 unsigned PICLabelUId = 0;
105
106 /// VarArgsFrameIndex - FrameIndex for start of varargs area.
107 int VarArgsFrameIndex = 0;
108
109 /// HasITBlocks - True if IT blocks have been inserted.
110 bool HasITBlocks = false;
111
112 // Security Extensions
113 bool IsCmseNSEntry;
114 bool IsCmseNSCall;
115
116 /// CPEClones - Track constant pool entries clones created by Constant Island
117 /// pass.
118 DenseMap<unsigned, unsigned> CPEClones;
119
120 /// ArgumentStackSize - amount of bytes on stack consumed by the arguments
121 /// being passed on the stack
122 unsigned ArgumentStackSize = 0;
123
124 /// ArgumentStackToRestore - amount of bytes on stack consumed that we must
125 /// restore on return.
126 unsigned ArgumentStackToRestore = 0;
127
128 /// CoalescedWeights - mapping of basic blocks to the rolling counter of
129 /// coalesced weights.
130 DenseMap<const MachineBasicBlock*, unsigned> CoalescedWeights;
131
132 /// True if this function has a subset of CSRs that is handled explicitly via
133 /// copies.
134 bool IsSplitCSR = false;
135
136 /// Globals that have had their storage promoted into the constant pool.
137 SmallPtrSet<const GlobalVariable*,2> PromotedGlobals;
138
139 /// The amount the literal pool has been increasedby due to promoted globals.
140 int PromotedGlobalsIncrease = 0;
141
142 /// True if r0 will be preserved by a call to this function (e.g. C++
143 /// con/destructors).
144 bool PreservesR0 = false;
145
146 /// True if the function should sign its return address.
147 bool SignReturnAddress = false;
148
149 /// True if the fucntion should sign its return address, even if LR is not
150 /// saved.
151 bool SignReturnAddressAll = false;
152
153 /// True if BTI instructions should be placed at potential indirect jump
154 /// destinations.
155 bool BranchTargetEnforcement = false;
156
157public:
158 ARMFunctionInfo() = default;
159
160 explicit ARMFunctionInfo(const Function &F, const ARMSubtarget *STI);
161
162 MachineFunctionInfo *
163 clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF,
164 const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB)
165 const override;
166
167 bool isThumbFunction() const { return isThumb; }
168 bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
169 bool isThumb2Function() const { return isThumb && hasThumb2; }
170
171 bool isCmseNSEntryFunction() const { return IsCmseNSEntry; }
172 bool isCmseNSCallFunction() const { return IsCmseNSCall; }
173
174 unsigned getArgRegsSaveSize() const { return ArgRegsSaveSize; }
175 void setArgRegsSaveSize(unsigned s) { ArgRegsSaveSize = s; }
176
177 unsigned getReturnRegsCount() const { return ReturnRegsCount; }
178 void setReturnRegsCount(unsigned s) { ReturnRegsCount = s; }
179
180 bool hasStackFrame() const { return HasStackFrame; }
181 void setHasStackFrame(bool s) { HasStackFrame = s; }
182
183 bool shouldRestoreSPFromFP() const { return RestoreSPFromFP; }
184 void setShouldRestoreSPFromFP(bool s) { RestoreSPFromFP = s; }
185
186 bool isLRSpilled() const { return LRSpilled; }
187 void setLRIsSpilled(bool s) { LRSpilled = s; }
188
189 unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
190 void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
191
192 unsigned getNumAlignedDPRCS2Regs() const { return NumAlignedDPRCS2Regs; }
193 void setNumAlignedDPRCS2Regs(unsigned n) { NumAlignedDPRCS2Regs = n; }
194
195 unsigned getGPRCalleeSavedArea1Offset() const { return GPRCS1Offset; }
196 unsigned getGPRCalleeSavedArea2Offset() const { return GPRCS2Offset; }
197 unsigned getDPRCalleeSavedAreaOffset() const { return DPRCSOffset; }
198
199 void setGPRCalleeSavedArea1Offset(unsigned o) { GPRCS1Offset = o; }
200 void setGPRCalleeSavedArea2Offset(unsigned o) { GPRCS2Offset = o; }
201 void setDPRCalleeSavedAreaOffset(unsigned o) { DPRCSOffset = o; }
202
203 unsigned getFPCXTSaveAreaSize() const { return FPCXTSaveSize; }
204 unsigned getFrameRecordSavedAreaSize() const { return FRSaveSize; }
205 unsigned getGPRCalleeSavedArea1Size() const { return GPRCS1Size; }
206 unsigned getGPRCalleeSavedArea2Size() const { return GPRCS2Size; }
207 unsigned getDPRCalleeSavedGapSize() const { return DPRCSAlignGapSize; }
208 unsigned getDPRCalleeSavedAreaSize() const { return DPRCSSize; }
209
210 void setFPCXTSaveAreaSize(unsigned s) { FPCXTSaveSize = s; }
211 void setFrameRecordSavedAreaSize(unsigned s) { FRSaveSize = s; }
212 void setGPRCalleeSavedArea1Size(unsigned s) { GPRCS1Size = s; }
213 void setGPRCalleeSavedArea2Size(unsigned s) { GPRCS2Size = s; }
214 void setDPRCalleeSavedGapSize(unsigned s) { DPRCSAlignGapSize = s; }
215 void setDPRCalleeSavedAreaSize(unsigned s) { DPRCSSize = s; }
216
217 unsigned getArgumentStackSize() const { return ArgumentStackSize; }
218 void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
219
220 unsigned getArgumentStackToRestore() const { return ArgumentStackToRestore; }
221 void setArgumentStackToRestore(unsigned v) { ArgumentStackToRestore = v; }
222
223 void initPICLabelUId(unsigned UId) {
224 PICLabelUId = UId;
225 }
226
227 unsigned getNumPICLabels() const {
228 return PICLabelUId;
229 }
230
231 unsigned createPICLabelUId() {
232 return PICLabelUId++;
233 }
234
235 int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
236 void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
237
238 bool hasITBlocks() const { return HasITBlocks; }
239 void setHasITBlocks(bool h) { HasITBlocks = h; }
240
241 bool isSplitCSR() const { return IsSplitCSR; }
242 void setIsSplitCSR(bool s) { IsSplitCSR = s; }
243
244 void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
245 if (!CPEClones.insert(KV: std::make_pair(x&: CPCloneIdx, y&: CPIdx)).second)
246 llvm_unreachable("Duplicate entries!");
247 }
248
249 unsigned getOriginalCPIdx(unsigned CloneIdx) const {
250 DenseMap<unsigned, unsigned>::const_iterator I = CPEClones.find(Val: CloneIdx);
251 if (I != CPEClones.end())
252 return I->second;
253 else
254 return -1U;
255 }
256
257 DenseMap<const MachineBasicBlock*, unsigned>::iterator getCoalescedWeight(
258 MachineBasicBlock* MBB) {
259 auto It = CoalescedWeights.find(Val: MBB);
260 if (It == CoalescedWeights.end()) {
261 It = CoalescedWeights.insert(KV: std::make_pair(x&: MBB, y: 0)).first;
262 }
263 return It;
264 }
265
266 /// Indicate to the backend that \c GV has had its storage changed to inside
267 /// a constant pool. This means it no longer needs to be emitted as a
268 /// global variable.
269 void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV) {
270 PromotedGlobals.insert(Ptr: GV);
271 }
272 SmallPtrSet<const GlobalVariable*, 2>& getGlobalsPromotedToConstantPool() {
273 return PromotedGlobals;
274 }
275 int getPromotedConstpoolIncrease() const {
276 return PromotedGlobalsIncrease;
277 }
278 void setPromotedConstpoolIncrease(int Sz) {
279 PromotedGlobalsIncrease = Sz;
280 }
281
282 DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;
283 DenseMap<unsigned, unsigned> EHPrologueOffsetInRegs;
284
285 void setPreservesR0() { PreservesR0 = true; }
286 bool getPreservesR0() const { return PreservesR0; }
287
288 bool shouldSignReturnAddress() const {
289 return shouldSignReturnAddress(SpillsLR: LRSpilled);
290 }
291
292 bool shouldSignReturnAddress(bool SpillsLR) const {
293 if (!SignReturnAddress)
294 return false;
295 if (SignReturnAddressAll)
296 return true;
297 return SpillsLR;
298 }
299
300 bool branchTargetEnforcement() const { return BranchTargetEnforcement; }
301
302 void initializeBaseYamlFields(const yaml::ARMFunctionInfo &YamlMFI);
303};
304
305namespace yaml {
306struct ARMFunctionInfo final : public yaml::MachineFunctionInfo {
307 bool LRSpilled;
308
309 ARMFunctionInfo() = default;
310 ARMFunctionInfo(const llvm::ARMFunctionInfo &MFI);
311
312 void mappingImpl(yaml::IO &YamlIO) override;
313 ~ARMFunctionInfo() = default;
314};
315
316template <> struct MappingTraits<ARMFunctionInfo> {
317 static void mapping(IO &YamlIO, ARMFunctionInfo &MFI) {
318 YamlIO.mapOptional(Key: "isLRSpilled", Val&: MFI.LRSpilled);
319 }
320};
321
322} // end namespace yaml
323
324} // end namespace llvm
325
326#endif // LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
327