blob: 3f6f3d86ce08db3a7dd4af0db42d706eb5398183 [file] [log] [blame]
Reid Spencer8a542ae2004-07-02 03:22:53 +00001//===-- llvm-bcanalyzer.cpp - Byte Code Analyzer --------------------------===//
Misha Brukman3da94ae2005-04-22 00:00:37 +00002//
Reid Spencerdac69c82004-06-07 17:53:43 +00003// The LLVM Compiler Infrastructure
4//
Misha Brukman3da94ae2005-04-22 00:00:37 +00005// This file was developed by Reid Spencer and is distributed under the
Reid Spencer96684ef2004-06-08 05:56:58 +00006// University of Illinois Open Source License. See LICENSE.TXT for details.
Misha Brukman3da94ae2005-04-22 00:00:37 +00007//
Reid Spencerdac69c82004-06-07 17:53:43 +00008//===----------------------------------------------------------------------===//
9//
Reid Spencer96684ef2004-06-08 05:56:58 +000010// This tool may be invoked in the following manner:
Reid Spencer8a542ae2004-07-02 03:22:53 +000011// llvm-bcanalyzer [options] - Read LLVM bytecode from stdin
12// llvm-bcanalyzer [options] x.bc - Read LLVM bytecode from the x.bc file
Reid Spencerdac69c82004-06-07 17:53:43 +000013//
Reid Spencer96684ef2004-06-08 05:56:58 +000014// Options:
Reid Spencer23d46e72004-06-10 18:38:44 +000015// --help - Output information about command line switches
Misha Brukman3da94ae2005-04-22 00:00:37 +000016// --nodetails - Don't print out detailed informaton about individual
Reid Spencer23d46e72004-06-10 18:38:44 +000017// blocks and functions
18// --dump - Dump low-level bytecode structure in readable format
Reid Spencer96684ef2004-06-08 05:56:58 +000019//
20// This tool provides analytical information about a bytecode file. It is
21// intended as an aid to developers of bytecode reading and writing software. It
Misha Brukman3da94ae2005-04-22 00:00:37 +000022// produces on std::out a summary of the bytecode file that shows various
Reid Spencer23d46e72004-06-10 18:38:44 +000023// statistics about the contents of the file. By default this information is
24// detailed and contains information about individual bytecode blocks and the
Misha Brukman3da94ae2005-04-22 00:00:37 +000025// functions in the module. To avoid this more detailed output, use the
Reid Spencer23d46e72004-06-10 18:38:44 +000026// -nodetails option to limit the output to just module level information.
Misha Brukman3da94ae2005-04-22 00:00:37 +000027// The tool is also able to print a bytecode file in a straight forward text
28// format that shows the containment and relationships of the information in
29// the bytecode file (-dump option).
Chris Lattner63db4852007-04-29 05:51:00 +000030//
Reid Spencerdac69c82004-06-07 17:53:43 +000031//===----------------------------------------------------------------------===//
32
Reid Spencer86a9a7a2004-06-29 23:34:27 +000033#include "llvm/Analysis/Verifier.h"
Chris Lattner45e0f892007-04-29 08:12:22 +000034#include "llvm/Bitcode/BitstreamReader.h"
Chris Lattner4238d472007-04-29 20:00:02 +000035#include "llvm/Bitcode/LLVMBitCodes.h"
Reid Spencerdac69c82004-06-07 17:53:43 +000036#include "llvm/Bytecode/Analyzer.h"
Reid Spencer551ccae2004-09-01 22:55:40 +000037#include "llvm/Support/CommandLine.h"
Chris Lattnerf2e292c2007-02-07 21:41:02 +000038#include "llvm/Support/Compressor.h"
Chris Lattnerc30598b2006-12-06 01:18:01 +000039#include "llvm/Support/ManagedStatic.h"
Chris Lattner45e0f892007-04-29 08:12:22 +000040#include "llvm/Support/MemoryBuffer.h"
Reid Spencerdac69c82004-06-07 17:53:43 +000041#include "llvm/System/Signals.h"
42#include <fstream>
43#include <iostream>
Reid Spencerdac69c82004-06-07 17:53:43 +000044using namespace llvm;
45
46static cl::opt<std::string>
47 InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));
48
Reid Spencer75937452004-08-21 21:00:24 +000049static cl::opt<std::string>
50 OutputFilename("-o", cl::init("-"), cl::desc("<output file>"));
51
Chris Lattner63db4852007-04-29 05:51:00 +000052static cl::opt<bool> NoDetails("nodetails", cl::desc("Skip detailed output"));
53static cl::opt<bool> Dump("dump", cl::desc("Dump low level bytecode trace"));
54static cl::opt<bool> Verify("verify", cl::desc("Progressively verify module"));
Chris Lattner32de6332007-04-29 08:31:14 +000055
56//===----------------------------------------------------------------------===//
57// Bitcode specific analysis.
58//===----------------------------------------------------------------------===//
59
Chris Lattner45e0f892007-04-29 08:12:22 +000060static cl::opt<bool> Bitcode("bitcode", cl::desc("Read a bitcode file"));
61
62/// CurStreamType - If we can sniff the flavor of this stream, we can produce
63/// better dump info.
64static enum {
65 UnknownBitstream,
66 LLVMIRBitstream
67} CurStreamType;
68
Chris Lattner4238d472007-04-29 20:00:02 +000069
70/// GetBlockName - Return a symbolic block name if known, otherwise return
71/// empty.
72static const char *GetBlockName(unsigned BlockID) {
73 if (CurStreamType != LLVMIRBitstream) return "";
74
75 switch (BlockID) {
76 default: return "<unknown LLVM IR block ID>";
77 case bitc::MODULE_BLOCK_ID: return "MODULE_BLOCK";
78 case bitc::TYPE_BLOCK_ID: return "TYPE_BLOCK";
79 case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK";
80 case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK";
81 case bitc::TYPE_SYMTAB_BLOCK_ID: return "TYPE_SYMTAB";
82 case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB";
83 }
84}
85
86
87struct PerBlockIDStats {
88 /// NumInstances - This the number of times this block ID has been seen.
89 unsigned NumInstances;
90
91 /// NumBits - The total size in bits of all of these blocks.
92 uint64_t NumBits;
93
94 /// NumSubBlocks - The total number of blocks these blocks contain.
95 unsigned NumSubBlocks;
96
97 /// NumAbbrevs - The total number of abbreviations.
98 unsigned NumAbbrevs;
99
100 /// NumRecords - The total number of records these blocks contain, and the
101 /// number that are abbreviated.
102 unsigned NumRecords, NumAbbreviatedRecords;
103
104 PerBlockIDStats()
105 : NumInstances(0), NumBits(0),
106 NumSubBlocks(0), NumAbbrevs(0), NumRecords(0), NumAbbreviatedRecords(0) {}
107};
108
109static std::map<unsigned, PerBlockIDStats> BlockIDStats;
110
111
112
Chris Lattner32de6332007-04-29 08:31:14 +0000113/// Error - All bitcode analysis errors go through this function, making this a
114/// good place to breakpoint if debugging.
115static bool Error(const std::string &Err) {
116 std::cerr << Err << "\n";
117 return true;
118}
119
120/// ParseBlock - Read a block, updating statistics, etc.
121static bool ParseBlock(BitstreamReader &Stream) {
Chris Lattner4238d472007-04-29 20:00:02 +0000122 uint64_t BlockBitStart = Stream.GetCurrentBitNo();
123
Chris Lattner32de6332007-04-29 08:31:14 +0000124 unsigned BlockID = Stream.ReadSubBlockID();
125
Chris Lattner4238d472007-04-29 20:00:02 +0000126 // Get the statistics for this BlockID.
127 PerBlockIDStats &BlockStats = BlockIDStats[BlockID];
128
129 BlockStats.NumInstances++;
Chris Lattner32de6332007-04-29 08:31:14 +0000130
131 if (Stream.EnterSubBlock())
132 return Error("Malformed block record");
133
134 SmallVector<uint64_t, 64> Record;
135
136 // Read all the records for this block.
137 while (1) {
138 if (Stream.AtEndOfStream())
139 return Error("Premature end of bitstream");
140
141 // Read the code for this record.
142 unsigned AbbrevID = Stream.ReadCode();
143 switch (AbbrevID) {
Chris Lattner4238d472007-04-29 20:00:02 +0000144 case bitc::END_BLOCK: {
Chris Lattner32de6332007-04-29 08:31:14 +0000145 if (Stream.ReadBlockEnd())
146 return Error("Error at end of block");
Chris Lattner4238d472007-04-29 20:00:02 +0000147 uint64_t BlockBitEnd = Stream.GetCurrentBitNo();
148 BlockStats.NumBits += BlockBitEnd-BlockBitStart;
Chris Lattner32de6332007-04-29 08:31:14 +0000149 return false;
Chris Lattner4238d472007-04-29 20:00:02 +0000150 }
Chris Lattner32de6332007-04-29 08:31:14 +0000151 case bitc::ENTER_SUBBLOCK:
152 if (ParseBlock(Stream))
153 return true;
Chris Lattner4238d472007-04-29 20:00:02 +0000154 ++BlockStats.NumSubBlocks;
Chris Lattner32de6332007-04-29 08:31:14 +0000155 break;
156 case bitc::DEFINE_ABBREV:
157 Stream.ReadAbbrevRecord();
Chris Lattner4238d472007-04-29 20:00:02 +0000158 ++BlockStats.NumAbbrevs;
Chris Lattner32de6332007-04-29 08:31:14 +0000159 break;
160 default:
Chris Lattner4238d472007-04-29 20:00:02 +0000161 ++BlockStats.NumRecords;
162 if (AbbrevID != bitc::UNABBREV_RECORD)
163 ++BlockStats.NumAbbreviatedRecords;
164
Chris Lattner32de6332007-04-29 08:31:14 +0000165 Record.clear();
166 unsigned Code = Stream.ReadRecord(AbbrevID, Record);
167 // TODO: Compute per-blockid/code stats.
168 Code = Code;
169 break;
170 }
171 }
172}
173
Chris Lattner4238d472007-04-29 20:00:02 +0000174static void PrintSize(double Bits) {
175 std::cerr << Bits << "b/" << Bits/8 << "B/" << Bits/32 << "W";
176}
177
178
Chris Lattner45e0f892007-04-29 08:12:22 +0000179/// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename.
180static int AnalyzeBitcode() {
181 // Read the input file.
182 MemoryBuffer *Buffer;
183 if (InputFilename == "-")
184 Buffer = MemoryBuffer::getSTDIN();
185 else
186 Buffer = MemoryBuffer::getFile(&InputFilename[0], InputFilename.size());
187
Chris Lattner32de6332007-04-29 08:31:14 +0000188 if (Buffer == 0)
189 return Error("Error reading '" + InputFilename + "'.");
Chris Lattner45e0f892007-04-29 08:12:22 +0000190
Chris Lattner32de6332007-04-29 08:31:14 +0000191 if (Buffer->getBufferSize() & 3)
192 return Error("Bitcode stream should be a multiple of 4 bytes in length");
Chris Lattner45e0f892007-04-29 08:12:22 +0000193
194 unsigned char *BufPtr = (unsigned char *)Buffer->getBufferStart();
195 BitstreamReader Stream(BufPtr, BufPtr+Buffer->getBufferSize());
196
197
198 // Read the stream signature.
199 char Signature[6];
200 Signature[0] = Stream.Read(8);
201 Signature[1] = Stream.Read(8);
202 Signature[2] = Stream.Read(4);
203 Signature[3] = Stream.Read(4);
204 Signature[4] = Stream.Read(4);
205 Signature[5] = Stream.Read(4);
206
Chris Lattner32de6332007-04-29 08:31:14 +0000207 // Autodetect the file contents, if it is one we know.
Chris Lattner45e0f892007-04-29 08:12:22 +0000208 CurStreamType = UnknownBitstream;
209 if (Signature[0] == 'B' && Signature[1] == 'C' &&
210 Signature[2] == 0x0 && Signature[3] == 0xC &&
211 Signature[4] == 0xE && Signature[5] == 0xD)
212 CurStreamType = LLVMIRBitstream;
213
Chris Lattner4238d472007-04-29 20:00:02 +0000214 unsigned NumTopBlocks = 0;
215
Chris Lattner32de6332007-04-29 08:31:14 +0000216 // Parse the top-level structure. We only allow blocks at the top-level.
217 while (!Stream.AtEndOfStream()) {
218 unsigned Code = Stream.ReadCode();
219 if (Code != bitc::ENTER_SUBBLOCK)
220 return Error("Invalid record at top-level");
221
222 if (ParseBlock(Stream))
223 return true;
Chris Lattner4238d472007-04-29 20:00:02 +0000224 ++NumTopBlocks;
Chris Lattner32de6332007-04-29 08:31:14 +0000225 }
226
227 // Print a summary of the read file.
Chris Lattner45e0f892007-04-29 08:12:22 +0000228 std::cerr << "Summary of " << InputFilename << ":\n";
Chris Lattner4238d472007-04-29 20:00:02 +0000229 std::cerr << " Total size: ";
230 PrintSize(Buffer->getBufferSize()*8);
231 std::cerr << "\n";
232 std::cerr << " Stream type: ";
Chris Lattner45e0f892007-04-29 08:12:22 +0000233 switch (CurStreamType) {
234 default: assert(0 && "Unknown bitstream type");
235 case UnknownBitstream: std::cerr << "unknown\n"; break;
236 case LLVMIRBitstream: std::cerr << "LLVM IR\n"; break;
237 }
Chris Lattner4238d472007-04-29 20:00:02 +0000238 std::cerr << " # Toplevel Blocks: " << NumTopBlocks << "\n";
239 std::cerr << "\n";
240
241 // Emit per-block stats.
242 std::cerr << "Per-block Summary:\n";
243 for (std::map<unsigned, PerBlockIDStats>::iterator I = BlockIDStats.begin(),
244 E = BlockIDStats.end(); I != E; ++I) {
245 std::cerr << " Block ID #" << I->first;
246 const char *BlockName = GetBlockName(I->first);
247 if (BlockName[0])
248 std::cerr << " (" << BlockName << ")";
249 std::cerr << ":\n";
250
251 const PerBlockIDStats &Stats = I->second;
252 std::cerr << " Num Instances: " << Stats.NumInstances << "\n";
253 std::cerr << " Total Size: ";
254 PrintSize(Stats.NumBits);
255 std::cerr << "\n";
256 std::cerr << " Average Size: ";
257 PrintSize(Stats.NumBits/(double)Stats.NumInstances);
258 std::cerr << "\n";
259 std::cerr << " Tot/Avg SubBlocks: " << Stats.NumSubBlocks << "/"
260 << Stats.NumSubBlocks/(double)Stats.NumInstances << "\n";
261 std::cerr << " Tot/Avg Abbrevs: " << Stats.NumAbbrevs << "/"
262 << Stats.NumAbbrevs/(double)Stats.NumInstances << "\n";
263 std::cerr << " Tot/Avg Records: " << Stats.NumRecords << "/"
264 << Stats.NumRecords/(double)Stats.NumInstances << "\n";
265 std::cerr << " % Abbrev Recs: " << (Stats.NumAbbreviatedRecords/
266 (double)Stats.NumRecords)*100 << "\n";
267 std::cerr << "\n";
268 }
Chris Lattner45e0f892007-04-29 08:12:22 +0000269 return 0;
270}
Reid Spencerdac69c82004-06-07 17:53:43 +0000271
Chris Lattner32de6332007-04-29 08:31:14 +0000272
273//===----------------------------------------------------------------------===//
274// Bytecode specific analysis.
275//===----------------------------------------------------------------------===//
276
Chris Lattnerc30598b2006-12-06 01:18:01 +0000277int main(int argc, char **argv) {
278 llvm_shutdown_obj X; // Call llvm_shutdown() on exit.
Chris Lattner45e0f892007-04-29 08:12:22 +0000279 cl::ParseCommandLineOptions(argc, argv, " llvm-bcanalyzer file analyzer\n");
280
281 sys::PrintStackTraceOnErrorSignal();
282
283 if (Bitcode)
284 return AnalyzeBitcode();
285
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000286 try {
Chris Lattner63db4852007-04-29 05:51:00 +0000287 std::ostream *Out = &std::cout; // Default to printing to stdout...
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000288 std::string ErrorMessage;
289 BytecodeAnalysis bca;
Reid Spencerdac69c82004-06-07 17:53:43 +0000290
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000291 /// Determine what to generate
292 bca.detailedResults = !NoDetails;
293 bca.progressiveVerify = Verify;
Reid Spencer96684ef2004-06-08 05:56:58 +0000294
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000295 /// Analyze the bytecode file
Chris Lattnerf2e292c2007-02-07 21:41:02 +0000296 Module* M = AnalyzeBytecodeFile(InputFilename, bca,
297 Compressor::decompressToNewBuffer,
298 &ErrorMessage, (Dump?Out:0));
Reid Spencer86a9a7a2004-06-29 23:34:27 +0000299
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000300 // All that bcanalyzer does is write the gathered statistics to the output
301 PrintBytecodeAnalysis(bca,*Out);
Reid Spencer86a9a7a2004-06-29 23:34:27 +0000302
Chris Lattner45e0f892007-04-29 08:12:22 +0000303 if (M && Verify) {
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000304 std::string verificationMsg;
Chris Lattner05ac92c2006-07-06 18:02:27 +0000305 if (verifyModule(*M, ReturnStatusAction, &verificationMsg))
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000306 std::cerr << "Final Verification Message: " << verificationMsg << "\n";
Reid Spencer86a9a7a2004-06-29 23:34:27 +0000307 }
Reid Spencer86a9a7a2004-06-29 23:34:27 +0000308
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000309 if (Out != &std::cout) {
310 ((std::ofstream*)Out)->close();
311 delete Out;
312 }
313 return 0;
314 } catch (const std::string& msg) {
315 std::cerr << argv[0] << ": " << msg << "\n";
316 } catch (...) {
317 std::cerr << argv[0] << ": Unexpected unknown exception occurred.\n";
Reid Spencerdac69c82004-06-07 17:53:43 +0000318 }
Reid Spencer1ef8bda2004-12-30 05:36:08 +0000319 return 1;
Reid Spencerdac69c82004-06-07 17:53:43 +0000320}