Type safety for Constants.cpp! Some of this is temporary, as I'm planning to push...
[oota-llvm.git] / lib / VMCore / Type.cpp
index 8509aa283c05ca42cc4eec6cf4cb7b5a3fc7979f..b815eec665b3c1b45a778dbd1fefcac3d2f99a26 100644 (file)
@@ -24,6 +24,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Threading.h"
+#include "llvm/System/Mutex.h"
 #include "llvm/System/RWMutex.h"
 #include <algorithm>
 #include <cstdarg>
@@ -45,6 +46,9 @@ AbstractTypeUser::~AbstractTypeUser() {}
 // Reader/writer lock used for guarding access to the type maps.
 static ManagedStatic<sys::RWMutex> TypeMapLock;
 
+// Recursive lock used for guarding access to AbstractTypeUsers.
+static ManagedStatic<sys::Mutex> AbstractTypeUsersLock;
+
 // Concrete/Abstract TypeDescriptions - We lazily calculate type descriptions
 // for types as they are needed.  Because resolution of types must invalidate
 // all of the abstract type descriptions, we keep them in a seperate map to make
@@ -1440,12 +1444,28 @@ bool PointerType::isValidElementType(const Type *ElemTy) {
 //                     Derived Type Refinement Functions
 //===----------------------------------------------------------------------===//
 
+// addAbstractTypeUser - Notify an abstract type that there is a new user of
+// it.  This function is called primarily by the PATypeHandle class.
+void Type::addAbstractTypeUser(AbstractTypeUser *U) const {
+  assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!");
+  if (llvm_is_multithreaded()) {
+    AbstractTypeUsersLock->acquire();
+    AbstractTypeUsers.push_back(U);
+    AbstractTypeUsersLock->release();
+  } else {
+    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 Type::removeAbstractTypeUser(AbstractTypeUser *U) const {
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->acquire();
+  
   // Search from back to front because we will notify users from back to
   // front.  Also, it is likely that there will be a stack like behavior to
   // users that register and unregister users.
@@ -1469,8 +1489,11 @@ void Type::removeAbstractTypeUser(AbstractTypeUser *U) const {
     DOUT << "DELETEing unused abstract type: <" << *this
          << ">[" << (void*)this << "]" << "\n";
 #endif
-    this->destroy();
+  
+  this->destroy();
   }
+  
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->release();
 }
 
 // unlockedRefineAbstractTypeTo - This function is used when it is discovered
@@ -1521,6 +1544,7 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) {
   // will not cause users to drop off of the use list.  If we resolve to ourself
   // we succeed!
   //
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->acquire();
   while (!AbstractTypeUsers.empty() && NewTy != this) {
     AbstractTypeUser *User = AbstractTypeUsers.back();
 
@@ -1536,6 +1560,7 @@ void DerivedType::unlockedRefineAbstractTypeTo(const Type *NewType) {
     assert(AbstractTypeUsers.size() != OldSize &&
            "AbsTyUser did not remove self from user list!");
   }
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->release();
 
   // If we were successful removing all users from the type, 'this' will be
   // deleted when the last PATypeHolder is destroyed or updated from this type.
@@ -1566,6 +1591,7 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() {
   DOUT << "typeIsREFINED type: " << (void*)this << " " << *this << "\n";
 #endif
 
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->acquire();
   unsigned OldSize = AbstractTypeUsers.size(); OldSize=OldSize;
   while (!AbstractTypeUsers.empty()) {
     AbstractTypeUser *ATU = AbstractTypeUsers.back();
@@ -1574,6 +1600,7 @@ void DerivedType::notifyUsesThatTypeBecameConcrete() {
     assert(AbstractTypeUsers.size() < OldSize-- &&
            "AbstractTypeUser did not remove itself from the use list!");
   }
+  if (llvm_is_multithreaded()) AbstractTypeUsersLock->release();
 }
 
 // refineAbstractType - Called when a contained type is found to be more