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