//===- ARMConstantPoolValue.cpp - ARM constantpool value --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the ARM specific constantpool value class. // //===----------------------------------------------------------------------===// #include "ARMConstantPoolValue.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Constant.h" #include "llvm/Constants.h" #include "llvm/GlobalValue.h" #include "llvm/Type.h" #include "llvm/Support/raw_ostream.h" #include using namespace llvm; ARMConstantPoolValue::ARMConstantPoolValue(const Constant *cval, unsigned id, ARMCP::ARMCPKind K, unsigned char PCAdj, ARMCP::ARMCPModifier Modif, bool AddCA) : MachineConstantPoolValue((const Type*)cval->getType()), CVal(cval), S(NULL), LabelId(id), Kind(K), PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {} ARMConstantPoolValue::ARMConstantPoolValue(LLVMContext &C, const char *s, unsigned id, unsigned char PCAdj, ARMCP::ARMCPModifier Modif, bool AddCA) : MachineConstantPoolValue((const Type*)Type::getInt32Ty(C)), CVal(NULL), S(strdup(s)), LabelId(id), Kind(ARMCP::CPExtSymbol), PCAdjust(PCAdj), Modifier(Modif), AddCurrentAddress(AddCA) {} ARMConstantPoolValue::ARMConstantPoolValue(const GlobalValue *gv, ARMCP::ARMCPModifier Modif) : MachineConstantPoolValue((const Type*)Type::getInt32Ty(gv->getContext())), CVal(gv), S(NULL), LabelId(0), Kind(ARMCP::CPValue), PCAdjust(0), Modifier(Modif) {} const GlobalValue *ARMConstantPoolValue::getGV() const { return dyn_cast_or_null(CVal); } const BlockAddress *ARMConstantPoolValue::getBlockAddress() const { return dyn_cast_or_null(CVal); } static bool CPV_streq(const char *S1, const char *S2) { if (S1 == S2) return true; if (S1 && S2 && strcmp(S1, S2) == 0) return true; return false; } int ARMConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) { unsigned AlignMask = Alignment - 1; const std::vector Constants = CP->getConstants(); for (unsigned i = 0, e = Constants.size(); i != e; ++i) { if (Constants[i].isMachineConstantPoolEntry() && (Constants[i].getAlignment() & AlignMask) == 0) { ARMConstantPoolValue *CPV = (ARMConstantPoolValue *)Constants[i].Val.MachineCPVal; if (CPV->CVal == CVal && CPV->LabelId == LabelId && CPV->PCAdjust == PCAdjust && CPV_streq(CPV->S, S) && CPV->Modifier == Modifier) return i; } } return -1; } ARMConstantPoolValue::~ARMConstantPoolValue() { free((void*)S); } void ARMConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { ID.AddPointer(CVal); ID.AddPointer(S); ID.AddInteger(LabelId); ID.AddInteger(PCAdjust); } bool ARMConstantPoolValue::hasSameValue(ARMConstantPoolValue *ACPV) { if (ACPV->Kind == Kind && ACPV->CVal == CVal && ACPV->PCAdjust == PCAdjust && CPV_streq(ACPV->S, S) && ACPV->Modifier == Modifier) { if (ACPV->LabelId == LabelId) return true; // Two PC relative constpool entries containing the same GV address or // external symbols. FIXME: What about blockaddress? if (Kind == ARMCP::CPValue || Kind == ARMCP::CPExtSymbol) return true; } return false; } void ARMConstantPoolValue::dump() const { errs() << " " << *this; } void ARMConstantPoolValue::print(raw_ostream &O) const { if (CVal) O << CVal->getName(); else O << S; if (Modifier) O << "(" << getModifierText() << ")"; if (PCAdjust != 0) { O << "-(LPC" << LabelId << "+" << (unsigned)PCAdjust; if (AddCurrentAddress) O << "-."; O << ")"; } }