Merge Dumper.cpp and AnalyzerWrappers.cpp into this file. Also, adjust the
[oota-llvm.git] / lib / Bytecode / Reader / AnalyzerWrappers.cpp
1 //===- AnalyzerWrappers.cpp - Analyze bytecode from file or buffer  -------===//
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 loading and analysis of a bytecode file and analyzing a
11 // bytecode buffer.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/Bytecode/Analyzer.h"
16 #include "AnalyzerInternals.h"
17 #include "Support/FileUtilities.h"
18 #include "Support/StringExtras.h"
19 #include "Config/unistd.h"
20 #include <cerrno>
21 #include <iomanip>
22
23 using namespace llvm;
24
25 //===----------------------------------------------------------------------===//
26 // BytecodeFileAnalyzer - Analyze from an mmap'able file descriptor.
27 //
28
29 namespace {
30   /// BytecodeFileAnalyzer - parses a bytecode file from a file
31   class BytecodeFileAnalyzer : public BytecodeAnalyzer {
32   private:
33     unsigned char *Buffer;
34     unsigned Length;
35
36     BytecodeFileAnalyzer(const BytecodeFileAnalyzer&); // Do not implement
37     void operator=(const BytecodeFileAnalyzer &BFR); // Do not implement
38
39   public:
40     BytecodeFileAnalyzer(const std::string &Filename, BytecodeAnalysis& bca);
41     ~BytecodeFileAnalyzer();
42   };
43 }
44
45 static std::string ErrnoMessage (int savedErrNum, std::string descr) {
46    return ::strerror(savedErrNum) + std::string(", while trying to ") + descr;
47 }
48
49 BytecodeFileAnalyzer::BytecodeFileAnalyzer(const std::string &Filename, 
50                                            BytecodeAnalysis& bca) {
51   Buffer = (unsigned char*)ReadFileIntoAddressSpace(Filename, Length);
52   if (Buffer == 0)
53     throw "Error reading file '" + Filename + "'.";
54
55   try {
56     // Parse the bytecode we mmapped in
57     if ( bca.dumpBytecode ) 
58       DumpBytecode(Buffer, Length, bca, Filename);
59     AnalyzeBytecode(Buffer, Length, bca, Filename);
60   } catch (...) {
61     UnmapFileFromAddressSpace(Buffer, Length);
62     throw;
63   }
64 }
65
66 BytecodeFileAnalyzer::~BytecodeFileAnalyzer() {
67   // Unmmap the bytecode...
68   UnmapFileFromAddressSpace(Buffer, Length);
69 }
70
71 //===----------------------------------------------------------------------===//
72 // BytecodeBufferAnalyzer - Read from a memory buffer
73 //
74
75 namespace {
76   /// BytecodeBufferAnalyzer - parses a bytecode file from a buffer
77   ///
78   class BytecodeBufferAnalyzer : public BytecodeAnalyzer {
79   private:
80     const unsigned char *Buffer;
81     bool MustDelete;
82
83     BytecodeBufferAnalyzer(const BytecodeBufferAnalyzer&); // Do not implement
84     void operator=(const BytecodeBufferAnalyzer &BFR);   // Do not implement
85
86   public:
87     BytecodeBufferAnalyzer(const unsigned char *Buf, unsigned Length,
88                            BytecodeAnalysis& bca, const std::string &ModuleID);
89     ~BytecodeBufferAnalyzer();
90
91   };
92 }
93
94 BytecodeBufferAnalyzer::BytecodeBufferAnalyzer(const unsigned char *Buf,
95                                                unsigned Length,
96                                                BytecodeAnalysis& bca,
97                                                const std::string &ModuleID) {
98   // If not aligned, allocate a new buffer to hold the bytecode...
99   const unsigned char *ParseBegin = 0;
100   if ((intptr_t)Buf & 3) {
101     Buffer = new unsigned char[Length+4];
102     unsigned Offset = 4 - ((intptr_t)Buffer & 3);   // Make sure it's aligned
103     ParseBegin = Buffer + Offset;
104     memcpy((unsigned char*)ParseBegin, Buf, Length);    // Copy it over
105     MustDelete = true;
106   } else {
107     // If we don't need to copy it over, just use the caller's copy
108     ParseBegin = Buffer = Buf;
109     MustDelete = false;
110   }
111   try {
112     if ( bca.dumpBytecode ) 
113       DumpBytecode(ParseBegin, Length, bca, ModuleID);
114     AnalyzeBytecode(ParseBegin, Length, bca, ModuleID);
115   } catch (...) {
116     if (MustDelete) delete [] Buffer;
117     throw;
118   }
119 }
120
121 BytecodeBufferAnalyzer::~BytecodeBufferAnalyzer() {
122   if (MustDelete) delete [] Buffer;
123 }
124
125 //===----------------------------------------------------------------------===//
126 //  BytecodeStdinAnalyzer - Read bytecode from Standard Input
127 //
128
129 namespace {
130   /// BytecodeStdinAnalyzer - parses a bytecode file from stdin
131   /// 
132   class BytecodeStdinAnalyzer : public BytecodeAnalyzer {
133   private:
134     std::vector<unsigned char> FileData;
135     unsigned char *FileBuf;
136
137     BytecodeStdinAnalyzer(const BytecodeStdinAnalyzer&); // Do not implement
138     void operator=(const BytecodeStdinAnalyzer &BFR);  // Do not implement
139
140   public:
141     BytecodeStdinAnalyzer(BytecodeAnalysis& bca);
142   };
143 }
144
145 BytecodeStdinAnalyzer::BytecodeStdinAnalyzer(BytecodeAnalysis& bca ) {
146   int BlockSize;
147   unsigned char Buffer[4096*4];
148
149   // Read in all of the data from stdin, we cannot mmap stdin...
150   while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
151     if (BlockSize == -1)
152       throw ErrnoMessage(errno, "read from standard input");
153     
154     FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
155   }
156
157   if (FileData.empty())
158     throw std::string("Standard Input empty!");
159
160   FileBuf = &FileData[0];
161   if (bca.dumpBytecode)
162     DumpBytecode(&FileData[0], FileData.size(), bca, "<stdin>");
163   AnalyzeBytecode(FileBuf, FileData.size(), bca, "<stdin>");
164 }
165
166 //===----------------------------------------------------------------------===//
167 // Wrapper functions
168 //===----------------------------------------------------------------------===//
169
170 // AnalyzeBytecodeFile - analyze one file
171 void llvm::AnalyzeBytecodeFile(const std::string &Filename, 
172                                BytecodeAnalysis& bca,
173                                std::string *ErrorStr) 
174 {
175   try {
176     if ( Filename != "-" )
177       BytecodeFileAnalyzer bfa(Filename,bca);
178     else
179       BytecodeStdinAnalyzer bsa(bca);
180   } catch (std::string &err) {
181     if (ErrorStr) *ErrorStr = err;
182   }
183 }
184
185 // AnalyzeBytecodeBuffer - analyze a buffer
186 void llvm::AnalyzeBytecodeBuffer(
187        const unsigned char* Buffer, ///< Pointer to start of bytecode buffer
188        unsigned BufferSize,         ///< Size of the bytecode buffer
189        BytecodeAnalysis& Results,   ///< The results of the analysis
190        std::string* ErrorStr        ///< Errors, if any.
191      ) 
192 {
193   try {
194     BytecodeBufferAnalyzer(Buffer, BufferSize, Results, "<buffer>" );
195   } catch (std::string& err ) {
196     if ( ErrorStr) *ErrorStr = err;
197   }
198 }
199
200
201 /// This function prints the contents of rhe BytecodeAnalysis structure in
202 /// a human legible form.
203 /// @brief Print BytecodeAnalysis structure to an ostream
204 namespace {
205 inline static void print(std::ostream& Out, const char*title, 
206   unsigned val, bool nl = true ) {
207   Out << std::setw(30) << std::right << title 
208       << std::setw(0) << ": "
209       << std::setw(9) << val << "\n";
210 }
211
212 inline static void print(std::ostream&Out, const char*title, 
213   double val ) {
214   Out << std::setw(30) << std::right << title 
215       << std::setw(0) << ": "
216       << std::setw(9) << std::setprecision(6) << val << "\n" ;
217 }
218
219 inline static void print(std::ostream&Out, const char*title, 
220   double top, double bot ) {
221   Out << std::setw(30) << std::right << title 
222       << std::setw(0) << ": "
223       << std::setw(9) << std::setprecision(6) << top 
224       << " (" << std::left << std::setw(0) << std::setprecision(4) 
225       << (top/bot)*100.0 << "%)\n";
226 }
227 inline static void print(std::ostream&Out, const char*title, 
228   std::string val, bool nl = true) {
229   Out << std::setw(30) << std::right << title 
230       << std::setw(0) << ": "
231       << std::left << val << (nl ? "\n" : "");
232 }
233
234 }
235
236 void llvm::PrintBytecodeAnalysis(BytecodeAnalysis& bca, std::ostream& Out )
237 {
238   print(Out, "Bytecode Analysis Of Module",     bca.ModuleId);
239   print(Out, "File Size",                       bca.byteSize);
240   print(Out, "Bytecode Compression Index",std::string("TBD"));
241   print(Out, "Number Of Bytecode Blocks",       bca.numBlocks);
242   print(Out, "Number Of Types",                 bca.numTypes);
243   print(Out, "Number Of Values",                bca.numValues);
244   print(Out, "Number Of Constants",             bca.numConstants);
245   print(Out, "Number Of Global Variables",      bca.numGlobalVars);
246   print(Out, "Number Of Functions",             bca.numFunctions);
247   print(Out, "Number Of Basic Blocks",          bca.numBasicBlocks);
248   print(Out, "Number Of Instructions",          bca.numInstructions);
249   print(Out, "Number Of Operands",              bca.numOperands);
250   print(Out, "Number Of Compaction Tables",     bca.numCmpctnTables);
251   print(Out, "Number Of Symbol Tables",         bca.numSymTab);
252   print(Out, "Long Instructions", bca.longInstructions);
253   print(Out, "Instruction Size", bca.instructionSize);
254   print(Out, "Average Instruction Size", 
255     double(bca.instructionSize)/double(bca.numInstructions));
256   print(Out, "Maximum Type Slot Number",        bca.maxTypeSlot);
257   print(Out, "Maximum Value Slot Number",       bca.maxValueSlot);
258   print(Out, "Bytes Thrown To Alignment",       double(bca.numAlignment), 
259     double(bca.byteSize));
260   print(Out, "File Density (bytes/def)",        bca.fileDensity);
261   print(Out, "Globals Density (bytes/def)",     bca.globalsDensity);
262   print(Out, "Function Density (bytes/func)",   bca.functionDensity);
263   print(Out, "Number of VBR 32-bit Integers",   bca.vbrCount32);
264   print(Out, "Number of VBR 64-bit Integers",   bca.vbrCount64);
265   print(Out, "Number of VBR Compressed Bytes",  bca.vbrCompBytes);
266   print(Out, "Number of VBR Expanded Bytes",    bca.vbrExpdBytes);
267   print(Out, "VBR Savings", 
268     double(bca.vbrExpdBytes)-double(bca.vbrCompBytes),
269     double(bca.byteSize));
270
271   if ( bca.detailedResults ) {
272     print(Out, "Module Bytes",
273         double(bca.BlockSizes[BytecodeFormat::Module]),
274         double(bca.byteSize));
275     print(Out, "Function Bytes", 
276         double(bca.BlockSizes[BytecodeFormat::Function]),
277         double(bca.byteSize));
278     print(Out, "Constant Pool Bytes", 
279         double(bca.BlockSizes[BytecodeFormat::ConstantPool]),
280         double(bca.byteSize));
281     print(Out, "Symbol Table Bytes", 
282         double(bca.BlockSizes[BytecodeFormat::SymbolTable]),
283         double(bca.byteSize));
284     print(Out, "Module Global Info Bytes", 
285         double(bca.BlockSizes[BytecodeFormat::ModuleGlobalInfo]),
286         double(bca.byteSize));
287     print(Out, "Global Type Plane Bytes", 
288         double(bca.BlockSizes[BytecodeFormat::GlobalTypePlane]),
289         double(bca.byteSize));
290     print(Out, "Basic Block Bytes", 
291         double(bca.BlockSizes[BytecodeFormat::BasicBlock]),
292         double(bca.byteSize));
293     print(Out, "Instruction List Bytes", 
294         double(bca.BlockSizes[BytecodeFormat::InstructionList]),
295         double(bca.byteSize));
296     print(Out, "Compaction Table Bytes", 
297         double(bca.BlockSizes[BytecodeFormat::CompactionTable]),
298         double(bca.byteSize));
299
300     std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator I = 
301       bca.FunctionInfo.begin();
302     std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator E = 
303       bca.FunctionInfo.end();
304
305     while ( I != E ) {
306       Out << std::left << std::setw(0);
307       Out << "Function: " << I->second.name << "\n";
308       print(Out, "Type:", I->second.description);
309       print(Out, "Byte Size", I->second.byteSize);
310       print(Out, "Instructions", I->second.numInstructions);
311       print(Out, "Long Instructions", I->second.longInstructions);
312       print(Out, "Instruction Size", I->second.instructionSize);
313       print(Out, "Average Instruction Size", 
314         double(I->second.instructionSize)/double(I->second.numInstructions));
315       print(Out, "Basic Blocks", I->second.numBasicBlocks);
316       print(Out, "Operand", I->second.numOperands);
317       print(Out, "Function Density", I->second.density);
318       print(Out, "Number of VBR 32-bit Integers",   I->second.vbrCount32);
319       print(Out, "Number of VBR 64-bit Integers",   I->second.vbrCount64);
320       print(Out, "Number of VBR Compressed Bytes",  I->second.vbrCompBytes);
321       print(Out, "Number of VBR Expanded Bytes",    I->second.vbrExpdBytes);
322       print(Out, "VBR Savings", 
323         double(I->second.vbrExpdBytes)-double(I->second.vbrCompBytes),
324         double(I->second.byteSize));
325       ++I;
326     }
327   }
328
329   if ( bca.dumpBytecode )
330     Out << bca.BytecodeDump;
331 }
332 // vim: sw=2