Add notes
[oota-llvm.git] / lib / VMCore / Type.cpp
index c25bdf02f85d9b801008f6e10f855603e7d61573..ad50ce08839b22482e550ae5e4b302f72920278c 100644 (file)
@@ -28,7 +28,7 @@ Type::Type(const string &name, PrimitiveID id)
   : Value(Type::TypeTy, Value::TypeVal) {
   setDescription(name);
   ID = id;
-  Abstract = false;
+  Abstract = Recursive = false;
   UID = CurUID++;       // Assign types UID's as they are created
   UIDMappings.push_back(this);
 }
@@ -303,15 +303,13 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
   if (isa<OpaqueType>(Ty))
     return false;  // Two nonequal opaque types are never equal
 
-  if (Ty != Ty2) {
-    map<const Type*, const Type*>::iterator I = EqTypes.find(Ty);
-    if (I != EqTypes.end())
-      return I->second == Ty2;    // Looping back on a type, check for equality
+  map<const Type*, const Type*>::iterator It = EqTypes.find(Ty);
+  if (It != EqTypes.end())
+    return It->second == Ty2;    // Looping back on a type, check for equality
 
-    // Otherwise, add the mapping to the table to make sure we don't get
-    // recursion on the types...
-    EqTypes.insert(make_pair(Ty, Ty2));
-  }
+  // Otherwise, add the mapping to the table to make sure we don't get
+  // recursion on the types...
+  EqTypes.insert(make_pair(Ty, Ty2));
 
   // Iterate over the types and make sure the the contents are equivalent...
   Type::subtype_iterator I  = Ty ->subtype_begin(), IE  = Ty ->subtype_end();
@@ -330,7 +328,6 @@ static bool TypesEqual(const Type *Ty, const Type *Ty2,
       return false;
   }
 
-
   return I == IE && I2 == IE2;    // Types equal if both iterators are done
 }
 
@@ -384,7 +381,16 @@ public:
   // corrected.
   //
   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
-    if (OldTy == NewTy) return;
+    if (OldTy == NewTy) {
+      if (!OldTy->isAbstract()) {
+        // Check to see if the type just became concrete.
+        // If so, remove self from user list.
+        for (MapTy::iterator I = Map.begin(), E = Map.end(); I != E; ++I)
+          if (I->second == OldTy)
+            I->second.removeUserFromConcrete();
+      }
+      return;
+    }
 #ifdef DEBUG_MERGE_TYPES
     cerr << "Removing Old type from Tab: " << (void*)OldTy << ", "
         << OldTy->getDescription() << "  replacement == " << (void*)NewTy
@@ -429,18 +435,29 @@ protected:
 
   // Subclass should override this... to update self as usual
   virtual void doRefinement(const DerivedType *OldTy, const Type *NewTy) = 0;
+
+  // typeBecameConcrete - This callback occurs when a contained type refines
+  // to itself, but becomes concrete in the process.  Our subclass should remove
+  // itself from the ATU list of the specified type.
+  //
+  virtual void typeBecameConcrete(const DerivedType *Ty) = 0;
   
   virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy) {
-    if (OldTy == NewTy) return;
+    if (OldTy == NewTy) {
+      if (!OldTy->isAbstract())
+        typeBecameConcrete(OldTy);
+      return;
+    }
     TypeMap<ValType, TypeClass> &Table = MyTable;     // Copy MyTable reference
     ValType Tmp(*(ValType*)this);                     // Copy this.
     PATypeHandle<TypeClass> OldType(Table.get(*(ValType*)this), this);
     Table.remove(*(ValType*)this);                    // Destroy's this!
-
+#if 1
     // Refine temporary to new state...
     Tmp.doRefinement(OldTy, NewTy); 
 
     Table.add((ValType&)Tmp, (TypeClass*)OldType.get());
+#endif
   }
 };
 
@@ -483,6 +500,13 @@ public:
       if (ArgTypes[i] == OldType) ArgTypes[i] = NewType;
   }
 
+  virtual void typeBecameConcrete(const DerivedType *Ty) {
+    if (RetTy == Ty) RetTy.removeUserFromConcrete();
+
+    for (unsigned i = 0; i < ArgTypes.size(); ++i)
+      if (ArgTypes[i] == Ty) ArgTypes[i].removeUserFromConcrete();
+  }
+
   inline bool operator<(const MethodValType &MTV) const {
     if (RetTy.get() < MTV.RetTy.get()) return true;
     if (RetTy.get() > MTV.RetTy.get()) return false;
@@ -533,6 +557,12 @@ public:
     if (ValTy == OldType) ValTy = NewType;
   }
 
+  virtual void typeBecameConcrete(const DerivedType *Ty) {
+    assert(ValTy == Ty &&
+           "Contained type became concrete but we're not using it!");
+    ValTy.removeUserFromConcrete();
+  }
+
   inline bool operator<(const ArrayValType &MTV) const {
     if (Size < MTV.Size) return true;
     return Size == MTV.Size && ValTy.get() < MTV.ValTy.get();
@@ -589,6 +619,11 @@ public:
       if (ElTypes[i] == OldType) ElTypes[i] = NewType;
   }
 
+  virtual void typeBecameConcrete(const DerivedType *Ty) {
+    for (unsigned i = 0; i < ElTypes.size(); ++i)
+      if (ElTypes[i] == Ty) ElTypes[i].removeUserFromConcrete();
+  }
+
   inline bool operator<(const StructValType &STV) const {
     return ElTypes < STV.ElTypes;
   }
@@ -633,6 +668,12 @@ public:
     if (ValTy == OldType) ValTy = NewType;
   }
 
+  virtual void typeBecameConcrete(const DerivedType *Ty) {
+    assert(ValTy == Ty &&
+           "Contained type became concrete but we're not using it!");
+    ValTy.removeUserFromConcrete();
+  }
+
   inline bool operator<(const PointerValType &MTV) const {
     return ValTy.get() < MTV.ValTy.get();
   }
@@ -677,22 +718,20 @@ void DerivedType::removeAbstractTypeUser(AbstractTypeUser *U) const {
       AbstractTypeUsers.erase(AbstractTypeUsers.begin()+i-1);
       
 #ifdef DEBUG_MERGE_TYPES
-      cerr << "  removeAbstractTypeUser[" << (void*)this << ", "
-          << getDescription() << "][" << AbstractTypeUsers.size()
-          << "] User = " << U << endl;
+      cerr << "  removeAbstractTypeUser<" << (void*)this << ", "
+          << getDescription() << ">[" << i << "] User = " << U << endl;
 #endif
 
-      if (AbstractTypeUsers.empty()) {
+      if (AbstractTypeUsers.empty() && isAbstract()) {
 #ifdef DEBUG_MERGE_TYPES
-       cerr << "DELETEing unused abstract type: " << getDescription()
-            << " " << (void*)this << endl;
+       cerr << "DELETEing unused abstract type: <" << getDescription()
+            << ">[" << (void*)this << "]" << endl;
 #endif
        delete this;                  // No users of this abstract type!
       }
       return;
     }
   }
-  assert(isAbstract() && "removeAbstractTypeUser: Type not abstract!");
   assert(0 && "AbstractTypeUser not in user list!");
 }
 
@@ -748,6 +787,9 @@ void DerivedType::refineAbstractTypeTo(const Type *NewType) {
 #endif
       User->refineAbstractType(this, NewTy);
 
+      if (AbstractTypeUsers.size() == OldSize) {
+        User->refineAbstractType(this, NewTy);
+      }
       assert(AbstractTypeUsers.size() != OldSize &&
             "AbsTyUser did not remove self from user list!");
     }
@@ -767,7 +809,7 @@ void DerivedType::refineAbstractTypeTo(const Type *NewType) {
 //
 void DerivedType::typeIsRefined() {
   assert(isRefining >= 0 && isRefining <= 2 && "isRefining out of bounds!");
-  if (isRefining == 2) return;  // Kill recursion here...
+  if (isRefining == 1) return;  // Kill recursion here...
   ++isRefining;
 
 #ifdef DEBUG_MERGE_TYPES
@@ -782,11 +824,25 @@ void DerivedType::typeIsRefined() {
     ATU->refineAbstractType(this, this);
     
     // If the user didn't remove itself from the list, continue...
-    if (AbstractTypeUsers.size() > i && AbstractTypeUsers[i] == ATU)
+    if (AbstractTypeUsers.size() > i && AbstractTypeUsers[i] == ATU) {
       ++i;
+    }
   }
 
   --isRefining;
+
+#ifndef _NDEBUG
+  if (!(isAbstract() || AbstractTypeUsers.empty()))
+    for (unsigned i = 0; i < AbstractTypeUsers.size(); ++i) {
+      if (AbstractTypeUsers[i] != this) {
+        // Debugging hook
+        cerr << "FOUND FAILURE\n";
+        AbstractTypeUsers[i]->refineAbstractType(this, this);
+        assert(0 && "Type became concrete,"
+               " but it still has abstract type users hanging around!");
+      }
+  }
+#endif
 }
   
 
@@ -804,37 +860,26 @@ void MethodType::refineAbstractType(const DerivedType *OldType,
        << NewType->getDescription() << "])\n";
 #endif
 
-  if (OldType == ResultType) {
-    ResultType = NewType;
-  } else {
-    unsigned i;
-    for (i = 0; i < ParamTys.size(); ++i)
-      if (OldType == ParamTys[i]) {
-       ParamTys[i] = NewType;
-       break;
-      }
-    assert(i != ParamTys.size() && "Did not contain oldtype!");
+  if (!OldType->isAbstract()) {
+    if (ResultType == OldType) ResultType.removeUserFromConcrete();
+    for (unsigned i = 0; i < ParamTys.size(); ++i)
+      if (ParamTys[i] == OldType) ParamTys[i].removeUserFromConcrete();
   }
 
+  if (OldType != NewType) {
+    if (ResultType == OldType) ResultType = NewType;
 
-  // Notify everyone that I have changed!
-  if (const MethodType *MTy = MethodTypes.containsEquivalent(this)) {
-#ifndef _NDEBUG
-    // Calculate accurate name for debugging purposes
-    vector<const Type *> TypeStack;
-    bool isAbstract = false, isRecursive = false;
-    setDescription(getTypeProps(this, TypeStack, isAbstract, isRecursive));
-#endif
+    for (unsigned i = 0; i < ParamTys.size(); ++i)
+      if (ParamTys[i] == OldType) ParamTys[i] = NewType;
+  }
 
-#ifdef DEBUG_MERGE_TYPES
-    cerr << "Type " << (void*)this << " equilivant to existing " << (void*)MTy
-        << " - destroying!\n";
-#endif
-    refineAbstractTypeTo(MTy);      // Different type altogether...
-    return;
+  const MethodType *MT = MethodTypes.containsEquivalent(this);
+  if (MT && MT != this) {
+    refineAbstractTypeTo(MT);            // Different type altogether...
+  } else {
+    setDerivedTypeProperties();          // Update the name and isAbstract
+    typeIsRefined();                     // Same type, different contents...
   }
-  setDerivedTypeProperties();  // Update the name and isAbstract
-  typeIsRefined();
 }
 
 
@@ -849,27 +894,20 @@ void ArrayType::refineAbstractType(const DerivedType *OldType,
        << OldType->getDescription() << "], " << (void*)NewType << " [" 
        << NewType->getDescription() << "])\n";
 #endif
-  assert(OldType == ElementType && "Cannot refine from OldType!");
-  ElementType = NewType;
 
-  // Notify everyone that I have changed!
-  if (const ArrayType *ATy = ArrayTypes.containsEquivalent(this)) {
-#ifndef _NDEBUG
-    // Calculate accurate name for debugging purposes
-    vector<const Type *> TypeStack;
-    bool isAbstract = false, isRecursive = false;
-    setDescription(getTypeProps(this, TypeStack, isAbstract, isRecursive));
-#endif
+  if (!OldType->isAbstract()) {
+    assert(ElementType == OldType);
+    ElementType.removeUserFromConcrete();
+  }
 
-#ifdef DEBUG_MERGE_TYPES
-    cerr << "Type " << (void*)this << " equilivant to existing " << (void*)ATy
-        << " - destroying!\n";
-#endif
-    refineAbstractTypeTo(ATy);      // Different type altogether...
-    return;
+  ElementType = NewType;
+  const ArrayType *AT = ArrayTypes.containsEquivalent(this);
+  if (AT && AT != this) {
+    refineAbstractTypeTo(AT);          // Different type altogether...
+  } else {
+    setDerivedTypeProperties();        // Update the name and isAbstract
+    typeIsRefined();                   // Same type, different contents...
   }
-  setDerivedTypeProperties();   // Update the name and isAbstract
-  typeIsRefined();              // Same type, different contents...
 }
 
 
@@ -884,40 +922,26 @@ void StructType::refineAbstractType(const DerivedType *OldType,
        << OldType->getDescription() << "], " << (void*)NewType << " [" 
        << NewType->getDescription() << "])\n";
 #endif
-
-  if (OldType != NewType) {
-    unsigned i;
-    for (i = 0; i < ETypes.size(); ++i)
-      if (OldType == ETypes[i]) {
-       ETypes[i] = NewType;
-       break;
-      }
-    assert(i != ETypes.size() && "Did not contain oldtype!");
+  if (!OldType->isAbstract()) {
+    for (unsigned i = 0; i < ETypes.size(); ++i)
+      if (ETypes[i] == OldType)
+        ETypes[i].removeUserFromConcrete();
   }
 
-  vector<const Type *> ElTypes(
-      map_iterator(ETypes.begin(), mem_fun_ref(&PATypeHandle<Type>::get)),
-      map_iterator(ETypes.end()  , mem_fun_ref(&PATypeHandle<Type>::get)));
-
-
-  // Notify everyone that I have changed!
-  if (const StructType *STy = StructTypes.containsEquivalent(this)) {
-#ifndef _NDEBUG
-    // Calculate accurate name for debugging purposes
-    vector<const Type *> TypeStack;
-    bool isAbstract = false, isRecursive = false;
-    setDescription(getTypeProps(this, TypeStack, isAbstract, isRecursive));
-#endif
-
-#ifdef DEBUG_MERGE_TYPES
-    cerr << "Type " << (void*)this << " equilivant to existing " << (void*)STy
-        << " - destroying!\n";
-#endif
-    refineAbstractTypeTo(STy);      // Different type altogether...
-    return;
+  if (OldType != NewType) {
+    // Update old type to new type in the array...
+    for (unsigned i = 0; i < ETypes.size(); ++i)
+      if (ETypes[i] == OldType)
+        ETypes[i] = NewType;
+  } 
+
+  const StructType *ST = StructTypes.containsEquivalent(this);
+  if (ST && ST != this) {
+    refineAbstractTypeTo(ST);          // Different type altogether...
+  } else {
+    setDerivedTypeProperties();        // Update the name and isAbstract
+    typeIsRefined();                   // Same type, different contents...
   }
-  setDerivedTypeProperties();          // Update the name and isAbstract
-  typeIsRefined();                   // Same type, different contents...
 }
 
 // refineAbstractType - Called when a contained type is found to be more
@@ -931,26 +955,20 @@ void PointerType::refineAbstractType(const DerivedType *OldType,
        << OldType->getDescription() << "], " << (void*)NewType << " [" 
        << NewType->getDescription() << "])\n";
 #endif
-  assert(OldType == ValueType && "Cannot refine from OldType!");
-  ValueType = NewType;
 
-  // Notify everyone that I have changed!
-  if (const PointerType *PTy = PointerTypes.containsEquivalent(this)) {
-#ifndef _NDEBUG
-    // Calculate accurate name for debugging purposes
-    vector<const Type *> TypeStack;
-    bool isAbstract = false, isRecursive = false;
-    setDescription(getTypeProps(this, TypeStack, isAbstract, isRecursive));
-#endif
+  if (!OldType->isAbstract()) {
+    assert(ValueType == OldType);
+    ValueType.removeUserFromConcrete();
+  }
 
-#ifdef DEBUG_MERGE_TYPES
-    cerr << "Type " << (void*)this << " equilivant to existing " << (void*)PTy
-        << " - destroying!\n";
-#endif
-    refineAbstractTypeTo(PTy);      // Different type altogether...
-    return;
+  ValueType = NewType;
+  const PointerType *PT = PointerTypes.containsEquivalent(this);
+
+  if (PT && PT != this) {
+    refineAbstractTypeTo(PT);          // Different type altogether...
+  } else {
+    setDerivedTypeProperties();        // Update the name and isAbstract
+    typeIsRefined();                   // Same type, different contents...
   }
-  setDerivedTypeProperties();  // Update the name and isAbstract
-  typeIsRefined();                   // Same type, different contents...
 }