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