}
};
+//===---------------------------------------------------------------------------
+/// ConstantAggregateZero - All zero aggregate value
+///
+class ConstantAggregateZero : public Constant {
+ friend struct ConstantCreator<ConstantAggregateZero, Type, char>;
+ ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT
+protected:
+ ConstantAggregateZero(const Type *Ty) : Constant(Ty) {}
+public:
+ /// get() - static factory method for creating a null aggregate. It is
+ /// illegal to call this method with a non-aggregate type.
+ static Constant *get(const Type *Ty);
+
+ /// isNullValue - Return true if this is the value that would be returned by
+ /// getNullValue.
+ virtual bool isNullValue() const { return true; }
+
+ virtual void destroyConstant();
+ virtual void replaceUsesOfWithOnConstant(Value *From, Value *To,
+ bool DisableChecking = false);
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast:
+ ///
+ static inline bool classof(const ConstantAggregateZero *) { return true; }
+ static bool classof(const Constant *CPV);
+ static inline bool classof(const Value *V) {
+ return isa<Constant>(V) && classof(cast<Constant>(V));
+ }
+};
+
//===---------------------------------------------------------------------------
/// ConstantArray - Constant Array Declarations
inline const std::vector<Use> &getValues() const { return Operands; }
/// isNullValue - Return true if this is the value that would be returned by
- /// getNullValue.
- virtual bool isNullValue() const {
- // FIXME: This should be made to be MUCH faster. Just check against well
- // known null value!
- if (getNumOperands()) {
- const Constant *First = cast<Constant>(getOperand(0));
- if (!First->isNullValue()) return false;
- for (unsigned i = 1, e = getNumOperands(); i != e; ++i)
- if (cast<Constant>(getOperand(i)) != First)
- return false;
- }
- return true;
- }
+ /// getNullValue. This always returns false because zero arrays are always
+ /// created as ConstantAggregateZero objects.
+ virtual bool isNullValue() const { return false; }
virtual void destroyConstant();
virtual void replaceUsesOfWithOnConstant(Value *From, Value *To,
inline const std::vector<Use> &getValues() const { return Operands; }
/// isNullValue - Return true if this is the value that would be returned by
- /// getNullValue.
+ /// getNullValue. This always returns false because zero structs are always
+ /// created as ConstantAggregateZero objects.
virtual bool isNullValue() const {
- // FIXME: This should be made to be MUCH faster. Just check against well
- // known null value!
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- if (!cast<Constant>(getOperand(i))->isNullValue())
- return false;
- return true;
+ return false;
}
virtual void destroyConstant();
delete this;
}
-static std::map<const Type *, Constant*> NullValues;
-
// Static constructor to create a '0' constant of arbitrary type...
Constant *Constant::getNullValue(const Type *Ty) {
switch (Ty->getPrimitiveID()) {
case Type::PointerTyID:
return ConstantPointerNull::get(cast<PointerType>(Ty));
- case Type::StructTyID: {
- if (!Ty->isAbstract())
- if (Constant *V = NullValues[Ty])
- return V;
-
- const StructType *ST = cast<StructType>(Ty);
- std::vector<Constant*> Elements;
- Elements.resize(ST->getNumElements());
- for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i)
- Elements[i] = Constant::getNullValue(ST->getElementType(i));
- Constant *Ret = ConstantStruct::get(ST, Elements);
- if (!Ty->isAbstract())
- NullValues[Ty] = Ret;
- return Ret;
- }
- case Type::ArrayTyID: {
- if (!Ty->isAbstract())
- if (Constant *V = NullValues[Ty])
- return V;
-
- const ArrayType *AT = cast<ArrayType>(Ty);
- Constant *El = Constant::getNullValue(AT->getElementType());
- unsigned NumElements = AT->getNumElements();
- Constant *Ret = ConstantArray::get(AT,
- std::vector<Constant*>(NumElements, El));
- if (!Ty->isAbstract())
- NullValues[Ty] = Ret;
- return Ret;
- }
+ case Type::StructTyID:
+ case Type::ArrayTyID:
+ return ConstantAggregateZero::get(Ty);
default:
// Function, Type, Label, or Opaque type?
assert(0 && "Cannot create a null constant of that type!");
return ((Ty == Type::FloatTy || Ty == Type::DoubleTy) &&
!isa<ConstantExpr>(CPV));
}
+bool ConstantAggregateZero::classof(const Constant *CPV) {
+ return (isa<ArrayType>(CPV->getType()) || isa<StructType>(CPV->getType())) &&
+ CPV->isNullValue();
+}
bool ConstantArray::classof(const Constant *CPV) {
- return isa<ArrayType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+ return isa<ArrayType>(CPV->getType()) && !CPV->isNullValue();
}
bool ConstantStruct::classof(const Constant *CPV) {
- return isa<StructType>(CPV->getType()) && !isa<ConstantExpr>(CPV);
+ return isa<StructType>(CPV->getType()) && !CPV->isNullValue();
}
bool ConstantPointerNull::classof(const Constant *CPV) {
}
}
+//---- ConstantAggregateZero::get() implementation...
+//
+namespace llvm {
+ // ConstantAggregateZero does not take extra "value" argument...
+ template<class ValType>
+ struct ConstantCreator<ConstantAggregateZero, Type, ValType> {
+ static ConstantAggregateZero *create(const Type *Ty, const ValType &V){
+ return new ConstantAggregateZero(Ty);
+ }
+ };
+
+ template<>
+ struct ConvertConstantType<ConstantAggregateZero, Type> {
+ static void convert(ConstantAggregateZero *OldC, const Type *NewTy) {
+ // Make everyone now use a constant of the new type...
+ Constant *New = ConstantAggregateZero::get(NewTy);
+ assert(New != OldC && "Didn't replace constant??");
+ OldC->uncheckedReplaceAllUsesWith(New);
+ OldC->destroyConstant(); // This constant is now dead, destroy it.
+ }
+ };
+}
+
+static ValueMap<char, Type, ConstantAggregateZero> AggZeroConstants;
+
+Constant *ConstantAggregateZero::get(const Type *Ty) {
+ return AggZeroConstants.getOrCreate(Ty, 0);
+}
+
+// destroyConstant - Remove the constant from the constant table...
+//
+void ConstantAggregateZero::destroyConstant() {
+ AggZeroConstants.remove(this);
+ destroyConstantImpl();
+}
+
+void ConstantAggregateZero::replaceUsesOfWithOnConstant(Value *From, Value *To,
+ bool DisableChecking) {
+ assert(0 && "No uses!");
+ abort();
+}
+
+
+
//---- ConstantArray::get() implementation...
//
namespace llvm {
ConstantArray> ArrayConstants;
Constant *ConstantArray::get(const ArrayType *Ty,
- const std::vector<Constant*> &V) {
- return ArrayConstants.getOrCreate(Ty, V);
+ const std::vector<Constant*> &V) {
+ // If this is an all-zero array, return a ConstantAggregateZero object
+ if (!V.empty()) {
+ Constant *C = V[0];
+ if (!C->isNullValue())
+ return ArrayConstants.getOrCreate(Ty, V);
+ for (unsigned i = 1, e = V.size(); i != e; ++i)
+ if (V[i] != C)
+ return ArrayConstants.getOrCreate(Ty, V);
+ }
+ return ConstantAggregateZero::get(Ty);
}
// destroyConstant - Remove the constant from the constant table...
Constant *ConstantStruct::get(const StructType *Ty,
const std::vector<Constant*> &V) {
- return StructConstants.getOrCreate(Ty, V);
+ // Create a ConstantAggregateZero value if all elements are zeros...
+ for (unsigned i = 0, e = V.size(); i != e; ++i)
+ if (!V[i]->isNullValue())
+ return StructConstants.getOrCreate(Ty, V);
+
+ return ConstantAggregateZero::get(Ty);
}
// destroyConstant - Remove the constant from the constant table...