Miscellaneous cleanups:
[oota-llvm.git] / lib / Bytecode / Writer / SlotCalculator.cpp
1 //===-- SlotCalculator.cpp - Calculate what slots values land in ------------=//
2 //
3 // This file implements a useful analysis step to figure out what numbered 
4 // slots values in a program will land in (keeping track of per plane
5 // information as required.
6 //
7 // This is used primarily for when writing a file to disk, either in bytecode
8 // or source format.
9 //
10 //===----------------------------------------------------------------------===//
11
12 #include "llvm/Analysis/SlotCalculator.h"
13 #include "llvm/ConstantPool.h"
14 #include "llvm/Method.h"
15 #include "llvm/Module.h"
16 #include "llvm/BasicBlock.h"
17 #include "llvm/ConstPoolVals.h"
18 #include "llvm/iOther.h"
19 #include "llvm/DerivedTypes.h"
20
21 SlotCalculator::SlotCalculator(const Module *M, bool IgnoreNamed) {
22   IgnoreNamedNodes = IgnoreNamed;
23   TheModule = M;
24
25   // Preload table... Make sure that all of the primitive types are in the table
26   // and that their Primitive ID is equal to their slot #
27   //
28   for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) {
29     assert(Type::getPrimitiveType((Type::PrimitiveID)i));
30     insertVal(Type::getPrimitiveType((Type::PrimitiveID)i));
31   }
32
33   if (M == 0) return;   // Empty table...
34
35   bool Result = processModule(M);
36   assert(Result == false && "Error in processModule!");
37 }
38
39 SlotCalculator::SlotCalculator(const Method *M, bool IgnoreNamed) {
40   IgnoreNamedNodes = IgnoreNamed;
41   TheModule = M ? M->getParent() : 0;
42
43   // Preload table... Make sure that all of the primitive types are in the table
44   // and that their Primitive ID is equal to their slot #
45   //
46   for (unsigned i = 0; i < Type::FirstDerivedTyID; ++i) {
47     assert(Type::getPrimitiveType((Type::PrimitiveID)i));
48     insertVal(Type::getPrimitiveType((Type::PrimitiveID)i));
49   }
50
51   if (TheModule == 0) return;   // Empty table...
52
53   bool Result = processModule(TheModule);
54   assert(Result == false && "Error in processModule!");
55
56   incorporateMethod(M);
57 }
58
59 void SlotCalculator::incorporateMethod(const Method *M) {
60   assert(ModuleLevel.size() == 0 && "Module already incorporated!");
61
62   // Save the Table state before we process the method...
63   for (unsigned i = 0; i < Table.size(); ++i) {
64     ModuleLevel.push_back(Table[i].size());
65   }
66
67   // Process the method to incorporate its values into our table
68   processMethod(M);
69 }
70
71 void SlotCalculator::purgeMethod() {
72   assert(ModuleLevel.size() != 0 && "Module not incorporated!");
73   unsigned NumModuleTypes = ModuleLevel.size();
74
75   // First, remove values from existing type planes
76   for (unsigned i = 0; i < NumModuleTypes; ++i) {
77     unsigned ModuleSize = ModuleLevel[i];  // Size of plane before method came
78     while (Table[i].size() != ModuleSize) {
79       NodeMap.erase(NodeMap.find(Table[i].back()));   // Erase from nodemap
80       Table[i].pop_back();                            // Shrink plane
81     }
82   }
83
84   // We don't need this state anymore, free it up.
85   ModuleLevel.clear();
86
87   // Next, remove any type planes defined by the method...
88   while (NumModuleTypes != Table.size()) {
89     TypePlane &Plane = Table.back();
90     while (Plane.size()) {
91       NodeMap.erase(NodeMap.find(Plane.back()));   // Erase from nodemap
92       Plane.pop_back();                            // Shrink plane
93     }
94
95     Table.pop_back();                      // Nuke the plane, we don't like it.
96   }
97 }
98
99 bool SlotCalculator::processConstant(const ConstPoolVal *CPV) { 
100   //cerr << "Inserting constant: '" << CPV->getStrValue() << endl;
101   insertVal(CPV);
102   return false;
103 }
104
105 // processType - This callback occurs when an derived type is discovered
106 // at the class level. This activity occurs when processing a constant pool.
107 //
108 bool SlotCalculator::processType(const Type *Ty) { 
109   //cerr << "processType: " << Ty->getName() << endl;
110   // TODO: Don't leak memory!!!  Free this in the dtor!
111   insertVal(new ConstPoolType(Ty));
112   return false; 
113 }
114
115 bool SlotCalculator::visitMethod(const Method *M) {
116   //cerr << "visitMethod: '" << M->getType()->getName() << "'\n";
117   insertVal(M);
118   return false; 
119 }
120
121 bool SlotCalculator::processMethodArgument(const MethodArgument *MA) {
122   insertVal(MA);
123   return false;
124 }
125
126 bool SlotCalculator::processBasicBlock(const BasicBlock *BB) {
127   insertVal(BB);
128   ModuleAnalyzer::processBasicBlock(BB);  // Lets visit the instructions too!
129   return false;
130 }
131
132 bool SlotCalculator::processInstruction(const Instruction *I) {
133   insertVal(I);
134   return false;
135 }
136
137 int SlotCalculator::getValSlot(const Value *D) const {
138   map<const Value*, unsigned>::const_iterator I = NodeMap.find(D);
139   if (I == NodeMap.end()) return -1;
140  
141   return (int)I->second;
142 }
143
144 void SlotCalculator::insertVal(const Value *D) {
145   if (D == 0) return;
146
147   // If this node does not contribute to a plane, or if the node has a 
148   // name and we don't want names, then ignore the silly node...
149   //
150   if (D->getType() == Type::VoidTy || (IgnoreNamedNodes && D->hasName())) 
151     return;
152
153   const Type *Typ = D->getType();
154   unsigned Ty = Typ->getPrimitiveID();
155   if (Typ->isDerivedType()) {
156     int DefSlot = getValSlot(Typ);
157     if (DefSlot == -1) {                // Have we already entered this type?
158       // This can happen if a type is first seen in an instruction.  For 
159       // example, if you say 'malloc uint', this defines a type 'uint*' that
160       // may be undefined at this point.
161       //
162       cerr << "SHOULDNT HAPPEN Adding Type ba: " << Typ->getName() << endl;
163       assert(0 && "SHouldn't this be taken care of by processType!?!?!");
164       // Nope... add this to the Type plane now!
165       insertVal(Typ);
166
167       DefSlot = getValSlot(Typ);
168       assert(DefSlot >= 0 && "Type didn't get inserted correctly!");
169     }
170     Ty = (unsigned)DefSlot;
171   }
172   
173   if (Table.size() <= Ty)    // Make sure we have the type plane allocated...
174     Table.resize(Ty+1, TypePlane());
175   
176   // Insert node into table and NodeMap...
177   NodeMap[D] = Table[Ty].size();
178
179   if (Typ == Type::TypeTy && !D->isType()) {
180     // If it's a type constant, add the Type also
181       
182     // All Type instances should be constant types!
183     const ConstPoolType *CPT = (const ConstPoolType*)D->castConstantAsserting();
184     int Slot = getValSlot(CPT->getValue());
185     if (Slot == -1) {
186       // Only add if it's not already here!
187       NodeMap[CPT->getValue()] = Table[Ty].size();
188     } else if (!CPT->hasName()) {    // If the type has no name...
189       NodeMap[D] = (unsigned)Slot;   // Don't readd type, merge.
190       return;
191     }
192   }
193   Table[Ty].push_back(D);
194 }