LLVM API Documentation

TypeSymbolTable.cpp

Go to the documentation of this file.
00001 //===-- TypeSymbolTable.cpp - Implement the TypeSymbolTable class ---------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file was developed by Reid Spencer. It is distributed under the 
00006 // University of Illinois Open Source License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the TypeSymbolTable class for the VMCore library.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 
00014 #include "llvm/TypeSymbolTable.h"
00015 #include "llvm/DerivedTypes.h"
00016 #include "llvm/ADT/StringExtras.h"
00017 #include <iostream>
00018 #include <algorithm>
00019 
00020 using namespace llvm;
00021 
00022 #define DEBUG_SYMBOL_TABLE 0
00023 #define DEBUG_ABSTYPE 0
00024 
00025 TypeSymbolTable::~TypeSymbolTable() {
00026   // Drop all abstract type references in the type plane...
00027   for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
00028     if (TI->second->isAbstract())   // If abstract, drop the reference...
00029       cast<DerivedType>(TI->second)->removeAbstractTypeUser(this);
00030   }
00031 }
00032 
00033 std::string TypeSymbolTable::getUniqueName(const std::string &BaseName) const {
00034   std::string TryName = BaseName;
00035   const_iterator End = tmap.end();
00036 
00037   // See if the name exists
00038   while (tmap.find(TryName) != End)            // Loop until we find a free
00039     TryName = BaseName + utostr(++LastUnique); // name in the symbol table
00040   return TryName;
00041 }
00042 
00043 // lookup a type by name - returns null on failure
00044 Type* TypeSymbolTable::lookup(const std::string& Name) const {
00045   const_iterator TI = tmap.find(Name);
00046   if (TI != tmap.end())
00047     return const_cast<Type*>(TI->second);
00048   return 0;
00049 }
00050 
00051 // Erase a specific type from the symbol table
00052 bool TypeSymbolTable::erase(Type *N) {
00053   for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
00054     if (TI->second == N) {
00055       this->erase(TI);
00056       return true;
00057     }
00058   }
00059   return false;
00060 }
00061 
00062 // remove - Remove a type from the symbol table...
00063 Type* TypeSymbolTable::erase(iterator Entry) {
00064   assert(Entry != tmap.end() && "Invalid entry to remove!");
00065 
00066   const Type* Result = Entry->second;
00067 
00068 #if DEBUG_SYMBOL_TABLE
00069   dump();
00070   std::cerr << " Removing Value: " << Result->getName() << "\n";
00071 #endif
00072 
00073   tmap.erase(Entry);
00074 
00075   // If we are removing an abstract type, remove the symbol table from it's use
00076   // list...
00077   if (Result->isAbstract()) {
00078 #if DEBUG_ABSTYPE
00079     std::cerr << "Removing abstract type from symtab" << Result->getDescription()<<"\n";
00080 #endif
00081     cast<DerivedType>(Result)->removeAbstractTypeUser(this);
00082   }
00083 
00084   return const_cast<Type*>(Result);
00085 }
00086 
00087 
00088 // insert - Insert a type into the symbol table with the specified name...
00089 void TypeSymbolTable::insert(const std::string& Name, const Type* T) {
00090   assert(T && "Can't insert null type into symbol table!");
00091 
00092   // Check to see if there is a naming conflict.  If so, rename this type!
00093   std::string UniqueName = Name;
00094   if (lookup(Name))
00095     UniqueName = getUniqueName(Name);
00096 
00097 #if DEBUG_SYMBOL_TABLE
00098   dump();
00099   std::cerr << " Inserting type: " << UniqueName << ": "
00100             << T->getDescription() << "\n";
00101 #endif
00102 
00103   // Insert the tmap entry
00104   tmap.insert(make_pair(UniqueName, T));
00105 
00106   // If we are adding an abstract type, add the symbol table to it's use list.
00107   if (T->isAbstract()) {
00108     cast<DerivedType>(T)->addAbstractTypeUser(this);
00109 #if DEBUG_ABSTYPE
00110     std::cerr << "Added abstract type to ST: " << T->getDescription() << "\n";
00111 #endif
00112   }
00113 }
00114 
00115 // Strip the symbol table of its names.
00116 bool TypeSymbolTable::strip() {
00117   bool RemovedSymbol = false;
00118   for (iterator TI = tmap.begin(); TI != tmap.end(); ) {
00119     erase(TI++);
00120     RemovedSymbol = true;
00121   }
00122 
00123   return RemovedSymbol;
00124 }
00125 
00126 /// rename - Given a value with a non-empty name, remove its existing entry
00127 /// from the symbol table and insert a new one for Name.  This is equivalent to
00128 /// doing "remove(V), V->Name = Name, insert(V)", but is faster, and will not
00129 /// temporarily remove the symbol table plane if V is the last value in the
00130 /// symtab with that name (which could invalidate iterators to that plane).
00131 bool TypeSymbolTable::rename(Type *T, const std::string &name) {
00132   for (iterator TI = tmap.begin(), TE = tmap.end(); TI != TE; ++TI) {
00133     if (TI->second == T) {
00134       // Remove the old entry.
00135       tmap.erase(TI);
00136       // Add the new entry.
00137       this->insert(name,T);
00138       return true;
00139     }
00140   }
00141   return false;
00142 }
00143 
00144 // This function is called when one of the types in the type plane are refined
00145 void TypeSymbolTable::refineAbstractType(const DerivedType *OldType,
00146                                          const Type *NewType) {
00147 
00148   // Loop over all of the types in the symbol table, replacing any references
00149   // to OldType with references to NewType.  Note that there may be multiple
00150   // occurrences, and although we only need to remove one at a time, it's
00151   // faster to remove them all in one pass.
00152   //
00153   for (iterator I = begin(), E = end(); I != E; ++I) {
00154     if (I->second == (Type*)OldType) {  // FIXME when Types aren't const.
00155 #if DEBUG_ABSTYPE
00156       std::cerr << "Removing type " << OldType->getDescription() << "\n";
00157 #endif
00158       OldType->removeAbstractTypeUser(this);
00159 
00160       I->second = (Type*)NewType;  // TODO FIXME when types aren't const
00161       if (NewType->isAbstract()) {
00162 #if DEBUG_ABSTYPE
00163         std::cerr << "Added type " << NewType->getDescription() << "\n";
00164 #endif
00165         cast<DerivedType>(NewType)->addAbstractTypeUser(this);
00166       }
00167     }
00168   }
00169 }
00170 
00171 
00172 // Handle situation where type becomes Concreate from Abstract
00173 void TypeSymbolTable::typeBecameConcrete(const DerivedType *AbsTy) {
00174   // Loop over all of the types in the symbol table, dropping any abstract
00175   // type user entries for AbsTy which occur because there are names for the
00176   // type.
00177   for (iterator TI = begin(), TE = end(); TI != TE; ++TI)
00178     if (TI->second == const_cast<Type*>(static_cast<const Type*>(AbsTy)))
00179       AbsTy->removeAbstractTypeUser(this);
00180 }
00181 
00182 static void DumpTypes(const std::pair<const std::string, const Type*>& T ) {
00183   std::cerr << "  '" << T.first << "' = ";
00184   T.second->dump();
00185   std::cerr << "\n";
00186 }
00187 
00188 void TypeSymbolTable::dump() const {
00189   std::cerr << "TypeSymbolPlane: ";
00190   for_each(tmap.begin(), tmap.end(), DumpTypes);
00191 }
00192 
00193 // vim: sw=2 ai