diff --git a/llvm/include/llvm/DerivedTypes.h b/llvm/include/llvm/DerivedTypes.h index 9fdff68b402b..c17fa3c522ac 100644 --- a/llvm/include/llvm/DerivedTypes.h +++ b/llvm/include/llvm/DerivedTypes.h @@ -19,7 +19,6 @@ #define LLVM_DERIVED_TYPES_H #include "llvm/Type.h" -#include namespace llvm { @@ -57,7 +56,7 @@ 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. - virtual void dropAllTypeUses() = 0; + void dropAllTypeUses(); public: @@ -122,8 +121,6 @@ public: class FunctionType : public DerivedType { friend class TypeMap; - PATypeHandle ResultType; - std::vector ParamTys; bool isVarArgs; FunctionType(const FunctionType &); // Do not implement @@ -137,11 +134,6 @@ protected: FunctionType(const Type *Result, const std::vector &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. - virtual void dropAllTypeUses(); - public: /// FunctionType::get - This static method is the primary way of constructing /// a FunctionType @@ -150,25 +142,19 @@ public: bool isVarArg); inline bool isVarArg() const { return isVarArgs; } - inline const Type *getReturnType() const { return ResultType; } + inline const Type *getReturnType() const { return ContainedTys[0]; } typedef std::vector::const_iterator param_iterator; - param_iterator param_begin() const { return ParamTys.begin(); } - param_iterator param_end() const { return ParamTys.end(); } + param_iterator param_begin() const { return ContainedTys.begin()+1; } + param_iterator param_end() const { return ContainedTys.end(); } // Parameter type accessors... - const Type *getParamType(unsigned i) const { return ParamTys[i]; } + const Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } // 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.get() : ParamTys[i-1].get(); - } - virtual unsigned getNumContainedTypes() const { return ParamTys.size()+1; } + unsigned getNumParams() const { return ContainedTys.size()-1; } // Implement the AbstractTypeUser interface. virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); @@ -213,8 +199,6 @@ public: class StructType : public CompositeType { friend class TypeMap; - std::vector ETypes; // Element types of struct - StructType(const StructType &); // Do not implement const StructType &operator=(const StructType &); // Do not implement @@ -226,11 +210,6 @@ protected: // Private ctor - Only can be created by a static member... StructType(const std::vector &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. - virtual void dropAllTypeUses(); - public: /// StructType::get - This static method is the primary way to create a /// StructType. @@ -238,21 +217,16 @@ public: // Iterator access to the elements typedef std::vector::const_iterator element_iterator; - element_iterator element_begin() const { return ETypes.begin(); } - element_iterator element_end() const { return ETypes.end(); } + element_iterator element_begin() const { return ContainedTys.begin(); } + element_iterator element_end() const { return ContainedTys.end(); } // Random access to the elements - unsigned getNumElements() const { return ETypes.size(); } + unsigned getNumElements() const { return ContainedTys.size(); } const Type *getElementType(unsigned N) const { - assert(N < ETypes.size() && "Element number out of range!"); - return ETypes[N]; + assert(N < ContainedTys.size() && "Element number out of range!"); + return ContainedTys[N]; } - virtual const Type *getContainedType(unsigned i) const { - return ETypes[i].get(); - } - 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... // @@ -284,25 +258,19 @@ 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)) { + SequentialType(PrimitiveID TID, const Type *ElType) : CompositeType(TID) { + ContainedTys.reserve(1); + ContainedTys.push_back(PATypeHandle(ElType, this)); } public: - inline const Type *getElementType() const { return ElementType; } - - virtual const Type *getContainedType(unsigned i) const { - return ElementType.get(); - } - virtual unsigned getNumContainedTypes() const { return 1; } + inline const Type *getElementType() const { return ContainedTys[0]; } // 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(); + return ContainedTys[0]; } virtual bool indexValid(const Value *V) const { return V->getType()->isInteger(); @@ -334,11 +302,6 @@ protected: // 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. - virtual void dropAllTypeUses(); - public: /// ArrayType::get - This static method is the primary way to construct an /// ArrayType @@ -374,10 +337,6 @@ protected: // 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. - virtual void dropAllTypeUses(); public: /// PointerType::get - This is the only way to construct a new pointer type. static PointerType *get(const Type *ElementType); @@ -408,13 +367,6 @@ protected: // 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() { - // FIXME: THIS IS NOT AN ABSTRACT TYPE USER! - } // No type uses - public: // OpaqueType::get - Static factory method for the OpaqueType class... static OpaqueType *get() { diff --git a/llvm/include/llvm/Type.h b/llvm/include/llvm/Type.h index ba4ac3415fd2..d18d7096d35a 100644 --- a/llvm/include/llvm/Type.h +++ b/llvm/include/llvm/Type.h @@ -36,6 +36,7 @@ #include "llvm/Value.h" #include "Support/GraphTraits.h" #include "Support/iterator" +#include namespace llvm { @@ -106,6 +107,15 @@ protected: /// to the more refined type. Only abstract types can be forwarded. mutable const Type *ForwardType; + /// ContainedTys - The list of types contained by this one. For example, this + /// includes the arguments of a function type, the elements of the structure, + /// the pointee of a pointer, etc. Note that keeping this vector in the Type + /// class wastes some space for types that do not contain anything (such as + /// primitive types). However, keeping it here allows the subtype_* members + /// to be implemented MUCH more efficiently, and dynamically very few types do + /// not contain any elements (most are derived). + std::vector ContainedTys; + public: virtual void print(std::ostream &O) const; @@ -204,22 +214,22 @@ public: //===--------------------------------------------------------------------===// // Type Iteration support // - class TypeIterator; - typedef TypeIterator subtype_iterator; - inline subtype_iterator subtype_begin() const; // DEFINED BELOW - inline subtype_iterator subtype_end() const; // DEFINED BELOW + typedef std::vector::const_iterator subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys.begin(); } + subtype_iterator subtype_end() const { return ContainedTys.end(); } /// getContainedType - This method is used to implement the type iterator /// (defined a the end of the file). For derived types, this returns the /// types 'contained' in the derived type. /// - virtual const Type *getContainedType(unsigned i) const { - assert(0 && "No contained types!"); - return 0; + const Type *getContainedType(unsigned i) const { + assert(i < ContainedTys.size() && "Index out of range!"); + return ContainedTys[i]; } - /// getNumContainedTypes - Return the number of types in the derived type - virtual unsigned getNumContainedTypes() const { return 0; } + /// getNumContainedTypes - Return the number of types in the derived type. + /// + unsigned getNumContainedTypes() const { return ContainedTys.size(); } //===--------------------------------------------------------------------===// // Static members exported by the Type class itself. Useful for getting @@ -249,50 +259,8 @@ public: } #include "llvm/Type.def" - -private: - class TypeIterator : public bidirectional_iterator { - const Type * const Ty; - unsigned Idx; - - typedef TypeIterator _Self; - public: - TypeIterator(const Type *ty, unsigned idx) : Ty(ty), Idx(idx) {} - ~TypeIterator() {} - - const _Self &operator=(const _Self &RHS) { - assert(Ty == RHS.Ty && "Cannot assign from different types!"); - Idx = RHS.Idx; - return *this; - } - - bool operator==(const _Self& x) const { return Idx == x.Idx; } - bool operator!=(const _Self& x) const { return !operator==(x); } - - pointer operator*() const { return Ty->getContainedType(Idx); } - pointer operator->() const { return operator*(); } - - _Self& operator++() { ++Idx; return *this; } // Preincrement - _Self operator++(int) { // Postincrement - _Self tmp = *this; ++*this; return tmp; - } - - _Self& operator--() { --Idx; return *this; } // Predecrement - _Self operator--(int) { // Postdecrement - _Self tmp = *this; --*this; return tmp; - } - }; }; -inline Type::TypeIterator Type::subtype_begin() const { - return TypeIterator(this, 0); -} - -inline Type::TypeIterator Type::subtype_end() const { - return TypeIterator(this, getNumContainedTypes()); -} - - // Provide specializations of GraphTraits to be able to treat a type as a // graph of sub types... diff --git a/llvm/lib/VMCore/Type.cpp b/llvm/lib/VMCore/Type.cpp index d649d08b4c55..5a8e2d90b12d 100644 --- a/llvm/lib/VMCore/Type.cpp +++ b/llvm/lib/VMCore/Type.cpp @@ -261,7 +261,7 @@ const std::string &Type::getDescription() const { bool StructType::indexValid(const Value *V) const { // Structure indexes require unsigned integer constants. if (const ConstantUInt *CU = dyn_cast(V)) - return CU->getValue() < ETypes.size(); + return CU->getValue() < ContainedTys.size(); return false; } @@ -271,9 +271,9 @@ bool StructType::indexValid(const Value *V) const { const Type *StructType::getTypeAtIndex(const Value *V) const { assert(isa(V) && "Structure index must be a constant!!"); unsigned Idx = cast(V)->getValue(); - assert(Idx < ETypes.size() && "Structure index out of range!"); + assert(Idx < ContainedTys.size() && "Structure index out of range!"); assert(indexValid(V) && "Invalid structure index!"); // Duplicate check - return ETypes[Idx]; + return ContainedTys[Idx]; } @@ -358,12 +358,13 @@ Type *Type::LabelTy = &TheLabelTy; FunctionType::FunctionType(const Type *Result, const std::vector &Params, bool IsVarArgs) : DerivedType(FunctionTyID), - ResultType(PATypeHandle(Result, this)), - isVarArgs(IsVarArgs) { + isVarArgs(IsVarArgs) { bool isAbstract = Result->isAbstract(); - ParamTys.reserve(Params.size()); - for (unsigned i = 0; i < Params.size(); ++i) { - ParamTys.push_back(PATypeHandle(Params[i], this)); + ContainedTys.reserve(Params.size()+1); + ContainedTys.push_back(PATypeHandle(Result, this)); + + for (unsigned i = 0; i != Params.size(); ++i) { + ContainedTys.push_back(PATypeHandle(Params[i], this)); isAbstract |= Params[i]->isAbstract(); } @@ -373,11 +374,11 @@ FunctionType::FunctionType(const Type *Result, StructType::StructType(const std::vector &Types) : CompositeType(StructTyID) { - ETypes.reserve(Types.size()); + ContainedTys.reserve(Types.size()); bool isAbstract = false; for (unsigned i = 0; i < Types.size(); ++i) { assert(Types[i] != Type::VoidTy && "Void type in method prototype!!"); - ETypes.push_back(PATypeHandle(Types[i], this)); + ContainedTys.push_back(PATypeHandle(Types[i], this)); isAbstract |= Types[i]->isAbstract(); } @@ -405,44 +406,22 @@ OpaqueType::OpaqueType() : DerivedType(OpaqueTyID) { #endif } - -// getAlwaysOpaqueTy - This function returns an opaque type. It doesn't matter -// _which_ opaque type it is, but the opaque type must never get resolved. -// -static Type *getAlwaysOpaqueTy() { - static Type *AlwaysOpaqueTy = OpaqueType::get(); - static PATypeHolder Holder(AlwaysOpaqueTy); - return AlwaysOpaqueTy; +// 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. +void DerivedType::dropAllTypeUses() { + if (!ContainedTys.empty()) { + while (ContainedTys.size() > 1) + ContainedTys.pop_back(); + + // The type must stay abstract. To do this, we insert a pointer to a type + // that will never get resolved, thus will always be abstract. + static Type *AlwaysOpaqueTy = OpaqueType::get(); + static PATypeHolder Holder(AlwaysOpaqueTy); + ContainedTys[0] = AlwaysOpaqueTy; + } } - -//===----------------------------------------------------------------------===// -// dropAllTypeUses methods - These methods eliminate any possibly recursive type -// references from a derived type. The type must remain abstract, so we make -// sure to use an always opaque type as an argument. -// - -void FunctionType::dropAllTypeUses() { - ResultType = getAlwaysOpaqueTy(); - ParamTys.clear(); -} - -void ArrayType::dropAllTypeUses() { - ElementType = getAlwaysOpaqueTy(); -} - -void StructType::dropAllTypeUses() { - ETypes.clear(); - ETypes.push_back(PATypeHandle(getAlwaysOpaqueTy(), this)); -} - -void PointerType::dropAllTypeUses() { - ElementType = getAlwaysOpaqueTy(); -} - - - - // isTypeAbstract - This is a recursive function that walks a type hierarchy // calculating whether or not a type is abstract. Worst case it will have to do // a lot of traversing if you have some whacko opaque types, but in most cases, @@ -465,7 +444,7 @@ bool Type::isTypeAbstract() { // one! for (Type::subtype_iterator I = subtype_begin(), E = subtype_end(); I != E; ++I) - if (const_cast(*I)->isTypeAbstract()) { + if (const_cast(I->get())->isTypeAbstract()) { setAbstract(true); // Restore the abstract bit. return true; // This type is abstract if subtype is abstract! } @@ -601,8 +580,8 @@ public: for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); I != E; ++I) { for (df_ext_iterator > - DFI = df_ext_begin(*I, VisitedTypes), - E = df_ext_end(*I, VisitedTypes); DFI != E; ++DFI) + DFI = df_ext_begin(I->get(), VisitedTypes), + E = df_ext_end(I->get(), VisitedTypes); DFI != E; ++DFI) if (*DFI == Ty) { HasTypeCycle = true; goto FoundCycle; @@ -1051,14 +1030,10 @@ void FunctionType::refineAbstractType(const DerivedType *OldType, FunctionTypes.getEntryForType(this); // Find the type element we are refining... - if (ResultType == OldType) { - ResultType.removeUserFromConcrete(); - ResultType = NewType; - } - for (unsigned i = 0, e = ParamTys.size(); i != e; ++i) - if (ParamTys[i] == OldType) { - ParamTys[i].removeUserFromConcrete(); - ParamTys[i] = NewType; + for (unsigned i = 0, e = ContainedTys.size(); i != e; ++i) + if (ContainedTys[i] == OldType) { + ContainedTys[i].removeUserFromConcrete(); + ContainedTys[i] = NewType; } FunctionTypes.finishRefinement(TMI); @@ -1088,8 +1063,8 @@ void ArrayType::refineAbstractType(const DerivedType *OldType, ArrayTypes.getEntryForType(this); assert(getElementType() == OldType); - ElementType.removeUserFromConcrete(); - ElementType = NewType; + ContainedTys[0].removeUserFromConcrete(); + ContainedTys[0] = NewType; ArrayTypes.finishRefinement(TMI); } @@ -1117,12 +1092,12 @@ void StructType::refineAbstractType(const DerivedType *OldType, TypeMap::iterator TMI = StructTypes.getEntryForType(this); - for (int i = ETypes.size()-1; i >= 0; --i) - if (ETypes[i] == OldType) { - ETypes[i].removeUserFromConcrete(); + for (int i = ContainedTys.size()-1; i >= 0; --i) + if (ContainedTys[i] == OldType) { + ContainedTys[i].removeUserFromConcrete(); // Update old type to new type in the array... - ETypes[i] = NewType; + ContainedTys[i] = NewType; } StructTypes.finishRefinement(TMI); @@ -1150,9 +1125,9 @@ void PointerType::refineAbstractType(const DerivedType *OldType, TypeMap::iterator TMI = PointerTypes.getEntryForType(this); - assert(ElementType == OldType); - ElementType.removeUserFromConcrete(); - ElementType = NewType; + assert(ContainedTys[0] == OldType); + ContainedTys[0].removeUserFromConcrete(); + ContainedTys[0] = NewType; PointerTypes.finishRefinement(TMI); }