-//===-- llvm/DerivedTypes.h - Classes for handling data types ----*- C++ -*--=//
+//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===//
//
// This file contains the declarations of classes that represent "derived
// types". These are things like "arrays of x" or "structure of x, y, z" or
#include "llvm/Type.h"
-class DerivedType : public Type {
- char isRefining; // Used for recursive types
-
+template<class ValType, class TypeClass> class TypeMap;
+class FunctionValType;
+class ArrayValType;
+class StructValType;
+class PointerValType;
+
+class DerivedType : public Type, public AbstractTypeUser {
+ /// RefCount - This counts the number of PATypeHolders that are pointing to
+ /// this type. When this number falls to zero, if the type is abstract and
+ /// has no AbstractTypeUsers, the type is deleted.
+ ///
+ mutable unsigned RefCount;
+
// AbstractTypeUsers - Implement a list of the users that need to be notified
// if I am a type, and I get resolved into a more concrete type.
//
mutable std::vector<AbstractTypeUser *> AbstractTypeUsers;
protected:
- inline DerivedType(PrimitiveID id) : Type("", id) {
- isRefining = 0;
+ DerivedType(PrimitiveID id) : Type("", id), RefCount(0) {
}
~DerivedType() {
assert(AbstractTypeUsers.empty());
}
- // typeIsRefined - Notify AbstractTypeUsers of this type that the current type
- // has been refined a bit. The pointer is still valid and still should be
- // used, but the subtypes have changed.
- //
- void typeIsRefined();
+ /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type
+ /// that the current type has transitioned from being abstract to being
+ /// concrete.
+ ///
+ void notifyUsesThatTypeBecameConcrete();
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
- // types, to avoid some circular reference problems. This also removes the
- // type from the internal tables of available types.
- virtual void dropAllTypeUses(bool inMap) = 0;
+ // types, to avoid some circular reference problems.
+ virtual void dropAllTypeUses() = 0;
-
- void refineAbstractTypeToInternal(const Type *NewType, bool inMap);
-
public:
//===--------------------------------------------------------------------===//
// addAbstractTypeUser - Notify an abstract type that there is a new user of
// it. This function is called primarily by the PATypeHandle class.
//
- void addAbstractTypeUser(AbstractTypeUser *U) const;
+ void addAbstractTypeUser(AbstractTypeUser *U) const {
+ assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
+ AbstractTypeUsers.push_back(U);
+ }
// removeAbstractTypeUser - Notify an abstract type that a user of the class
// no longer has a handle to the type. This function is called primarily by
// This causes all users of 'this' to switch to reference the more concrete
// type NewType and for 'this' to be deleted.
//
- void refineAbstractTypeTo(const Type *NewType) {
- refineAbstractTypeToInternal(NewType, true);
+ void refineAbstractTypeTo(const Type *NewType);
+
+ void addRef() const {
+ assert(isAbstract() && "Cannot add a reference to a non-abstract type!");
+ ++RefCount;
+ }
+
+ void dropRef() const {
+ assert(isAbstract() && "Cannot drop a refernce to a non-abstract type!");
+ assert(RefCount && "No objects are currently referencing this object!");
+
+ // If this is the last PATypeHolder using this object, and there are no
+ // PATypeHandles using it, the type is dead, delete it now.
+ if (--RefCount == 0 && AbstractTypeUsers.empty())
+ delete this;
}
+
+ void dump() const { Value::dump(); }
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const DerivedType *T) { return true; }
static inline bool classof(const Type *T) {
struct FunctionType : public DerivedType {
typedef std::vector<PATypeHandle> ParamTypes;
+ friend class TypeMap<FunctionValType, FunctionType>;
private:
PATypeHandle ResultType;
ParamTypes ParamTys;
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
- // types, to avoid some circular reference problems. This also removes the
- // type from the internal tables of available types.
- virtual void dropAllTypeUses(bool inMap);
+ // types, to avoid some circular reference problems.
+ virtual void dropAllTypeUses();
public:
+ /// FunctionType::get - This static method is the primary way of constructing
+ /// a FunctionType
+ static FunctionType *get(const Type *Result,
+ const std::vector<const Type*> &Params,
+ bool isVarArg);
inline bool isVarArg() const { return isVarArgs; }
inline const Type *getReturnType() const { return ResultType; }
virtual const Type *getContainedType(unsigned i) const {
- return i == 0 ? ResultType :
- (i <= ParamTys.size() ? ParamTys[i-1].get() : 0);
+ return i == 0 ? ResultType.get() : ParamTys[i-1].get();
}
virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; }
- // refineAbstractType - Called when a contained type is found to be more
- // concrete - this could potentially change us from an abstract type to a
- // concrete type.
- //
+ // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
-
- static FunctionType *get(const Type *Result,
- const std::vector<const Type*> &Params,
- bool isVarArg);
-
-
+ virtual void typeBecameConcrete(const DerivedType *AbsTy);
+
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const FunctionType *T) { return true; }
static inline bool classof(const Type *T) {
};
-class StructType : public CompositeType {
-public:
+struct StructType : public CompositeType {
+ friend class TypeMap<StructValType, StructType>;
typedef std::vector<PATypeHandle> ElementTypes;
private:
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
- // types, to avoid some circular reference problems. This also removes the
- // type from the internal tables of available types.
- virtual void dropAllTypeUses(bool inMap);
+ // types, to avoid some circular reference problems.
+ virtual void dropAllTypeUses();
public:
+ /// StructType::get - This static method is the primary way to create a
+ /// StructType.
+ static StructType *get(const std::vector<const Type*> &Params);
+
inline const ElementTypes &getElementTypes() const { return ETypes; }
virtual const Type *getContainedType(unsigned i) const {
- return i < ETypes.size() ? ETypes[i].get() : 0;
+ return ETypes[i].get();
}
virtual unsigned getNumContainedTypes() const { return ETypes.size(); }
//
virtual const Type *getIndexType() const { return Type::UByteTy; }
- // refineAbstractType - Called when a contained type is found to be more
- // concrete - this could potentially change us from an abstract type to a
- // concrete type.
- //
+ // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
-
- static StructType *get(const std::vector<const Type*> &Params);
+ virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const StructType *T) { return true; }
inline const Type *getElementType() const { return ElementType; }
virtual const Type *getContainedType(unsigned i) const {
- return i == 0 ? ElementType.get() : 0;
+ return ElementType.get();
}
virtual unsigned getNumContainedTypes() const { return 1; }
class ArrayType : public SequentialType {
+ friend class TypeMap<ArrayValType, ArrayType>;
unsigned NumElements;
ArrayType(const ArrayType &); // Do not implement
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
- // types, to avoid some circular reference problems. This also removes the
- // type from the internal tables of available types.
- virtual void dropAllTypeUses(bool inMap);
+ // types, to avoid some circular reference problems.
+ virtual void dropAllTypeUses();
public:
+ /// ArrayType::get - This static method is the primary way to construct an
+ /// ArrayType
+ static ArrayType *get(const Type *ElementType, unsigned NumElements);
+
inline unsigned getNumElements() const { return NumElements; }
- // refineAbstractType - Called when a contained type is found to be more
- // concrete - this could potentially change us from an abstract type to a
- // concrete type.
- //
+ // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
-
- static ArrayType *get(const Type *ElementType, unsigned NumElements);
+ virtual void typeBecameConcrete(const DerivedType *AbsTy);
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const ArrayType *T) { return true; }
class PointerType : public SequentialType {
+ friend class TypeMap<PointerValType, PointerType>;
PointerType(const PointerType &); // Do not implement
const PointerType &operator=(const PointerType &); // Do not implement
protected:
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
- // types, to avoid some circular reference problems. This also removes the
- // type from the internal tables of available types.
- virtual void dropAllTypeUses(bool inMap);
+ // types, to avoid some circular reference problems.
+ virtual void dropAllTypeUses();
public:
- // PointerType::get - Named constructor for pointer types...
+ /// PointerType::get - This is the only way to construct a new pointer type.
static PointerType *get(const Type *ElementType);
- // refineAbstractType - Called when a contained type is found to be more
- // concrete - this could potentially change us from an abstract type to a
- // concrete type.
- //
+ // Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
+ virtual void typeBecameConcrete(const DerivedType *AbsTy);
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ // Implement support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const PointerType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == PointerTyID;
// dropAllTypeUses - When this (abstract) type is resolved to be equal to
// another (more concrete) type, we must eliminate all references to other
// types, to avoid some circular reference problems.
- virtual void dropAllTypeUses(bool inMap) {} // No type uses
+ virtual void dropAllTypeUses() {
+ // FIXME: THIS IS NOT AN ABSTRACT TYPE USER!
+ } // No type uses
public:
-
- // get - Static factory method for the OpaqueType class...
+ // OpaqueType::get - Static factory method for the OpaqueType class...
static OpaqueType *get() {
return new OpaqueType(); // All opaque types are distinct
}
- // Methods for support type inquiry through isa, cast, and dyn_cast:
+ // Implement the AbstractTypeUser interface.
+ virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
+ abort(); // FIXME: this is not really an AbstractTypeUser!
+ }
+ virtual void typeBecameConcrete(const DerivedType *AbsTy) {
+ abort(); // FIXME: this is not really an AbstractTypeUser!
+ }
+
+ // Implement support for type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const OpaqueType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == OpaqueTyID;
cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
}
+// Define inline methods for PATypeHolder...
+
+inline void PATypeHolder::addRef() {
+ if (Ty->isAbstract())
+ cast<DerivedType>(Ty)->addRef();
+}
+
+inline void PATypeHolder::dropRef() {
+ if (Ty->isAbstract())
+ cast<DerivedType>(Ty)->dropRef();
+}
+
+/// get - This implements the forwarding part of the union-find algorithm for
+/// abstract types. Before every access to the Type*, we check to see if the
+/// type we are pointing to is forwarding to a new type. If so, we drop our
+/// reference to the type.
+inline const Type* PATypeHolder::get() const {
+ const Type *NewTy = Ty->getForwardedType();
+ if (!NewTy) return Ty;
+ return *const_cast<PATypeHolder*>(this) = NewTy;
+}
+
#endif