10b57cec5SDimitry Andric //===- ARMConstantPoolValue.cpp - ARM constantpool value ------------------===// 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 #include "ARMConstantPoolValue.h" 140b57cec5SDimitry Andric #include "llvm/ADT/FoldingSet.h" 150b57cec5SDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h" 160b57cec5SDimitry Andric #include "llvm/Config/llvm-config.h" 170b57cec5SDimitry Andric #include "llvm/IR/Constant.h" 180b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 190b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h" 20*8bcb0991SDimitry Andric #include "llvm/IR/GlobalVariable.h" 210b57cec5SDimitry Andric #include "llvm/IR/Type.h" 220b57cec5SDimitry Andric #include "llvm/Support/Casting.h" 230b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric using namespace llvm; 280b57cec5SDimitry Andric 290b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 300b57cec5SDimitry Andric // ARMConstantPoolValue 310b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric ARMConstantPoolValue::ARMConstantPoolValue(Type *Ty, unsigned id, 340b57cec5SDimitry Andric ARMCP::ARMCPKind kind, 350b57cec5SDimitry Andric unsigned char PCAdj, 360b57cec5SDimitry Andric ARMCP::ARMCPModifier modifier, 370b57cec5SDimitry Andric bool addCurrentAddress) 380b57cec5SDimitry Andric : MachineConstantPoolValue(Ty), LabelId(id), Kind(kind), 390b57cec5SDimitry Andric PCAdjust(PCAdj), Modifier(modifier), 400b57cec5SDimitry Andric AddCurrentAddress(addCurrentAddress) {} 410b57cec5SDimitry Andric 420b57cec5SDimitry Andric ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, unsigned id, 430b57cec5SDimitry Andric ARMCP::ARMCPKind kind, 440b57cec5SDimitry Andric unsigned char PCAdj, 450b57cec5SDimitry Andric ARMCP::ARMCPModifier modifier, 460b57cec5SDimitry Andric bool addCurrentAddress) 470b57cec5SDimitry Andric : MachineConstantPoolValue((Type*)Type::getInt32Ty(C)), 480b57cec5SDimitry Andric LabelId(id), Kind(kind), PCAdjust(PCAdj), Modifier(modifier), 490b57cec5SDimitry Andric AddCurrentAddress(addCurrentAddress) {} 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric ARMConstantPoolValue::~ARMConstantPoolValue() = default; 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric StringRef ARMConstantPoolValue::getModifierText() const { 540b57cec5SDimitry Andric switch (Modifier) { 550b57cec5SDimitry Andric // FIXME: Are these case sensitive? It'd be nice to lower-case all the 560b57cec5SDimitry Andric // strings if that's legal. 570b57cec5SDimitry Andric case ARMCP::no_modifier: 580b57cec5SDimitry Andric return "none"; 590b57cec5SDimitry Andric case ARMCP::TLSGD: 600b57cec5SDimitry Andric return "tlsgd"; 610b57cec5SDimitry Andric case ARMCP::GOT_PREL: 620b57cec5SDimitry Andric return "GOT_PREL"; 630b57cec5SDimitry Andric case ARMCP::GOTTPOFF: 640b57cec5SDimitry Andric return "gottpoff"; 650b57cec5SDimitry Andric case ARMCP::TPOFF: 660b57cec5SDimitry Andric return "tpoff"; 670b57cec5SDimitry Andric case ARMCP::SBREL: 680b57cec5SDimitry Andric return "SBREL"; 690b57cec5SDimitry Andric case ARMCP::SECREL: 700b57cec5SDimitry Andric return "secrel32"; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric llvm_unreachable("Unknown modifier!"); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, 760b57cec5SDimitry Andric unsigned Alignment) { 770b57cec5SDimitry Andric llvm_unreachable("Shouldn't be calling this directly!"); 780b57cec5SDimitry Andric } 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric void 810b57cec5SDimitry Andric ARMConstantPoolValue::addSelectionDAGCSEId(FoldingSetNodeID &ID) { 820b57cec5SDimitry Andric ID.AddInteger(LabelId); 830b57cec5SDimitry Andric ID.AddInteger(PCAdjust); 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric bool 870b57cec5SDimitry Andric ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) { 880b57cec5SDimitry Andric if (ACPV->Kind == Kind && 890b57cec5SDimitry Andric ACPV->PCAdjust == PCAdjust && 900b57cec5SDimitry Andric ACPV->Modifier == Modifier && 910b57cec5SDimitry Andric ACPV->LabelId == LabelId && 920b57cec5SDimitry Andric ACPV->AddCurrentAddress == AddCurrentAddress) { 930b57cec5SDimitry Andric // Two PC relative constpool entries containing the same GV address or 940b57cec5SDimitry Andric // external symbols. FIXME: What about blockaddress? 950b57cec5SDimitry Andric if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol) 960b57cec5SDimitry Andric return true; 970b57cec5SDimitry Andric } 980b57cec5SDimitry Andric return false; 990b57cec5SDimitry Andric } 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 1020b57cec5SDimitry Andric LLVM_DUMP_METHOD void ARMConstantPoolValue::dump() const { 1030b57cec5SDimitry Andric errs() << " " << *this; 1040b57cec5SDimitry Andric } 1050b57cec5SDimitry Andric #endif 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric void ARMConstantPoolValue::print(raw_ostream &O) const { 1080b57cec5SDimitry Andric if (Modifier) O << "(" << getModifierText() << ")"; 1090b57cec5SDimitry Andric if (PCAdjust != 0) { 1100b57cec5SDimitry Andric O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; 1110b57cec5SDimitry Andric if (AddCurrentAddress) O << "-."; 1120b57cec5SDimitry Andric O << ")"; 1130b57cec5SDimitry Andric } 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1170b57cec5SDimitry Andric // ARMConstantPoolConstant 1180b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric ARMConstantPoolConstant::ARMConstantPoolConstant(Type *Ty, 1210b57cec5SDimitry Andric const Constant *C, 1220b57cec5SDimitry Andric unsigned ID, 1230b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1240b57cec5SDimitry Andric unsigned char PCAdj, 1250b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1260b57cec5SDimitry Andric bool AddCurrentAddress) 1270b57cec5SDimitry Andric : ARMConstantPoolValue(Ty, ID, Kind, PCAdj, Modifier, AddCurrentAddress), 1280b57cec5SDimitry Andric CVal(C) {} 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric ARMConstantPoolConstant::ARMConstantPoolConstant(const Constant *C, 1310b57cec5SDimitry Andric unsigned ID, 1320b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, 1330b57cec5SDimitry Andric unsigned char PCAdj, 1340b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1350b57cec5SDimitry Andric bool AddCurrentAddress) 1360b57cec5SDimitry Andric : ARMConstantPoolValue((Type*)C->getType(), ID, Kind, PCAdj, Modifier, 1370b57cec5SDimitry Andric AddCurrentAddress), 1380b57cec5SDimitry Andric CVal(C) {} 1390b57cec5SDimitry Andric 1400b57cec5SDimitry Andric ARMConstantPoolConstant::ARMConstantPoolConstant(const GlobalVariable *GV, 1410b57cec5SDimitry Andric const Constant *C) 1420b57cec5SDimitry Andric : ARMConstantPoolValue((Type *)C->getType(), 0, ARMCP::CPPromotedGlobal, 0, 1430b57cec5SDimitry Andric ARMCP::no_modifier, false), CVal(C) { 1440b57cec5SDimitry Andric GVars.insert(GV); 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric ARMConstantPoolConstant * 1480b57cec5SDimitry Andric ARMConstantPoolConstant::Create(const Constant *C, unsigned ID) { 1490b57cec5SDimitry Andric return new ARMConstantPoolConstant(C, ID, ARMCP::CPValue, 0, 1500b57cec5SDimitry Andric ARMCP::no_modifier, false); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric ARMConstantPoolConstant * 1540b57cec5SDimitry Andric ARMConstantPoolConstant::Create(const GlobalVariable *GVar, 1550b57cec5SDimitry Andric const Constant *Initializer) { 1560b57cec5SDimitry Andric return new ARMConstantPoolConstant(GVar, Initializer); 1570b57cec5SDimitry Andric } 1580b57cec5SDimitry Andric 1590b57cec5SDimitry Andric ARMConstantPoolConstant * 1600b57cec5SDimitry Andric ARMConstantPoolConstant::Create(const GlobalValue *GV, 1610b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier) { 1620b57cec5SDimitry Andric return new ARMConstantPoolConstant((Type*)Type::getInt32Ty(GV->getContext()), 1630b57cec5SDimitry Andric GV, 0, ARMCP::CPValue, 0, 1640b57cec5SDimitry Andric Modifier, false); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric ARMConstantPoolConstant * 1680b57cec5SDimitry Andric ARMConstantPoolConstant::Create(const Constant *C, unsigned ID, 1690b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, unsigned char PCAdj) { 1700b57cec5SDimitry Andric return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, 1710b57cec5SDimitry Andric ARMCP::no_modifier, false); 1720b57cec5SDimitry Andric } 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric ARMConstantPoolConstant * 1750b57cec5SDimitry Andric ARMConstantPoolConstant::Create(const Constant *C, unsigned ID, 1760b57cec5SDimitry Andric ARMCP::ARMCPKind Kind, unsigned char PCAdj, 1770b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 1780b57cec5SDimitry Andric bool AddCurrentAddress) { 1790b57cec5SDimitry Andric return new ARMConstantPoolConstant(C, ID, Kind, PCAdj, Modifier, 1800b57cec5SDimitry Andric AddCurrentAddress); 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric const GlobalValue *ARMConstantPoolConstant::getGV() const { 1840b57cec5SDimitry Andric return dyn_cast_or_null<GlobalValue>(CVal); 1850b57cec5SDimitry Andric } 1860b57cec5SDimitry Andric 1870b57cec5SDimitry Andric const BlockAddress *ARMConstantPoolConstant::getBlockAddress() const { 1880b57cec5SDimitry Andric return dyn_cast_or_null<BlockAddress>(CVal); 1890b57cec5SDimitry Andric } 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric int ARMConstantPoolConstant::getExistingMachineCPValue(MachineConstantPool *CP, 1920b57cec5SDimitry Andric unsigned Alignment) { 1930b57cec5SDimitry Andric int index = 1940b57cec5SDimitry Andric getExistingMachineCPValueImpl<ARMConstantPoolConstant>(CP, Alignment); 1950b57cec5SDimitry Andric if (index != -1) { 1960b57cec5SDimitry Andric auto *CPV = static_cast<ARMConstantPoolValue*>( 1970b57cec5SDimitry Andric CP->getConstants()[index].Val.MachineCPVal); 1980b57cec5SDimitry Andric auto *Constant = cast<ARMConstantPoolConstant>(CPV); 1990b57cec5SDimitry Andric Constant->GVars.insert(GVars.begin(), GVars.end()); 2000b57cec5SDimitry Andric } 2010b57cec5SDimitry Andric return index; 2020b57cec5SDimitry Andric } 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric bool ARMConstantPoolConstant::hasSameValue(ARMConstantPoolValue *ACPV) { 2050b57cec5SDimitry Andric const ARMConstantPoolConstant *ACPC = dyn_cast<ARMConstantPoolConstant>(ACPV); 2060b57cec5SDimitry Andric return ACPC && ACPC->CVal == CVal && ARMConstantPoolValue::hasSameValue(ACPV); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric void ARMConstantPoolConstant::addSelectionDAGCSEId(FoldingSetNodeID &ID) { 2100b57cec5SDimitry Andric ID.AddPointer(CVal); 2110b57cec5SDimitry Andric for (const auto *GV : GVars) 2120b57cec5SDimitry Andric ID.AddPointer(GV); 2130b57cec5SDimitry Andric ARMConstantPoolValue::addSelectionDAGCSEId(ID); 2140b57cec5SDimitry Andric } 2150b57cec5SDimitry Andric 2160b57cec5SDimitry Andric void ARMConstantPoolConstant::print(raw_ostream &O) const { 2170b57cec5SDimitry Andric O << CVal->getName(); 2180b57cec5SDimitry Andric ARMConstantPoolValue::print(O); 2190b57cec5SDimitry Andric } 2200b57cec5SDimitry Andric 2210b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2220b57cec5SDimitry Andric // ARMConstantPoolSymbol 2230b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2240b57cec5SDimitry Andric 2250b57cec5SDimitry Andric ARMConstantPoolSymbol::ARMConstantPoolSymbol(LLVMContext &C, StringRef s, 2260b57cec5SDimitry Andric unsigned id, unsigned char PCAdj, 2270b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 2280b57cec5SDimitry Andric bool AddCurrentAddress) 2290b57cec5SDimitry Andric : ARMConstantPoolValue(C, id, ARMCP::CPExtSymbol, PCAdj, Modifier, 2300b57cec5SDimitry Andric AddCurrentAddress), 2310b57cec5SDimitry Andric S(s) {} 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric ARMConstantPoolSymbol *ARMConstantPoolSymbol::Create(LLVMContext &C, 2340b57cec5SDimitry Andric StringRef s, unsigned ID, 2350b57cec5SDimitry Andric unsigned char PCAdj) { 2360b57cec5SDimitry Andric return new ARMConstantPoolSymbol(C, s, ID, PCAdj, ARMCP::no_modifier, false); 2370b57cec5SDimitry Andric } 2380b57cec5SDimitry Andric 2390b57cec5SDimitry Andric int ARMConstantPoolSymbol::getExistingMachineCPValue(MachineConstantPool *CP, 2400b57cec5SDimitry Andric unsigned Alignment) { 2410b57cec5SDimitry Andric return getExistingMachineCPValueImpl<ARMConstantPoolSymbol>(CP, Alignment); 2420b57cec5SDimitry Andric } 2430b57cec5SDimitry Andric 2440b57cec5SDimitry Andric bool ARMConstantPoolSymbol::hasSameValue(ARMConstantPoolValue *ACPV) { 2450b57cec5SDimitry Andric const ARMConstantPoolSymbol *ACPS = dyn_cast<ARMConstantPoolSymbol>(ACPV); 2460b57cec5SDimitry Andric return ACPS && ACPS->S == S && ARMConstantPoolValue::hasSameValue(ACPV); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric void ARMConstantPoolSymbol::addSelectionDAGCSEId(FoldingSetNodeID &ID) { 2500b57cec5SDimitry Andric ID.AddString(S); 2510b57cec5SDimitry Andric ARMConstantPoolValue::addSelectionDAGCSEId(ID); 2520b57cec5SDimitry Andric } 2530b57cec5SDimitry Andric 2540b57cec5SDimitry Andric void ARMConstantPoolSymbol::print(raw_ostream &O) const { 2550b57cec5SDimitry Andric O << S; 2560b57cec5SDimitry Andric ARMConstantPoolValue::print(O); 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2600b57cec5SDimitry Andric // ARMConstantPoolMBB 2610b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric ARMConstantPoolMBB::ARMConstantPoolMBB(LLVMContext &C, 2640b57cec5SDimitry Andric const MachineBasicBlock *mbb, 2650b57cec5SDimitry Andric unsigned id, unsigned char PCAdj, 2660b57cec5SDimitry Andric ARMCP::ARMCPModifier Modifier, 2670b57cec5SDimitry Andric bool AddCurrentAddress) 2680b57cec5SDimitry Andric : ARMConstantPoolValue(C, id, ARMCP::CPMachineBasicBlock, PCAdj, 2690b57cec5SDimitry Andric Modifier, AddCurrentAddress), 2700b57cec5SDimitry Andric MBB(mbb) {} 2710b57cec5SDimitry Andric 2720b57cec5SDimitry Andric ARMConstantPoolMBB *ARMConstantPoolMBB::Create(LLVMContext &C, 2730b57cec5SDimitry Andric const MachineBasicBlock *mbb, 2740b57cec5SDimitry Andric unsigned ID, 2750b57cec5SDimitry Andric unsigned char PCAdj) { 2760b57cec5SDimitry Andric return new ARMConstantPoolMBB(C, mbb, ID, PCAdj, ARMCP::no_modifier, false); 2770b57cec5SDimitry Andric } 2780b57cec5SDimitry Andric 2790b57cec5SDimitry Andric int ARMConstantPoolMBB::getExistingMachineCPValue(MachineConstantPool *CP, 2800b57cec5SDimitry Andric unsigned Alignment) { 2810b57cec5SDimitry Andric return getExistingMachineCPValueImpl<ARMConstantPoolMBB>(CP, Alignment); 2820b57cec5SDimitry Andric } 2830b57cec5SDimitry Andric 2840b57cec5SDimitry Andric bool ARMConstantPoolMBB::hasSameValue(ARMConstantPoolValue *ACPV) { 2850b57cec5SDimitry Andric const ARMConstantPoolMBB *ACPMBB = dyn_cast<ARMConstantPoolMBB>(ACPV); 2860b57cec5SDimitry Andric return ACPMBB && ACPMBB->MBB == MBB && 2870b57cec5SDimitry Andric ARMConstantPoolValue::hasSameValue(ACPV); 2880b57cec5SDimitry Andric } 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric void ARMConstantPoolMBB::addSelectionDAGCSEId(FoldingSetNodeID &ID) { 2910b57cec5SDimitry Andric ID.AddPointer(MBB); 2920b57cec5SDimitry Andric ARMConstantPoolValue::addSelectionDAGCSEId(ID); 2930b57cec5SDimitry Andric } 2940b57cec5SDimitry Andric 2950b57cec5SDimitry Andric void ARMConstantPoolMBB::print(raw_ostream &O) const { 2960b57cec5SDimitry Andric O << printMBBReference(*MBB); 2970b57cec5SDimitry Andric ARMConstantPoolValue::print(O); 2980b57cec5SDimitry Andric } 299