Now that all of the derived types have disciplined interfaces, we can eliminate
authorChris Lattner <sabre@nondot.org>
Mon, 9 Feb 2004 05:40:24 +0000 (05:40 +0000)
committerChris Lattner <sabre@nondot.org>
Mon, 9 Feb 2004 05:40:24 +0000 (05:40 +0000)
all of the ad-hoc storage of contained types.  This allows getContainedType to
not be virtual, and allows us to entirely delete the TypeIterator class.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@11230 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DerivedTypes.h
include/llvm/Type.h
lib/VMCore/Type.cpp

index 9fdff68b402b68f4667909c1e7a2869f4d34e339..c17fa3c522ace50b977c81e3b4a72bc09e2b16eb 100644 (file)
@@ -19,7 +19,6 @@
 #define LLVM_DERIVED_TYPES_H
 
 #include "llvm/Type.h"
-#include <vector>
 
 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<FunctionValType, FunctionType>;
-  PATypeHandle ResultType;
-  std::vector<PATypeHandle> ParamTys;
   bool isVarArgs;
 
   FunctionType(const FunctionType &);                   // Do not implement
@@ -137,11 +134,6 @@ protected:
   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.
-  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<PATypeHandle>::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<StructValType, StructType>;
-  std::vector<PATypeHandle> 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<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.
-  virtual void dropAllTypeUses();
-  
 public:
   /// StructType::get - This static method is the primary way to create a
   /// StructType.
@@ -238,20 +217,15 @@ public:
 
   // Iterator access to the elements
   typedef std::vector<PATypeHandle>::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];
-  }
-
-  virtual const Type *getContainedType(unsigned i) const { 
-    return ETypes[i].get();
+    assert(N < ContainedTys.size() && "Element number out of range!");
+    return ContainedTys[N];
   }
-  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() {
index ba4ac3415fd2d3b037cb3a3b2543c7a03df4a599..d18d7096d35aeafd75aae3d4d69e5fc78e1bf924 100644 (file)
@@ -36,6 +36,7 @@
 #include "llvm/Value.h"
 #include "Support/GraphTraits.h"
 #include "Support/iterator"
+#include <vector>
 
 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<PATypeHandle> 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<PATypeHandle>::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, ptrdiff_t> {
-    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...
 
index d649d08b4c55785cb839447fc8f2308e00f9c0b6..5a8e2d90b12d7689d2cb8184a2d5c6e91e72ff1e 100644 (file)
@@ -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<ConstantUInt>(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<Constant>(V) && "Structure index must be a constant!!");
   unsigned Idx = cast<ConstantUInt>(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<const Type*> &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<const Type*> &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 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();
+// 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;
+  }
 }
 
-
-
-
 // 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<Type*>(*I)->isTypeAbstract()) {
+    if (const_cast<Type*>(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<const Type *, std::set<const Type*> > 
-               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<StructValType, StructType>::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<PointerValType, PointerType>::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);
 }