Register the WriteBytecodePass
[oota-llvm.git] / lib / Bytecode / Writer / Writer.cpp
1 //===-- Writer.cpp - Library for writing VM bytecode files -------*- C++ -*--=//
2 //
3 // This library implements the functionality defined in llvm/Bytecode/Writer.h
4 //
5 // Note that this file uses an unusual technique of outputting all the bytecode
6 // to a deque of unsigned char's, then copies the deque to an ostream.  The
7 // reason for this is that we must do "seeking" in the stream to do back-
8 // patching, and some very important ostreams that we want to support (like
9 // pipes) do not support seeking.  :( :( :(
10 //
11 // The choice of the deque data structure is influenced by the extremely fast
12 // "append" speed, plus the free "seek"/replace in the middle of the stream. I
13 // didn't use a vector because the stream could end up very large and copying
14 // the whole thing to reallocate would be kinda silly.
15 //
16 // Note that the performance of this library is not terribly important, because
17 // it shouldn't be used by JIT type applications... so it is not a huge focus
18 // at least.  :)
19 //
20 //===----------------------------------------------------------------------===//
21
22 #include "WriterInternals.h"
23 #include "llvm/Bytecode/WriteBytecodePass.h"
24 #include "llvm/Module.h"
25 #include "llvm/SymbolTable.h"
26 #include "llvm/DerivedTypes.h"
27 #include "Support/STLExtras.h"
28 #include <string.h>
29 #include <algorithm>
30
31 static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");
32
33
34
35 BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M) 
36   : Out(o), Table(M, false) {
37
38   outputSignature();
39
40   // Emit the top level CLASS block.
41   BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out);
42
43   // Output the ID of first "derived" type:
44   output_vbr((unsigned)Type::FirstDerivedTyID, Out);
45   align32(Out);
46
47   // Output module level constants, including types used by the function protos
48   outputConstants(false);
49
50   // The ModuleInfoBlock follows directly after the Module constant pool
51   outputModuleInfoBlock(M);
52
53   // Do the whole module now! Process each function at a time...
54   for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
55     processMethod(I);
56
57   // If needed, output the symbol table for the module...
58   if (M->hasSymbolTable())
59     outputSymbolTable(*M->getSymbolTable());
60 }
61
62 // Helper function for outputConstants().
63 // Writes out all the constants in the plane Plane starting at entry StartNo.
64 // 
65 void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
66                                             &Plane, unsigned StartNo) {
67   unsigned ValNo = StartNo;
68   
69   // Scan through and ignore function arguments...
70   for (; ValNo < Plane.size() && isa<Argument>(Plane[ValNo]); ValNo++)
71     /*empty*/;
72
73   unsigned NC = ValNo;              // Number of constants
74   for (; NC < Plane.size() && 
75          (isa<Constant>(Plane[NC]) || isa<Type>(Plane[NC])); NC++)
76     /*empty*/;
77   NC -= ValNo;                      // Convert from index into count
78   if (NC == 0) return;              // Skip empty type planes...
79
80   // Output type header: [num entries][type id number]
81   //
82   output_vbr(NC, Out);
83
84   // Output the Type ID Number...
85   int Slot = Table.getValSlot(Plane.front()->getType());
86   assert (Slot != -1 && "Type in constant pool but not in function!!");
87   output_vbr((unsigned)Slot, Out);
88
89   //cerr << "Emitting " << NC << " constants of type '" 
90   //     << Plane.front()->getType()->getName() << "' = Slot #" << Slot << "\n";
91
92   for (unsigned i = ValNo; i < ValNo+NC; ++i) {
93     const Value *V = Plane[i];
94     if (const Constant *CPV = dyn_cast<Constant>(V)) {
95       //cerr << "Serializing value: <" << V->getType() << ">: " << V << ":" 
96       //     << Out.size() << "\n";
97       outputConstant(CPV);
98     } else {
99       outputType(cast<const Type>(V));
100     }
101   }
102 }
103
104 void BytecodeWriter::outputConstants(bool isFunction) {
105   BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out);
106
107   unsigned NumPlanes = Table.getNumPlanes();
108   
109   // Write the type plane for types first because earlier planes
110   // (e.g. for a primitive type like float) may have constants constructed
111   // using types coming later (e.g., via getelementptr from a pointer type).
112   // The type plane is needed before types can be fwd or bkwd referenced.
113   if (!isFunction) {
114     const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
115     assert(!Plane.empty() && "No types at all?");
116     unsigned ValNo = Type::FirstDerivedTyID; // Start at the derived types...
117     outputConstantsInPlane(Plane, ValNo);      // Write out the types
118   }
119   
120   for (unsigned pno = 0; pno < NumPlanes; pno++) {
121     const std::vector<const Value*> &Plane = Table.getPlane(pno);
122     if (Plane.empty()) continue;      // Skip empty type planes...
123     
124     unsigned ValNo = 0;
125     if (isFunction)                   // Don't reemit module constants
126       ValNo = Table.getModuleLevel(pno);
127     else if (pno == Type::TypeTyID)
128       continue;                       // Type plane was written out above
129     
130     outputConstantsInPlane(Plane, ValNo); // Write out constants in the plane
131   }
132 }
133
134 void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
135   BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);
136   
137   // Output the types for the global variables in the module...
138   for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
139     int Slot = Table.getValSlot(I->getType());
140     assert(Slot != -1 && "Module global vars is broken!");
141
142     // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2=InternalLinkage,
143     // bit3+ = slot#
144     unsigned oSlot = ((unsigned)Slot << 3) | (I->hasInternalLinkage() << 2) |
145                      (I->hasInitializer() << 1) | I->isConstant();
146     output_vbr(oSlot, Out);
147
148     // If we have an initializer, output it now.
149     if (I->hasInitializer()) {
150       Slot = Table.getValSlot((Value*)I->getInitializer());
151       assert(Slot != -1 && "No slot for global var initializer!");
152       output_vbr((unsigned)Slot, Out);
153     }
154   }
155   output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
156
157   // Output the types of the functions in this module...
158   for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
159     int Slot = Table.getValSlot(I->getType());
160     assert(Slot != -1 && "Module const pool is broken!");
161     assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
162     output_vbr((unsigned)Slot, Out);
163   }
164   output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
165
166
167   align32(Out);
168 }
169
170 void BytecodeWriter::processMethod(const Function *F) {
171   BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out);
172   output_vbr((unsigned)F->hasInternalLinkage(), Out);
173   // Only output the constant pool and other goodies if needed...
174   if (!F->isExternal()) {
175
176     // Get slot information about the function...
177     Table.incorporateFunction(F);
178
179     // Output information about the constants in the function...
180     outputConstants(true);
181
182     // Output basic block nodes...
183     for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I)
184       processBasicBlock(*I);
185     
186     // If needed, output the symbol table for the function...
187     if (F->hasSymbolTable())
188       outputSymbolTable(*F->getSymbolTable());
189     
190     Table.purgeFunction();
191   }
192 }
193
194
195 void BytecodeWriter::processBasicBlock(const BasicBlock &BB) {
196   BytecodeBlock FunctionBlock(BytecodeFormat::BasicBlock, Out);
197   // Process all the instructions in the bb...
198   for(BasicBlock::const_iterator I = BB.begin(), E = BB.end(); I != E; ++I)
199     processInstruction(*I);
200 }
201
202 void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
203   BytecodeBlock FunctionBlock(BytecodeFormat::SymbolTable, Out);
204
205   for (SymbolTable::const_iterator TI = MST.begin(); TI != MST.end(); ++TI) {
206     SymbolTable::type_const_iterator I = MST.type_begin(TI->first);
207     SymbolTable::type_const_iterator End = MST.type_end(TI->first);
208     int Slot;
209     
210     if (I == End) continue;  // Don't mess with an absent type...
211
212     // Symtab block header: [num entries][type id number]
213     output_vbr(MST.type_size(TI->first), Out);
214
215     Slot = Table.getValSlot(TI->first);
216     assert(Slot != -1 && "Type in symtab, but not in table!");
217     output_vbr((unsigned)Slot, Out);
218
219     for (; I != End; ++I) {
220       // Symtab entry: [def slot #][name]
221       Slot = Table.getValSlot(I->second);
222       assert(Slot != -1 && "Value in symtab but has no slot number!!");
223       output_vbr((unsigned)Slot, Out);
224       output(I->first, Out, false); // Don't force alignment...
225     }
226   }
227 }
228
229 void WriteBytecodeToFile(const Module *C, std::ostream &Out) {
230   assert(C && "You can't write a null module!!");
231
232   std::deque<unsigned char> Buffer;
233
234   // This object populates buffer for us...
235   BytecodeWriter BCW(Buffer, C);
236
237   // Okay, write the deque out to the ostream now... the deque is not
238   // sequential in memory, however, so write out as much as possible in big
239   // chunks, until we're done.
240   //
241   std::deque<unsigned char>::const_iterator I = Buffer.begin(),E = Buffer.end();
242   while (I != E) {                           // Loop until it's all written
243     // Scan to see how big this chunk is...
244     const unsigned char *ChunkPtr = &*I;
245     const unsigned char *LastPtr = ChunkPtr;
246     while (I != E) {
247       const unsigned char *ThisPtr = &*++I;
248       if (LastPtr+1 != ThisPtr) {   // Advanced by more than a byte of memory?
249         ++LastPtr;
250         break;
251       }
252       LastPtr = ThisPtr;
253     }
254     
255     // Write out the chunk...
256     Out.write((char*)ChunkPtr, LastPtr-ChunkPtr);
257   }
258
259   Out.flush();
260 }