diff --git a/llvm/include/llvm/Constant.h b/llvm/include/llvm/Constant.h index 708573874d61..3105cea319d9 100644 --- a/llvm/include/llvm/Constant.h +++ b/llvm/include/llvm/Constant.h @@ -16,10 +16,11 @@ protected: void destroyConstantImpl(); public: - /// setName - Specialize setName to handle symbol table majik... + // setName - Specialize setName to handle symbol table majik... virtual void setName(const std::string &name, SymbolTable *ST = 0); /// Static constructor to get a '0' constant of arbitrary type... + /// static Constant *getNullValue(const Type *Ty); /// isNullValue - Return true if this is the value that would be returned by @@ -29,6 +30,7 @@ public: virtual void print(std::ostream &O) const; /// isConstantExpr - Return true if this is a ConstantExpr + /// virtual bool isConstantExpr() const { return false; } @@ -49,12 +51,31 @@ public: virtual void destroyConstant() { assert(0 && "Not reached!"); } - /// Methods for support type inquiry through isa, cast, and dyn_cast: + //// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const Constant *) { return true; } static inline bool classof(const Value *V) { return V->getValueType() == Value::ConstantVal; } + /// replaceUsesOfWithOnConstant - This method is a special form of + /// User::replaceUsesOfWith (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To) { + // Provide a default implementation for constants (like integers) that + // cannot use any other values. This cannot be called at runtime, but needs + // to be here to avoid link errors. + assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " + "implemented for all constants that have operands!"); + assert(0 && "Constants that do not have operands cannot be using 'From'!"); + } + // WARNING: Only to be used by Bytecode & Assembly Parsers! USER CODE SHOULD // NOT USE THIS!! // Returns the number of uses of OldV that were replaced. diff --git a/llvm/include/llvm/Constants.h b/llvm/include/llvm/Constants.h index 63d1bfdd5592..a91c1971fa4f 100644 --- a/llvm/include/llvm/Constants.h +++ b/llvm/include/llvm/Constants.h @@ -292,6 +292,7 @@ public: virtual bool isNullValue() const { return false; } virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantArray *) { return true; } @@ -330,6 +331,7 @@ public: virtual bool isNullValue() const { return false; } virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantStruct *) { return true; } @@ -423,6 +425,7 @@ public: } virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantPointerRef *) { return true; } @@ -489,6 +492,7 @@ public: virtual bool isConstantExpr() const { return true; } virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To); /// Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const ConstantExpr *) { return true; } diff --git a/llvm/lib/VMCore/Constants.cpp b/llvm/lib/VMCore/Constants.cpp index de61c37d6e32..d0413f12b343 100644 --- a/llvm/lib/VMCore/Constants.cpp +++ b/llvm/lib/VMCore/Constants.cpp @@ -326,6 +326,112 @@ bool ConstantFP::isValueValidForType(const Type *Ty, double Val) { } }; +//===----------------------------------------------------------------------===// +// replaceUsesOfWithOnConstant implementations + +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!"); + + // Everyone using this now uses the replacement... + replaceAllUsesWith(Replacement); + + // Delete the old constant! + destroyConstant(); +} + +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(); + } +} + +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(); +} + + + //===----------------------------------------------------------------------===// // Factory Function Implementation