blob: 0f75c0351c96f7f33450ac851403d052398c73c4 [file] [log] [blame]
Chris Lattner14999342004-01-10 19:07:06 +00001//===-- Writer.cpp - Library for writing LLVM bytecode files --------------===//
John Criswellb576c942003-10-20 19:43:21 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by the LLVM research group and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
Chris Lattner00950542001-06-06 20:29:01 +00009//
10// This library implements the functionality defined in llvm/Bytecode/Writer.h
11//
Chris Lattner00950542001-06-06 20:29:01 +000012// Note that this file uses an unusual technique of outputting all the bytecode
Chris Lattnerabe83ae2003-09-15 00:33:20 +000013// to a deque of unsigned char, then copies the deque to an ostream. The
Chris Lattner00950542001-06-06 20:29:01 +000014// reason for this is that we must do "seeking" in the stream to do back-
15// patching, and some very important ostreams that we want to support (like
16// pipes) do not support seeking. :( :( :(
17//
Chris Lattnere8fdde12001-09-07 16:39:41 +000018// The choice of the deque data structure is influenced by the extremely fast
19// "append" speed, plus the free "seek"/replace in the middle of the stream. I
20// didn't use a vector because the stream could end up very large and copying
21// the whole thing to reallocate would be kinda silly.
Chris Lattner00950542001-06-06 20:29:01 +000022//
Chris Lattner00950542001-06-06 20:29:01 +000023//===----------------------------------------------------------------------===//
24
25#include "WriterInternals.h"
Chris Lattner635cd932002-07-23 19:56:44 +000026#include "llvm/Bytecode/WriteBytecodePass.h"
Chris Lattner83bb3d22004-01-14 23:36:54 +000027#include "llvm/Constants.h"
28#include "llvm/DerivedTypes.h"
Chris Lattner00950542001-06-06 20:29:01 +000029#include "llvm/Module.h"
Chris Lattner00950542001-06-06 20:29:01 +000030#include "llvm/SymbolTable.h"
Chris Lattnerf60dc882001-11-29 16:32:16 +000031#include "Support/STLExtras.h"
Chris Lattnera92f6962002-10-01 22:38:41 +000032#include "Support/Statistic.h"
Chris Lattner32abce62004-01-10 19:10:01 +000033#include <cstring>
Chris Lattner00950542001-06-06 20:29:01 +000034#include <algorithm>
Chris Lattner44f549b2004-01-10 18:49:43 +000035using namespace llvm;
Brian Gaeked0fde302003-11-11 22:41:34 +000036
Chris Lattner635cd932002-07-23 19:56:44 +000037static RegisterPass<WriteBytecodePass> X("emitbytecode", "Bytecode Writer");
38
Chris Lattnerce6ef112002-07-26 18:40:14 +000039static Statistic<>
Chris Lattnera92f6962002-10-01 22:38:41 +000040BytesWritten("bytecodewriter", "Number of bytecode bytes written");
Chris Lattner635cd932002-07-23 19:56:44 +000041
Chris Lattner697954c2002-01-20 22:54:45 +000042BytecodeWriter::BytecodeWriter(std::deque<unsigned char> &o, const Module *M)
Reid Spencer798ff642004-05-26 07:37:11 +000043 : Out(o), Table(M) {
Chris Lattner00950542001-06-06 20:29:01 +000044
Chris Lattner83bb3d22004-01-14 23:36:54 +000045 // Emit the signature...
46 static const unsigned char *Sig = (const unsigned char*)"llvm";
47 output_data(Sig, Sig+4, Out);
Chris Lattner00950542001-06-06 20:29:01 +000048
49 // Emit the top level CLASS block.
50 BytecodeBlock ModuleBlock(BytecodeFormat::Module, Out);
51
Chris Lattnerd445c6b2003-08-24 13:47:36 +000052 bool isBigEndian = M->getEndianness() == Module::BigEndian;
53 bool hasLongPointers = M->getPointerSize() == Module::Pointer64;
54 bool hasNoEndianness = M->getEndianness() == Module::AnyEndianness;
55 bool hasNoPointerSize = M->getPointerSize() == Module::AnyPointerSize;
Chris Lattner186a1f72003-03-19 20:56:46 +000056
Chris Lattner5fa428f2004-04-05 01:27:26 +000057 // Output the version identifier... we are currently on bytecode version #2,
58 // which corresponds to LLVM v1.3.
Chris Lattner036de032004-06-25 20:52:10 +000059 unsigned Version = (2 << 4) | (unsigned)isBigEndian | (hasLongPointers << 1) |
Chris Lattnerd445c6b2003-08-24 13:47:36 +000060 (hasNoEndianness << 2) | (hasNoPointerSize << 3);
Chris Lattner186a1f72003-03-19 20:56:46 +000061 output_vbr(Version, Out);
Chris Lattner00950542001-06-06 20:29:01 +000062 align32(Out);
63
Chris Lattner186a1f72003-03-19 20:56:46 +000064 {
65 BytecodeBlock CPool(BytecodeFormat::GlobalTypePlane, Out);
66
67 // Write the type plane for types first because earlier planes (e.g. for a
68 // primitive type like float) may have constants constructed using types
69 // coming later (e.g., via getelementptr from a pointer type). The type
70 // plane is needed before types can be fwd or bkwd referenced.
71 const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
72 assert(!Plane.empty() && "No types at all?");
73 unsigned ValNo = Type::FirstDerivedTyID; // Start at the derived types...
74 outputConstantsInPlane(Plane, ValNo); // Write out the types
75 }
Chris Lattner00950542001-06-06 20:29:01 +000076
Chris Lattner186a1f72003-03-19 20:56:46 +000077 // The ModuleInfoBlock follows directly after the type information
Chris Lattnere8fdde12001-09-07 16:39:41 +000078 outputModuleInfoBlock(M);
79
Chris Lattner186a1f72003-03-19 20:56:46 +000080 // Output module level constants, used for global variable initializers
81 outputConstants(false);
82
Chris Lattnerb5794002002-04-07 22:49:37 +000083 // Do the whole module now! Process each function at a time...
Chris Lattner0b12b5f2002-06-25 16:13:21 +000084 for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
Chris Lattner186a1f72003-03-19 20:56:46 +000085 outputFunction(I);
Chris Lattnere8fdde12001-09-07 16:39:41 +000086
87 // If needed, output the symbol table for the module...
Chris Lattner6e6026b2002-11-20 18:36:02 +000088 outputSymbolTable(M->getSymbolTable());
Chris Lattner00950542001-06-06 20:29:01 +000089}
90
Vikram S. Advea7dac3d2002-07-14 23:07:51 +000091// Helper function for outputConstants().
92// Writes out all the constants in the plane Plane starting at entry StartNo.
93//
94void BytecodeWriter::outputConstantsInPlane(const std::vector<const Value*>
95 &Plane, unsigned StartNo) {
96 unsigned ValNo = StartNo;
97
Chris Lattner83bb3d22004-01-14 23:36:54 +000098 // Scan through and ignore function arguments, global values, and constant
99 // strings.
100 for (; ValNo < Plane.size() &&
101 (isa<Argument>(Plane[ValNo]) || isa<GlobalValue>(Plane[ValNo]) ||
102 (isa<ConstantArray>(Plane[ValNo]) &&
103 cast<ConstantArray>(Plane[ValNo])->isString())); ValNo++)
Vikram S. Advea7dac3d2002-07-14 23:07:51 +0000104 /*empty*/;
105
106 unsigned NC = ValNo; // Number of constants
107 for (; NC < Plane.size() &&
108 (isa<Constant>(Plane[NC]) || isa<Type>(Plane[NC])); NC++)
109 /*empty*/;
110 NC -= ValNo; // Convert from index into count
111 if (NC == 0) return; // Skip empty type planes...
112
Chris Lattnerd6942d72004-01-14 16:54:21 +0000113 // FIXME: Most slabs only have 1 or 2 entries! We should encode this much
114 // more compactly.
115
Vikram S. Advea7dac3d2002-07-14 23:07:51 +0000116 // Output type header: [num entries][type id number]
117 //
118 output_vbr(NC, Out);
119
120 // Output the Type ID Number...
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000121 int Slot = Table.getSlot(Plane.front()->getType());
Vikram S. Advea7dac3d2002-07-14 23:07:51 +0000122 assert (Slot != -1 && "Type in constant pool but not in function!!");
123 output_vbr((unsigned)Slot, Out);
124
125 //cerr << "Emitting " << NC << " constants of type '"
126 // << Plane.front()->getType()->getName() << "' = Slot #" << Slot << "\n";
127
128 for (unsigned i = ValNo; i < ValNo+NC; ++i) {
129 const Value *V = Plane[i];
130 if (const Constant *CPV = dyn_cast<Constant>(V)) {
131 //cerr << "Serializing value: <" << V->getType() << ">: " << V << ":"
132 // << Out.size() << "\n";
133 outputConstant(CPV);
134 } else {
Chris Lattner186a1f72003-03-19 20:56:46 +0000135 outputType(cast<Type>(V));
Vikram S. Advea7dac3d2002-07-14 23:07:51 +0000136 }
137 }
138}
139
Chris Lattner80b97342004-01-17 23:25:43 +0000140static inline bool hasNullValue(unsigned TyID) {
141 return TyID != Type::LabelTyID && TyID != Type::TypeTyID &&
142 TyID != Type::VoidTyID;
143}
144
Chris Lattner79df7c02002-03-26 18:01:55 +0000145void BytecodeWriter::outputConstants(bool isFunction) {
Chris Lattner0baa0af2004-01-15 21:06:57 +0000146 BytecodeBlock CPool(BytecodeFormat::ConstantPool, Out,
147 true /* Elide block if empty */);
Chris Lattner00950542001-06-06 20:29:01 +0000148
149 unsigned NumPlanes = Table.getNumPlanes();
Chris Lattnerf69315b2003-05-22 18:35:38 +0000150
151 // Output the type plane before any constants!
152 if (isFunction && NumPlanes > Type::TypeTyID) {
153 const std::vector<const Value*> &Plane = Table.getPlane(Type::TypeTyID);
Chris Lattner186a1f72003-03-19 20:56:46 +0000154 if (!Plane.empty()) { // Skip empty type planes...
Chris Lattnerf69315b2003-05-22 18:35:38 +0000155 unsigned ValNo = Table.getModuleLevel(Type::TypeTyID);
156 outputConstantsInPlane(Plane, ValNo);
Chris Lattner6463e0d2002-10-14 03:34:17 +0000157 }
Chris Lattner00950542001-06-06 20:29:01 +0000158 }
Chris Lattnerf69315b2003-05-22 18:35:38 +0000159
Chris Lattner83bb3d22004-01-14 23:36:54 +0000160 // Output module-level string constants before any other constants.x
161 if (!isFunction)
162 outputConstantStrings();
163
Chris Lattnerf69315b2003-05-22 18:35:38 +0000164 for (unsigned pno = 0; pno != NumPlanes; pno++)
165 if (pno != Type::TypeTyID) { // Type plane handled above.
166 const std::vector<const Value*> &Plane = Table.getPlane(pno);
167 if (!Plane.empty()) { // Skip empty type planes...
168 unsigned ValNo = 0;
Misha Brukman37f92e22003-09-11 22:34:13 +0000169 if (isFunction) // Don't re-emit module constants
Chris Lattnerf69315b2003-05-22 18:35:38 +0000170 ValNo += Table.getModuleLevel(pno);
171
Chris Lattner80b97342004-01-17 23:25:43 +0000172 if (hasNullValue(pno)) {
Chris Lattnerf69315b2003-05-22 18:35:38 +0000173 // Skip zero initializer
174 if (ValNo == 0)
175 ValNo = 1;
176 }
177
178 // Write out constants in the plane
179 outputConstantsInPlane(Plane, ValNo);
180 }
181 }
Chris Lattner00950542001-06-06 20:29:01 +0000182}
183
Chris Lattner6b252422003-10-16 18:28:50 +0000184static unsigned getEncodedLinkage(const GlobalValue *GV) {
185 switch (GV->getLinkage()) {
186 default: assert(0 && "Invalid linkage!");
187 case GlobalValue::ExternalLinkage: return 0;
Chris Lattner6b252422003-10-16 18:28:50 +0000188 case GlobalValue::WeakLinkage: return 1;
189 case GlobalValue::AppendingLinkage: return 2;
190 case GlobalValue::InternalLinkage: return 3;
Chris Lattner22482a12003-10-18 06:30:21 +0000191 case GlobalValue::LinkOnceLinkage: return 4;
Chris Lattner6b252422003-10-16 18:28:50 +0000192 }
193}
194
Chris Lattner00950542001-06-06 20:29:01 +0000195void BytecodeWriter::outputModuleInfoBlock(const Module *M) {
196 BytecodeBlock ModuleInfoBlock(BytecodeFormat::ModuleGlobalInfo, Out);
197
Chris Lattner70cc3392001-09-10 07:58:01 +0000198 // Output the types for the global variables in the module...
199 for (Module::const_giterator I = M->gbegin(), End = M->gend(); I != End;++I) {
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000200 int Slot = Table.getSlot(I->getType());
Chris Lattner70cc3392001-09-10 07:58:01 +0000201 assert(Slot != -1 && "Module global vars is broken!");
Chris Lattnerd70684f2001-09-18 04:01:05 +0000202
Chris Lattner22482a12003-10-18 06:30:21 +0000203 // Fields: bit0 = isConstant, bit1 = hasInitializer, bit2-4=Linkage,
204 // bit5+ = Slot # for type
205 unsigned oSlot = ((unsigned)Slot << 5) | (getEncodedLinkage(I) << 2) |
Chris Lattner036de032004-06-25 20:52:10 +0000206 (I->hasInitializer() << 1) | (unsigned)I->isConstant();
Chris Lattnerd70684f2001-09-18 04:01:05 +0000207 output_vbr(oSlot, Out);
208
Chris Lattner1b98c5c2001-10-13 06:48:38 +0000209 // If we have an initializer, output it now.
Chris Lattner0b12b5f2002-06-25 16:13:21 +0000210 if (I->hasInitializer()) {
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000211 Slot = Table.getSlot((Value*)I->getInitializer());
Chris Lattnerd70684f2001-09-18 04:01:05 +0000212 assert(Slot != -1 && "No slot for global var initializer!");
213 output_vbr((unsigned)Slot, Out);
214 }
Chris Lattner70cc3392001-09-10 07:58:01 +0000215 }
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000216 output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);
Chris Lattner70cc3392001-09-10 07:58:01 +0000217
Chris Lattnerb5794002002-04-07 22:49:37 +0000218 // Output the types of the functions in this module...
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000219 for (Module::const_iterator I = M->begin(), End = M->end(); I != End; ++I) {
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000220 int Slot = Table.getSlot(I->getType());
Chris Lattner00950542001-06-06 20:29:01 +0000221 assert(Slot != -1 && "Module const pool is broken!");
222 assert(Slot >= Type::FirstDerivedTyID && "Derived type not in range!");
223 output_vbr((unsigned)Slot, Out);
Chris Lattner00950542001-06-06 20:29:01 +0000224 }
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000225 output_vbr((unsigned)Table.getSlot(Type::VoidTy), Out);
Chris Lattner00950542001-06-06 20:29:01 +0000226}
227
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000228void BytecodeWriter::outputInstructions(const Function *F) {
229 BytecodeBlock ILBlock(BytecodeFormat::InstructionList, Out);
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000230 for (Function::const_iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
231 for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I)
232 outputInstruction(*I);
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000233}
234
Chris Lattner186a1f72003-03-19 20:56:46 +0000235void BytecodeWriter::outputFunction(const Function *F) {
Chris Lattnerc9aa7df2002-03-29 03:51:11 +0000236 BytecodeBlock FunctionBlock(BytecodeFormat::Function, Out);
Chris Lattner6b252422003-10-16 18:28:50 +0000237 output_vbr(getEncodedLinkage(F), Out);
Chris Lattnerd23b1d32001-11-26 18:56:10 +0000238
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000239 // If this is an external function, there is nothing else to emit!
240 if (F->isExternal()) return;
Chris Lattner00950542001-06-06 20:29:01 +0000241
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000242 // Get slot information about the function...
243 Table.incorporateFunction(F);
244
245 if (Table.getCompactionTable().empty()) {
246 // Output information about the constants in the function if the compaction
247 // table is not being used.
Chris Lattnere8fdde12001-09-07 16:39:41 +0000248 outputConstants(true);
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000249 } else {
250 // Otherwise, emit the compaction table.
251 outputCompactionTable();
Chris Lattnere8fdde12001-09-07 16:39:41 +0000252 }
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000253
254 // Output all of the instructions in the body of the function
255 outputInstructions(F);
256
257 // If needed, output the symbol table for the function...
258 outputSymbolTable(F->getSymbolTable());
259
260 Table.purgeFunction();
261}
262
263void BytecodeWriter::outputCompactionTablePlane(unsigned PlaneNo,
264 const std::vector<const Value*> &Plane,
265 unsigned StartNo) {
266 unsigned End = Table.getModuleLevel(PlaneNo);
Chris Lattner52f86d62004-01-20 00:54:06 +0000267 if (Plane.empty() || StartNo == End || End == 0) return; // Nothing to emit
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000268 assert(StartNo < End && "Cannot emit negative range!");
269 assert(StartNo < Plane.size() && End <= Plane.size());
270
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000271 // Do not emit the null initializer!
272 if (PlaneNo != Type::TypeTyID) ++StartNo;
273
Chris Lattner24102432004-01-18 22:35:34 +0000274 // Figure out which encoding to use. By far the most common case we have is
275 // to emit 0-2 entries in a compaction table plane.
276 switch (End-StartNo) {
277 case 0: // Avoid emitting two vbr's if possible.
278 case 1:
279 case 2:
280 output_vbr((PlaneNo << 2) | End-StartNo, Out);
281 break;
282 default:
283 // Output the number of things.
284 output_vbr((unsigned(End-StartNo) << 2) | 3, Out);
285 output_vbr(PlaneNo, Out); // Emit the type plane this is
286 break;
287 }
288
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000289 for (unsigned i = StartNo; i != End; ++i)
290 output_vbr(Table.getGlobalSlot(Plane[i]), Out);
291}
292
293void BytecodeWriter::outputCompactionTable() {
Chris Lattnercf3e67f2004-01-18 21:08:52 +0000294 BytecodeBlock CTB(BytecodeFormat::CompactionTable, Out, true/*ElideIfEmpty*/);
295 const std::vector<std::vector<const Value*> > &CT =Table.getCompactionTable();
296
297 // First thing is first, emit the type compaction table if there is one.
298 if (CT.size() > Type::TypeTyID)
299 outputCompactionTablePlane(Type::TypeTyID, CT[Type::TypeTyID],
300 Type::FirstDerivedTyID);
301
302 for (unsigned i = 0, e = CT.size(); i != e; ++i)
303 if (i != Type::TypeTyID)
304 outputCompactionTablePlane(i, CT[i], 0);
Chris Lattner00950542001-06-06 20:29:01 +0000305}
306
Chris Lattner00950542001-06-06 20:29:01 +0000307void BytecodeWriter::outputSymbolTable(const SymbolTable &MST) {
Chris Lattner737d3cd2004-01-10 19:56:59 +0000308 // Do not output the Bytecode block for an empty symbol table, it just wastes
309 // space!
Reid Spencer6ed81e22004-05-27 20:18:51 +0000310 if ( MST.isEmpty() ) return;
Chris Lattner737d3cd2004-01-10 19:56:59 +0000311
Chris Lattner0baa0af2004-01-15 21:06:57 +0000312 BytecodeBlock SymTabBlock(BytecodeFormat::SymbolTable, Out,
313 true/* ElideIfEmpty*/);
Chris Lattner00950542001-06-06 20:29:01 +0000314
Reid Spencer94f2df22004-05-25 17:29:59 +0000315 //Symtab block header: [num entries][type id number]
316 output_vbr(MST.num_types(), Out);
317 output_vbr((unsigned)Table.getSlot(Type::TypeTy), Out);
318 for (SymbolTable::type_const_iterator TI = MST.type_begin(),
319 TE = MST.type_end(); TI != TE; ++TI ) {
320 //Symtab entry:[def slot #][name]
321 output_vbr((unsigned)Table.getSlot(TI->second), Out);
322 output(TI->first, Out, /*align=*/false);
323 }
324
325 // Now do each of the type planes in order.
326 for (SymbolTable::plane_const_iterator PI = MST.plane_begin(),
327 PE = MST.plane_end(); PI != PE; ++PI) {
328 SymbolTable::value_const_iterator I = MST.value_begin(PI->first);
329 SymbolTable::value_const_iterator End = MST.value_end(PI->first);
Chris Lattner00950542001-06-06 20:29:01 +0000330 int Slot;
331
332 if (I == End) continue; // Don't mess with an absent type...
333
334 // Symtab block header: [num entries][type id number]
Reid Spencer94f2df22004-05-25 17:29:59 +0000335 output_vbr(MST.type_size(PI->first), Out);
Chris Lattner00950542001-06-06 20:29:01 +0000336
Reid Spencer94f2df22004-05-25 17:29:59 +0000337 Slot = Table.getSlot(PI->first);
Chris Lattner00950542001-06-06 20:29:01 +0000338 assert(Slot != -1 && "Type in symtab, but not in table!");
339 output_vbr((unsigned)Slot, Out);
340
Chris Lattner7fc9fe32001-06-27 23:41:11 +0000341 for (; I != End; ++I) {
Chris Lattner00950542001-06-06 20:29:01 +0000342 // Symtab entry: [def slot #][name]
Alkis Evlogimenos60596382003-10-17 02:02:40 +0000343 Slot = Table.getSlot(I->second);
Chris Lattnere8fdde12001-09-07 16:39:41 +0000344 assert(Slot != -1 && "Value in symtab but has no slot number!!");
Chris Lattner00950542001-06-06 20:29:01 +0000345 output_vbr((unsigned)Slot, Out);
346 output(I->first, Out, false); // Don't force alignment...
347 }
348 }
349}
350
Chris Lattner44f549b2004-01-10 18:49:43 +0000351void llvm::WriteBytecodeToFile(const Module *C, std::ostream &Out) {
Chris Lattnere8fdde12001-09-07 16:39:41 +0000352 assert(C && "You can't write a null module!!");
Chris Lattner00950542001-06-06 20:29:01 +0000353
Chris Lattner697954c2002-01-20 22:54:45 +0000354 std::deque<unsigned char> Buffer;
Chris Lattner00950542001-06-06 20:29:01 +0000355
356 // This object populates buffer for us...
357 BytecodeWriter BCW(Buffer, C);
358
Chris Lattnerce6ef112002-07-26 18:40:14 +0000359 // Keep track of how much we've written...
360 BytesWritten += Buffer.size();
361
Chris Lattnere8fdde12001-09-07 16:39:41 +0000362 // Okay, write the deque out to the ostream now... the deque is not
363 // sequential in memory, however, so write out as much as possible in big
364 // chunks, until we're done.
365 //
Chris Lattner036de032004-06-25 20:52:10 +0000366
Chris Lattner697954c2002-01-20 22:54:45 +0000367 std::deque<unsigned char>::const_iterator I = Buffer.begin(),E = Buffer.end();
Chris Lattnere8fdde12001-09-07 16:39:41 +0000368 while (I != E) { // Loop until it's all written
369 // Scan to see how big this chunk is...
370 const unsigned char *ChunkPtr = &*I;
371 const unsigned char *LastPtr = ChunkPtr;
372 while (I != E) {
373 const unsigned char *ThisPtr = &*++I;
Chris Lattner036de032004-06-25 20:52:10 +0000374 if (++LastPtr != ThisPtr) // Advanced by more than a byte of memory?
Chris Lattner5cb17412001-11-04 21:32:41 +0000375 break;
Chris Lattnere8fdde12001-09-07 16:39:41 +0000376 }
377
378 // Write out the chunk...
Chris Lattnerd6162282004-06-25 00:35:55 +0000379 Out.write((char*)ChunkPtr, unsigned(LastPtr-ChunkPtr));
Chris Lattnere8fdde12001-09-07 16:39:41 +0000380 }
Chris Lattner00950542001-06-06 20:29:01 +0000381 Out.flush();
382}