mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-07 11:33:44 +00:00
1cf5024de1
instructions generated. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14154 91177308-0d34-0410-b5e6-96231b3b80d8
333 lines
12 KiB
C++
333 lines
12 KiB
C++
//===- 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 <cerrno>
|
|
#include <iomanip>
|
|
|
|
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<unsigned char> 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, "<stdin>");
|
|
AnalyzeBytecode(FileBuf, FileData.size(), bca, "<stdin>");
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// 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, "<buffer>" );
|
|
} 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<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::iterator I =
|
|
bca.FunctionInfo.begin();
|
|
std::map<const Function*,BytecodeAnalysis::BytecodeFunctionInfo>::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
|