//===- AnalyzerWrappers.cpp - Analyze bytecode from file or buffer -------===// // // The LLVM Compiler Infrastructure // // This file was developed by Reid Spencer and is distributed under the // University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements loading and analysis of a bytecode file and analyzing a // bytecode buffer. // //===----------------------------------------------------------------------===// #include "llvm/Bytecode/Analyzer.h" #include "AnalyzerInternals.h" #include "Support/FileUtilities.h" #include "Support/StringExtras.h" #include "Config/unistd.h" #include #include using namespace llvm; //===----------------------------------------------------------------------===// // BytecodeFileAnalyzer - Analyze from an mmap'able file descriptor. // namespace { /// BytecodeFileAnalyzer - parses a bytecode file from a file class BytecodeFileAnalyzer : public BytecodeAnalyzer { private: unsigned char *Buffer; unsigned Length; BytecodeFileAnalyzer(const BytecodeFileAnalyzer&); // Do not implement void operator=(const BytecodeFileAnalyzer &BFR); // Do not implement public: BytecodeFileAnalyzer(const std::string &Filename, BytecodeAnalysis& bca); ~BytecodeFileAnalyzer(); }; } static std::string ErrnoMessage (int savedErrNum, std::string descr) { return ::strerror(savedErrNum) + std::string(", while trying to ") + descr; } BytecodeFileAnalyzer::BytecodeFileAnalyzer(const std::string &Filename, BytecodeAnalysis& bca) { Buffer = (unsigned char*)ReadFileIntoAddressSpace(Filename, Length); if (Buffer == 0) throw "Error reading file '" + Filename + "'."; try { // Parse the bytecode we mmapped in if ( bca.dumpBytecode ) DumpBytecode(Buffer, Length, bca, Filename); AnalyzeBytecode(Buffer, Length, bca, Filename); } catch (...) { UnmapFileFromAddressSpace(Buffer, Length); throw; } } BytecodeFileAnalyzer::~BytecodeFileAnalyzer() { // Unmmap the bytecode... UnmapFileFromAddressSpace(Buffer, Length); } //===----------------------------------------------------------------------===// // BytecodeBufferAnalyzer - Read from a memory buffer // namespace { /// BytecodeBufferAnalyzer - parses a bytecode file from a buffer /// class BytecodeBufferAnalyzer : public BytecodeAnalyzer { private: const unsigned char *Buffer; bool MustDelete; BytecodeBufferAnalyzer(const BytecodeBufferAnalyzer&); // Do not implement void operator=(const BytecodeBufferAnalyzer &BFR); // Do not implement public: BytecodeBufferAnalyzer(const unsigned char *Buf, unsigned Length, BytecodeAnalysis& bca, const std::string &ModuleID); ~BytecodeBufferAnalyzer(); }; } BytecodeBufferAnalyzer::BytecodeBufferAnalyzer(const unsigned char *Buf, unsigned Length, BytecodeAnalysis& bca, const std::string &ModuleID) { // If not aligned, allocate a new buffer to hold the bytecode... const unsigned char *ParseBegin = 0; if ((intptr_t)Buf & 3) { Buffer = new unsigned char[Length+4]; unsigned Offset = 4 - ((intptr_t)Buffer & 3); // Make sure it's aligned ParseBegin = Buffer + Offset; memcpy((unsigned char*)ParseBegin, Buf, Length); // Copy it over MustDelete = true; } else { // If we don't need to copy it over, just use the caller's copy ParseBegin = Buffer = Buf; MustDelete = false; } try { if ( bca.dumpBytecode ) DumpBytecode(ParseBegin, Length, bca, ModuleID); AnalyzeBytecode(ParseBegin, Length, bca, ModuleID); } catch (...) { if (MustDelete) delete [] Buffer; throw; } } BytecodeBufferAnalyzer::~BytecodeBufferAnalyzer() { if (MustDelete) delete [] Buffer; } //===----------------------------------------------------------------------===// // BytecodeStdinAnalyzer - Read bytecode from Standard Input // namespace { /// BytecodeStdinAnalyzer - parses a bytecode file from stdin /// class BytecodeStdinAnalyzer : public BytecodeAnalyzer { private: std::vector FileData; unsigned char *FileBuf; BytecodeStdinAnalyzer(const BytecodeStdinAnalyzer&); // Do not implement void operator=(const BytecodeStdinAnalyzer &BFR); // Do not implement public: BytecodeStdinAnalyzer(BytecodeAnalysis& bca); }; } BytecodeStdinAnalyzer::BytecodeStdinAnalyzer(BytecodeAnalysis& bca ) { int BlockSize; unsigned char Buffer[4096*4]; // Read in all of the data from stdin, we cannot mmap stdin... while ((BlockSize = ::read(0 /*stdin*/, Buffer, 4096*4))) { if (BlockSize == -1) throw ErrnoMessage(errno, "read from standard input"); FileData.insert(FileData.end(), Buffer, Buffer+BlockSize); } if (FileData.empty()) throw std::string("Standard Input empty!"); FileBuf = &FileData[0]; if (bca.dumpBytecode) DumpBytecode(&FileData[0], FileData.size(), bca, ""); AnalyzeBytecode(FileBuf, FileData.size(), bca, ""); } //===----------------------------------------------------------------------===// // Wrapper functions //===----------------------------------------------------------------------===// // AnalyzeBytecodeFile - analyze one file void llvm::AnalyzeBytecodeFile(const std::string &Filename, BytecodeAnalysis& bca, std::string *ErrorStr) { try { if ( Filename != "-" ) BytecodeFileAnalyzer bfa(Filename,bca); else BytecodeStdinAnalyzer bsa(bca); } catch (std::string &err) { if (ErrorStr) *ErrorStr = err; } } // AnalyzeBytecodeBuffer - analyze a buffer void llvm::AnalyzeBytecodeBuffer( const unsigned char* Buffer, ///< Pointer to start of bytecode buffer unsigned BufferSize, ///< Size of the bytecode buffer BytecodeAnalysis& Results, ///< The results of the analysis std::string* ErrorStr ///< Errors, if any. ) { try { BytecodeBufferAnalyzer(Buffer, BufferSize, Results, "" ); } catch (std::string& err ) { if ( ErrorStr) *ErrorStr = err; } } /// This function prints the contents of rhe BytecodeAnalysis structure in /// a human legible form. /// @brief Print BytecodeAnalysis structure to an ostream namespace { inline static void print(std::ostream& Out, const char*title, unsigned val, bool nl = true ) { Out << std::setw(30) << std::right << title << std::setw(0) << ": " << std::setw(9) << val << "\n"; } inline static void print(std::ostream&Out, const char*title, double val ) { Out << std::setw(30) << std::right << title << std::setw(0) << ": " << std::setw(9) << std::setprecision(6) << val << "\n" ; } inline static void print(std::ostream&Out, const char*title, double top, double bot ) { Out << std::setw(30) << std::right << title << std::setw(0) << ": " << std::setw(9) << std::setprecision(6) << top << " (" << std::left << std::setw(0) << std::setprecision(4) << (top/bot)*100.0 << "%)\n"; } inline static void print(std::ostream&Out, const char*title, std::string val, bool nl = true) { Out << std::setw(30) << std::right << title << std::setw(0) << ": " << std::left << val << (nl ? "\n" : ""); } } void llvm::PrintBytecodeAnalysis(BytecodeAnalysis& bca, std::ostream& Out ) { print(Out, "Bytecode Analysis Of Module", bca.ModuleId); print(Out, "File Size", bca.byteSize); print(Out, "Bytecode Compression Index",std::string("TBD")); print(Out, "Number Of Bytecode Blocks", bca.numBlocks); print(Out, "Number Of Types", bca.numTypes); print(Out, "Number Of Values", bca.numValues); print(Out, "Number Of Constants", bca.numConstants); print(Out, "Number Of Global Variables", bca.numGlobalVars); print(Out, "Number Of Functions", bca.numFunctions); print(Out, "Number Of Basic Blocks", bca.numBasicBlocks); print(Out, "Number Of Instructions", bca.numInstructions); print(Out, "Number Of Operands", bca.numOperands); print(Out, "Number Of Compaction Tables", bca.numCmpctnTables); print(Out, "Number Of Symbol Tables", bca.numSymTab); print(Out, "Long Instructions", bca.longInstructions); print(Out, "Instruction Size", bca.instructionSize); print(Out, "Average Instruction Size", double(bca.instructionSize)/double(bca.numInstructions)); print(Out, "Maximum Type Slot Number", bca.maxTypeSlot); print(Out, "Maximum Value Slot Number", bca.maxValueSlot); print(Out, "Bytes Thrown To Alignment", double(bca.numAlignment), double(bca.byteSize)); print(Out, "File Density (bytes/def)", bca.fileDensity); print(Out, "Globals Density (bytes/def)", bca.globalsDensity); print(Out, "Function Density (bytes/func)", bca.functionDensity); print(Out, "Number of VBR 32-bit Integers", bca.vbrCount32); print(Out, "Number of VBR 64-bit Integers", bca.vbrCount64); print(Out, "Number of VBR Compressed Bytes", bca.vbrCompBytes); print(Out, "Number of VBR Expanded Bytes", bca.vbrExpdBytes); print(Out, "VBR Savings", double(bca.vbrExpdBytes)-double(bca.vbrCompBytes), double(bca.byteSize)); if ( bca.detailedResults ) { print(Out, "Module Bytes", double(bca.BlockSizes[BytecodeFormat::Module]), double(bca.byteSize)); print(Out, "Function Bytes", double(bca.BlockSizes[BytecodeFormat::Function]), double(bca.byteSize)); print(Out, "Constant Pool Bytes", double(bca.BlockSizes[BytecodeFormat::ConstantPool]), double(bca.byteSize)); print(Out, "Symbol Table Bytes", double(bca.BlockSizes[BytecodeFormat::SymbolTable]), double(bca.byteSize)); print(Out, "Module Global Info Bytes", double(bca.BlockSizes[BytecodeFormat::ModuleGlobalInfo]), double(bca.byteSize)); print(Out, "Global Type Plane Bytes", double(bca.BlockSizes[BytecodeFormat::GlobalTypePlane]), double(bca.byteSize)); print(Out, "Basic Block Bytes", double(bca.BlockSizes[BytecodeFormat::BasicBlock]), double(bca.byteSize)); print(Out, "Instruction List Bytes", double(bca.BlockSizes[BytecodeFormat::InstructionList]), double(bca.byteSize)); print(Out, "Compaction Table Bytes", double(bca.BlockSizes[BytecodeFormat::CompactionTable]), double(bca.byteSize)); std::map::iterator I = bca.FunctionInfo.begin(); std::map::iterator E = bca.FunctionInfo.end(); while ( I != E ) { Out << std::left << std::setw(0); Out << "Function: " << I->second.name << "\n"; print(Out, "Type:", I->second.description); print(Out, "Byte Size", I->second.byteSize); print(Out, "Instructions", I->second.numInstructions); print(Out, "Long Instructions", I->second.longInstructions); print(Out, "Instruction Size", I->second.instructionSize); print(Out, "Average Instruction Size", double(I->second.instructionSize)/double(I->second.numInstructions)); print(Out, "Basic Blocks", I->second.numBasicBlocks); print(Out, "Operand", I->second.numOperands); print(Out, "Function Density", I->second.density); print(Out, "Number of VBR 32-bit Integers", I->second.vbrCount32); print(Out, "Number of VBR 64-bit Integers", I->second.vbrCount64); print(Out, "Number of VBR Compressed Bytes", I->second.vbrCompBytes); print(Out, "Number of VBR Expanded Bytes", I->second.vbrExpdBytes); print(Out, "VBR Savings", double(I->second.vbrExpdBytes)-double(I->second.vbrCompBytes), double(I->second.byteSize)); ++I; } } if ( bca.dumpBytecode ) Out << bca.BytecodeDump; } // vim: sw=2