blob: f8493170fa471c34f2c30f3b32748ec1416b9f56 [file] [log] [blame]
Reid Spencerdac69c82004-06-07 17:53:43 +00001//===- 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>
Reid Spencer00c28a72004-06-10 08:09:13 +000021#include <iomanip>
Reid Spencerdac69c82004-06-07 17:53:43 +000022
23using namespace llvm;
24
25//===----------------------------------------------------------------------===//
26// BytecodeFileAnalyzer - Analyze from an mmap'able file descriptor.
27//
28
29namespace {
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
45static std::string ErrnoMessage (int savedErrNum, std::string descr) {
46 return ::strerror(savedErrNum) + std::string(", while trying to ") + descr;
47}
48
49BytecodeFileAnalyzer::BytecodeFileAnalyzer(const std::string &Filename,
Reid Spencer00c28a72004-06-10 08:09:13 +000050 BytecodeAnalysis& bca) {
Reid Spencerdac69c82004-06-07 17:53:43 +000051 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
66BytecodeFileAnalyzer::~BytecodeFileAnalyzer() {
67 // Unmmap the bytecode...
68 UnmapFileFromAddressSpace(Buffer, Length);
69}
70
71//===----------------------------------------------------------------------===//
72// BytecodeBufferAnalyzer - Read from a memory buffer
73//
74
75namespace {
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,
Reid Spencer00c28a72004-06-10 08:09:13 +000088 BytecodeAnalysis& bca, const std::string &ModuleID);
Reid Spencerdac69c82004-06-07 17:53:43 +000089 ~BytecodeBufferAnalyzer();
90
91 };
92}
93
94BytecodeBufferAnalyzer::BytecodeBufferAnalyzer(const unsigned char *Buf,
Reid Spencer00c28a72004-06-10 08:09:13 +000095 unsigned Length,
96 BytecodeAnalysis& bca,
97 const std::string &ModuleID) {
Reid Spencerdac69c82004-06-07 17:53:43 +000098 // 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
121BytecodeBufferAnalyzer::~BytecodeBufferAnalyzer() {
122 if (MustDelete) delete [] Buffer;
123}
124
125//===----------------------------------------------------------------------===//
126// BytecodeStdinAnalyzer - Read bytecode from Standard Input
127//
128
129namespace {
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
145BytecodeStdinAnalyzer::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
171void 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
186void 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
Reid Spencer00c28a72004-06-10 08:09:13 +0000204namespace {
205inline 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
212inline 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
219inline 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}
227inline 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
Reid Spencerdac69c82004-06-07 17:53:43 +0000236void llvm::PrintBytecodeAnalysis(BytecodeAnalysis& bca, std::ostream& Out )
237{
Reid Spencer00c28a72004-06-10 08:09:13 +0000238 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);
Reid Spencer1cf50242004-06-11 15:10:38 +0000252 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));
Reid Spencer00c28a72004-06-10 08:09:13 +0000256 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));
Reid Spenceredc3b582004-06-09 06:17:58 +0000270
Reid Spencer00c28a72004-06-10 08:09:13 +0000271 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
Reid Spencercbb22e22004-06-10 22:00:54 +0000300 std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator I =
Reid Spencer00c28a72004-06-10 08:09:13 +0000301 bca.FunctionInfo.begin();
Reid Spencercbb22e22004-06-10 22:00:54 +0000302 std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator E =
Reid Spencer00c28a72004-06-10 08:09:13 +0000303 bca.FunctionInfo.end();
304
305 while ( I != E ) {
306 Out << std::left << std::setw(0);
Reid Spencercbb22e22004-06-10 22:00:54 +0000307 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);
Reid Spencer1cf50242004-06-11 15:10:38 +0000311 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));
Reid Spencercbb22e22004-06-10 22:00:54 +0000315 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",
Reid Spencer7c7680a2004-06-10 22:03:00 +0000323 double(I->second.vbrExpdBytes)-double(I->second.vbrCompBytes),
324 double(I->second.byteSize));
Reid Spencer00c28a72004-06-10 08:09:13 +0000325 ++I;
326 }
327 }
Reid Spenceredc3b582004-06-09 06:17:58 +0000328
329 if ( bca.dumpBytecode )
330 Out << bca.BytecodeDump;
Reid Spencerdac69c82004-06-07 17:53:43 +0000331}
Reid Spencerdac69c82004-06-07 17:53:43 +0000332// vim: sw=2