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 
24 namespace llvm {
25 
26 class BlockAddress;
27 class Constant;
28 class GlobalValue;
29 class GlobalVariable;
30 class LLVMContext;
31 class MachineBasicBlock;
32 class raw_ostream;
33 class Type;
34 
35 namespace 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)).
61 class 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 
69 protected:
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 
97 public:
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 
136 inline 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.
143 class 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 
161 public:
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.
212 class 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 
219 public:
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.
247 class 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 
254 public:
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