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/MachineFunction.h"
19#include "llvm/IR/GlobalVariable.h"
20#include "llvm/Support/ErrorHandling.h"
21#include <utility>
22
23namespace llvm {
24
25/// ARMFunctionInfo - This class is derived from MachineFunctionInfo and
26/// contains private ARM-specific information for each MachineFunction.
27class ARMFunctionInfo : public MachineFunctionInfo {
28  virtual void anchor();
29
30  /// isThumb - True if this function is compiled under Thumb mode.
31  /// Used to initialized Align, so must precede it.
32  bool isThumb = false;
33
34  /// hasThumb2 - True if the target architecture supports Thumb2. Do not use
35  /// to determine if function is compiled under Thumb mode, for that use
36  /// 'isThumb'.
37  bool hasThumb2 = false;
38
39  /// StByValParamsPadding - For parameter that is split between
40  /// GPRs and memory; while recovering GPRs part, when
41  /// StackAlignment > 4, and GPRs-part-size mod StackAlignment != 0,
42  /// we need to insert gap before parameter start address. It allows to
43  /// "attach" GPR-part to the part that was passed via stack.
44  unsigned StByValParamsPadding = 0;
45
46  /// VarArgsRegSaveSize - Size of the register save area for vararg functions.
47  ///
48  unsigned ArgRegsSaveSize = 0;
49
50  /// ReturnRegsCount - Number of registers used up in the return.
51  unsigned ReturnRegsCount = 0;
52
53  /// HasStackFrame - True if this function has a stack frame. Set by
54  /// determineCalleeSaves().
55  bool HasStackFrame = false;
56
57  /// RestoreSPFromFP - True if epilogue should restore SP from FP. Set by
58  /// emitPrologue.
59  bool RestoreSPFromFP = false;
60
61  /// LRSpilled - True if the LR register has been for spilled for
62  /// any reason, so it's legal to emit an ARM::tBfar (i.e. "bl").
63  bool LRSpilled = false;
64
65  /// FramePtrSpillOffset - If HasStackFrame, this records the frame pointer
66  /// spill stack offset.
67  unsigned FramePtrSpillOffset = 0;
68
69  /// GPRCS1Offset, GPRCS2Offset, DPRCSOffset - Starting offset of callee saved
70  /// register spills areas. For Mac OS X:
71  ///
72  /// GPR callee-saved (1) : r4, r5, r6, r7, lr
73  /// --------------------------------------------
74  /// GPR callee-saved (2) : r8, r10, r11
75  /// --------------------------------------------
76  /// DPR callee-saved : d8 - d15
77  ///
78  /// Also see AlignedDPRCSRegs below. Not all D-regs need to go in area 3.
79  /// Some may be spilled after the stack has been realigned.
80  unsigned GPRCS1Offset = 0;
81  unsigned GPRCS2Offset = 0;
82  unsigned DPRCSOffset = 0;
83
84  /// GPRCS1Size, GPRCS2Size, DPRCSSize - Sizes of callee saved register spills
85  /// areas.
86  unsigned FPCXTSaveSize = 0;
87  unsigned GPRCS1Size = 0;
88  unsigned GPRCS2Size = 0;
89  unsigned DPRCSAlignGapSize = 0;
90  unsigned DPRCSSize = 0;
91
92  /// NumAlignedDPRCS2Regs - The number of callee-saved DPRs that are saved in
93  /// the aligned portion of the stack frame.  This is always a contiguous
94  /// sequence of D-registers starting from d8.
95  ///
96  /// We do not keep track of the frame indices used for these registers - they
97  /// behave like any other frame index in the aligned stack frame.  These
98  /// registers also aren't included in DPRCSSize above.
99  unsigned NumAlignedDPRCS2Regs = 0;
100
101  unsigned PICLabelUId = 0;
102
103  /// VarArgsFrameIndex - FrameIndex for start of varargs area.
104  int VarArgsFrameIndex = 0;
105
106  /// HasITBlocks - True if IT blocks have been inserted.
107  bool HasITBlocks = false;
108
109  // Security Extensions
110  bool IsCmseNSEntry;
111  bool IsCmseNSCall;
112
113  /// CPEClones - Track constant pool entries clones created by Constant Island
114  /// pass.
115  DenseMap<unsigned, unsigned> CPEClones;
116
117  /// ArgumentStackSize - amount of bytes on stack consumed by the arguments
118  /// being passed on the stack
119  unsigned ArgumentStackSize = 0;
120
121  /// CoalescedWeights - mapping of basic blocks to the rolling counter of
122  /// coalesced weights.
123  DenseMap<const MachineBasicBlock*, unsigned> CoalescedWeights;
124
125  /// True if this function has a subset of CSRs that is handled explicitly via
126  /// copies.
127  bool IsSplitCSR = false;
128
129  /// Globals that have had their storage promoted into the constant pool.
130  SmallPtrSet<const GlobalVariable*,2> PromotedGlobals;
131
132  /// The amount the literal pool has been increasedby due to promoted globals.
133  int PromotedGlobalsIncrease = 0;
134
135  /// True if r0 will be preserved by a call to this function (e.g. C++
136  /// con/destructors).
137  bool PreservesR0 = false;
138
139public:
140  ARMFunctionInfo() = default;
141
142  explicit ARMFunctionInfo(MachineFunction &MF);
143
144  bool isThumbFunction() const { return isThumb; }
145  bool isThumb1OnlyFunction() const { return isThumb && !hasThumb2; }
146  bool isThumb2Function() const { return isThumb && hasThumb2; }
147
148  bool isCmseNSEntryFunction() const { return IsCmseNSEntry; }
149  bool isCmseNSCallFunction() const { return IsCmseNSCall; }
150
151  unsigned getStoredByValParamsPadding() const { return StByValParamsPadding; }
152  void setStoredByValParamsPadding(unsigned p) { StByValParamsPadding = p; }
153
154  unsigned getArgRegsSaveSize() const { return ArgRegsSaveSize; }
155  void setArgRegsSaveSize(unsigned s) { ArgRegsSaveSize = s; }
156
157  unsigned getReturnRegsCount() const { return ReturnRegsCount; }
158  void setReturnRegsCount(unsigned s) { ReturnRegsCount = s; }
159
160  bool hasStackFrame() const { return HasStackFrame; }
161  void setHasStackFrame(bool s) { HasStackFrame = s; }
162
163  bool shouldRestoreSPFromFP() const { return RestoreSPFromFP; }
164  void setShouldRestoreSPFromFP(bool s) { RestoreSPFromFP = s; }
165
166  bool isLRSpilled() const { return LRSpilled; }
167  void setLRIsSpilled(bool s) { LRSpilled = s; }
168
169  unsigned getFramePtrSpillOffset() const { return FramePtrSpillOffset; }
170  void setFramePtrSpillOffset(unsigned o) { FramePtrSpillOffset = o; }
171
172  unsigned getNumAlignedDPRCS2Regs() const { return NumAlignedDPRCS2Regs; }
173  void setNumAlignedDPRCS2Regs(unsigned n) { NumAlignedDPRCS2Regs = n; }
174
175  unsigned getGPRCalleeSavedArea1Offset() const { return GPRCS1Offset; }
176  unsigned getGPRCalleeSavedArea2Offset() const { return GPRCS2Offset; }
177  unsigned getDPRCalleeSavedAreaOffset()  const { return DPRCSOffset; }
178
179  void setGPRCalleeSavedArea1Offset(unsigned o) { GPRCS1Offset = o; }
180  void setGPRCalleeSavedArea2Offset(unsigned o) { GPRCS2Offset = o; }
181  void setDPRCalleeSavedAreaOffset(unsigned o)  { DPRCSOffset = o; }
182
183  unsigned getFPCXTSaveAreaSize() const       { return FPCXTSaveSize; }
184  unsigned getGPRCalleeSavedArea1Size() const { return GPRCS1Size; }
185  unsigned getGPRCalleeSavedArea2Size() const { return GPRCS2Size; }
186  unsigned getDPRCalleeSavedGapSize() const   { return DPRCSAlignGapSize; }
187  unsigned getDPRCalleeSavedAreaSize()  const { return DPRCSSize; }
188
189  void setFPCXTSaveAreaSize(unsigned s)       { FPCXTSaveSize = s; }
190  void setGPRCalleeSavedArea1Size(unsigned s) { GPRCS1Size = s; }
191  void setGPRCalleeSavedArea2Size(unsigned s) { GPRCS2Size = s; }
192  void setDPRCalleeSavedGapSize(unsigned s)   { DPRCSAlignGapSize = s; }
193  void setDPRCalleeSavedAreaSize(unsigned s)  { DPRCSSize = s; }
194
195  unsigned getArgumentStackSize() const { return ArgumentStackSize; }
196  void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
197
198  void initPICLabelUId(unsigned UId) {
199    PICLabelUId = UId;
200  }
201
202  unsigned getNumPICLabels() const {
203    return PICLabelUId;
204  }
205
206  unsigned createPICLabelUId() {
207    return PICLabelUId++;
208  }
209
210  int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
211  void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
212
213  bool hasITBlocks() const { return HasITBlocks; }
214  void setHasITBlocks(bool h) { HasITBlocks = h; }
215
216  bool isSplitCSR() const { return IsSplitCSR; }
217  void setIsSplitCSR(bool s) { IsSplitCSR = s; }
218
219  void recordCPEClone(unsigned CPIdx, unsigned CPCloneIdx) {
220    if (!CPEClones.insert(std::make_pair(CPCloneIdx, CPIdx)).second)
221      llvm_unreachable("Duplicate entries!");
222  }
223
224  unsigned getOriginalCPIdx(unsigned CloneIdx) const {
225    DenseMap<unsigned, unsigned>::const_iterator I = CPEClones.find(CloneIdx);
226    if (I != CPEClones.end())
227      return I->second;
228    else
229      return -1U;
230  }
231
232  DenseMap<const MachineBasicBlock*, unsigned>::iterator getCoalescedWeight(
233                                                  MachineBasicBlock* MBB) {
234    auto It = CoalescedWeights.find(MBB);
235    if (It == CoalescedWeights.end()) {
236      It = CoalescedWeights.insert(std::make_pair(MBB, 0)).first;
237    }
238    return It;
239  }
240
241  /// Indicate to the backend that \c GV has had its storage changed to inside
242  /// a constant pool. This means it no longer needs to be emitted as a
243  /// global variable.
244  void markGlobalAsPromotedToConstantPool(const GlobalVariable *GV) {
245    PromotedGlobals.insert(GV);
246  }
247  SmallPtrSet<const GlobalVariable*, 2>& getGlobalsPromotedToConstantPool() {
248    return PromotedGlobals;
249  }
250  int getPromotedConstpoolIncrease() const {
251    return PromotedGlobalsIncrease;
252  }
253  void setPromotedConstpoolIncrease(int Sz) {
254    PromotedGlobalsIncrease = Sz;
255  }
256
257  DenseMap<unsigned, unsigned> EHPrologueRemappedRegs;
258  DenseMap<unsigned, unsigned> EHPrologueOffsetInRegs;
259
260  void setPreservesR0() { PreservesR0 = true; }
261  bool getPreservesR0() const { return PreservesR0; }
262};
263
264} // end namespace llvm
265
266#endif // LLVM_LIB_TARGET_ARM_ARMMACHINEFUNCTIONINFO_H
267