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
This commit is contained in:
Duncan P. N. Exon Smith 2016-02-21 02:39:49 +00:00
parent 78f46bea08
commit b6452798a5
4 changed files with 66 additions and 98 deletions

View File

@ -40,26 +40,47 @@ class SequentialType;
struct ConstantExprKeyType;
template <class ConstantClass> 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);

View File

@ -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

View File

@ -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<Constant, Value> {
}
};
template <> struct isa_impl<ConstantData, Value> {
static inline bool doit(const Value &Val) {
return Val.getValueID() >= Value::ConstantDataFirstVal &&
Val.getValueID() <= Value::ConstantDataLastVal;
}
};
template <> struct isa_impl<Argument, Value> {
static inline bool doit (const Value &Val) {
return Val.getValueID() == Value::ArgumentVal;

View File

@ -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<ConstantFP>(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<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);