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