Bytecode Analyzer Cleanup:
[oota-llvm.git] / lib / Bytecode / Reader / Analyzer.cpp
1 //===-- Analyzer.cpp - Analysis and Dumping of Bytecode 000000---*- C++ -*-===//
2 // 
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file was developed by Reid Spencer and is distributed under the 
6 // University of Illinois Open Source License. See LICENSE.TXT for details.
7 // 
8 //===----------------------------------------------------------------------===//
9 //
10 //  This file implements the AnalyzerHandler class and PrintBytecodeAnalysis
11 //  function which together comprise the basic functionality of the llmv-abcd
12 //  tool. The AnalyzerHandler collects information about the bytecode file into
13 //  the BytecodeAnalysis structure. The PrintBytecodeAnalysis function prints
14 //  out the content of that structure.
15 //  @see include/llvm/Bytecode/Analysis.h
16 //
17 //===----------------------------------------------------------------------===//
18
19 #include "Reader.h"
20 #include "llvm/Constants.h"
21 #include "llvm/DerivedTypes.h"
22 #include "llvm/Module.h"
23 #include "llvm/Analysis/Verifier.h"
24 #include "llvm/Bytecode/BytecodeHandler.h"
25 #include "llvm/Assembly/Writer.h"
26 #include <iomanip>
27 #include <sstream>
28
29 using namespace llvm;
30
31 namespace {
32
33 /// @brief Bytecode reading handler for analyzing bytecode.
34 class AnalyzerHandler : public BytecodeHandler {
35   BytecodeAnalysis& bca;     ///< The structure in which data is recorded
36   std::ostream* os;        ///< A convenience for osing data.
37   /// @brief Keeps track of current function
38   BytecodeAnalysis::BytecodeFunctionInfo* currFunc; 
39   Module* M; ///< Keeps track of current module
40
41 /// @name Constructor
42 /// @{
43 public:
44   /// The only way to construct an AnalyzerHandler. All that is needed is a
45   /// reference to the BytecodeAnalysis structure where the output will be
46   /// placed.
47   AnalyzerHandler(BytecodeAnalysis& TheBca, std::ostream* output) 
48     : bca(TheBca) 
49     , os(output)
50     , currFunc(0)
51     { }
52
53 /// @}
54 /// @name BytecodeHandler Implementations
55 /// @{
56 public:
57   virtual void handleError(const std::string& str ) { 
58     if (os)
59       *os << "ERROR: " << str << "\n";
60   }
61
62   virtual void handleStart( Module* Mod, unsigned theSize ) {
63     M = Mod;
64     if (os)
65       *os << "Bytecode {\n";
66     bca.byteSize = theSize;
67     bca.ModuleId.clear();
68     bca.numBlocks = 0;
69     bca.numTypes = 0;
70     bca.numValues = 0;
71     bca.numFunctions = 0;
72     bca.numConstants = 0;
73     bca.numGlobalVars = 0;
74     bca.numInstructions = 0;
75     bca.numBasicBlocks = 0;
76     bca.numOperands = 0;
77     bca.numCmpctnTables = 0;
78     bca.numSymTab = 0;
79     bca.numLibraries = 0;
80     bca.libSize = 0;
81     bca.maxTypeSlot = 0;
82     bca.maxValueSlot = 0;
83     bca.numAlignment = 0;
84     bca.fileDensity = 0.0;
85     bca.globalsDensity = 0.0;
86     bca.functionDensity = 0.0;
87     bca.instructionSize = 0;
88     bca.longInstructions = 0;
89     bca.vbrCount32 = 0;
90     bca.vbrCount64 = 0;
91     bca.vbrCompBytes = 0;
92     bca.vbrExpdBytes = 0;
93     bca.FunctionInfo.clear();
94     bca.BlockSizes[BytecodeFormat::Reserved_DoNotUse] = 0;
95     bca.BlockSizes[BytecodeFormat::ModuleBlockID] = theSize;
96     bca.BlockSizes[BytecodeFormat::FunctionBlockID] = 0;
97     bca.BlockSizes[BytecodeFormat::ConstantPoolBlockID] = 0;
98     bca.BlockSizes[BytecodeFormat::SymbolTableBlockID] = 0;
99     bca.BlockSizes[BytecodeFormat::ModuleGlobalInfoBlockID] = 0;
100     bca.BlockSizes[BytecodeFormat::GlobalTypePlaneBlockID] = 0;
101     bca.BlockSizes[BytecodeFormat::InstructionListBlockID] = 0;
102     bca.BlockSizes[BytecodeFormat::CompactionTableBlockID] = 0;
103   }
104
105   virtual void handleFinish() {
106     if (os)
107       *os << "} End Bytecode\n"; 
108
109     bca.fileDensity = double(bca.byteSize) / double( bca.numTypes + bca.numValues );
110     double globalSize = 0.0;
111     globalSize += double(bca.BlockSizes[BytecodeFormat::ConstantPoolBlockID]);
112     globalSize += double(bca.BlockSizes[BytecodeFormat::ModuleGlobalInfoBlockID]);
113     globalSize += double(bca.BlockSizes[BytecodeFormat::GlobalTypePlaneBlockID]);
114     bca.globalsDensity = globalSize / double( bca.numTypes + bca.numConstants + 
115       bca.numGlobalVars );
116     bca.functionDensity = double(bca.BlockSizes[BytecodeFormat::FunctionBlockID]) / 
117       double(bca.numFunctions);
118
119     if ( bca.progressiveVerify ) {
120       try {
121         verifyModule(*M, ThrowExceptionAction);
122       } catch ( std::string& msg ) {
123         bca.VerifyInfo += "Verify@Finish: " + msg + "\n";
124       }
125     }
126   }
127
128   virtual void handleModuleBegin(const std::string& id) {
129     if (os)
130       *os << "  Module " << id << " {\n";
131     bca.ModuleId = id;
132   }
133
134   virtual void handleModuleEnd(const std::string& id) { 
135     if (os)
136       *os << "  } End Module " << id << "\n";
137     if ( bca.progressiveVerify ) {
138       try {
139         verifyModule(*M, ThrowExceptionAction);
140       } catch ( std::string& msg ) {
141         bca.VerifyInfo += "Verify@EndModule: " + msg + "\n";
142       }
143     }
144   }
145
146   virtual void handleVersionInfo(
147     unsigned char RevisionNum,        ///< Byte code revision number
148     Module::Endianness Endianness,    ///< Endianness indicator
149     Module::PointerSize PointerSize   ///< PointerSize indicator
150   ) { 
151     if (os)
152       *os << "    RevisionNum: " << int(RevisionNum) 
153          << " Endianness: " << Endianness
154          << " PointerSize: " << PointerSize << "\n";
155     bca.version = RevisionNum;
156   }
157
158   virtual void handleModuleGlobalsBegin() { 
159     if (os)
160       *os << "    BLOCK: ModuleGlobalInfo {\n";
161   }
162
163   virtual void handleGlobalVariable( 
164     const Type* ElemType,     
165     bool isConstant,          
166     GlobalValue::LinkageTypes Linkage,
167     unsigned SlotNum,
168     unsigned initSlot
169   ) {
170     if (os) {
171       *os << "      GV: "
172           << ( initSlot == 0 ? "Uni" : "I" ) << "nitialized, "
173           << ( isConstant? "Constant, " : "Variable, ")
174           << " Linkage=" << Linkage << " Type=";
175       WriteTypeSymbolic(*os, ElemType, M);
176       *os << " Slot=" << SlotNum << " InitSlot=" << initSlot 
177           << "\n";
178     }
179
180     bca.numGlobalVars++;
181     bca.numValues++;
182     if (SlotNum > bca.maxValueSlot)
183       bca.maxValueSlot = SlotNum;
184     if (initSlot > bca.maxValueSlot)
185       bca.maxValueSlot = initSlot;
186
187   }
188
189   virtual void handleTypeList(unsigned numEntries) {
190     bca.maxTypeSlot = numEntries - 1;
191   }
192
193   virtual void handleType( const Type* Ty ) { 
194     bca.numTypes++; 
195     if (os) {
196       *os << "      Type: ";
197       WriteTypeSymbolic(*os,Ty,M);
198       *os << "\n";
199     }
200   }
201
202   virtual void handleFunctionDeclaration( 
203     Function* Func            ///< The function
204   ) {
205     bca.numFunctions++;
206     bca.numValues++;
207     if (os) {
208       *os << "      Function Decl: ";
209       WriteTypeSymbolic(*os,Func->getType(),M);
210       *os << "\n";
211     }
212   }
213
214   virtual void handleGlobalInitializer(GlobalVariable* GV, Constant* CV) {
215     if (os) {
216       *os << "    Initializer: GV=";
217       GV->print(*os);
218       *os << "      CV=";
219       CV->print(*os);
220       *os << "\n";
221     }
222   }
223
224   virtual void handleDependentLibrary(const std::string& libName) {
225     bca.numLibraries++;
226     bca.libSize += libName.size() + (libName.size() < 128 ? 1 : 2);
227   }
228
229   virtual void handleModuleGlobalsEnd() { 
230     if (os)
231       *os << "    } END BLOCK: ModuleGlobalInfo\n";
232     if ( bca.progressiveVerify ) {
233       try {
234         verifyModule(*M, ThrowExceptionAction);
235       } catch ( std::string& msg ) {
236         bca.VerifyInfo += "Verify@EndModuleGlobalInfo: " + msg + "\n";
237       }
238     }
239   }
240
241   virtual void handleCompactionTableBegin() { 
242     if (os)
243       *os << "      BLOCK: CompactionTable {\n";
244   }
245
246   virtual void handleCompactionTablePlane( unsigned Ty, unsigned NumEntries) {
247     bca.numCmpctnTables++;
248     if (os)
249       *os << "        Plane: Ty=" << Ty << " Size=" << NumEntries << "\n";
250   }
251
252   virtual void handleCompactionTableType( unsigned i, unsigned TypSlot, 
253       const Type* Ty ) {
254     if (os) {
255       *os << "          Type: " << i << " Slot:" << TypSlot << " is ";
256       WriteTypeSymbolic(*os,Ty,M);
257       *os << "\n"; 
258     }
259   }
260
261   virtual void handleCompactionTableValue(unsigned i, unsigned TypSlot,
262                                           unsigned ValSlot) { 
263     if (os)
264       *os << "          Value: " << i << " TypSlot: " << TypSlot 
265          << " ValSlot:" << ValSlot << "\n";
266     if (ValSlot > bca.maxValueSlot)
267       bca.maxValueSlot = ValSlot;
268   }
269
270   virtual void handleCompactionTableEnd() { 
271     if (os)
272       *os << "      } END BLOCK: CompactionTable\n";
273   }
274
275   virtual void handleSymbolTableBegin(Function* CF, SymbolTable* ST) { 
276     bca.numSymTab++; 
277     if (os)
278       *os << "    BLOCK: SymbolTable {\n";
279   }
280
281   virtual void handleSymbolTablePlane(unsigned Ty, unsigned NumEntries, 
282     const Type* Typ) { 
283     if (os) {
284       *os << "      Plane: Ty=" << Ty << " Size=" << NumEntries << " Type: ";
285       WriteTypeSymbolic(*os,Typ,M);
286       *os << "\n"; 
287     }
288   }
289
290   virtual void handleSymbolTableType(unsigned i, unsigned TypSlot, 
291     const std::string& name ) { 
292     if (os)
293       *os << "        Type " << i << " Slot=" << TypSlot
294          << " Name: " << name << "\n"; 
295   }
296
297   virtual void handleSymbolTableValue(unsigned i, unsigned ValSlot, 
298     const std::string& name ) { 
299     if (os)
300       *os << "        Value " << i << " Slot=" << ValSlot
301          << " Name: " << name << "\n";
302     if (ValSlot > bca.maxValueSlot)
303       bca.maxValueSlot = ValSlot;
304   }
305
306   virtual void handleSymbolTableEnd() { 
307     if (os)
308       *os << "    } END BLOCK: SymbolTable\n";
309   }
310
311   virtual void handleFunctionBegin(Function* Func, unsigned Size) {
312     if (os) {
313       *os << "    BLOCK: Function {\n"
314           << "      Linkage: " << Func->getLinkage() << "\n"
315           << "      Type: "; 
316       WriteTypeSymbolic(*os,Func->getType(),M);
317       *os << "\n";
318     }
319
320     currFunc = &bca.FunctionInfo[Func];
321     std::ostringstream tmp;
322     WriteTypeSymbolic(tmp,Func->getType(),M);
323     currFunc->description = tmp.str();
324     currFunc->name = Func->getName();
325     currFunc->byteSize = Size;
326     currFunc->numInstructions = 0;
327     currFunc->numBasicBlocks = 0;
328     currFunc->numPhis = 0;
329     currFunc->numOperands = 0;
330     currFunc->density = 0.0;
331     currFunc->instructionSize = 0;
332     currFunc->longInstructions = 0;
333     currFunc->vbrCount32 = 0;
334     currFunc->vbrCount64 = 0;
335     currFunc->vbrCompBytes = 0;
336     currFunc->vbrExpdBytes = 0;
337
338   }
339
340   virtual void handleFunctionEnd( Function* Func) {
341     if (os)
342       *os << "    } END BLOCK: Function\n";
343     currFunc->density = double(currFunc->byteSize) /
344       double(currFunc->numInstructions+currFunc->numBasicBlocks);
345
346     if ( bca.progressiveVerify ) {
347       try {
348         verifyModule(*M, ThrowExceptionAction);
349       } catch ( std::string& msg ) {
350         bca.VerifyInfo += "Verify@EndFunction: " + msg + "\n";
351       }
352     }
353   }
354
355   virtual void handleBasicBlockBegin( unsigned blocknum) {
356     if (os)
357       *os << "      BLOCK: BasicBlock #" << blocknum << "{\n";
358     bca.numBasicBlocks++;
359     bca.numValues++;
360     if ( currFunc ) currFunc->numBasicBlocks++;
361   }
362
363   virtual bool handleInstruction( unsigned Opcode, const Type* iType, 
364                                 std::vector<unsigned>& Operands, unsigned Size){
365     if (os) {
366       *os << "        INST: OpCode=" 
367          << Instruction::getOpcodeName(Opcode) << " Type=\"";
368       WriteTypeSymbolic(*os,iType,M);
369       *os << "\"";
370       for ( unsigned i = 0; i < Operands.size(); ++i ) 
371         *os << " Op(" << i << ")=Slot(" << Operands[i] << ")";
372       *os << "\n";
373     }
374
375     bca.numInstructions++;
376     bca.numValues++;
377     bca.instructionSize += Size;
378     if (Size > 4 ) bca.longInstructions++;
379     bca.numOperands += Operands.size();
380     for (unsigned i = 0; i < Operands.size(); ++i )
381       if (Operands[i] > bca.maxValueSlot)
382         bca.maxValueSlot = Operands[i];
383     if ( currFunc ) {
384       currFunc->numInstructions++;
385       currFunc->instructionSize += Size;
386       if (Size > 4 ) currFunc->longInstructions++;
387       if ( Opcode == Instruction::PHI ) currFunc->numPhis++;
388     }
389     return Instruction::isTerminator(Opcode); 
390   }
391
392   virtual void handleBasicBlockEnd(unsigned blocknum) { 
393     if (os)
394       *os << "      } END BLOCK: BasicBlock #" << blocknum << "{\n";
395   }
396
397   virtual void handleGlobalConstantsBegin() { 
398     if (os)
399       *os << "    BLOCK: GlobalConstants {\n";
400   }
401
402   virtual void handleConstantExpression( unsigned Opcode, 
403       std::vector<Constant*> ArgVec, Constant* C ) {
404     if (os) {
405       *os << "      EXPR: " << Instruction::getOpcodeName(Opcode) << "\n";
406       for ( unsigned i = 0; i < ArgVec.size(); ++i ) {
407         *os << "        Arg#" << i << " "; ArgVec[i]->print(*os); 
408         *os << "\n";
409       }
410       *os << "        Value=";
411       C->print(*os);
412       *os << "\n";
413     }
414     bca.numConstants++;
415     bca.numValues++;
416   }
417
418   virtual void handleConstantValue( Constant * c ) {
419     if (os) {
420       *os << "      VALUE: ";
421       c->print(*os);
422       *os << "\n";
423     }
424     bca.numConstants++;
425     bca.numValues++;
426   }
427
428   virtual void handleConstantArray( const ArrayType* AT, 
429           std::vector<Constant*>& Elements,
430           unsigned TypeSlot,
431           Constant* ArrayVal ) {
432     if (os) {
433       *os << "      ARRAY: ";
434       WriteTypeSymbolic(*os,AT,M); 
435       *os << " TypeSlot=" << TypeSlot << "\n";
436       for ( unsigned i = 0; i < Elements.size(); ++i ) {
437         *os << "        #" << i;
438         Elements[i]->print(*os);
439         *os << "\n";
440       }
441       *os << "        Value=";
442       ArrayVal->print(*os);
443       *os << "\n";
444     }
445
446     bca.numConstants++;
447     bca.numValues++;
448   }
449
450   virtual void handleConstantStruct(
451         const StructType* ST,
452         std::vector<Constant*>& Elements,
453         Constant* StructVal)
454   {
455     if (os) {
456       *os << "      STRUC: ";
457       WriteTypeSymbolic(*os,ST,M);
458       *os << "\n";
459       for ( unsigned i = 0; i < Elements.size(); ++i ) {
460         *os << "        #" << i << " "; Elements[i]->print(*os); 
461         *os << "\n";
462       }
463       *os << "        Value=";
464       StructVal->print(*os);
465       *os << "\n";
466     }
467     bca.numConstants++;
468     bca.numValues++;
469   }
470
471   virtual void handleConstantPacked( 
472     const PackedType* PT,                
473     std::vector<Constant*>& Elements,
474     unsigned TypeSlot,                  
475     Constant* PackedVal) 
476   {
477     if (os) {
478       *os << "      PACKD: ";
479       WriteTypeSymbolic(*os,PT,M);
480       *os << " TypeSlot=" << TypeSlot << "\n";
481       for ( unsigned i = 0; i < Elements.size(); ++i ) {
482         *os << "        #" << i;
483         Elements[i]->print(*os);
484         *os << "\n";
485       }
486       *os << "        Value=";
487       PackedVal->print(*os);
488       *os << "\n";
489     }
490
491     bca.numConstants++;
492     bca.numValues++;
493   }
494
495   virtual void handleConstantPointer( const PointerType* PT, 
496       unsigned Slot, GlobalValue* GV ) {
497     if (os) {
498       *os << "       PNTR: ";
499       WriteTypeSymbolic(*os,PT,M);
500       *os << " Slot=" << Slot << " GlobalValue=";
501       GV->print(*os);
502       *os << "\n";
503     }
504     bca.numConstants++;
505     bca.numValues++;
506   }
507
508   virtual void handleConstantString( const ConstantArray* CA ) {
509     if (os) {
510       *os << "      STRNG: ";
511       CA->print(*os); 
512       *os << "\n";
513     }
514     bca.numConstants++;
515     bca.numValues++;
516   }
517
518   virtual void handleGlobalConstantsEnd() { 
519     if (os)
520       *os << "    } END BLOCK: GlobalConstants\n";
521
522     if ( bca.progressiveVerify ) {
523       try {
524         verifyModule(*M, ThrowExceptionAction);
525       } catch ( std::string& msg ) {
526         bca.VerifyInfo += "Verify@EndGlobalConstants: " + msg + "\n";
527       }
528     }
529   }
530
531   virtual void handleAlignment(unsigned numBytes) {
532     bca.numAlignment += numBytes;
533   }
534
535   virtual void handleBlock(
536     unsigned BType, const unsigned char* StartPtr, unsigned Size) {
537     bca.numBlocks++;
538     assert(BType >= BytecodeFormat::ModuleBlockID);
539     assert(BType < BytecodeFormat::NumberOfBlockIDs);
540     bca.BlockSizes[
541       llvm::BytecodeFormat::CompressedBytecodeBlockIdentifiers(BType)] += Size;
542
543     if (bca.version < 3) // Check for long block headers versions
544       bca.BlockSizes[llvm::BytecodeFormat::Reserved_DoNotUse] += 8;
545     else
546       bca.BlockSizes[llvm::BytecodeFormat::Reserved_DoNotUse] += 4;
547   }
548
549   virtual void handleVBR32(unsigned Size ) {
550     bca.vbrCount32++;
551     bca.vbrCompBytes += Size;
552     bca.vbrExpdBytes += sizeof(uint32_t);
553     if (currFunc) {
554       currFunc->vbrCount32++;
555       currFunc->vbrCompBytes += Size;
556       currFunc->vbrExpdBytes += sizeof(uint32_t);
557     }
558   }
559
560   virtual void handleVBR64(unsigned Size ) {
561     bca.vbrCount64++;
562     bca.vbrCompBytes += Size;
563     bca.vbrExpdBytes += sizeof(uint64_t);
564     if ( currFunc ) {
565       currFunc->vbrCount64++;
566       currFunc->vbrCompBytes += Size;
567       currFunc->vbrExpdBytes += sizeof(uint64_t);
568     }
569   }
570 };
571
572
573 /// @brief Utility for printing a titled unsigned value with
574 /// an aligned colon.
575 inline static void print(std::ostream& Out, const char*title, 
576   unsigned val, bool nl = true ) {
577   Out << std::setw(30) << std::right << title 
578       << std::setw(0) << ": "
579       << std::setw(9) << val << "\n";
580 }
581
582 /// @brief Utility for printing a titled double value with an
583 /// aligned colon
584 inline static void print(std::ostream&Out, const char*title, 
585   double val ) {
586   Out << std::setw(30) << std::right << title 
587       << std::setw(0) << ": "
588       << std::setw(9) << std::setprecision(6) << val << "\n" ;
589 }
590
591 /// @brief Utility for printing a titled double value with a
592 /// percentage and aligned colon.
593 inline static void print(std::ostream&Out, const char*title, 
594   double top, double bot ) {
595   Out << std::setw(30) << std::right << title 
596       << std::setw(0) << ": "
597       << std::setw(9) << std::setprecision(6) << top 
598       << " (" << std::left << std::setw(0) << std::setprecision(4) 
599       << (top/bot)*100.0 << "%)\n";
600 }
601
602 /// @brief Utility for printing a titled string value with
603 /// an aligned colon.
604 inline static void print(std::ostream&Out, const char*title, 
605   std::string val, bool nl = true) {
606   Out << std::setw(30) << std::right << title 
607       << std::setw(0) << ": "
608       << std::left << val << (nl ? "\n" : "");
609 }
610
611 }
612
613 namespace llvm {
614
615 /// This function prints the contents of rhe BytecodeAnalysis structure in
616 /// a human legible form.
617 /// @brief Print BytecodeAnalysis structure to an ostream
618 void PrintBytecodeAnalysis(BytecodeAnalysis& bca, std::ostream& Out )
619 {
620   Out << "\nSummary Analysis Of " << bca.ModuleId << ": \n\n";
621   print(Out, "Bytecode Analysis Of Module",     bca.ModuleId);
622   print(Out, "Bytecode Version Number",         bca.version);
623   print(Out, "File Size",                       bca.byteSize);
624   print(Out, "Module Bytes",
625         double(bca.BlockSizes[BytecodeFormat::ModuleBlockID]),
626         double(bca.byteSize));
627   print(Out, "Function Bytes", 
628         double(bca.BlockSizes[BytecodeFormat::FunctionBlockID]),
629         double(bca.byteSize));
630   print(Out, "Global Types Bytes", 
631         double(bca.BlockSizes[BytecodeFormat::GlobalTypePlaneBlockID]),
632         double(bca.byteSize));
633   print(Out, "Constant Pool Bytes", 
634         double(bca.BlockSizes[BytecodeFormat::ConstantPoolBlockID]),
635         double(bca.byteSize));
636   print(Out, "Module Globals Bytes", 
637         double(bca.BlockSizes[BytecodeFormat::ModuleGlobalInfoBlockID]),
638         double(bca.byteSize));
639   print(Out, "Instruction List Bytes", 
640         double(bca.BlockSizes[BytecodeFormat::InstructionListBlockID]),
641         double(bca.byteSize));
642   print(Out, "Compaction Table Bytes", 
643         double(bca.BlockSizes[BytecodeFormat::CompactionTableBlockID]),
644         double(bca.byteSize));
645   print(Out, "Symbol Table Bytes", 
646         double(bca.BlockSizes[BytecodeFormat::SymbolTableBlockID]),
647         double(bca.byteSize));
648   print(Out, "Alignment Bytes", 
649         double(bca.numAlignment), double(bca.byteSize));
650   print(Out, "Block Header Bytes", 
651         double(bca.BlockSizes[BytecodeFormat::Reserved_DoNotUse]),
652         double(bca.byteSize));
653   print(Out, "Dependent Libraries Bytes", double(bca.libSize), 
654         double(bca.byteSize));
655   print(Out, "Number Of Bytecode Blocks",       bca.numBlocks);
656   print(Out, "Number Of Functions",             bca.numFunctions);
657   print(Out, "Number Of Types",                 bca.numTypes);
658   print(Out, "Number Of Constants",             bca.numConstants);
659   print(Out, "Number Of Global Variables",      bca.numGlobalVars);
660   print(Out, "Number Of Values",                bca.numValues);
661   print(Out, "Number Of Basic Blocks",          bca.numBasicBlocks);
662   print(Out, "Number Of Instructions",          bca.numInstructions);
663   print(Out, "Number Of Long Instructions",     bca.longInstructions);
664   print(Out, "Number Of Operands",              bca.numOperands);
665   print(Out, "Number Of Compaction Tables",     bca.numCmpctnTables);
666   print(Out, "Number Of Symbol Tables",         bca.numSymTab);
667   print(Out, "Number Of Dependent Libs",        bca.numLibraries);
668   print(Out, "Total Instruction Size",          bca.instructionSize);
669   print(Out, "Average Instruction Size", 
670         double(bca.instructionSize)/double(bca.numInstructions));
671
672   print(Out, "Maximum Type Slot Number",        bca.maxTypeSlot);
673   print(Out, "Maximum Value Slot Number",       bca.maxValueSlot);
674   print(Out, "File Density (bytes/def)",        bca.fileDensity);
675   print(Out, "Globals Density (bytes/def)",     bca.globalsDensity);
676   print(Out, "Function Density (bytes/func)",   bca.functionDensity);
677   print(Out, "Number of VBR 32-bit Integers",   bca.vbrCount32);
678   print(Out, "Number of VBR 64-bit Integers",   bca.vbrCount64);
679   print(Out, "Number of VBR Compressed Bytes",  bca.vbrCompBytes);
680   print(Out, "Number of VBR Expanded Bytes",    bca.vbrExpdBytes);
681   print(Out, "VBR Savings", 
682         double(bca.vbrExpdBytes)-double(bca.vbrCompBytes),
683         double(bca.vbrExpdBytes));
684
685   if (bca.detailedResults) {
686     Out << "\nDetailed Analysis Of " << bca.ModuleId << " Functions:\n";
687
688     std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator I = 
689       bca.FunctionInfo.begin();
690     std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator E = 
691       bca.FunctionInfo.end();
692
693     while ( I != E ) {
694       Out << std::left << std::setw(0);
695       Out << "\nFunction: " << I->second.name << "\n";
696       print(Out, "Type:", I->second.description);
697       print(Out, "Byte Size", I->second.byteSize);
698       print(Out, "Instructions", I->second.numInstructions);
699       print(Out, "Long Instructions", I->second.longInstructions);
700       print(Out, "Instruction Size", I->second.instructionSize);
701       print(Out, "Average Instruction Size", 
702             double(I->second.instructionSize)/double(I->second.numInstructions));
703       print(Out, "Basic Blocks", I->second.numBasicBlocks);
704       print(Out, "Operand", I->second.numOperands);
705       print(Out, "Function Density", I->second.density);
706       print(Out, "Number of VBR 32-bit Integers",   I->second.vbrCount32);
707       print(Out, "Number of VBR 64-bit Integers",   I->second.vbrCount64);
708       print(Out, "Number of VBR Compressed Bytes",  I->second.vbrCompBytes);
709       print(Out, "Number of VBR Expanded Bytes",    I->second.vbrExpdBytes);
710       print(Out, "VBR Savings", 
711             double(I->second.vbrExpdBytes)-double(I->second.vbrCompBytes),
712             double(I->second.vbrExpdBytes));
713       ++I;
714     }
715   }
716
717   if ( bca.progressiveVerify )
718     Out << bca.VerifyInfo;
719 }
720
721 BytecodeHandler* createBytecodeAnalyzerHandler(BytecodeAnalysis& bca,
722                                                std::ostream* output)
723 {
724   return new AnalyzerHandler(bca,output);
725 }
726
727 }
728
729 // vim: sw=2