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>
getExistingMachineCPValueImpl(MachineConstantPool * CP,Align Alignment)79   int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) {
80     const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants();
81     for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
82       if (Constants[i].isMachineConstantPoolEntry() &&
83           Constants[i].getAlign() >= Alignment) {
84         auto *CPV =
85           static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal);
86         if (Derived *APC = dyn_cast<Derived>(CPV))
87           if (cast<Derived>(this)->equals(APC))
88             return i;
89       }
90     }
91 
92     return -1;
93   }
94 
95 public:
96   ~ARMConstantPoolValue() override;
97 
getModifier()98   ARMCP::ARMCPModifier getModifier() const { return Modifier; }
99   StringRef getModifierText() const;
hasModifier()100   bool hasModifier() const { return Modifier != ARMCP::no_modifier; }
101 
mustAddCurrentAddress()102   bool mustAddCurrentAddress() const { return AddCurrentAddress; }
103 
getLabelId()104   unsigned getLabelId() const { return LabelId; }
getPCAdjustment()105   unsigned char getPCAdjustment() const { return PCAdjust; }
106 
isGlobalValue()107   bool isGlobalValue() const { return Kind == ARMCP::CPValue; }
isExtSymbol()108   bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; }
isBlockAddress()109   bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; }
isLSDA()110   bool isLSDA() const { return Kind == ARMCP::CPLSDA; }
isMachineBasicBlock()111   bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; }
isPromotedGlobal()112   bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; }
113 
114   int getExistingMachineCPValue(MachineConstantPool *CP,
115                                 Align Alignment) override;
116 
117   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
118 
119   /// hasSameValue - Return true if this ARM constpool value can share the same
120   /// constantpool entry as another ARM constpool value.
121   virtual bool hasSameValue(ARMConstantPoolValue *ACPV);
122 
equals(const ARMConstantPoolValue * A)123   bool equals(const ARMConstantPoolValue *A) const {
124     return this->LabelId == A->LabelId &&
125       this->PCAdjust == A->PCAdjust &&
126       this->Modifier == A->Modifier;
127   }
128 
129   void print(raw_ostream &O) const override;
print(raw_ostream * O)130   void print(raw_ostream *O) const { if (O) print(*O); }
131   void dump() const;
132 };
133 
134 inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) {
135   V.print(O);
136   return O;
137 }
138 
139 /// ARMConstantPoolConstant - ARM-specific constant pool values for Constants,
140 /// Functions, and BlockAddresses.
141 class ARMConstantPoolConstant : public ARMConstantPoolValue {
142   const Constant *CVal;         // Constant being loaded.
143   SmallPtrSet<const GlobalVariable*, 1> GVars;
144 
145   ARMConstantPoolConstant(const Constant *C,
146                           unsigned ID,
147                           ARMCP::ARMCPKind Kind,
148                           unsigned char PCAdj,
149                           ARMCP::ARMCPModifier Modifier,
150                           bool AddCurrentAddress);
151   ARMConstantPoolConstant(Type *Ty, const Constant *C,
152                           unsigned ID,
153                           ARMCP::ARMCPKind Kind,
154                           unsigned char PCAdj,
155                           ARMCP::ARMCPModifier Modifier,
156                           bool AddCurrentAddress);
157   ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init);
158 
159 public:
160   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID);
161   static ARMConstantPoolConstant *Create(const GlobalValue *GV,
162                                          ARMCP::ARMCPModifier Modifier);
163   static ARMConstantPoolConstant *Create(const GlobalVariable *GV,
164                                          const Constant *Initializer);
165   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
166                                          ARMCP::ARMCPKind Kind,
167                                          unsigned char PCAdj);
168   static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID,
169                                          ARMCP::ARMCPKind Kind,
170                                          unsigned char PCAdj,
171                                          ARMCP::ARMCPModifier Modifier,
172                                          bool AddCurrentAddress);
173 
174   const GlobalValue *getGV() const;
175   const BlockAddress *getBlockAddress() const;
176 
177   using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator;
178 
promotedGlobals()179   iterator_range<promoted_iterator> promotedGlobals() {
180     return iterator_range<promoted_iterator>(GVars.begin(), GVars.end());
181   }
182 
getPromotedGlobalInit()183   const Constant *getPromotedGlobalInit() const {
184     return CVal;
185   }
186 
187   int getExistingMachineCPValue(MachineConstantPool *CP,
188                                 Align Alignment) override;
189 
190   /// hasSameValue - Return true if this ARM constpool value can share the same
191   /// constantpool entry as another ARM constpool value.
192   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
193 
194   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
195 
196   void print(raw_ostream &O) const override;
197 
classof(const ARMConstantPoolValue * APV)198   static bool classof(const ARMConstantPoolValue *APV) {
199     return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() ||
200            APV->isPromotedGlobal();
201   }
202 
equals(const ARMConstantPoolConstant * A)203   bool equals(const ARMConstantPoolConstant *A) const {
204     return CVal == A->CVal && ARMConstantPoolValue::equals(A);
205   }
206 };
207 
208 /// ARMConstantPoolSymbol - ARM-specific constantpool values for external
209 /// symbols.
210 class ARMConstantPoolSymbol : public ARMConstantPoolValue {
211   const std::string S;          // ExtSymbol being loaded.
212 
213   ARMConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id,
214                         unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
215                         bool AddCurrentAddress);
216 
217 public:
218   static ARMConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID,
219                                        unsigned char PCAdj);
220 
getSymbol()221   StringRef getSymbol() const { return S; }
222 
223   int getExistingMachineCPValue(MachineConstantPool *CP,
224                                 Align Alignment) override;
225 
226   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
227 
228   /// hasSameValue - Return true if this ARM constpool value can share the same
229   /// constantpool entry as another ARM constpool value.
230   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
231 
232   void print(raw_ostream &O) const override;
233 
classof(const ARMConstantPoolValue * ACPV)234   static bool classof(const ARMConstantPoolValue *ACPV) {
235     return ACPV->isExtSymbol();
236   }
237 
equals(const ARMConstantPoolSymbol * A)238   bool equals(const ARMConstantPoolSymbol *A) const {
239     return S == A->S && ARMConstantPoolValue::equals(A);
240   }
241 };
242 
243 /// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic
244 /// block.
245 class ARMConstantPoolMBB : public ARMConstantPoolValue {
246   const MachineBasicBlock *MBB; // Machine basic block.
247 
248   ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id,
249                      unsigned char PCAdj, ARMCP::ARMCPModifier Modifier,
250                      bool AddCurrentAddress);
251 
252 public:
253   static ARMConstantPoolMBB *Create(LLVMContext &C,
254                                     const MachineBasicBlock *mbb,
255                                     unsigned ID, unsigned char PCAdj);
256 
getMBB()257   const MachineBasicBlock *getMBB() const { return MBB; }
258 
259   int getExistingMachineCPValue(MachineConstantPool *CP,
260                                 Align Alignment) override;
261 
262   void addSelectionDAGCSEId(FoldingSetNodeID &ID) override;
263 
264   /// hasSameValue - Return true if this ARM constpool value can share the same
265   /// constantpool entry as another ARM constpool value.
266   bool hasSameValue(ARMConstantPoolValue *ACPV) override;
267 
268   void print(raw_ostream &O) const override;
269 
classof(const ARMConstantPoolValue * ACPV)270   static bool classof(const ARMConstantPoolValue *ACPV) {
271     return ACPV->isMachineBasicBlock();
272   }
273 
equals(const ARMConstantPoolMBB * A)274   bool equals(const ARMConstantPoolMBB *A) const {
275     return MBB == A->MBB && ARMConstantPoolValue::equals(A);
276   }
277 };
278 
279 } // end namespace llvm
280 
281 #endif // LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H
282