Convert a runtime check into an assertion
[oota-llvm.git] / lib / VMCore / SymbolTable.cpp
index 395c23f2abc944ac0a2e704defb7e1d0fb6c4041..4317968d4cdba654e71d4141a49ea24d9a09c9ff 100644 (file)
@@ -6,23 +6,32 @@
 
 #include "llvm/SymbolTable.h"
 #include "llvm/InstrTypes.h"
-#ifndef NDEBUG
-#include "llvm/BasicBlock.h"   // Required for assertions to work.
-#include "llvm/Type.h"
-#endif
+#include "llvm/Support/StringExtras.h"
+#include "llvm/DerivedTypes.h"
 
 SymbolTable::~SymbolTable() {
-#ifndef NDEBUG   // Only do this in -g mode...
-  bool Good = true;
-  for (iterator i = begin(); i != end(); i++) {
-    if (i->second.begin() != i->second.end()) {
-      for (type_iterator I = i->second.begin(); I != i->second.end(); I++)
-        cerr << "Value still in symbol table! Type = " << i->first->getName() 
-             << "  Name = " << I->first << endl;
-      Good = false;
+  // Drop all abstract type references in the type plane...
+  iterator TyPlane = find(Type::TypeTy);
+  if (TyPlane != end()) {
+    VarMap &TyP = TyPlane->second;
+    for (VarMap::iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) {
+      const Type *Ty = cast<const Type>(I->second);
+      if (Ty->isAbstract())   // If abstract, drop the reference...
+       cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
     }
   }
-  assert(Good && "Values remain in symbol table!");
+#ifndef NDEBUG   // Only do this in -g mode...
+  bool LeftoverValues = true;
+  for (iterator i = begin(); i != end(); ++i) {
+    for (type_iterator I = i->second.begin(); I != i->second.end(); ++I)
+      if (!isa<ConstPoolVal>(I->second) && !isa<Type>(I->second)) {
+       cerr << "Value still in symbol table! Type = '"
+            << i->first->getDescription() << "' Name = '" << I->first << "'\n";
+       LeftoverValues = false;
+      }
+  }
+  
+  assert(LeftoverValues && "Values remain in symbol table!");
 #endif
 }
 
@@ -45,6 +54,24 @@ SymbolTable::type_iterator SymbolTable::type_find(const Type *Ty,
   return I->second.find(Name);
 }
 
+// getUniqueName - Given a base name, return a string that is either equal to
+// it (or derived from it) that does not already occur in the symbol table for
+// the specified type.
+//
+string SymbolTable::getUniqueName(const Type *Ty, const string &BaseName) {
+  iterator I = find(Ty);
+  if (I == end()) return BaseName;
+
+  string TryName = BaseName;
+  unsigned Counter = 0;
+  type_iterator End = I->second.end();
+
+  while (I->second.find(TryName) != End)     // Loop until we find unoccupied
+    TryName = BaseName + utostr(++Counter);  // Name in the symbol table
+  return TryName;
+}
+
+
 
 // lookup - Returns null on failure...
 Value *SymbolTable::lookup(const Type *Ty, const string &Name) {
@@ -70,37 +97,102 @@ void SymbolTable::remove(Value *N) {
 
 Value *SymbolTable::type_remove(const type_iterator &It) {
   Value *Result = It->second;
+  const Type *Ty = Result->getType();
 #if DEBUG_SYMBOL_TABLE
   cerr << this << " Removing Value: " << Result->getName() << endl;
 #endif
 
-  find(Result->getType())->second.erase(It);
+  // Remove the value from the plane...
+  find(Ty)->second.erase(It);
+
+  // If we are removing an abstract type, remove the symbol table from it's use
+  // list...
+  if (Ty == Type::TypeTy) {
+    const Type *T = cast<const Type>(Result);
+    if (T->isAbstract())
+      cast<DerivedType>(T)->removeAbstractTypeUser(this);
+  }
 
   return Result;
 }
 
-void SymbolTable::insert(Value *N) {
-  assert(N->hasName() && "Value must be named to go into symbol table!");
+// insertEntry - Insert a value into the symbol table with the specified
+// name...
+//
+void SymbolTable::insertEntry(const string &Name, Value *V) {
+  const Type *VTy = V->getType();
 
   // TODO: The typeverifier should catch this when its implemented
-  if (lookup(N->getType(), N->getName())) {
-    cerr << "SymbolTable WARNING: Name already in symbol table: '" 
-         << N->getName() << "'\n";
-    abort();  // TODO: REMOVE THIS
-  }
+  assert(lookup(VTy, Name) == 0 && 
+        "SymbolTable::insertEntry - Name already in symbol table!");
 
 #if DEBUG_SYMBOL_TABLE
-  cerr << this << " Inserting definition: " << N->getName() << ": " 
-       << N->getType()->getName() << endl;
+  cerr << this << " Inserting definition: " << Name << ": " 
+       << VTy->getDescription() << endl;
 #endif
 
-  iterator I = find(N->getType());
+  iterator I = find(VTy);
   if (I == end()) {      // Not in collection yet... insert dummy entry
-    (*this)[N->getType()] = VarMap();
-    I = find(N->getType());
+    (*this)[VTy] = VarMap();
+    I = find(VTy);
     assert(I != end() && "How did insert fail?");
   }
 
-  I->second.insert(make_pair(N->getName(), N));
+  I->second.insert(make_pair(Name, V));
+
+  // If we are adding an abstract type, add the symbol table to it's use list.
+  if (VTy == Type::TypeTy) {
+    const Type *T = cast<const Type>(V);
+    if (T->isAbstract())
+      cast<DerivedType>(T)->addAbstractTypeUser(this);
+  }
+}
+
+// This function is called when one of the types in the type plane are refined
+void SymbolTable::refineAbstractType(const DerivedType *OldType,
+                                    const Type *NewType) {
+  if (OldType == NewType) return;  // Noop, don't waste time dinking around
+
+  iterator TPI = find(Type::TypeTy);
+  assert(TPI != end() &&"Type plane not in symbol table but we contain types!");
+
+  // Loop over all of the types in the symbol table, replacing any references to
+  // OldType with references to NewType.  Note that there may be multiple
+  // occurances, and although we only need to remove one at a time, it's faster
+  // to remove them all in one pass.
+  //
+  VarMap &TyPlane = TPI->second;
+  for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I)
+    if (I->second == (Value*)OldType) {  // FIXME when Types aren't const.
+      OldType->removeAbstractTypeUser(this);
+      I->second = (Value*)NewType;  // TODO FIXME when types aren't const
+      if (NewType->isAbstract())
+       cast<const DerivedType>(NewType)->addAbstractTypeUser(this);
+    }
+}
+
+
+#ifndef NDEBUG
+#include "llvm/Assembly/Writer.h"
+#include <algorithm>
+
+static void DumpVal(const pair<const string, Value *> &V) {
+  cout << "  '%" << V.first << "' = " << V.second << endl;
+}
+
+static void DumpPlane(const pair<const Type *, map<const string, Value *> >&P) {
+  cout << "  Plane: " << P.first << endl;
+  for_each(P.second.begin(), P.second.end(), DumpVal);
+}
+
+void SymbolTable::dump() const {
+  cout << "Symbol table dump:\n";
+  for_each(begin(), end(), DumpPlane);
+
+  if (ParentSymTab) {
+    cout << "Parent ";
+    ParentSymTab->dump();
+  }
 }
 
+#endif