X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FVMCore%2FConstants.cpp;h=3887e33274a693d72cae36299a8f2ac9e491822c;hb=ec4d36276f3b2916dd2430144dc228759d8b2ea2;hp=b2335bc9444a0cd90e84223bd884a443a580a605;hpb=a3b63668d4684adcceee13284133c0088061943f;p=oota-llvm.git diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index b2335bc9444..3887e33274a 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -1,14 +1,13 @@ -//===-- ConstantVals.cpp - Implement Constant nodes --------------*- C++ -*--=// +//===-- Constants.cpp - Implement Constant nodes -----------------*- C++ -*--=// // // This file implements the Constant* classes... // //===----------------------------------------------------------------------===// -#define __STDC_LIMIT_MACROS // Get defs for INT64_MAX and friends... -#include "llvm/ConstantVals.h" +#include "llvm/Constants.h" #include "llvm/DerivedTypes.h" +#include "llvm/iMemory.h" #include "llvm/SymbolTable.h" -#include "llvm/GlobalValue.h" #include "llvm/Module.h" #include "llvm/SlotCalculator.h" #include "Support/StringExtras.h" @@ -17,6 +16,7 @@ using std::map; using std::pair; using std::make_pair; +using std::vector; ConstantBool *ConstantBool::True = new ConstantBool(true); ConstantBool *ConstantBool::False = new ConstantBool(false); @@ -33,8 +33,36 @@ void Constant::setName(const std::string &Name, SymbolTable *ST) { if (Name.size()) ST->insert(Name, this); } +void Constant::destroyConstantImpl() { + // When a Constant is destroyed, there may be lingering + // references to the constant by other constants in the constant pool. These + // constants are implicitly dependant on the module that is being deleted, + // but they don't know that. Because we only find out when the CPV is + // deleted, we must now notify all of our users (that should only be + // Constants) that they are, in fact, invalid now and should be deleted. + // + while (!use_empty()) { + Value *V = use_back(); +#ifndef NDEBUG // Only in -g mode... + if (!isa(V)) + std::cerr << "While deleting: " << *this + << "\n\nUse still stuck around after Def is destroyed: " + << *V << "\n\n"; +#endif + assert(isa(V) && "References remain to Constant being destroyed"); + Constant *CPV = cast(V); + CPV->destroyConstant(); + + // The constant should remove itself from our use list... + assert((use_empty() || use_back() != V) && "Constant not removed!"); + } + + // Value has no outstanding references it is safe to delete it now... + delete this; +} + // Static constructor to create a '0' constant of arbitrary type... -Constant *Constant::getNullConstant(const Type *Ty) { +Constant *Constant::getNullValue(const Type *Ty) { switch (Ty->getPrimitiveID()) { case Type::BoolTyID: return ConstantBool::get(false); case Type::SByteTyID: @@ -57,37 +85,78 @@ Constant *Constant::getNullConstant(const Type *Ty) { } } -void Constant::destroyConstantImpl() { - // When a Constant is destroyed, there may be lingering - // references to the constant by other constants in the constant pool. These - // constants are implicitly dependant on the module that is being deleted, - // but they don't know that. Because we only find out when the CPV is - // deleted, we must now notify all of our users (that should only be - // Constants) that they are, in fact, invalid now and should be deleted. - // - while (!use_empty()) { - Value *V = use_back(); -#ifndef NDEBUG // Only in -g mode... - if (!isa(V)) { - std::cerr << "While deleting: "; - dump(); - std::cerr << "\nUse still stuck around after Def is destroyed: "; - V->dump(); - std::cerr << "\n"; - } -#endif - assert(isa(V) && "References remain to ConstantPointerRef!"); - Constant *CPV = cast(V); - CPV->destroyConstant(); +// Static constructor to create the maximum constant of an integral type... +ConstantIntegral *ConstantIntegral::getMaxValue(const Type *Ty) { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: return ConstantBool::True; + case Type::SByteTyID: + case Type::ShortTyID: + case Type::IntTyID: + case Type::LongTyID: { + // Calculate 011111111111111... + unsigned TypeBits = Ty->getPrimitiveSize()*8; + int64_t Val = INT64_MAX; // All ones + Val >>= 64-TypeBits; // Shift out unwanted 1 bits... + return ConstantSInt::get(Ty, Val); + } - // The constant should remove itself from our use list... - assert((use_empty() || use_back() == V) && "Constant not removed!"); + case Type::UByteTyID: + case Type::UShortTyID: + case Type::UIntTyID: + case Type::ULongTyID: return getAllOnesValue(Ty); + + default: return 0; } +} - // Value has no outstanding references it is safe to delete it now... - delete this; +// Static constructor to create the minimum constant for an integral type... +ConstantIntegral *ConstantIntegral::getMinValue(const Type *Ty) { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: return ConstantBool::False; + case Type::SByteTyID: + case Type::ShortTyID: + case Type::IntTyID: + case Type::LongTyID: { + // Calculate 1111111111000000000000 + unsigned TypeBits = Ty->getPrimitiveSize()*8; + int64_t Val = -1; // All ones + Val <<= TypeBits-1; // Shift over to the right spot + return ConstantSInt::get(Ty, Val); + } + + case Type::UByteTyID: + case Type::UShortTyID: + case Type::UIntTyID: + case Type::ULongTyID: return ConstantUInt::get(Ty, 0); + + default: return 0; + } +} + +// Static constructor to create an integral constant with all bits set +ConstantIntegral *ConstantIntegral::getAllOnesValue(const Type *Ty) { + switch (Ty->getPrimitiveID()) { + case Type::BoolTyID: return ConstantBool::True; + case Type::SByteTyID: + case Type::ShortTyID: + case Type::IntTyID: + case Type::LongTyID: return ConstantSInt::get(Ty, -1); + + case Type::UByteTyID: + case Type::UShortTyID: + case Type::UIntTyID: + case Type::ULongTyID: { + // Calculate ~0 of the right type... + unsigned TypeBits = Ty->getPrimitiveSize()*8; + uint64_t Val = ~0ULL; // All ones + Val >>= 64-TypeBits; // Shift out unwanted 1 bits... + return ConstantUInt::get(Ty, Val); + } + default: return 0; + } } + //===----------------------------------------------------------------------===// // ConstantXXX Classes //===----------------------------------------------------------------------===// @@ -95,19 +164,23 @@ void Constant::destroyConstantImpl() { //===----------------------------------------------------------------------===// // Normal Constructors -ConstantBool::ConstantBool(bool V) : Constant(Type::BoolTy) { +ConstantBool::ConstantBool(bool V) : ConstantIntegral(Type::BoolTy) { Val = V; } -ConstantInt::ConstantInt(const Type *Ty, uint64_t V) : Constant(Ty) { +ConstantInt::ConstantInt(const Type *Ty, uint64_t V) : ConstantIntegral(Ty) { Val.Unsigned = V; } ConstantSInt::ConstantSInt(const Type *Ty, int64_t V) : ConstantInt(Ty, V) { + assert(Ty->isInteger() && Ty->isSigned() && + "Illegal type for unsigned integer constant!"); assert(isValueValidForType(Ty, V) && "Value too large for type!"); } ConstantUInt::ConstantUInt(const Type *Ty, uint64_t V) : ConstantInt(Ty, V) { + assert(Ty->isInteger() && Ty->isUnsigned() && + "Illegal type for unsigned integer constant!"); assert(isValueValidForType(Ty, V) && "Value too large for type!"); } @@ -118,7 +191,8 @@ ConstantFP::ConstantFP(const Type *Ty, double V) : Constant(Ty) { ConstantArray::ConstantArray(const ArrayType *T, const std::vector &V) : Constant(T) { - for (unsigned i = 0; i < V.size(); i++) { + Operands.reserve(V.size()); + for (unsigned i = 0, e = V.size(); i != e; ++i) { assert(V[i]->getType() == T->getElementType()); Operands.push_back(Use(V[i], this)); } @@ -127,8 +201,10 @@ ConstantArray::ConstantArray(const ArrayType *T, ConstantStruct::ConstantStruct(const StructType *T, const std::vector &V) : Constant(T) { const StructType::ElementTypes &ETypes = T->getElementTypes(); - - for (unsigned i = 0; i < V.size(); i++) { + assert(V.size() == ETypes.size() && + "Invalid initializer vector for constant structure"); + Operands.reserve(V.size()); + for (unsigned i = 0, e = V.size(); i != e; ++i) { assert(V[i]->getType() == ETypes[i]); Operands.push_back(Use(V[i], this)); } @@ -139,163 +215,61 @@ ConstantPointerRef::ConstantPointerRef(GlobalValue *GV) Operands.push_back(Use(GV, this)); } - - -//===----------------------------------------------------------------------===// -// getStrValue implementations - -std::string ConstantBool::getStrValue() const { - return Val ? "true" : "false"; -} - -std::string ConstantSInt::getStrValue() const { - return itostr(Val.Signed); -} - -std::string ConstantUInt::getStrValue() const { - return utostr(Val.Unsigned); -} - -// ConstantFP::getStrValue - We would like to output the FP constant value in -// exponential notation, but we cannot do this if doing so will lose precision. -// Check here to make sure that we only output it in exponential format if we -// can parse the value back and get the same value. -// -std::string ConstantFP::getStrValue() const { - std::string StrVal = ftostr(Val); - - // Check to make sure that the stringized number is not some string like "Inf" - // or NaN, that atof will accept, but the lexer will not. Check that the - // string matches the "[-+]?[0-9]" regex. - // - if ((StrVal[0] >= '0' && StrVal[0] <= '9') || - ((StrVal[0] == '-' || StrVal[0] == '+') && - (StrVal[0] >= '0' && StrVal[0] <= '9'))) { - double TestVal = atof(StrVal.c_str()); // Reparse stringized version! - if (TestVal == Val) - return StrVal; - } - - // Otherwise we could not reparse it to exactly the same value, so we must - // output the string in hexadecimal format! - // - // Behave nicely in the face of C TBAA rules... see: - // http://www.nullstone.com/htmls/category/aliastyp.htm - // - char *Ptr = (char*)&Val; - assert(sizeof(double) == sizeof(uint64_t) && sizeof(double) == 8 && - "assuming that double is 64 bits!"); - return "0x"+utohexstr(*(uint64_t*)Ptr); -} - -std::string ConstantArray::getStrValue() const { - std::string Result; - - // As a special case, print the array as a string if it is an array of - // ubytes or an array of sbytes with positive values. - // - const Type *ETy = getType()->getElementType(); - bool isString = (ETy == Type::SByteTy || ETy == Type::UByteTy); - - if (ETy == Type::SByteTy) { - for (unsigned i = 0; i < Operands.size(); ++i) - if (ETy == Type::SByteTy && - cast(Operands[i])->getValue() < 0) { - isString = false; - break; - } - } - - if (isString) { - Result = "c\""; - for (unsigned i = 0; i < Operands.size(); ++i) { - unsigned char C = (ETy == Type::SByteTy) ? - (unsigned char)cast(Operands[i])->getValue() : - (unsigned char)cast(Operands[i])->getValue(); - - if (isprint(C)) { - Result += C; - } else { - Result += '\\'; - Result += ( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A'); - Result += ((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A'); - } - } - Result += "\""; - - } else { - Result = "["; - if (Operands.size()) { - Result += " " + Operands[0]->getType()->getDescription() + - " " + cast(Operands[0])->getStrValue(); - for (unsigned i = 1; i < Operands.size(); i++) - Result += ", " + Operands[i]->getType()->getDescription() + - " " + cast(Operands[i])->getStrValue(); - } - Result += " ]"; - } - - return Result; +ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C, const Type *Ty) + : Constant(Ty), iType(Opcode) { + Operands.push_back(Use(C, this)); } -std::string ConstantStruct::getStrValue() const { - std::string Result = "{"; - if (Operands.size()) { - Result += " " + Operands[0]->getType()->getDescription() + - " " + cast(Operands[0])->getStrValue(); - for (unsigned i = 1; i < Operands.size(); i++) - Result += ", " + Operands[i]->getType()->getDescription() + - " " + cast(Operands[i])->getStrValue(); - } - - return Result + " }"; +ConstantExpr::ConstantExpr(unsigned Opcode, Constant *C1, Constant *C2) + : Constant(C1->getType()), iType(Opcode) { + Operands.push_back(Use(C1, this)); + Operands.push_back(Use(C2, this)); } -std::string ConstantPointerNull::getStrValue() const { - return "null"; +ConstantExpr::ConstantExpr(Constant *C, const std::vector &IdxList, + const Type *DestTy) + : Constant(DestTy), iType(Instruction::GetElementPtr) { + Operands.reserve(1+IdxList.size()); + Operands.push_back(Use(C, this)); + for (unsigned i = 0, E = IdxList.size(); i != E; ++i) + Operands.push_back(Use(IdxList[i], this)); } -std::string ConstantPointerRef::getStrValue() const { - const GlobalValue *V = getValue(); - if (V->hasName()) return "%" + V->getName(); - - // FIXME: This is a gross hack. - SlotCalculator *Table = new SlotCalculator(V->getParent(), true); - int Slot = Table->getValSlot(V); - delete Table; - - if (Slot >= 0) return std::string(" %") + itostr(Slot); - else return ""; -} //===----------------------------------------------------------------------===// // classof implementations +bool ConstantIntegral::classof(const Constant *CPV) { + return CPV->getType()->isIntegral() && !isa(CPV); +} + bool ConstantInt::classof(const Constant *CPV) { - return CPV->getType()->isIntegral(); + return CPV->getType()->isInteger() && !isa(CPV); } bool ConstantSInt::classof(const Constant *CPV) { - return CPV->getType()->isSigned(); + return CPV->getType()->isSigned() && !isa(CPV); } bool ConstantUInt::classof(const Constant *CPV) { - return CPV->getType()->isUnsigned(); + return CPV->getType()->isUnsigned() && !isa(CPV); } bool ConstantFP::classof(const Constant *CPV) { const Type *Ty = CPV->getType(); - return Ty == Type::FloatTy || Ty == Type::DoubleTy; + return ((Ty == Type::FloatTy || Ty == Type::DoubleTy) && + !isa(CPV)); } bool ConstantArray::classof(const Constant *CPV) { - return isa(CPV->getType()); + return isa(CPV->getType()) && !isa(CPV); } bool ConstantStruct::classof(const Constant *CPV) { - return isa(CPV->getType()); + return isa(CPV->getType()) && !isa(CPV); } bool ConstantPointer::classof(const Constant *CPV) { - return isa(CPV->getType()); + return (isa(CPV->getType()) && !isa(CPV)); } + //===----------------------------------------------------------------------===// // isValueValidForType implementations @@ -353,36 +327,110 @@ bool ConstantFP::isValueValidForType(const Type *Ty, double Val) { }; //===----------------------------------------------------------------------===// -// Hash Function Implementations -#if 0 -unsigned ConstantSInt::hash(const Type *Ty, int64_t V) { - return unsigned(Ty->getPrimitiveID() ^ V); -} +// replaceUsesOfWithOnConstant implementations -unsigned ConstantUInt::hash(const Type *Ty, uint64_t V) { - return unsigned(Ty->getPrimitiveID() ^ V); -} +void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + std::vector Values; + Values.reserve(getValues().size()); // Build replacement array... + for (unsigned i = 0, e = getValues().size(); i != e; ++i) { + Constant *Val = cast(getValues()[i]); + if (Val == From) Val = cast(To); + Values.push_back(Val); + } + + ConstantArray *Replacement = ConstantArray::get(getType(), Values); + assert(Replacement != this && "I didn't contain From!"); -unsigned ConstantFP::hash(const Type *Ty, double V) { - return Ty->getPrimitiveID() ^ unsigned(V); + // Everyone using this now uses the replacement... + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); } -unsigned ConstantArray::hash(const ArrayType *Ty, - const std::vector &V) { - unsigned Result = (Ty->getUniqueID() << 5) ^ (Ty->getUniqueID() * 7); - for (unsigned i = 0; i < V.size(); ++i) - Result ^= V[i]->getHash() << (i & 7); - return Result; +void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + std::vector Values; + Values.reserve(getValues().size()); + for (unsigned i = 0, e = getValues().size(); i != e; ++i) { + Constant *Val = cast(getValues()[i]); + if (Val == From) Val = cast(To); + Values.push_back(Val); + } + + ConstantStruct *Replacement = ConstantStruct::get(getType(), Values); + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + +void ConstantPointerRef::replaceUsesOfWithOnConstant(Value *From, Value *To) { + if (isa(To)) { + assert(From == getOperand(0) && "Doesn't contain from!"); + ConstantPointerRef *Replacement = + ConstantPointerRef::get(cast(To)); + + // Everyone using this now uses the replacement... + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); + } else { + // Just replace ourselves with the To value specified. + replaceAllUsesWith(To); + + // Delete the old constant! + destroyConstant(); + } } -unsigned ConstantStruct::hash(const StructType *Ty, - const std::vector &V) { - unsigned Result = (Ty->getUniqueID() << 5) ^ (Ty->getUniqueID() * 7); - for (unsigned i = 0; i < V.size(); ++i) - Result ^= V[i]->getHash() << (i & 7); - return Result; +void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *To) { + assert(isa(To) && "Cannot make Constant refer to non-constant!"); + + ConstantExpr *Replacement = 0; + if (getOpcode() == Instruction::GetElementPtr) { + std::vector Indices; + Constant *Pointer = cast(getOperand(0)); + Indices.reserve(getNumOperands()-1); + if (Pointer == From) Pointer = cast(To); + + for (unsigned i = 1, e = getNumOperands(); i != e; ++i) { + Constant *Val = cast(getOperand(i)); + if (Val == From) Val = cast(To); + Indices.push_back(Val); + } + Replacement = ConstantExpr::getGetElementPtr(Pointer, Indices); + } else if (getOpcode() == Instruction::Cast) { + assert(getOperand(0) == From && "Cast only has one use!"); + Replacement = ConstantExpr::getCast(cast(To), getType()); + } else if (getNumOperands() == 2) { + Constant *C1 = cast(getOperand(0)); + Constant *C2 = cast(getOperand(1)); + if (C1 == From) C1 = cast(To); + if (C2 == From) C2 = cast(To); + Replacement = ConstantExpr::get(getOpcode(), C1, C2); + } else { + assert(0 && "Unknown ConstantExpr type!"); + return; + } + + assert(Replacement != this && "I didn't contain From!"); + + // Everyone using this now uses the replacement... + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); } -#endif + + //===----------------------------------------------------------------------===// // Factory Function Implementation @@ -393,7 +441,7 @@ struct ValueMap { map Map; inline ConstantClass *get(const Type *Ty, ValType V) { - map::iterator I = + typename map::iterator I = Map.find(ConstHashKey(Ty, V)); return (I != Map.end()) ? I->second : 0; } @@ -403,7 +451,7 @@ struct ValueMap { } inline void remove(ConstantClass *CP) { - for (map::iterator I = Map.begin(), + for (typename map::iterator I = Map.begin(), E = Map.end(); I != E;++I) if (I->second == CP) { Map.erase(I); @@ -484,6 +532,24 @@ void ConstantArray::destroyConstant() { destroyConstantImpl(); } +// getAsString - If the sub-element type of this array is either sbyte or ubyte, +// then this method converts the array to an std::string and returns it. +// Otherwise, it asserts out. +// +std::string ConstantArray::getAsString() const { + std::string Result; + if (getType()->getElementType() == Type::SByteTy) + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + Result += (char)cast(getOperand(i))->getValue(); + else { + assert(getType()->getElementType() == Type::UByteTy && "Not a string!"); + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + Result += (char)cast(getOperand(i))->getValue(); + } + return Result; +} + + //---- ConstantStruct::get() implementation... // static ValueMap, ConstantStruct> StructConstants; @@ -503,6 +569,7 @@ void ConstantStruct::destroyConstant() { destroyConstantImpl(); } + //---- ConstantPointerNull::get() implementation... // static ValueMap NullPtrConstants; @@ -514,17 +581,129 @@ ConstantPointerNull *ConstantPointerNull::get(const PointerType *Ty) { return Result; } +// destroyConstant - Remove the constant from the constant table... +// +void ConstantPointerNull::destroyConstant() { + NullPtrConstants.remove(this); + destroyConstantImpl(); +} + + //---- ConstantPointerRef::get() implementation... // ConstantPointerRef *ConstantPointerRef::get(GlobalValue *GV) { assert(GV->getParent() && "Global Value must be attached to a module!"); - + // The Module handles the pointer reference sharing... return GV->getParent()->getConstantPointerRef(GV); } +// destroyConstant - Remove the constant from the constant table... +// +void ConstantPointerRef::destroyConstant() { + getValue()->getParent()->destroyConstantPointerRef(this); + destroyConstantImpl(); +} + + +//---- ConstantExpr::get() implementations... +// +typedef pair > ExprMapKeyType; +static ValueMap ExprConstants; + +ConstantExpr *ConstantExpr::getCast(Constant *C, const Type *Ty) { -void ConstantPointerRef::mutateReference(GlobalValue *NewGV) { - getValue()->getParent()->mutateConstantPointerRef(getValue(), NewGV); - Operands[0] = NewGV; + // Look up the constant in the table first to ensure uniqueness + vector argVec(1, C); + const ExprMapKeyType &Key = make_pair(Instruction::Cast, argVec); + ConstantExpr *Result = ExprConstants.get(Ty, Key); + if (Result) return Result; + + // Its not in the table so create a new one and put it in the table. + Result = new ConstantExpr(Instruction::Cast, C, Ty); + ExprConstants.add(Ty, Key, Result); + return Result; +} + +ConstantExpr *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { + // Look up the constant in the table first to ensure uniqueness + vector argVec(1, C1); argVec.push_back(C2); + const ExprMapKeyType &Key = make_pair(Opcode, argVec); + ConstantExpr *Result = ExprConstants.get(C1->getType(), Key); + if (Result) return Result; + + // Its not in the table so create a new one and put it in the table. + // Check the operands for consistency first + assert((Opcode >= Instruction::BinaryOpsBegin && + Opcode < Instruction::BinaryOpsEnd) && + "Invalid opcode in binary constant expression"); + + assert(C1->getType() == C2->getType() && + "Operand types in binary constant expression should match"); + + Result = new ConstantExpr(Opcode, C1, C2); + ExprConstants.add(C1->getType(), Key, Result); + return Result; +} + +ConstantExpr *ConstantExpr::getGetElementPtr(Constant *C, + const std::vector &IdxList) { + const Type *Ty = C->getType(); + + // Look up the constant in the table first to ensure uniqueness + vector argVec(1, C); + argVec.insert(argVec.end(), IdxList.begin(), IdxList.end()); + + const ExprMapKeyType &Key = make_pair(Instruction::GetElementPtr, argVec); + ConstantExpr *Result = ExprConstants.get(Ty, Key); + if (Result) return Result; + + // Its not in the table so create a new one and put it in the table. + // Check the operands for consistency first + // + assert(isa(Ty) && + "Non-pointer type for constant GelElementPtr expression"); + + // Check that the indices list is valid... + std::vector ValIdxList(IdxList.begin(), IdxList.end()); + const Type *DestTy = GetElementPtrInst::getIndexedType(Ty, ValIdxList, true); + assert(DestTy && "Invalid index list for constant GelElementPtr expression"); + + Result = new ConstantExpr(C, IdxList, PointerType::get(DestTy)); + ExprConstants.add(Ty, Key, Result); + return Result; +} + +// destroyConstant - Remove the constant from the constant table... +// +void ConstantExpr::destroyConstant() { + ExprConstants.remove(this); + destroyConstantImpl(); +} + +const char *ConstantExpr::getOpcodeName() const { + return Instruction::getOpcodeName(getOpcode()); +} + +unsigned Constant::mutateReferences(Value *OldV, Value *NewV) { + // Uses of constant pointer refs are global values, not constants! + if (ConstantPointerRef *CPR = dyn_cast(this)) { + GlobalValue *NewGV = cast(NewV); + GlobalValue *OldGV = CPR->getValue(); + + assert(OldGV == OldV && "Cannot mutate old value if I'm not using it!"); + + OldGV->getParent()->mutateConstantPointerRef(OldGV, NewGV); + Operands[0] = NewGV; + return 1; + } else { + Constant *NewC = cast(NewV); + unsigned NumReplaced = 0; + for (unsigned i = 0, N = getNumOperands(); i != N; ++i) + if (Operands[i] == OldV) { + ++NumReplaced; + Operands[i] = NewC; + } + return NumReplaced; + } }