1//===- ARMConstantPoolValue.h - ARM constantpool value ----------*- 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 implements the ARM specific constantpool value class.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
14#define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
15
16#include "llvm/ADT/SmallPtrSet.h"
17#include "llvm/ADT/StringRef.h"
18#include "llvm/ADT/iterator_range.h"
19#include "llvm/CodeGen/MachineConstantPool.h"
20#include "llvm/Support/Casting.h"
21#include <string>
22#include <vector>
23
24namespace llvm {
25
26class BlockAddress;
27class Constant;
28class GlobalValue;
29class GlobalVariable;
30class LLVMContext;
31class MachineBasicBlock;
32class raw_ostream;
33class Type;
34
35namespace ARMCP {
36
37  enum ARMCPKind {
38    CPValue,
39    CPExtSymbol,
40    CPBlockAddress,
41    CPLSDA,
42    CPMachineBasicBlock,
43    CPPromotedGlobal
44  };
45
46  enum ARMCPModifier {
47    no_modifier, /// None
48    TLSGD,       /// Thread Local Storage (General Dynamic Mode)
49    GOT_PREL,    /// Global Offset Table, PC Relative
50    GOTTPOFF,    /// Global Offset Table, Thread Pointer Offset
51    TPOFF,       /// Thread Pointer Offset
52    SECREL,      /// Section Relative (Windows TLS)
53    SBREL,       /// Static Base Relative (RWPI)
54  };
55
56} // end namespace ARMCP
57
58/// ARMConstantPoolValue - ARM specific constantpool value. This is used to
59/// represent PC-relative displacement between the address of the load
60/// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)).
61class ARMConstantPoolValue : public MachineConstantPoolValue {
62  unsigned LabelId;        // Label id of the load.
63  ARMCP::ARMCPKind Kind;   // Kind of constant.
64  unsigned char PCAdjust;  // Extra adjustment if constantpool is pc-relative.
65                           // 8 for ARM, 4 for Thumb.
66  ARMCP::ARMCPModifier Modifier;   // GV modifier i.e. (&GV(modifier)-(LPIC+8))
67  bool AddCurrentAddress;
68
69protected:
70  ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind,
71                       unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
72                       bool AddCurrentAddress);
73
74  ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind,
75                       unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
76                       bool AddCurrentAddress);
77
78  template <typename Derived>
79  int getExistingMachineCPValueImpl(MachineConstantPool *CP,
80                                    unsigned Alignment) {
81    unsigned AlignMask = Alignment - 1;
82    const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
83    for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
84      if (Constants[i].isMachineConstantPoolEntry() &&
85          (Constants[i].getAlignment() & AlignMask) == 0) {
86        auto *CPV =
87          static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
88        if (Derived *APC = dyn_cast<Derived>(CPV))
89          if (cast<Derived>(this)->equals(APC))
90            return i;
91      }
92    }
93
94    return -1;
95  }
96
97public:
98  ~ARMConstantPoolValue() override;
99
100  ARMCP::ARMCPModifier getModifier() const { return Modifier; }
101  StringRef getModifierText() const;
102  bool hasModifier() const { return Modifier != ARMCP::no_modifier; }
103
104  bool mustAddCurrentAddress() const { return AddCurrentAddress; }
105
106  unsigned getLabelId() const { return LabelId; }
107  unsigned char getPCAdjustment() const { return PCAdjust; }
108
109  bool isGlobalValue() const { return Kind == ARMCP::CPValue; }
110  bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; }
111  bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
112  bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
113  bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
114  bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; }
115
116  int getExistingMachineCPValue(MachineConstantPool *CP,
117                                unsigned Alignment) override;
118
119  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
120
121  /// hasSameValue - Return true if this ARM constpool value can share the same
122  /// constantpool entry as another ARM constpool value.
123  virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
124
125  bool equals(const ARMConstantPoolValue *A) const {
126    return this->LabelId == A->LabelId &&
127      this->PCAdjust == A->PCAdjust &&
128      this->Modifier == A->Modifier;
129  }
130
131  void print(raw_ostream &O) const override;
132  void print(raw_ostream *O) const { if (O) print(*O); }
133  void dump() const;
134};
135
136inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
137  V.print(O);
138  return O;
139}
140
141/// ARMConstantPoolConstant - ARM-specific constant pool values for Constants,
142/// Functions, and BlockAddresses.
143class ARMConstantPoolConstant : public ARMConstantPoolValue {
144  const Constant *CVal;         // Constant being loaded.
145  SmallPtrSet<const GlobalVariable*, 1> GVars;
146
147  ARMConstantPoolConstant(const Constant *C,
148                          unsigned ID,
149                          ARMCP::ARMCPKind Kind,
150                          unsigned char PCAdj,
151                          ARMCP::ARMCPModifier Modifier,
152                          bool AddCurrentAddress);
153  ARMConstantPoolConstant(Type *Ty, const Constant *C,
154                          unsigned ID,
155                          ARMCP::ARMCPKind Kind,
156                          unsigned char PCAdj,
157                          ARMCP::ARMCPModifier Modifier,
158                          bool AddCurrentAddress);
159  ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
160
161public:
162  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
163  static ARMConstantPoolConstant *Create(const GlobalValue *GV,
164                                         ARMCP::ARMCPModifier Modifier);
165  static ARMConstantPoolConstant *Create(const GlobalVariable *GV,
166                                         const Constant *Initializer);
167  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
168                                         ARMCP::ARMCPKind Kind,
169                                         unsigned char PCAdj);
170  static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
171                                         ARMCP::ARMCPKind Kind,
172                                         unsigned char PCAdj,
173                                         ARMCP::ARMCPModifier Modifier,
174                                         bool AddCurrentAddress);
175
176  const GlobalValue *getGV() const;
177  const BlockAddress *getBlockAddress() const;
178
179  using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
180
181  iterator_range<promoted_iterator> promotedGlobals() {
182    return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
183  }
184
185  const Constant *getPromotedGlobalInit() const {
186    return CVal;
187  }
188
189  int getExistingMachineCPValue(MachineConstantPool *CP,
190                                unsigned Alignment) override;
191
192  /// hasSameValue - Return true if this ARM constpool value can share the same
193  /// constantpool entry as another ARM constpool value.
194  bool hasSameValue(ARMConstantPoolValue *ACPV) override;
195
196  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
197
198  void print(raw_ostream &O) const override;
199
200  static bool classof(const ARMConstantPoolValue *APV) {
201    return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() ||
202           APV->isPromotedGlobal();
203  }
204
205  bool equals(const ARMConstantPoolConstant *A) const {
206    return CVal == A->CVal && ARMConstantPoolValue::equals(A);
207  }
208};
209
210/// ARMConstantPoolSymbol - ARM-specific constantpool values for external
211/// symbols.
212class ARMConstantPoolSymbol : public ARMConstantPoolValue {
213  const std::string S;          // ExtSymbol being loaded.
214
215  ARMConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id,
216                        unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
217                        bool AddCurrentAddress);
218
219public:
220  static ARMConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID,
221                                       unsigned char PCAdj);
222
223  StringRef getSymbol() const { return S; }
224
225  int getExistingMachineCPValue(MachineConstantPool *CP,
226                                unsigned Alignment) override;
227
228  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
229
230  /// hasSameValue - Return true if this ARM constpool value can share the same
231  /// constantpool entry as another ARM constpool value.
232  bool hasSameValue(ARMConstantPoolValue *ACPV) override;
233
234  void print(raw_ostream &O) const override;
235
236  static bool classof(const ARMConstantPoolValue *ACPV) {
237    return ACPV->isExtSymbol();
238  }
239
240  bool equals(const ARMConstantPoolSymbol *A) const {
241    return S == A->S && ARMConstantPoolValue::equals(A);
242  }
243};
244
245/// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic
246/// block.
247class ARMConstantPoolMBB : public ARMConstantPoolValue {
248  const MachineBasicBlock *MBB; // Machine basic block.
249
250  ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id,
251                     unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
252                     bool AddCurrentAddress);
253
254public:
255  static ARMConstantPoolMBB *Create(LLVMContext &C,
256                                    const MachineBasicBlock *mbb,
257                                    unsigned ID, unsigned char PCAdj);
258
259  const MachineBasicBlock *getMBB() const { return MBB; }
260
261  int getExistingMachineCPValue(MachineConstantPool *CP,
262                                unsigned Alignment) override;
263
264  void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
265
266  /// hasSameValue - Return true if this ARM constpool value can share the same
267  /// constantpool entry as another ARM constpool value.
268  bool hasSameValue(ARMConstantPoolValue *ACPV) override;
269
270  void print(raw_ostream &O) const override;
271
272  static bool classof(const ARMConstantPoolValue *ACPV) {
273    return ACPV->isMachineBasicBlock();
274  }
275
276  bool equals(const ARMConstantPoolMBB *A) const {
277    return MBB == A->MBB && ARMConstantPoolValue::equals(A);
278  }
279};
280
281} // end namespace llvm
282
283#endif // LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
284