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