Add an arg to insertVal to allow us to prevent builtin types from being ignored
[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), true);
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), true);
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, bool dontIgnore = false) {
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 (!dontIgnore)                               // Don't ignore nonignorables!
151     if (D->getType() == Type::VoidTy ||          // Ignore void type nodes
152         (IgnoreNamedNodes && 
153          (D->hasName() || (D->isConstant() && !(D->getType() == Type::TypeTy)))))
154          return;// If IgnoreNamed nodes, ignore if it's a constant or has a name
155
156   const Type *Typ = D->getType();
157   unsigned Ty;
158
159   // Used for debugging DefSlot=-1 assertion...
160   //if (Typ == Type::TypeTy)
161   //  cerr << "Inserting type '" << D->castTypeAsserting()->getName() << "'!\n";
162
163   if (Typ->isDerivedType()) {
164     int DefSlot = getValSlot(Typ);
165     if (DefSlot == -1) {                // Have we already entered this type?
166       // This can happen if a type is first seen in an instruction.  For 
167       // example, if you say 'malloc uint', this defines a type 'uint*' that
168       // may be undefined at this point.
169       //
170       cerr << "Type '" << Typ->getName() << "' unknown!\n";
171       assert(0 && "Shouldn't type be in constant pool!?!?!");
172       abort();
173     }
174     Ty = (unsigned)DefSlot;
175   } else {
176     Ty = Typ->getPrimitiveID();
177   }
178   
179   if (Table.size() <= Ty)    // Make sure we have the type plane allocated...
180     Table.resize(Ty+1, TypePlane());
181   
182   // Insert node into table and NodeMap...
183   NodeMap[D] = Table[Ty].size();
184
185   if (Typ == Type::TypeTy && !D->isType()) {
186     // If it's a type constant, add the Type also
187       
188     // All Type instances should be constant types!
189     const ConstPoolType *CPT = (const ConstPoolType*)D->castConstantAsserting();
190     int Slot = getValSlot(CPT->getValue());
191     if (Slot == -1) {
192       // Only add if it's not already here!
193       NodeMap[CPT->getValue()] = Table[Ty].size();
194     } else if (!CPT->hasName()) {    // If the type has no name...
195       NodeMap[D] = (unsigned)Slot;   // Don't readd type, merge.
196       return;
197     }
198   }
199   Table[Ty].push_back(D);
200 }