From b6452798a5a2d578cdc451984821d9cd94c38db0 Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Sun, 21 Feb 2016 02:39:49 +0000 Subject: [PATCH] IR: Add ConstantData, for operand-less Constants Add a common parent `ConstantData` to the constants that have no operands. These are guaranteed to represent abstract data that is in no way tied to a specific Module. This is a good cleanup on its own. It also makes it simpler to disallow RAUW (and factor away use-lists) on these constants in the future. (I have some experimental patches that make RAUW illegal on ConstantData, and they seem to catch a bunch of bugs...) llvm-svn: 261464 --- llvm/include/llvm/IR/Constants.h | 106 +++++++++++++------------------ llvm/include/llvm/IR/Value.def | 12 ++-- llvm/include/llvm/IR/Value.h | 8 +++ llvm/lib/IR/Constants.cpp | 38 ++--------- 4 files changed, 66 insertions(+), 98 deletions(-) diff --git a/llvm/include/llvm/IR/Constants.h b/llvm/include/llvm/IR/Constants.h index f97fe8ce7115..f91bc99c807b 100644 --- a/llvm/include/llvm/IR/Constants.h +++ b/llvm/include/llvm/IR/Constants.h @@ -40,26 +40,47 @@ class SequentialType; struct ConstantExprKeyType; template struct ConstantAggrKeyType; +/// Base class for constants with no operands. +/// +/// These constants have no operands; they represent their data directly. +/// Since they can be in use by unrelated modules (and are never based on +/// GlobalValues), it never makes sensee to RAUW them. +class ConstantData : public Constant { + void anchor() override; + void *operator new(size_t, unsigned) = delete; + ConstantData() = delete; + ConstantData(const ConstantData &) = delete; + + friend class Constant; + Value *handleOperandChangeImpl(Value *From, Value *To) { + llvm_unreachable("Constant data does not have operands!"); + } + +protected: + explicit ConstantData(Type *Ty, ValueTy VT) : Constant(Ty, VT, nullptr, 0) {} + void *operator new(size_t s) { return User::operator new(s, 0); } + +public: + /// Methods to support type inquiry through isa, cast, and dyn_cast. + static bool classof(const Value *V) { + return V->getValueID() >= ConstantDataFirstVal && + V->getValueID() <= ConstantDataLastVal; + } +}; + //===----------------------------------------------------------------------===// /// This is the shared class of boolean and integer constants. This class /// represents both boolean and integral constants. /// @brief Class for constant integers. -class ConstantInt : public Constant { +class ConstantInt : public ConstantData { void anchor() override; - void *operator new(size_t, unsigned) = delete; ConstantInt(const ConstantInt &) = delete; ConstantInt(IntegerType *Ty, const APInt& V); APInt Val; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); -protected: - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s, 0); - } public: static ConstantInt *getTrue(LLVMContext &Context); static ConstantInt *getFalse(LLVMContext &Context); @@ -230,24 +251,17 @@ public: //===----------------------------------------------------------------------===// /// ConstantFP - Floating Point Values [float, double] /// -class ConstantFP : public Constant { +class ConstantFP : public ConstantData { APFloat Val; void anchor() override; - void *operator new(size_t, unsigned) = delete; ConstantFP(const ConstantFP &) = delete; - friend class LLVMContextImpl; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: ConstantFP(Type *Ty, const APFloat& V); -protected: - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s, 0); - } + public: /// Floating point negation must be implemented with f(x) = -0.0 - x. This /// method returns the negative zero constant for floating point or vector @@ -304,22 +318,16 @@ public: //===----------------------------------------------------------------------===// /// All zero aggregate value /// -class ConstantAggregateZero : public Constant { - void *operator new(size_t, unsigned) = delete; +class ConstantAggregateZero : public ConstantData { ConstantAggregateZero(const ConstantAggregateZero &) = delete; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: - explicit ConstantAggregateZero(Type *ty) - : Constant(ty, ConstantAggregateZeroVal, nullptr, 0) {} -protected: - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s, 0); - } + explicit ConstantAggregateZero(Type *Ty) + : ConstantData(Ty, ConstantAggregateZeroVal) {} + public: static ConstantAggregateZero *get(Type *Ty); @@ -503,24 +511,16 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantVector, Constant) //===----------------------------------------------------------------------===// /// A constant pointer value that points to null /// -class ConstantPointerNull : public Constant { - void *operator new(size_t, unsigned) = delete; +class ConstantPointerNull : public ConstantData { ConstantPointerNull(const ConstantPointerNull &) = delete; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: explicit ConstantPointerNull(PointerType *T) - : Constant(T, - Value::ConstantPointerNullVal, nullptr, 0) {} + : ConstantData(T, Value::ConstantPointerNullVal) {} -protected: - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s, 0); - } public: /// Static factory methods - Return objects of the specified value static ConstantPointerNull *get(PointerType *T); @@ -546,7 +546,7 @@ public: /// /// This is the common base class of ConstantDataArray and ConstantDataVector. /// -class ConstantDataSequential : public Constant { +class ConstantDataSequential : public ConstantData { friend class LLVMContextImpl; /// A pointer to the bytes underlying this constant (which is owned by the /// uniquing StringMap). @@ -557,27 +557,19 @@ class ConstantDataSequential : public Constant { /// element array of i8, or a 1-element array of i32. They'll both end up in /// the same StringMap bucket, linked up. ConstantDataSequential *Next; - void *operator new(size_t, unsigned) = delete; ConstantDataSequential(const ConstantDataSequential &) = delete; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) - : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} + : ConstantData(ty, VT), DataElements(Data), Next(nullptr) {} ~ConstantDataSequential() override { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); -protected: - // Allocate space for exactly zero operands. - void *operator new(size_t s) { - return User::operator new(s, 0); - } public: - /// Return true if a ConstantDataSequential can be formed with a vector or /// array of the specified element type. /// ConstantDataArray only works with normal float and int types that are @@ -780,19 +772,15 @@ public: //===----------------------------------------------------------------------===// /// A constant token which is empty /// -class ConstantTokenNone : public Constant { - void *operator new(size_t, unsigned) = delete; +class ConstantTokenNone : public ConstantData { ConstantTokenNone(const ConstantTokenNone &) = delete; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: explicit ConstantTokenNone(LLVMContext &Context) - : Constant(Type::getTokenTy(Context), ConstantTokenNoneVal, nullptr, 0) {} - // allocate space for exactly zero operands - void *operator new(size_t s) { return User::operator new(s, 0); } + : ConstantData(Type::getTokenTy(Context), ConstantTokenNoneVal) {} public: /// Return the ConstantTokenNone. @@ -1223,21 +1211,15 @@ DEFINE_TRANSPARENT_OPERAND_ACCESSORS(ConstantExpr, Constant) /// can appear to have different bit patterns at each use. See /// LangRef.html#undefvalues for details. /// -class UndefValue : public Constant { - void *operator new(size_t, unsigned) = delete; +class UndefValue : public ConstantData { UndefValue(const UndefValue &) = delete; friend class Constant; void destroyConstantImpl(); - Value *handleOperandChangeImpl(Value *From, Value *To); protected: - explicit UndefValue(Type *T) : Constant(T, UndefValueVal, nullptr, 0) {} -protected: - // allocate space for exactly zero operands - void *operator new(size_t s) { - return User::operator new(s, 0); - } + explicit UndefValue(Type *T) : ConstantData(T, UndefValueVal) {} + public: /// Static factory methods - Return an 'undef' object of the specified type. static UndefValue *get(Type *T); diff --git a/llvm/include/llvm/IR/Value.def b/llvm/include/llvm/IR/Value.def index 8fd32cb9a7c2..eb47738810f9 100644 --- a/llvm/include/llvm/IR/Value.def +++ b/llvm/include/llvm/IR/Value.def @@ -61,17 +61,19 @@ HANDLE_VALUE(MemoryPhi) HANDLE_GLOBAL_VALUE(Function) HANDLE_GLOBAL_VALUE(GlobalAlias) HANDLE_GLOBAL_VALUE(GlobalVariable) -HANDLE_CONSTANT(UndefValue) HANDLE_CONSTANT(BlockAddress) HANDLE_CONSTANT(ConstantExpr) +HANDLE_CONSTANT(ConstantArray) +HANDLE_CONSTANT(ConstantStruct) +HANDLE_CONSTANT(ConstantVector) + +// ConstantData. +HANDLE_CONSTANT(UndefValue) HANDLE_CONSTANT(ConstantAggregateZero) HANDLE_CONSTANT(ConstantDataArray) HANDLE_CONSTANT(ConstantDataVector) HANDLE_CONSTANT(ConstantInt) HANDLE_CONSTANT(ConstantFP) -HANDLE_CONSTANT(ConstantArray) -HANDLE_CONSTANT(ConstantStruct) -HANDLE_CONSTANT(ConstantVector) HANDLE_CONSTANT(ConstantPointerNull) HANDLE_CONSTANT(ConstantTokenNone) @@ -84,6 +86,8 @@ HANDLE_INSTRUCTION(Instruction) HANDLE_CONSTANT_MARKER(ConstantFirstVal, Function) HANDLE_CONSTANT_MARKER(ConstantLastVal, ConstantTokenNone) +HANDLE_CONSTANT_MARKER(ConstantDataFirstVal, UndefValue) +HANDLE_CONSTANT_MARKER(ConstantDataLastVal, ConstantTokenNone) #undef HANDLE_GLOBAL_VALUE #undef HANDLE_CONSTANT diff --git a/llvm/include/llvm/IR/Value.h b/llvm/include/llvm/IR/Value.h index c2997e9a4d15..00b02f2fb618 100644 --- a/llvm/include/llvm/IR/Value.h +++ b/llvm/include/llvm/IR/Value.h @@ -27,6 +27,7 @@ class Argument; class AssemblyAnnotationWriter; class BasicBlock; class Constant; +class ConstantData; class DataLayout; class Function; class GlobalAlias; @@ -685,6 +686,13 @@ template <> struct isa_impl { } }; +template <> struct isa_impl { + static inline bool doit(const Value &Val) { + return Val.getValueID() >= Value::ConstantDataFirstVal && + Val.getValueID() <= Value::ConstantDataLastVal; + } +}; + template <> struct isa_impl { static inline bool doit (const Value &Val) { return Val.getValueID() == Value::ArgumentVal; diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index 87e870e627b3..54d0f1f8c2fa 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -42,6 +42,8 @@ using namespace llvm; void Constant::anchor() { } +void ConstantData::anchor() {} + bool Constant::isNegativeZeroValue() const { // Floating point values have an explicit -0.0 value. if (const ConstantFP *CFP = dyn_cast(this)) @@ -521,8 +523,8 @@ void Constant::removeDeadConstantUsers() const { void ConstantInt::anchor() { } -ConstantInt::ConstantInt(IntegerType *Ty, const APInt& V) - : Constant(Ty, ConstantIntVal, nullptr, 0), Val(V) { +ConstantInt::ConstantInt(IntegerType *Ty, const APInt &V) + : ConstantData(Ty, ConstantIntVal), Val(V) { assert(V.getBitWidth() == Ty->getBitWidth() && "Invalid constant for type"); } @@ -748,8 +750,8 @@ Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) { return C; } -ConstantFP::ConstantFP(Type *Ty, const APFloat& V) - : Constant(Ty, ConstantFPVal, nullptr, 0), Val(V) { +ConstantFP::ConstantFP(Type *Ty, const APFloat &V) + : ConstantData(Ty, ConstantFPVal), Val(V) { assert(&V.getSemantics() == TypeToFloatSemantics(Ty) && "FP type Mismatch"); } @@ -2816,34 +2818,6 @@ void Constant::handleOperandChange(Value *From, Value *To) { destroyConstant(); } -Value *ConstantInt::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *ConstantFP::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *ConstantTokenNone::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *UndefValue::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *ConstantPointerNull::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *ConstantAggregateZero::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - -Value *ConstantDataSequential::handleOperandChangeImpl(Value *From, Value *To) { - llvm_unreachable("Unsupported class for handleOperandChange()!"); -} - Value *ConstantArray::handleOperandChangeImpl(Value *From, Value *To) { assert(isa(To) && "Cannot make Constant refer to non-constant!"); Constant *ToC = cast(To);