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, 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 98 ARMCP::ARMCPModifier getModifier() const { return Modifier; } 99 StringRef getModifierText() const; 100 bool hasModifier() const { return Modifier != ARMCP::no_modifier; } 101 102 bool mustAddCurrentAddress() const { return AddCurrentAddress; } 103 104 unsigned getLabelId() const { return LabelId; } 105 unsigned char getPCAdjustment() const { return PCAdjust; } 106 107 bool isGlobalValue() const { return Kind == ARMCP::CPValue; } 108 bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; } 109 bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; } 110 bool isLSDA() const { return Kind == ARMCP::CPLSDA; } 111 bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; } 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 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; 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 179 iterator_range<promoted_iterator> promotedGlobals() { 180 return iterator_range<promoted_iterator>(GVars.begin(), GVars.end()); 181 } 182 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 198 static bool classof(const ARMConstantPoolValue *APV) { 199 return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() || 200 APV->isPromotedGlobal(); 201 } 202 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 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 234 static bool classof(const ARMConstantPoolValue *ACPV) { 235 return ACPV->isExtSymbol(); 236 } 237 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 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 270 static bool classof(const ARMConstantPoolValue *ACPV) { 271 return ACPV->isMachineBasicBlock(); 272 } 273 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