llvm-6502/include/llvm/DerivedTypes.h
Chris Lattner 7685ac8d35 This checkin basically amounts to a complete rewrite of the type-resolution
machinery.  This dramatically simplifies how things works, removes irritating
little corner cases, and overall improves speed and reliability.

Highlights of this change are:

1. The exponential algorithm built into the code is now gone.  For example
   the time to disassemble one bytecode file from the mesa benchmark went
   from taking 12.5s to taking 0.16s.
2. The linker bugs should be dramatically reduced.  The one remaining bug
   has to do with constant handling, which I actually introduced in
   "union-find" checkins.
3. The code is much easier to follow, as a result of fewer special cases.
   It's probably also smaller.  yaay.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@8842 91177308-0d34-0410-b5e6-96231b3b80d8
2003-10-03 18:46:24 +00:00

495 lines
18 KiB
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
// "method returning x taking (y,z) as parameters", etc...
//
// The implementations of these classes live in the Type.cpp file.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DERIVED_TYPES_H
#define LLVM_DERIVED_TYPES_H
#include "llvm/Type.h"
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.
//
///// FIXME: kill mutable nonsense when Type's are not const
mutable std::vector<AbstractTypeUser *> AbstractTypeUsers;
protected:
DerivedType(PrimitiveID id) : Type("", id), RefCount(0) {
}
~DerivedType() {
assert(AbstractTypeUsers.empty());
}
/// 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;
void refineAbstractTypeToInternal(const Type *NewType, bool inMap);
public:
//===--------------------------------------------------------------------===//
// Abstract Type handling methods - These types have special lifetimes, which
// are managed by (add|remove)AbstractTypeUser. See comments in
// AbstractTypeUser.h for more information.
// 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 {
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
// the PATypeHandle class. When there are no users of the abstract type, it
// is annihilated, because there is no way to get a reference to it ever
// again.
//
void removeAbstractTypeUser(AbstractTypeUser *U) const;
// refineAbstractTypeTo - This function is used to when it is discovered that
// the 'this' abstract type is actually equivalent to the NewType specified.
// 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 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) {
return T->isDerivedType();
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
struct FunctionType : public DerivedType {
typedef std::vector<PATypeHandle> ParamTypes;
friend class TypeMap<FunctionValType, FunctionType>;
private:
PATypeHandle ResultType;
ParamTypes ParamTys;
bool isVarArgs;
FunctionType(const FunctionType &); // Do not implement
const FunctionType &operator=(const FunctionType &); // Do not implement
protected:
// This should really be private, but it squelches a bogus warning
// from GCC to make them protected: warning: `class FunctionType' only
// defines private constructors and has no friends
// Private ctor - Only can be created by a static member...
FunctionType(const Type *Result, const std::vector<const Type*> &Params,
bool IsVarArgs);
// 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);
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; }
inline const ParamTypes &getParamTypes() const { return ParamTys; }
// Parameter type accessors...
const Type *getParamType(unsigned i) const { return ParamTys[i]; }
// getNumParams - Return the number of fixed parameters this function type
// requires. This does not consider varargs.
//
unsigned getNumParams() const { return ParamTys.size(); }
virtual const Type *getContainedType(unsigned i) const {
return i == 0 ? ResultType :
(i <= ParamTys.size() ? ParamTys[i-1].get() : 0);
}
virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; }
// 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:
static inline bool classof(const FunctionType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == FunctionTyID;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
// CompositeType - Common super class of ArrayType, StructType, and PointerType
//
class CompositeType : public DerivedType {
protected:
inline CompositeType(PrimitiveID id) : DerivedType(id) { }
public:
// getTypeAtIndex - Given an index value into the type, return the type of the
// element.
//
virtual const Type *getTypeAtIndex(const Value *V) const = 0;
virtual bool indexValid(const Value *V) const = 0;
// getIndexType - Return the type required of indices for this composite.
// For structures, this is ubyte, for arrays, this is uint
//
virtual const Type *getIndexType() const = 0;
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const CompositeType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == ArrayTyID ||
T->getPrimitiveID() == StructTyID ||
T->getPrimitiveID() == PointerTyID;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
struct StructType : public CompositeType {
friend class TypeMap<StructValType, StructType>;
typedef std::vector<PATypeHandle> ElementTypes;
private:
ElementTypes ETypes; // Element types of struct
StructType(const StructType &); // Do not implement
const StructType &operator=(const StructType &); // Do not implement
protected:
// This should really be private, but it squelches a bogus warning
// from GCC to make them protected: warning: `class StructType' only
// defines private constructors and has no friends
// Private ctor - Only can be created by a static member...
StructType(const std::vector<const Type*> &Types);
// 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);
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;
}
virtual unsigned getNumContainedTypes() const { return ETypes.size(); }
// getTypeAtIndex - Given an index value into the type, return the type of the
// element. For a structure type, this must be a constant value...
//
virtual const Type *getTypeAtIndex(const Value *V) const ;
virtual bool indexValid(const Value *V) const;
// getIndexType - Return the type required of indices for this composite.
// For structures, this is ubyte, for arrays, this is uint
//
virtual const Type *getIndexType() const { return Type::UByteTy; }
// 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:
static inline bool classof(const StructType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == StructTyID;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
// SequentialType - This is the superclass of the array and pointer type
// classes. Both of these represent "arrays" in memory. The array type
// represents a specifically sized array, pointer types are unsized/unknown size
// arrays. SequentialType holds the common features of both, which stem from
// the fact that both lay their components out in memory identically.
//
class SequentialType : public CompositeType {
SequentialType(const SequentialType &); // Do not implement!
const SequentialType &operator=(const SequentialType &); // Do not implement!
protected:
PATypeHandle ElementType;
SequentialType(PrimitiveID TID, const Type *ElType)
: CompositeType(TID), ElementType(PATypeHandle(ElType, this)) {
}
public:
inline const Type *getElementType() const { return ElementType; }
virtual const Type *getContainedType(unsigned i) const {
return i == 0 ? ElementType.get() : 0;
}
virtual unsigned getNumContainedTypes() const { return 1; }
// getTypeAtIndex - Given an index value into the type, return the type of the
// element. For sequential types, there is only one subtype...
//
virtual const Type *getTypeAtIndex(const Value *V) const {
return ElementType.get();
}
virtual bool indexValid(const Value *V) const {
return V->getType() == Type::LongTy; // Must be a 'long' index
}
// getIndexType() - Return the type required of indices for this composite.
// For structures, this is ubyte, for arrays, this is uint
//
virtual const Type *getIndexType() const { return Type::LongTy; }
// Methods for support type inquiry through isa, cast, and dyn_cast:
static inline bool classof(const SequentialType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == ArrayTyID ||
T->getPrimitiveID() == PointerTyID;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
class ArrayType : public SequentialType {
friend class TypeMap<ArrayValType, ArrayType>;
unsigned NumElements;
ArrayType(const ArrayType &); // Do not implement
const ArrayType &operator=(const ArrayType &); // Do not implement
protected:
// This should really be private, but it squelches a bogus warning
// from GCC to make them protected: warning: `class ArrayType' only
// defines private constructors and has no friends
// Private ctor - Only can be created by a static member...
ArrayType(const Type *ElType, unsigned NumEl);
// 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);
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; }
// 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:
static inline bool classof(const ArrayType *T) { return true; }
static inline bool classof(const Type *T) {
return T->getPrimitiveID() == ArrayTyID;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
class PointerType : public SequentialType {
friend class TypeMap<PointerValType, PointerType>;
PointerType(const PointerType &); // Do not implement
const PointerType &operator=(const PointerType &); // Do not implement
protected:
// This should really be private, but it squelches a bogus warning
// from GCC to make them protected: warning: `class PointerType' only
// defines private constructors and has no friends
// Private ctor - Only can be created by a static member...
PointerType(const Type *ElType);
// 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);
public:
/// PointerType::get - This is the only way to construct a new pointer type.
static PointerType *get(const Type *ElementType);
// Implement the AbstractTypeUser interface.
virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy);
virtual void typeBecameConcrete(const DerivedType *AbsTy);
// 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;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
class OpaqueType : public DerivedType {
OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT
const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT
protected:
// This should really be private, but it squelches a bogus warning
// from GCC to make them protected: warning: `class OpaqueType' only
// defines private constructors and has no friends
// Private ctor - Only can be created by a static member...
OpaqueType();
// 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
public:
// OpaqueType::get - Static factory method for the OpaqueType class...
static OpaqueType *get() {
return new OpaqueType(); // All opaque types are distinct
}
// 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;
}
static inline bool classof(const Value *V) {
return isa<Type>(V) && classof(cast<Type>(V));
}
};
// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class.
// These are defined here because they MUST be inlined, yet are dependent on
// the definition of the Type class. Of course Type derives from Value, which
// contains an AbstractTypeUser instance, so there is no good way to factor out
// the code. Hence this bit of uglyness.
//
inline void PATypeHandle::addUser() {
assert(Ty && "Type Handle has a null type!");
if (Ty->isAbstract())
cast<DerivedType>(Ty)->addAbstractTypeUser(User);
}
inline void PATypeHandle::removeUser() {
if (Ty->isAbstract())
cast<DerivedType>(Ty)->removeAbstractTypeUser(User);
}
inline void PATypeHandle::removeUserFromConcrete() {
if (!Ty->isAbstract())
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