10b57cec5SDimitry Andric //===- ARMConstantPoolValue.h - ARM constantpool value ----------*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file implements the ARM specific constantpool value class. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 170b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h" 180b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h" 190b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h" 200b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 210b57cec5SDimitry Andric #include <string> 220b57cec5SDimitry Andric #include <vector> 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric namespace llvm { 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric class BlockAddress; 270b57cec5SDimitry Andric class Constant; 280b57cec5SDimitry Andric class GlobalValue; 290b57cec5SDimitry Andric class GlobalVariable; 300b57cec5SDimitry Andric class LLVMContext; 310b57cec5SDimitry Andric class MachineBasicBlock; 320b57cec5SDimitry Andric class raw_ostream; 330b57cec5SDimitry Andric class Type; 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric namespace ARMCP { 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric enum ARMCPKind { 380b57cec5SDimitry Andric CPValue, 390b57cec5SDimitry Andric CPExtSymbol, 400b57cec5SDimitry Andric CPBlockAddress, 410b57cec5SDimitry Andric CPLSDA, 420b57cec5SDimitry Andric CPMachineBasicBlock, 430b57cec5SDimitry Andric CPPromotedGlobal 440b57cec5SDimitry Andric }; 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric enum ARMCPModifier { 470b57cec5SDimitry Andric no_modifier, /// None 480b57cec5SDimitry Andric TLSGD, /// Thread Local Storage (General Dynamic Mode) 490b57cec5SDimitry Andric GOT_PREL, /// Global Offset Table, PC Relative 500b57cec5SDimitry Andric GOTTPOFF, /// Global Offset Table, Thread Pointer Offset 510b57cec5SDimitry Andric TPOFF, /// Thread Pointer Offset 520b57cec5SDimitry Andric SECREL, /// Section Relative (Windows TLS) 530b57cec5SDimitry Andric SBREL, /// Static Base Relative (RWPI) 540b57cec5SDimitry Andric }; 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric } // end namespace ARMCP 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric /// ARMConstantPoolValue - ARM specific constantpool value. This is used to 590b57cec5SDimitry Andric /// represent PC-relative displacement between the address of the load 600b57cec5SDimitry Andric /// instruction and the constant being loaded, i.e. (&GV-(LPIC+8)). 610b57cec5SDimitry Andric class ARMConstantPoolValue : public MachineConstantPoolValue { 620b57cec5SDimitry Andric unsigned LabelId; // Label id of the load. 630b57cec5SDimitry Andric ARMCP::ARMCPKind Kind; // Kind of constant. 640b57cec5SDimitry Andric unsigned char PCAdjust; // Extra adjustment if constantpool is pc-relative. 650b57cec5SDimitry Andric // 8 for ARM, 4 for Thumb. 660b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) 670b57cec5SDimitry Andric bool AddCurrentAddress; 680b57cec5SDimitry Andric 690b57cec5SDimitry Andric protected: 700b57cec5SDimitry Andric ARMConstantPoolValue(Type *Ty, unsigned id, ARMCP::ARMCPKind Kind, 710b57cec5SDimitry Andric unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, 720b57cec5SDimitry Andric bool AddCurrentAddress); 730b57cec5SDimitry Andric 740b57cec5SDimitry Andric ARMConstantPoolValue(LLVMContext &C, unsigned id, ARMCP::ARMCPKind Kind, 750b57cec5SDimitry Andric unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, 760b57cec5SDimitry Andric bool AddCurrentAddress); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric template <typename Derived> getExistingMachineCPValueImpl(MachineConstantPool * CP,Align Alignment)79*5ffd83dbSDimitry Andric int getExistingMachineCPValueImpl(MachineConstantPool *CP, Align Alignment) { 800b57cec5SDimitry Andric const std::vector<MachineConstantPoolEntry> &Constants = CP->getConstants(); 810b57cec5SDimitry Andric for (unsigned i = 0, e = Constants.size(); i != e; ++i) { 820b57cec5SDimitry Andric if (Constants[i].isMachineConstantPoolEntry() && 83*5ffd83dbSDimitry Andric Constants[i].getAlign() >= Alignment) { 840b57cec5SDimitry Andric auto *CPV = 850b57cec5SDimitry Andric static_cast<ARMConstantPoolValue*>(Constants[i].Val.MachineCPVal); 860b57cec5SDimitry Andric if (Derived *APC = dyn_cast<Derived>(CPV)) 870b57cec5SDimitry Andric if (cast<Derived>(this)->equals(APC)) 880b57cec5SDimitry Andric return i; 890b57cec5SDimitry Andric } 900b57cec5SDimitry Andric } 910b57cec5SDimitry Andric 920b57cec5SDimitry Andric return -1; 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric public: 960b57cec5SDimitry Andric ~ARMConstantPoolValue() override; 970b57cec5SDimitry Andric getModifier()980b57cec5SDimitry Andric ARMCP::ARMCPModifier getModifier() const { return Modifier; } 990b57cec5SDimitry Andric StringRef getModifierText() const; hasModifier()1000b57cec5SDimitry Andric bool hasModifier() const { return Modifier != ARMCP::no_modifier; } 1010b57cec5SDimitry Andric mustAddCurrentAddress()1020b57cec5SDimitry Andric bool mustAddCurrentAddress() const { return AddCurrentAddress; } 1030b57cec5SDimitry Andric getLabelId()1040b57cec5SDimitry Andric unsigned getLabelId() const { return LabelId; } getPCAdjustment()1050b57cec5SDimitry Andric unsigned char getPCAdjustment() const { return PCAdjust; } 1060b57cec5SDimitry Andric isGlobalValue()1070b57cec5SDimitry Andric bool isGlobalValue() const { return Kind == ARMCP::CPValue; } isExtSymbol()1080b57cec5SDimitry Andric bool isExtSymbol() const { return Kind == ARMCP::CPExtSymbol; } isBlockAddress()1090b57cec5SDimitry Andric bool isBlockAddress() const { return Kind == ARMCP::CPBlockAddress; } isLSDA()1100b57cec5SDimitry Andric bool isLSDA() const { return Kind == ARMCP::CPLSDA; } isMachineBasicBlock()1110b57cec5SDimitry Andric bool isMachineBasicBlock() const{ return Kind == ARMCP::CPMachineBasicBlock; } isPromotedGlobal()1120b57cec5SDimitry Andric bool isPromotedGlobal() const{ return Kind == ARMCP::CPPromotedGlobal; } 1130b57cec5SDimitry Andric 1140b57cec5SDimitry Andric int getExistingMachineCPValue(MachineConstantPool *CP, 115*5ffd83dbSDimitry Andric Align Alignment) override; 1160b57cec5SDimitry Andric 1170b57cec5SDimitry Andric void addSelectionDAGCSEId(FoldingSetNodeID &ID) override; 1180b57cec5SDimitry Andric 1190b57cec5SDimitry Andric /// hasSameValue - Return true if this ARM constpool value can share the same 1200b57cec5SDimitry Andric /// constantpool entry as another ARM constpool value. 1210b57cec5SDimitry Andric virtual bool hasSameValue(ARMConstantPoolValue *ACPV); 1220b57cec5SDimitry Andric equals(const ARMConstantPoolValue * A)1230b57cec5SDimitry Andric bool equals(const ARMConstantPoolValue *A) const { 1240b57cec5SDimitry Andric return this->LabelId == A->LabelId && 1250b57cec5SDimitry Andric this->PCAdjust == A->PCAdjust && 1260b57cec5SDimitry Andric this->Modifier == A->Modifier; 1270b57cec5SDimitry Andric } 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric void print(raw_ostream &O) const override; print(raw_ostream * O)1300b57cec5SDimitry Andric void print(raw_ostream *O) const { if (O) print(*O); } 1310b57cec5SDimitry Andric void dump() const; 1320b57cec5SDimitry Andric }; 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric inline raw_ostream &operator<<(raw_ostream &O, const ARMConstantPoolValue &V) { 1350b57cec5SDimitry Andric V.print(O); 1360b57cec5SDimitry Andric return O; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric /// ARMConstantPoolConstant - ARM-specific constant pool values for Constants, 1400b57cec5SDimitry Andric /// Functions, and BlockAddresses. 1410b57cec5SDimitry Andric class ARMConstantPoolConstant : public ARMConstantPoolValue { 1420b57cec5SDimitry Andric const Constant *CVal; // Constant being loaded. 1430b57cec5SDimitry Andric SmallPtrSet<const GlobalVariable*, 1> GVars; 1440b57cec5SDimitry Andric 1450b57cec5SDimitry Andric ARMConstantPoolConstant(const Constant *C, 1460b57cec5SDimitry Andric unsigned ID, 1470b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1480b57cec5SDimitry Andric unsigned char PCAdj, 1490b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1500b57cec5SDimitry Andric bool AddCurrentAddress); 1510b57cec5SDimitry Andric ARMConstantPoolConstant(Type *Ty, const Constant *C, 1520b57cec5SDimitry Andric unsigned ID, 1530b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1540b57cec5SDimitry Andric unsigned char PCAdj, 1550b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1560b57cec5SDimitry Andric bool AddCurrentAddress); 1570b57cec5SDimitry Andric ARMConstantPoolConstant(const GlobalVariable *GV, const Constant *Init); 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric public: 1600b57cec5SDimitry Andric static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID); 1610b57cec5SDimitry Andric static ARMConstantPoolConstant *Create(const GlobalValue *GV, 1620b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier); 1630b57cec5SDimitry Andric static ARMConstantPoolConstant *Create(const GlobalVariable *GV, 1640b57cec5SDimitry Andric const Constant *Initializer); 1650b57cec5SDimitry Andric static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID, 1660b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1670b57cec5SDimitry Andric unsigned char PCAdj); 1680b57cec5SDimitry Andric static ARMConstantPoolConstant *Create(const Constant *C, unsigned ID, 1690b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1700b57cec5SDimitry Andric unsigned char PCAdj, 1710b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1720b57cec5SDimitry Andric bool AddCurrentAddress); 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric const GlobalValue *getGV() const; 1750b57cec5SDimitry Andric const BlockAddress *getBlockAddress() const; 1760b57cec5SDimitry Andric 1770b57cec5SDimitry Andric using promoted_iterator = SmallPtrSet<const GlobalVariable *, 1>::iterator; 1780b57cec5SDimitry Andric promotedGlobals()1790b57cec5SDimitry Andric iterator_range<promoted_iterator> promotedGlobals() { 1800b57cec5SDimitry Andric return iterator_range<promoted_iterator>(GVars.begin(), GVars.end()); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric getPromotedGlobalInit()1830b57cec5SDimitry Andric const Constant *getPromotedGlobalInit() const { 1840b57cec5SDimitry Andric return CVal; 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric int getExistingMachineCPValue(MachineConstantPool *CP, 188*5ffd83dbSDimitry Andric Align Alignment) override; 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric /// hasSameValue - Return true if this ARM constpool value can share the same 1910b57cec5SDimitry Andric /// constantpool entry as another ARM constpool value. 1920b57cec5SDimitry Andric bool hasSameValue(ARMConstantPoolValue *ACPV) override; 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void addSelectionDAGCSEId(FoldingSetNodeID &ID) override; 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric void print(raw_ostream &O) const override; 1970b57cec5SDimitry Andric classof(const ARMConstantPoolValue * APV)1980b57cec5SDimitry Andric static bool classof(const ARMConstantPoolValue *APV) { 1990b57cec5SDimitry Andric return APV->isGlobalValue() || APV->isBlockAddress() || APV->isLSDA() || 2000b57cec5SDimitry Andric APV->isPromotedGlobal(); 2010b57cec5SDimitry Andric } 2020b57cec5SDimitry Andric equals(const ARMConstantPoolConstant * A)2030b57cec5SDimitry Andric bool equals(const ARMConstantPoolConstant *A) const { 2040b57cec5SDimitry Andric return CVal == A->CVal && ARMConstantPoolValue::equals(A); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric }; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric /// ARMConstantPoolSymbol - ARM-specific constantpool values for external 2090b57cec5SDimitry Andric /// symbols. 2100b57cec5SDimitry Andric class ARMConstantPoolSymbol : public ARMConstantPoolValue { 2110b57cec5SDimitry Andric const std::string S; // ExtSymbol being loaded. 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric ARMConstantPoolSymbol(LLVMContext &C, StringRef s, unsigned id, 2140b57cec5SDimitry Andric unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, 2150b57cec5SDimitry Andric bool AddCurrentAddress); 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric public: 2180b57cec5SDimitry Andric static ARMConstantPoolSymbol *Create(LLVMContext &C, StringRef s, unsigned ID, 2190b57cec5SDimitry Andric unsigned char PCAdj); 2200b57cec5SDimitry Andric getSymbol()2210b57cec5SDimitry Andric StringRef getSymbol() const { return S; } 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric int getExistingMachineCPValue(MachineConstantPool *CP, 224*5ffd83dbSDimitry Andric Align Alignment) override; 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric void addSelectionDAGCSEId(FoldingSetNodeID &ID) override; 2270b57cec5SDimitry Andric 2280b57cec5SDimitry Andric /// hasSameValue - Return true if this ARM constpool value can share the same 2290b57cec5SDimitry Andric /// constantpool entry as another ARM constpool value. 2300b57cec5SDimitry Andric bool hasSameValue(ARMConstantPoolValue *ACPV) override; 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric void print(raw_ostream &O) const override; 2330b57cec5SDimitry Andric classof(const ARMConstantPoolValue * ACPV)2340b57cec5SDimitry Andric static bool classof(const ARMConstantPoolValue *ACPV) { 2350b57cec5SDimitry Andric return ACPV->isExtSymbol(); 2360b57cec5SDimitry Andric } 2370b57cec5SDimitry Andric equals(const ARMConstantPoolSymbol * A)2380b57cec5SDimitry Andric bool equals(const ARMConstantPoolSymbol *A) const { 2390b57cec5SDimitry Andric return S == A->S && ARMConstantPoolValue::equals(A); 2400b57cec5SDimitry Andric } 2410b57cec5SDimitry Andric }; 2420b57cec5SDimitry Andric 2430b57cec5SDimitry Andric /// ARMConstantPoolMBB - ARM-specific constantpool value of a machine basic 2440b57cec5SDimitry Andric /// block. 2450b57cec5SDimitry Andric class ARMConstantPoolMBB : public ARMConstantPoolValue { 2460b57cec5SDimitry Andric const MachineBasicBlock *MBB; // Machine basic block. 2470b57cec5SDimitry Andric 2480b57cec5SDimitry Andric ARMConstantPoolMBB(LLVMContext &C, const MachineBasicBlock *mbb, unsigned id, 2490b57cec5SDimitry Andric unsigned char PCAdj, ARMCP::ARMCPModifier Modifier, 2500b57cec5SDimitry Andric bool AddCurrentAddress); 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric public: 2530b57cec5SDimitry Andric static ARMConstantPoolMBB *Create(LLVMContext &C, 2540b57cec5SDimitry Andric const MachineBasicBlock *mbb, 2550b57cec5SDimitry Andric unsigned ID, unsigned char PCAdj); 2560b57cec5SDimitry Andric getMBB()2570b57cec5SDimitry Andric const MachineBasicBlock *getMBB() const { return MBB; } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric int getExistingMachineCPValue(MachineConstantPool *CP, 260*5ffd83dbSDimitry Andric Align Alignment) override; 2610b57cec5SDimitry Andric 2620b57cec5SDimitry Andric void addSelectionDAGCSEId(FoldingSetNodeID &ID) override; 2630b57cec5SDimitry Andric 2640b57cec5SDimitry Andric /// hasSameValue - Return true if this ARM constpool value can share the same 2650b57cec5SDimitry Andric /// constantpool entry as another ARM constpool value. 2660b57cec5SDimitry Andric bool hasSameValue(ARMConstantPoolValue *ACPV) override; 2670b57cec5SDimitry Andric 2680b57cec5SDimitry Andric void print(raw_ostream &O) const override; 2690b57cec5SDimitry Andric classof(const ARMConstantPoolValue * ACPV)2700b57cec5SDimitry Andric static bool classof(const ARMConstantPoolValue *ACPV) { 2710b57cec5SDimitry Andric return ACPV->isMachineBasicBlock(); 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric equals(const ARMConstantPoolMBB * A)2740b57cec5SDimitry Andric bool equals(const ARMConstantPoolMBB *A) const { 2750b57cec5SDimitry Andric return MBB == A->MBB && ARMConstantPoolValue::equals(A); 2760b57cec5SDimitry Andric } 2770b57cec5SDimitry Andric }; 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric } // end namespace llvm 2800b57cec5SDimitry Andric 2810b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_ARM_ARMCONSTANTPOOLVALUE_H 282