blob: 423514582293fe29fa65171422e4a522d0db8c68 [file] [log] [blame]
Chris Lattner2f7c9632001-06-06 20:29:01 +00001//===-- Writer.cpp - Library for writing VM bytecode files -------*- C++ -*--=//
2//
3// This library implements the functionality defined in llvm/Bytecode/Writer.h
4//
5// This library uses the Analysis library to figure out offsets for
6// variables in the method tables...
7//
8// Note that this file uses an unusual technique of outputting all the bytecode
Chris Lattnerb97ef9f2001-09-07 16:39:41 +00009// to a deque of unsigned char's, then copies the deque to an ostream. The
Chris Lattner2f7c9632001-06-06 20:29:01 +000010// reason for this is that we must do "seeking" in the stream to do back-
11// patching, and some very important ostreams that we want to support (like
12// pipes) do not support seeking. :( :( :(
13//
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000014// The choice of the deque data structure is influenced by the extremely fast
15// "append" speed, plus the free "seek"/replace in the middle of the stream. I
16// didn't use a vector because the stream could end up very large and copying
17// the whole thing to reallocate would be kinda silly.
Chris Lattner2f7c9632001-06-06 20:29:01 +000018//
19// Note that the performance of this library is not terribly important, because
20// it shouldn't be used by JIT type applications... so it is not a huge focus
21// at least. :)
22//
23//===----------------------------------------------------------------------===//
24
25#include "WriterInternals.h"
26#include "llvm/Module.h"
27#include "llvm/Method.h"
28#include "llvm/BasicBlock.h"
29#include "llvm/ConstPoolVals.h"
30#include "llvm/SymbolTable.h"
31#include "llvm/DerivedTypes.h"
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000032#include "llvm/Support/STLExtras.h"
Chris Lattner2f7c9632001-06-06 20:29:01 +000033#include <string.h>
34#include <algorithm>
35
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000036BytecodeWriter::BytecodeWriter(deque<unsigned char> &o, const Module *M)
Chris Lattner2f7c9632001-06-06 20:29:01 +000037 : Out(o), Table(M, false) {
38
39 outputSignature();
40
41 // Emit the top level CLASS block.
42 BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out);
43
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000044 // Output the ID of first "derived" type:
Chris Lattner2f7c9632001-06-06 20:29:01 +000045 output_vbr((unsigned)Type::FirstDerivedTyID, Out);
46 align32(Out);
47
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000048 // Output module level constants, including types used by the method protos
49 outputConstants(false);
Chris Lattner2f7c9632001-06-06 20:29:01 +000050
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000051 // The ModuleInfoBlock follows directly after the Module constant pool
52 outputModuleInfoBlock(M);
53
54 // Do the whole module now! Process each method at a time...
55 for_each(M->begin(), M->end(),
56 bind_obj(this, &BytecodeWriter::processMethod));
57
58 // If needed, output the symbol table for the module...
Chris Lattner2f7c9632001-06-06 20:29:01 +000059 if (M->hasSymbolTable())
60 outputSymbolTable(*M->getSymbolTable());
61}
62
63// TODO: REMOVE
64#include "llvm/Assembly/Writer.h"
65
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000066void BytecodeWriter::outputConstants(bool isMethod) {
67 BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out);
Chris Lattner2f7c9632001-06-06 20:29:01 +000068
69 unsigned NumPlanes = Table.getNumPlanes();
Chris Lattner2f7c9632001-06-06 20:29:01 +000070 for (unsigned pno = 0; pno < NumPlanes; pno++) {
71 const vector<const Value*> &Plane = Table.getPlane(pno);
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000072 if (Plane.empty()) continue; // Skip empty type planes...
Chris Lattner2f7c9632001-06-06 20:29:01 +000073
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000074 unsigned ValNo = 0;
75 if (isMethod) // Don't reemit module constants
76 ValNo = Table.getModuleLevel(pno);
77 else if (pno == Type::TypeTyID)
78 ValNo = Type::FirstDerivedTyID; // Start emitting at the derived types...
Chris Lattner2f7c9632001-06-06 20:29:01 +000079
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000080 // Scan through and ignore method arguments...
81 for (; ValNo < Plane.size() && Plane[ValNo]->isMethodArgument(); ValNo++)
82 /*empty*/;
Chris Lattner2f7c9632001-06-06 20:29:01 +000083
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000084 unsigned NC = ValNo; // Number of constants
85 for (; NC < Plane.size() &&
86 (Plane[NC]->isConstant() || Plane[NC]->isType()); NC++) /*empty*/;
87 NC -= ValNo; // Convert from index into count
88 if (NC == 0) continue; // Skip empty type planes...
Chris Lattner2f7c9632001-06-06 20:29:01 +000089
90 // Output type header: [num entries][type id number]
91 //
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000092 output_vbr(NC, Out);
Chris Lattner2f7c9632001-06-06 20:29:01 +000093
94 // Output the Type ID Number...
95 int Slot = Table.getValSlot(Plane.front()->getType());
96 assert (Slot != -1 && "Type in constant pool but not in method!!");
97 output_vbr((unsigned)Slot, Out);
98
Chris Lattnerb97ef9f2001-09-07 16:39:41 +000099 //cout << "Emitting " << NC << " constants of type '"
100 // << Plane.front()->getType()->getName() << "' = Slot #" << Slot << endl;
Chris Lattner2f7c9632001-06-06 20:29:01 +0000101
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000102 for (unsigned i = ValNo; i < ValNo+NC; ++i) {
103 const Value *V = Plane[i];
Chris Lattner4cee8d82001-06-27 23:41:11 +0000104 if (const ConstPoolVal *CPV = V->castConstant()) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000105 //cerr << "Serializing value: <" << V->getType() << ">: "
106 // << ((const ConstPoolVal*)V)->getStrValue() << ":"
107 // << Out.size() << "\n";
Chris Lattner4cee8d82001-06-27 23:41:11 +0000108 outputConstant(CPV);
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000109 } else {
110 const Type *Ty = V->castTypeAsserting();
111 outputType(Ty);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000112 }
113 }
114 }
Chris Lattner2f7c9632001-06-06 20:29:01 +0000115}
116
117void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
118 BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);
119
120 // Output the types of the methods in this class
Chris Lattner4cee8d82001-06-27 23:41:11 +0000121 for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000122 int Slot = Table.getValSlot((*I)->getType());
123 assert(Slot != -1 && "Module const pool is broken!");
124 assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
125 output_vbr((unsigned)Slot, Out);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000126 }
127 output_vbr((unsigned)Table.getValSlot(Type::VoidTy), Out);
128 align32(Out);
129}
130
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000131void BytecodeWriter::processMethod(const Method *M) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000132 BytecodeBlock MethodBlock(BytecodeFormat::Method, Out);
133
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000134 // Only output the constant pool and other goodies if needed...
135 if (!M->isExternal()) {
136 // Get slot information about the method...
137 Table.incorporateMethod(M);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000138
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000139 // Output information about the constants in the method...
140 outputConstants(true);
Chris Lattner2f7c9632001-06-06 20:29:01 +0000141
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000142 // Output basic block nodes...
143 for_each(M->begin(), M->end(),
144 bind_obj(this, &BytecodeWriter::processBasicBlock));
145
146 // If needed, output the symbol table for the method...
147 if (M->hasSymbolTable())
148 outputSymbolTable(*M->getSymbolTable());
149
150 Table.purgeMethod();
151 }
Chris Lattner2f7c9632001-06-06 20:29:01 +0000152}
153
154
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000155void BytecodeWriter::processBasicBlock(const BasicBlock *BB) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000156 BytecodeBlock MethodBlock(BytecodeFormat::BasicBlock, Out);
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000157 // Process all the instructions in the bb...
158 for_each(BB->begin(), BB->end(),
159 bind_obj(this, &BytecodeWriter::processInstruction));
Chris Lattner2f7c9632001-06-06 20:29:01 +0000160}
161
162void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
163 BytecodeBlock MethodBlock(BytecodeFormat::SymbolTable, Out);
164
Chris Lattner4cee8d82001-06-27 23:41:11 +0000165 for (SymbolTable::const_iterator TI = MST.begin(); TI != MST.end(); ++TI) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000166 SymbolTable::type_const_iterator I = MST.type_begin(TI->first);
167 SymbolTable::type_const_iterator End = MST.type_end(TI->first);
168 int Slot;
169
170 if (I == End) continue; // Don't mess with an absent type...
171
172 // Symtab block header: [num entries][type id number]
173 output_vbr(MST.type_size(TI->first), Out);
174
175 Slot = Table.getValSlot(TI->first);
176 assert(Slot != -1 && "Type in symtab, but not in table!");
177 output_vbr((unsigned)Slot, Out);
178
Chris Lattner4cee8d82001-06-27 23:41:11 +0000179 for (; I != End; ++I) {
Chris Lattner2f7c9632001-06-06 20:29:01 +0000180 // Symtab entry: [def slot #][name]
181 Slot = Table.getValSlot(I->second);
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000182 assert(Slot != -1 && "Value in symtab but has no slot number!!");
Chris Lattner2f7c9632001-06-06 20:29:01 +0000183 output_vbr((unsigned)Slot, Out);
184 output(I->first, Out, false); // Don't force alignment...
185 }
186 }
187}
188
189void WriteBytecodeToFile(const Module *C, ostream &Out) {
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000190 assert(C && "You can't write a null module!!");
Chris Lattner2f7c9632001-06-06 20:29:01 +0000191
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000192 deque<unsigned char> Buffer;
Chris Lattner2f7c9632001-06-06 20:29:01 +0000193
194 // This object populates buffer for us...
195 BytecodeWriter BCW(Buffer, C);
196
Chris Lattnerb97ef9f2001-09-07 16:39:41 +0000197 // Okay, write the deque out to the ostream now... the deque is not
198 // sequential in memory, however, so write out as much as possible in big
199 // chunks, until we're done.
200 //
201 deque<unsigned char>::const_iterator I = Buffer.begin(), E = Buffer.end();
202 while (I != E) { // Loop until it's all written
203 // Scan to see how big this chunk is...
204 const unsigned char *ChunkPtr = &*I;
205 const unsigned char *LastPtr = ChunkPtr;
206 while (I != E) {
207 const unsigned char *ThisPtr = &*++I;
208 if (LastPtr+1 != ThisPtr) break;// Advanced by more than a byte of memory?
209 LastPtr = ThisPtr;
210 }
211
212 // Write out the chunk...
213 Out.write(ChunkPtr, LastPtr-ChunkPtr+(I != E));
214 }
215
Chris Lattner2f7c9632001-06-06 20:29:01 +0000216 Out.flush();
217}