Minor cleanups (use dyn_cast instead of testing manually)
[oota-llvm.git] / lib / VMCore / SymbolTable.cpp
1 //===-- SymbolTable.cpp - Implement the SymbolTable class -------------------=//
2 //
3 // This file implements the SymbolTable class for the VMCore library.
4 //
5 //===----------------------------------------------------------------------===//
6
7 #include "llvm/SymbolTable.h"
8 #include "llvm/InstrTypes.h"
9 #include "llvm/DerivedTypes.h"
10 #include "llvm/Module.h"
11 #include "llvm/Function.h"
12 #include "Support/StringExtras.h"
13 #include <iostream>
14
15 using std::string;
16 using std::pair;
17 using std::make_pair;
18 using std::map;
19 using std::cerr;
20 using std::cout;
21
22 #define DEBUG_SYMBOL_TABLE 0
23 #define DEBUG_ABSTYPE 0
24
25 SymbolTable::~SymbolTable() {
26   // Drop all abstract type references in the type plane...
27   iterator TyPlane = find(Type::TypeTy);
28   if (TyPlane != end()) {
29     VarMap &TyP = TyPlane->second;
30     for (VarMap::iterator I = TyP.begin(), E = TyP.end(); I != E; ++I) {
31       const Type *Ty = cast<const Type>(I->second);
32       if (Ty->isAbstract())   // If abstract, drop the reference...
33         cast<DerivedType>(Ty)->removeAbstractTypeUser(this);
34     }
35   }
36
37  // TODO: FIXME: BIG ONE: This doesn't unreference abstract types for the planes
38  // that could still have entries!
39
40 #ifndef NDEBUG   // Only do this in -g mode...
41   bool LeftoverValues = true;
42   for (iterator i = begin(); i != end(); ++i) {
43     for (type_iterator I = i->second.begin(); I != i->second.end(); ++I)
44       if (!isa<Constant>(I->second) && !isa<Type>(I->second)) {
45         cerr << "Value still in symbol table! Type = '"
46              << i->first->getDescription() << "' Name = '"
47              << I->first << "'\n";
48         LeftoverValues = false;
49       }
50   }
51   
52   assert(LeftoverValues && "Values remain in symbol table!");
53 #endif
54 }
55
56 // getUniqueName - Given a base name, return a string that is either equal to
57 // it (or derived from it) that does not already occur in the symbol table for
58 // the specified type.
59 //
60 string SymbolTable::getUniqueName(const Type *Ty, const string &BaseName) {
61   iterator I = find(Ty);
62   if (I == end()) return BaseName;
63
64   string TryName = BaseName;
65   unsigned Counter = 0;
66   type_iterator End = I->second.end();
67
68   while (I->second.find(TryName) != End)     // Loop until we find unoccupied
69     TryName = BaseName + utostr(++Counter);  // Name in the symbol table
70   return TryName;
71 }
72
73
74
75 // lookup - Returns null on failure...
76 Value *SymbolTable::localLookup(const Type *Ty, const string &Name) {
77   iterator I = find(Ty);
78   if (I != end()) {                      // We have symbols in that plane...
79     type_iterator J = I->second.find(Name);
80     if (J != I->second.end())            // and the name is in our hash table...
81       return J->second;
82   }
83
84   return 0;
85 }
86
87 // lookup - Returns null on failure...
88 Value *SymbolTable::lookup(const Type *Ty, const string &Name) {
89   Value *LV = localLookup(Ty, Name);
90   if (LV) return LV;
91   return ParentSymTab ? ParentSymTab->lookup(Ty, Name) : 0;
92 }
93
94 void SymbolTable::remove(Value *N) {
95   assert(N->hasName() && "Value doesn't have name!");
96   if (InternallyInconsistent) return;
97
98   iterator I = find(N->getType());
99   assert(I != end() &&
100          "Trying to remove a type that doesn't have a plane yet!");
101   removeEntry(I, I->second.find(N->getName()));
102 }
103
104 // removeEntry - Remove a value from the symbol table...
105 //
106 Value *SymbolTable::removeEntry(iterator Plane, type_iterator Entry) {
107   if (InternallyInconsistent) return 0;
108   assert(Plane != super::end() &&
109          Entry != Plane->second.end() && "Invalid entry to remove!");
110
111   Value *Result = Entry->second;
112   const Type *Ty = Result->getType();
113 #if DEBUG_SYMBOL_TABLE
114   cerr << this << " Removing Value: " << Result->getName() << endl;
115 #endif
116
117   // Remove the value from the plane...
118   Plane->second.erase(Entry);
119
120   // If the plane is empty, remove it now!
121   if (Plane->second.empty()) {
122     // If the plane represented an abstract type that we were interested in,
123     // unlink ourselves from this plane.
124     //
125     if (Plane->first->isAbstract()) {
126 #if DEBUG_ABSTYPE
127       cerr << "Plane Empty: Removing type: " << Plane->first->getDescription()
128            << endl;
129 #endif
130       cast<DerivedType>(Plane->first)->removeAbstractTypeUser(this);
131     }
132
133     erase(Plane);
134   }
135
136   // If we are removing an abstract type, remove the symbol table from it's use
137   // list...
138   if (Ty == Type::TypeTy) {
139     const Type *T = cast<const Type>(Result);
140     if (T->isAbstract()) {
141 #if DEBUG_ABSTYPE
142       cerr << "Removing abs type from symtab" << T->getDescription() << endl;
143 #endif
144       cast<DerivedType>(T)->removeAbstractTypeUser(this);
145     }
146   }
147
148   return Result;
149 }
150
151 // insertEntry - Insert a value into the symbol table with the specified
152 // name...
153 //
154 void SymbolTable::insertEntry(const string &Name, const Type *VTy, Value *V) {
155
156   // Check to see if there is a naming conflict.  If so, rename this value!
157   if (localLookup(VTy, Name)) {
158     string UniqueName = getUniqueName(VTy, Name);
159     assert(InternallyInconsistent == false && "Infinite loop inserting entry!");
160     InternallyInconsistent = true;
161     V->setName(UniqueName, this);
162     InternallyInconsistent = false;
163     return;
164   }
165
166 #if DEBUG_SYMBOL_TABLE
167   cerr << this << " Inserting definition: " << Name << ": " 
168        << VTy->getDescription() << endl;
169 #endif
170
171   iterator I = find(VTy);
172   if (I == end()) {      // Not in collection yet... insert dummy entry
173     // Insert a new empty element.  I points to the new elements.
174     I = super::insert(make_pair(VTy, VarMap())).first;
175     assert(I != end() && "How did insert fail?");
176
177     // Check to see if the type is abstract.  If so, it might be refined in the
178     // future, which would cause the plane of the old type to get merged into
179     // a new type plane.
180     //
181     if (VTy->isAbstract()) {
182       cast<DerivedType>(VTy)->addAbstractTypeUser(this);
183 #if DEBUG_ABSTYPE
184       cerr << "Added abstract type value: " << VTy->getDescription() << endl;
185 #endif
186     }
187   }
188
189   I->second.insert(make_pair(Name, V));
190
191   // If we are adding an abstract type, add the symbol table to it's use list.
192   if (VTy == Type::TypeTy) {
193     const Type *T = cast<const Type>(V);
194     if (T->isAbstract()) {
195       cast<DerivedType>(T)->addAbstractTypeUser(this);
196 #if DEBUG_ABSTYPE
197       cerr << "Added abstract type to ST: " << T->getDescription() << endl;
198 #endif
199     }
200   }
201 }
202
203 // This function is called when one of the types in the type plane are refined
204 void SymbolTable::refineAbstractType(const DerivedType *OldType,
205                                      const Type *NewType) {
206   if (OldType == NewType && OldType->isAbstract())
207     return;  // Noop, don't waste time dinking around
208
209   // Search to see if we have any values of the type oldtype.  If so, we need to
210   // move them into the newtype plane...
211   iterator TPI = find(OldType);
212   if (OldType != NewType && TPI != end()) {
213     // Get a handle to the new type plane...
214     iterator NewTypeIt = find(NewType);
215     if (NewTypeIt == super::end()) {      // If no plane exists, add one
216       NewTypeIt = super::insert(make_pair(NewType, VarMap())).first;
217       
218       if (NewType->isAbstract()) {
219         cast<DerivedType>(NewType)->addAbstractTypeUser(this);
220 #if DEBUG_ABSTYPE
221         cerr << "[Added] refined to abstype: "<<NewType->getDescription()<<endl;
222 #endif
223       }
224     }
225
226     VarMap &NewPlane = NewTypeIt->second;
227     VarMap &OldPlane = TPI->second;
228     while (!OldPlane.empty()) {
229       pair<const string, Value*> V = *OldPlane.begin();
230
231       // Check to see if there is already a value in the symbol table that this
232       // would collide with.
233       type_iterator TI = NewPlane.find(V.first);
234       if (TI != NewPlane.end() && TI->second == V.second) {
235         // No action
236
237       } else if (TI != NewPlane.end()) {
238         // The only thing we are allowing for now is two method prototypes being
239         // folded into one.
240         //
241         Function *ExistM = dyn_cast<Function>(TI->second);
242         Function *NewM = dyn_cast<Function>(V.second);
243
244         if (ExistM && NewM && ExistM->isExternal() && NewM->isExternal()) {
245           // Ok we have two external methods.  Make all uses of the new one
246           // use the old one...
247           //
248           NewM->replaceAllUsesWith(ExistM);
249           
250           // Now we just convert it to an unnamed method... which won't get
251           // added to our symbol table.  The problem is that if we call
252           // setName on the method that it will try to remove itself from
253           // the symbol table and die... because it's not in the symtab
254           // right now.  To fix this, we have an internally consistent flag
255           // that turns remove into a noop.  Thus the name will get null'd
256           // out, but the symbol table won't get upset.
257           //
258           assert(InternallyInconsistent == false &&
259                  "Symbol table already inconsistent!");
260           InternallyInconsistent = true;
261
262           // Remove newM from the symtab
263           NewM->setName("");
264           InternallyInconsistent = false;
265
266           // Now we can remove this method from the module entirely...
267           NewM->getParent()->getFunctionList().remove(NewM);
268           delete NewM;
269
270         } else {
271           assert(0 && "Two ploanes folded together with overlapping "
272                  "value names!");
273         }
274       } else {
275         insertEntry(V.first, NewType, V.second);
276
277       }
278       // Remove the item from the old type plane
279       OldPlane.erase(OldPlane.begin());
280     }
281
282     // Ok, now we are not referencing the type anymore... take me off your user
283     // list please!
284 #if DEBUG_ABSTYPE
285     cerr << "Removing type " << OldType->getDescription() << endl;
286 #endif
287     OldType->removeAbstractTypeUser(this);
288
289     // Remove the plane that is no longer used
290     erase(TPI);
291   } else if (TPI != end()) {
292     assert(OldType == NewType);
293 #if DEBUG_ABSTYPE
294     cerr << "Removing SELF type " << OldType->getDescription() << endl;
295 #endif
296     OldType->removeAbstractTypeUser(this);
297   }
298
299   TPI = find(Type::TypeTy);
300   if (TPI != end()) {  
301     // Loop over all of the types in the symbol table, replacing any references to
302     // OldType with references to NewType.  Note that there may be multiple
303     // occurances, and although we only need to remove one at a time, it's faster
304     // to remove them all in one pass.
305     //
306     VarMap &TyPlane = TPI->second;
307     for (VarMap::iterator I = TyPlane.begin(), E = TyPlane.end(); I != E; ++I)
308       if (I->second == (Value*)OldType) {  // FIXME when Types aren't const.
309 #if DEBUG_ABSTYPE
310         cerr << "Removing type " << OldType->getDescription() << endl;
311 #endif
312         OldType->removeAbstractTypeUser(this);
313         
314         I->second = (Value*)NewType;  // TODO FIXME when types aren't const
315         if (NewType->isAbstract()) {
316 #if DEBUG_ABSTYPE
317           cerr << "Added type " << NewType->getDescription() << endl;
318 #endif
319           cast<const DerivedType>(NewType)->addAbstractTypeUser(this);
320         }
321       }
322   }
323 }
324
325
326 #ifndef NDEBUG
327 #include "llvm/Assembly/Writer.h"
328 #include <algorithm>
329
330 static void DumpVal(const pair<const string, Value *> &V) {
331   cout << "  '" << V.first << "' = " << V.second << "\n";
332 }
333
334 static void DumpPlane(const pair<const Type *, map<const string, Value *> >&P) {
335   cout << "  Plane: " << P.first << "\n";
336   for_each(P.second.begin(), P.second.end(), DumpVal);
337 }
338
339 void SymbolTable::dump() const {
340   cout << "Symbol table dump:\n";
341   for_each(begin(), end(), DumpPlane);
342
343   if (ParentSymTab) {
344     cout << "Parent ";
345     ParentSymTab->dump();
346   }
347 }
348
349 #endif