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