blob: 2a221bf37c22a5f3069c00c83d62fdf1d20360b1 [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>
21
22using namespace llvm;
23
24//===----------------------------------------------------------------------===//
25// BytecodeFileAnalyzer - Analyze from an mmap'able file descriptor.
26//
27
28namespace {
29 /// BytecodeFileAnalyzer - parses a bytecode file from a file
30 class BytecodeFileAnalyzer : public BytecodeAnalyzer {
31 private:
32 unsigned char *Buffer;
33 unsigned Length;
34
35 BytecodeFileAnalyzer(const BytecodeFileAnalyzer&); // Do not implement
36 void operator=(const BytecodeFileAnalyzer &BFR); // Do not implement
37
38 public:
39 BytecodeFileAnalyzer(const std::string &Filename, BytecodeAnalysis& bca);
40 ~BytecodeFileAnalyzer();
41 };
42}
43
44static std::string ErrnoMessage (int savedErrNum, std::string descr) {
45 return ::strerror(savedErrNum) + std::string(", while trying to ") + descr;
46}
47
48BytecodeFileAnalyzer::BytecodeFileAnalyzer(const std::string &Filename,
49 BytecodeAnalysis& bca) {
50 Buffer = (unsigned char*)ReadFileIntoAddressSpace(Filename, Length);
51 if (Buffer == 0)
52 throw "Error reading file '" + Filename + "'.";
53
54 try {
55 // Parse the bytecode we mmapped in
56 if ( bca.dumpBytecode )
57 DumpBytecode(Buffer, Length, bca, Filename);
58 AnalyzeBytecode(Buffer, Length, bca, Filename);
59 } catch (...) {
60 UnmapFileFromAddressSpace(Buffer, Length);
61 throw;
62 }
63}
64
65BytecodeFileAnalyzer::~BytecodeFileAnalyzer() {
66 // Unmmap the bytecode...
67 UnmapFileFromAddressSpace(Buffer, Length);
68}
69
70//===----------------------------------------------------------------------===//
71// BytecodeBufferAnalyzer - Read from a memory buffer
72//
73
74namespace {
75 /// BytecodeBufferAnalyzer - parses a bytecode file from a buffer
76 ///
77 class BytecodeBufferAnalyzer : public BytecodeAnalyzer {
78 private:
79 const unsigned char *Buffer;
80 bool MustDelete;
81
82 BytecodeBufferAnalyzer(const BytecodeBufferAnalyzer&); // Do not implement
83 void operator=(const BytecodeBufferAnalyzer &BFR); // Do not implement
84
85 public:
86 BytecodeBufferAnalyzer(const unsigned char *Buf, unsigned Length,
87 BytecodeAnalysis& bca, const std::string &ModuleID);
88 ~BytecodeBufferAnalyzer();
89
90 };
91}
92
93BytecodeBufferAnalyzer::BytecodeBufferAnalyzer(const unsigned char *Buf,
94 unsigned Length,
95 BytecodeAnalysis& bca,
96 const std::string &ModuleID) {
97 // If not aligned, allocate a new buffer to hold the bytecode...
98 const unsigned char *ParseBegin = 0;
99 if ((intptr_t)Buf & 3) {
100 Buffer = new unsigned char[Length+4];
101 unsigned Offset = 4 - ((intptr_t)Buffer & 3); // Make sure it's aligned
102 ParseBegin = Buffer + Offset;
103 memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over
104 MustDelete = true;
105 } else {
106 // If we don't need to copy it over, just use the caller's copy
107 ParseBegin = Buffer = Buf;
108 MustDelete = false;
109 }
110 try {
111 if ( bca.dumpBytecode )
112 DumpBytecode(ParseBegin, Length, bca, ModuleID);
113 AnalyzeBytecode(ParseBegin, Length, bca, ModuleID);
114 } catch (...) {
115 if (MustDelete) delete [] Buffer;
116 throw;
117 }
118}
119
120BytecodeBufferAnalyzer::~BytecodeBufferAnalyzer() {
121 if (MustDelete) delete [] Buffer;
122}
123
124//===----------------------------------------------------------------------===//
125// BytecodeStdinAnalyzer - Read bytecode from Standard Input
126//
127
128namespace {
129 /// BytecodeStdinAnalyzer - parses a bytecode file from stdin
130 ///
131 class BytecodeStdinAnalyzer : public BytecodeAnalyzer {
132 private:
133 std::vector<unsigned char> FileData;
134 unsigned char *FileBuf;
135
136 BytecodeStdinAnalyzer(const BytecodeStdinAnalyzer&); // Do not implement
137 void operator=(const BytecodeStdinAnalyzer &BFR); // Do not implement
138
139 public:
140 BytecodeStdinAnalyzer(BytecodeAnalysis& bca);
141 };
142}
143
144BytecodeStdinAnalyzer::BytecodeStdinAnalyzer(BytecodeAnalysis& bca ) {
145 int BlockSize;
146 unsigned char Buffer[4096*4];
147
148 // Read in all of the data from stdin, we cannot mmap stdin...
149 while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) {
150 if (BlockSize == -1)
151 throw ErrnoMessage(errno, "read from standard input");
152
153 FileData.insert(FileData.end(), Buffer, Buffer+BlockSize);
154 }
155
156 if (FileData.empty())
157 throw std::string("Standard Input empty!");
158
159 FileBuf = &FileData[0];
160 if (bca.dumpBytecode)
161 DumpBytecode(&FileData[0], FileData.size(), bca, "<stdin>");
162 AnalyzeBytecode(FileBuf, FileData.size(), bca, "<stdin>");
163}
164
165//===----------------------------------------------------------------------===//
166// Wrapper functions
167//===----------------------------------------------------------------------===//
168
169// AnalyzeBytecodeFile - analyze one file
170void llvm::AnalyzeBytecodeFile(const std::string &Filename,
171 BytecodeAnalysis& bca,
172 std::string *ErrorStr)
173{
174 try {
175 if ( Filename != "-" )
176 BytecodeFileAnalyzer bfa(Filename,bca);
177 else
178 BytecodeStdinAnalyzer bsa(bca);
179 } catch (std::string &err) {
180 if (ErrorStr) *ErrorStr = err;
181 }
182}
183
184// AnalyzeBytecodeBuffer - analyze a buffer
185void llvm::AnalyzeBytecodeBuffer(
186 const unsigned char* Buffer, ///< Pointer to start of bytecode buffer
187 unsigned BufferSize, ///< Size of the bytecode buffer
188 BytecodeAnalysis& Results, ///< The results of the analysis
189 std::string* ErrorStr ///< Errors, if any.
190 )
191{
192 try {
193 BytecodeBufferAnalyzer(Buffer, BufferSize, Results, "<buffer>" );
194 } catch (std::string& err ) {
195 if ( ErrorStr) *ErrorStr = err;
196 }
197}
198
199
200/// This function prints the contents of rhe BytecodeAnalysis structure in
201/// a human legible form.
202/// @brief Print BytecodeAnalysis structure to an ostream
203void llvm::PrintBytecodeAnalysis(BytecodeAnalysis& bca, std::ostream& Out )
204{
Reid Spenceredc3b582004-06-09 06:17:58 +0000205 Out << "Bytecode Analysis of " << bca.ModuleId << "\n";
206 Out << " File Size:" << bca.byteSize << "\n";
207 Out << " Number Of Types:" << bca.numTypes << "\n";
208 Out << " Number Of Constants:" << bca.numConstants << "\n";
209 Out << " Number Of Global Variables:" << bca.numGlobalVars << "\n";
210 Out << " Number Of Functions:" << bca.numFunctions << "\n";
211 Out << " Number Of Basic Blocks:" << bca.numBasicBlocks << "\n";
212 Out << " Number Of Instructions:" << bca.numInstructions << "\n";
213 Out << " Number Of Operands:" << bca.numOperands << "\n";
214 Out << "Number Of Compaction Tables:" << bca.numCmpctnTables << "\n";
215 Out << " Number Of Symbol Tables:" << bca.numSymTab << "\n";
216 Out << " Maximum Type Slot Number:" << bca.maxTypeSlot << "\n";
217 Out << " Maximum Value Slot Number:" << bca.maxValueSlot << "\n";
218 Out << " Bytecode Density:" << bca.density << "\n";
219
220 if ( bca.detailedResults )
221 Out << "Detailed Results Not Implemented Yet.\n";
222
223 if ( bca.dumpBytecode )
224 Out << bca.BytecodeDump;
Reid Spencerdac69c82004-06-07 17:53:43 +0000225}
226
227// vim: sw=2