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