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