From: Reid Spencer Date: Tue, 29 Jun 2004 23:21:53 +0000 (+0000) Subject: Analyzer moved to ../Reader directory. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=cc1091e66b0b4be95479ed0575950c466ca180b6;p=oota-llvm.git Analyzer moved to ../Reader directory. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@14491 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Bytecode/Analyzer/Analyzer.cpp b/lib/Bytecode/Analyzer/Analyzer.cpp deleted file mode 100644 index 94680949cb5..00000000000 --- a/lib/Bytecode/Analyzer/Analyzer.cpp +++ /dev/null @@ -1,297 +0,0 @@ -//===-- BytecodeHandler.cpp - Parsing Handler -------------------*- C++ -*-===// -// -// 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 header file defines the BytecodeHandler class that gets called by the -// AbstractBytecodeParser when parsing events occur. -// -//===----------------------------------------------------------------------===// - -#include "AnalyzerInternals.h" -#include - -using namespace llvm; - - -namespace { - -class AnalyzerHandler : public BytecodeHandler { - BytecodeAnalysis& bca; - BytecodeAnalysis::BytecodeFunctionInfo* currFunc; -public: - AnalyzerHandler(BytecodeAnalysis& TheBca) - : bca(TheBca) - , currFunc(0) - { } - - virtual bool handleError(const std::string& str ) { - return false; - } - - virtual void handleStart() { - bca.ModuleId.clear(); - bca.numBlocks = 0; - bca.numTypes = 0; - bca.numValues = 0; - bca.numFunctions = 0; - bca.numConstants = 0; - bca.numGlobalVars = 0; - bca.numInstructions = 0; - bca.numBasicBlocks = 0; - bca.numOperands = 0; - bca.numCmpctnTables = 0; - bca.numSymTab = 0; - bca.maxTypeSlot = 0; - bca.maxValueSlot = 0; - bca.numAlignment = 0; - bca.fileDensity = 0.0; - bca.globalsDensity = 0.0; - bca.functionDensity = 0.0; - bca.instructionSize = 0; - bca.longInstructions = 0; - bca.vbrCount32 = 0; - bca.vbrCount64 = 0; - bca.vbrCompBytes = 0; - bca.vbrExpdBytes = 0; - bca.FunctionInfo.clear(); - bca.BytecodeDump.clear(); - bca.BlockSizes[BytecodeFormat::Module] = 0; - bca.BlockSizes[BytecodeFormat::Function] = 0; - bca.BlockSizes[BytecodeFormat::ConstantPool] = 0; - bca.BlockSizes[BytecodeFormat::SymbolTable] = 0; - bca.BlockSizes[BytecodeFormat::ModuleGlobalInfo] = 0; - bca.BlockSizes[BytecodeFormat::GlobalTypePlane] = 0; - bca.BlockSizes[BytecodeFormat::BasicBlock] = 0; - bca.BlockSizes[BytecodeFormat::InstructionList] = 0; - bca.BlockSizes[BytecodeFormat::CompactionTable] = 0; - } - - virtual void handleFinish() { - bca.fileDensity = double(bca.byteSize) / double( bca.numTypes + bca.numValues ); - double globalSize = 0.0; - globalSize += double(bca.BlockSizes[BytecodeFormat::ConstantPool]); - globalSize += double(bca.BlockSizes[BytecodeFormat::ModuleGlobalInfo]); - globalSize += double(bca.BlockSizes[BytecodeFormat::GlobalTypePlane]); - bca.globalsDensity = globalSize / double( bca.numTypes + bca.numConstants + - bca.numGlobalVars ); - bca.functionDensity = double(bca.BlockSizes[BytecodeFormat::Function]) / - double(bca.numFunctions); - } - - virtual void handleModuleBegin(const std::string& id) { - bca.ModuleId = id; - } - - virtual void handleModuleEnd(const std::string& id) { } - - virtual void handleVersionInfo( - unsigned char RevisionNum, ///< Byte code revision number - Module::Endianness Endianness, ///< Endianness indicator - Module::PointerSize PointerSize ///< PointerSize indicator - ) { } - - virtual void handleModuleGlobalsBegin(unsigned size) { } - - virtual void handleGlobalVariable( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes ///< The linkage type of the GV - ) { - bca.numGlobalVars++; - bca.numValues++; - } - - virtual void handleInitializedGV( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes,///< The linkage type of the GV - unsigned initSlot ///< Slot number of GV's initializer - ) { - bca.numGlobalVars++; - bca.numValues++; - } - - virtual void handleType( const Type* Ty ) { bca.numTypes++; } - - virtual void handleFunctionDeclaration( - Function* Func, ///< The function - const FunctionType* FuncType ///< The type of the function - ) { - bca.numFunctions++; - bca.numValues++; - } - - virtual void handleModuleGlobalsEnd() { } - - virtual void handleCompactionTableBegin() { } - - virtual void handleCompactionTablePlane( unsigned Ty, unsigned NumEntries) { - bca.numCmpctnTables++; - } - - virtual void handleCompactionTableType( unsigned i, unsigned TypSlot, - const Type* ) {} - - virtual void handleCompactionTableValue( - unsigned i, - unsigned ValSlot, - const Type* ) { } - - virtual void handleCompactionTableEnd() { } - - virtual void handleSymbolTableBegin() { bca.numSymTab++; } - - virtual void handleSymbolTablePlane( unsigned Ty, unsigned NumEntries, - const Type* Typ) { } - - virtual void handleSymbolTableType( unsigned i, unsigned slot, - const std::string& name ) { } - - virtual void handleSymbolTableValue( unsigned i, unsigned slot, - const std::string& name ) { } - - virtual void handleSymbolTableEnd() { } - - virtual void handleFunctionBegin( Function* Func, unsigned Size) { - const FunctionType* FType = - cast(Func->getType()->getElementType()); - currFunc = &bca.FunctionInfo[Func]; - currFunc->description = FType->getDescription(); - currFunc->name = Func->getName(); - currFunc->byteSize = Size; - currFunc->numInstructions = 0; - currFunc->numBasicBlocks = 0; - currFunc->numPhis = 0; - currFunc->numOperands = 0; - currFunc->density = 0.0; - currFunc->instructionSize = 0; - currFunc->longInstructions = 0; - currFunc->vbrCount32 = 0; - currFunc->vbrCount64 = 0; - currFunc->vbrCompBytes = 0; - currFunc->vbrExpdBytes = 0; - } - - virtual void handleFunctionEnd( Function* Func) { - currFunc->density = double(currFunc->byteSize) / - double(currFunc->numInstructions+currFunc->numBasicBlocks); - } - - virtual void handleBasicBlockBegin( unsigned blocknum) { - bca.numBasicBlocks++; - bca.numValues++; - if ( currFunc ) currFunc->numBasicBlocks++; - } - - virtual bool handleInstruction( unsigned Opcode, const Type* iType, - std::vector& Operands, unsigned Size) { - bca.numInstructions++; - bca.numValues++; - bca.instructionSize += Size; - if (Size > 4 ) bca.longInstructions++; - bca.numOperands += Operands.size(); - if ( currFunc ) { - currFunc->numInstructions++; - currFunc->instructionSize += Size; - if (Size > 4 ) currFunc->longInstructions++; - if ( Opcode == Instruction::PHI ) currFunc->numPhis++; - } - return Instruction::isTerminator(Opcode); - } - - virtual void handleBasicBlockEnd(unsigned blocknum) { } - - virtual void handleGlobalConstantsBegin() { } - - virtual void handleConstantExpression( unsigned Opcode, const Type* Typ, - std::vector > ArgVec ) { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleConstantValue( Constant * c ) { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleConstantArray( const ArrayType* AT, - std::vector& Elements ) { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleConstantStruct( - const StructType* ST, - std::vector& ElementSlots) - { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleConstantPointer( const PointerType* PT, unsigned Slot) { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleConstantString( const ConstantArray* CA ) { - bca.numConstants++; - bca.numValues++; - } - - virtual void handleGlobalConstantsEnd() { } - - virtual void handleAlignment(unsigned numBytes) { - bca.numAlignment += numBytes; - } - - virtual void handleBlock( - unsigned BType, const unsigned char* StartPtr, unsigned Size) { - bca.numBlocks++; - bca.BlockSizes[llvm::BytecodeFormat::FileBlockIDs(BType)] += Size; - } - - virtual void handleVBR32(unsigned Size ) { - bca.vbrCount32++; - bca.vbrCompBytes += Size; - bca.vbrExpdBytes += sizeof(uint32_t); - if (currFunc) { - currFunc->vbrCount32++; - currFunc->vbrCompBytes += Size; - currFunc->vbrExpdBytes += sizeof(uint32_t); - } - } - - virtual void handleVBR64(unsigned Size ) { - bca.vbrCount64++; - bca.vbrCompBytes += Size; - bca.vbrExpdBytes += sizeof(uint64_t); - if ( currFunc ) { - currFunc->vbrCount64++; - currFunc->vbrCompBytes += Size; - currFunc->vbrExpdBytes += sizeof(uint64_t); - } - } -}; - -} - -void llvm::BytecodeAnalyzer::AnalyzeBytecode( - const unsigned char *Buf, - unsigned Length, - BytecodeAnalysis& bca, - const std::string &ModuleID -) -{ - bca.byteSize = Length; - AnalyzerHandler TheHandler(bca); - AbstractBytecodeParser TheParser(&TheHandler, true, true, true); - TheParser.ParseBytecode( Buf, Length, ModuleID ); - TheParser.ParseAllFunctionBodies(); -} - -// vim: sw=2 diff --git a/lib/Bytecode/Analyzer/AnalyzerInternals.h b/lib/Bytecode/Analyzer/AnalyzerInternals.h deleted file mode 100644 index d7733c7176b..00000000000 --- a/lib/Bytecode/Analyzer/AnalyzerInternals.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- ReaderInternals.h - Definitions internal to the reader --*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header file defines various stuff that is used by the bytecode reader. -// -//===----------------------------------------------------------------------===// - -#ifndef ANALYZER_INTERNALS_H -#define ANALYZER_INTERNALS_H - -#include "Parser.h" -#include "llvm/Bytecode/Analyzer.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" - - -namespace llvm { - -class BytecodeAnalyzer { - BytecodeAnalyzer(const BytecodeAnalyzer &); // DO NOT IMPLEMENT - void operator=(const BytecodeAnalyzer &); // DO NOT IMPLEMENT -public: - BytecodeAnalyzer() { } - ~BytecodeAnalyzer() { } - - void AnalyzeBytecode( - const unsigned char *Buf, - unsigned Length, - BytecodeAnalysis& bca, - const std::string &ModuleID - ); - - void DumpBytecode( - const unsigned char *Buf, - unsigned Length, - BytecodeAnalysis& bca, - const std::string &ModuleID - ); -}; - -} // End llvm namespace - -#endif - -// vim: sw=2 diff --git a/lib/Bytecode/Analyzer/AnalyzerWrappers.cpp b/lib/Bytecode/Analyzer/AnalyzerWrappers.cpp deleted file mode 100644 index f8493170fa4..00000000000 --- a/lib/Bytecode/Analyzer/AnalyzerWrappers.cpp +++ /dev/null @@ -1,332 +0,0 @@ -//===- 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 diff --git a/lib/Bytecode/Analyzer/Dumper.cpp b/lib/Bytecode/Analyzer/Dumper.cpp deleted file mode 100644 index 280a12ba73f..00000000000 --- a/lib/Bytecode/Analyzer/Dumper.cpp +++ /dev/null @@ -1,274 +0,0 @@ -//===-- BytecodeDumper.cpp - Parsing Handler --------------------*- C++ -*-===// -// -// 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 header file defines the BytecodeDumper class that gets called by the -// AbstractBytecodeParser when parsing events occur. It merely dumps the -// information presented to it from the parser. -// -//===----------------------------------------------------------------------===// - -#include "AnalyzerInternals.h" -#include "llvm/Constant.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Instruction.h" -#include "llvm/Type.h" - -using namespace llvm; - -namespace { - -class BytecodeDumper : public llvm::BytecodeHandler { -public: - - virtual bool handleError(const std::string& str ) - { - std::cout << "ERROR: " << str << "\n"; - return true; - } - - virtual void handleStart() - { - std::cout << "Bytecode {\n"; - } - - virtual void handleFinish() - { - std::cout << "} End Bytecode\n"; - } - - virtual void handleModuleBegin(const std::string& id) - { - std::cout << " Module " << id << " {\n"; - } - - virtual void handleModuleEnd(const std::string& id) - { - std::cout << " } End Module " << id << "\n"; - } - - virtual void handleVersionInfo( - unsigned char RevisionNum, ///< Byte code revision number - Module::Endianness Endianness, ///< Endianness indicator - Module::PointerSize PointerSize ///< PointerSize indicator - ) - { - std::cout << " RevisionNum: " << int(RevisionNum) - << " Endianness: " << Endianness - << " PointerSize: " << PointerSize << "\n"; - } - - virtual void handleModuleGlobalsBegin() - { - std::cout << " BLOCK: ModuleGlobalInfo {\n"; - } - - virtual void handleGlobalVariable( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes Linkage ///< The linkage type of the GV - ) - { - std::cout << " GV: Uninitialized, " - << ( isConstant? "Constant, " : "Variable, ") - << " Linkage=" << Linkage << " Type=" - << ElemType->getDescription() << "\n"; - } - - virtual void handleInitializedGV( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes Linkage,///< The linkage type of the GV - unsigned initSlot ///< Slot number of GV's initializer - ) - { - std::cout << " GV: Initialized, " - << ( isConstant? "Constant, " : "Variable, ") - << " Linkage=" << Linkage << " Type=" - << ElemType->getDescription() - << " InitializerSlot=" << initSlot << "\n"; - } - - virtual void handleType( const Type* Ty ) { - std::cout << " Type: " << Ty->getDescription() << "\n"; - } - - virtual void handleFunctionDeclaration( - Function* Func, - const FunctionType* FuncType) { - std::cout << " Function: " << FuncType->getDescription() << "\n"; - } - - virtual void handleModuleGlobalsEnd() { - std::cout << " } END BLOCK: ModuleGlobalInfo\n"; - } - - virtual void handleCompactionTableBegin() { - std::cout << " BLOCK: CompactionTable {\n"; - } - - virtual void handleCompactionTablePlane( unsigned Ty, unsigned NumEntries ) { - std::cout << " Plane: Ty=" << Ty << " Size=" << NumEntries << "\n"; - } - - virtual void handleCompactionTableType( - unsigned i, - unsigned TypSlot, - const Type* Ty) { - std::cout << " Type: " << i << " Slot:" << TypSlot - << " is " << Ty->getDescription() << "\n"; - } - - virtual void handleCompactionTableValue( - unsigned i, - unsigned ValSlot, - const Type* Ty ) { - std::cout << " Value: " << i << " Slot:" << ValSlot - << " is " << Ty->getDescription() << "\n"; - } - - virtual void handleCompactionTableEnd() { - std::cout << " } END BLOCK: CompactionTable\n"; - } - - virtual void handleSymbolTableBegin() { - std::cout << " BLOCK: SymbolTable {\n"; - } - - virtual void handleSymbolTablePlane( - unsigned Ty, - unsigned NumEntries, - const Type* Typ) { - std::cout << " Plane: Ty=" << Ty << " Size=" << NumEntries - << " Type: " << Typ->getDescription() << "\n"; - } - - virtual void handleSymbolTableType( - unsigned i, - unsigned slot, - const std::string& name ) { - std::cout << " Type " << i << " Slot=" << slot - << " Name: " << name << "\n"; - } - - virtual void handleSymbolTableValue( - unsigned i, - unsigned slot, - const std::string& name ) { - std::cout << " Value " << i << " Slot=" << slot - << " Name: " << name << "\n"; - } - - virtual void handleSymbolTableEnd() { - std::cout << " } END BLOCK: SymbolTable\n"; - } - - virtual void handleFunctionBegin( - const Type* FType, GlobalValue::LinkageTypes linkage ) { - std::cout << "BLOCK: Function {\n"; - std::cout << " Linkage: " << linkage << "\n"; - std::cout << " Type: " << FType->getDescription() << "\n"; - } - - virtual void handleFunctionEnd( const Type* FType) { - std::cout << "} END BLOCK: Function\n"; - } - - virtual void handleBasicBlockBegin( unsigned blocknum) { - std::cout << " BLOCK: BasicBlock #" << blocknum << "{\n"; - } - - virtual bool handleInstruction( - unsigned Opcode, - const Type* iType, - std::vector& Operands, - unsigned Size) { - std::cout << " INST: OpCode=" - << Instruction::getOpcodeName(Opcode) << " Type=" - << iType->getDescription() << "\n"; - for ( unsigned i = 0; i < Operands.size(); ++i ) - std::cout << " Op#" << i << " Slot=" << Operands[i] << "\n"; - - return Instruction::isTerminator(Opcode); - } - - virtual void handleBasicBlockEnd(unsigned blocknum) { - std::cout << " } END BLOCK: BasicBlock #" << blocknum << "{\n"; - } - - virtual void handleGlobalConstantsBegin() { - std::cout << " BLOCK: GlobalConstants {\n"; - } - - virtual void handleConstantExpression( - unsigned Opcode, - const Type* Typ, - std::vector > ArgVec - ) { - std::cout << " EXPR: " << Instruction::getOpcodeName(Opcode) - << " Type=" << Typ->getDescription() << "\n"; - for ( unsigned i = 0; i < ArgVec.size(); ++i ) - std::cout << " Arg#" << i << " Type=" - << ArgVec[i].first->getDescription() << " Slot=" - << ArgVec[i].second << "\n"; - } - - virtual void handleConstantValue( Constant * c ) { - std::cout << " VALUE: "; - c->print(std::cout); - std::cout << "\n"; - } - - virtual void handleConstantArray(const ArrayType* AT, - std::vector& Elements ) { - std::cout << " ARRAY: " << AT->getDescription() << "\n"; - for ( unsigned i = 0; i < Elements.size(); ++i ) - std::cout << " #" << i << " Slot=" << Elements[i] << "\n"; - } - - virtual void handleConstantStruct( const StructType* ST, - std::vector& Elements) { - std::cout << " STRUC: " << ST->getDescription() << "\n"; - for ( unsigned i = 0; i < Elements.size(); ++i ) - std::cout << " #" << i << " Slot=" << Elements[i] << "\n"; - } - - virtual void handleConstantPointer( - const PointerType* PT, unsigned Slot) - { - std::cout << " POINT: " << PT->getDescription() - << " Slot=" << Slot << "\n"; - } - - virtual void handleConstantString( const ConstantArray* CA ) { - std::cout << " STRNG: "; - CA->print(std::cout); - std::cout << "\n"; - } - - virtual void handleGlobalConstantsEnd() { - std::cout << " } END BLOCK: GlobalConstants\n"; - } -}; - -} - -void BytecodeAnalyzer::DumpBytecode( - const unsigned char *Buf, - unsigned Length, - BytecodeAnalysis& bca, - const std::string &ModuleID) { - BytecodeDumper TheHandler; - AbstractBytecodeParser TheParser(&TheHandler); - TheParser.ParseBytecode( Buf, Length, ModuleID ); - if ( bca.detailedResults ) - TheParser.ParseAllFunctionBodies(); -} - -// vim: sw=2 diff --git a/lib/Bytecode/Analyzer/Makefile b/lib/Bytecode/Analyzer/Makefile deleted file mode 100644 index f3327cd8d5a..00000000000 --- a/lib/Bytecode/Analyzer/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -##===- lib/Bytecode/Reader/Makefile ------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file was developed by the LLVM research group and is distributed under -# the University of Illinois Open Source License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../.. -LIBRARYNAME = bcanalyzer - -include $(LEVEL)/Makefile.common - diff --git a/lib/Bytecode/Analyzer/Parser.cpp b/lib/Bytecode/Analyzer/Parser.cpp deleted file mode 100644 index c79318a02c9..00000000000 --- a/lib/Bytecode/Analyzer/Parser.cpp +++ /dev/null @@ -1,1062 +0,0 @@ -//===- Parser.cpp - Code to parse bytecode files --------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file was developed by the LLVM research group and is distributed under -// the University of Illinois Open Source License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This library implements the functionality defined in llvm/Bytecode/Parser.h -// -// Note that this library should be as fast as possible, reentrant, and -// threadsafe!! -// -// TODO: Allow passing in an option to ignore the symbol table -// -//===----------------------------------------------------------------------===// - -#include "AnalyzerInternals.h" -#include "llvm/Module.h" -#include "llvm/Bytecode/Format.h" -#include "Support/StringExtras.h" -#include -#include - -using namespace llvm; - -// Enable to trace to figure out what the heck is going on when parsing fails -//#define TRACE_LEVEL 10 -//#define DEBUG_OUTPUT - -#if TRACE_LEVEL // ByteCodeReading_TRACEr -#define BCR_TRACE(n, X) \ - if (n < TRACE_LEVEL) std::cerr << std::string(n*2, ' ') << X -#else -#define BCR_TRACE(n, X) -#endif - -#define PARSE_ERROR(inserters) { \ - std::ostringstream errormsg; \ - errormsg << inserters; \ - if ( ! handler->handleError( errormsg.str() ) ) \ - throw std::string(errormsg.str()); \ - } - -inline bool AbstractBytecodeParser::moreInBlock() { - return At < BlockEnd; -} - -inline void AbstractBytecodeParser::checkPastBlockEnd(const char * block_name) { - if ( At > BlockEnd ) - PARSE_ERROR("Attempt to read past the end of " << block_name << " block."); -} - -inline void AbstractBytecodeParser::align32() { - BufPtr Save = At; - At = (const unsigned char *)((unsigned long)(At+3) & (~3UL)); - if ( reportAlignment && At > Save ) handler->handleAlignment( At - Save ); - if (At > BlockEnd) - throw std::string("Ran out of data while aligning!"); -} - -inline unsigned AbstractBytecodeParser::read_uint() { - if (At+4 > BlockEnd) - throw std::string("Ran out of data reading uint!"); - At += 4; - return At[-4] | (At[-3] << 8) | (At[-2] << 16) | (At[-1] << 24); -} - -inline unsigned AbstractBytecodeParser::read_vbr_uint() { - unsigned Shift = 0; - unsigned Result = 0; - BufPtr Save = At; - - do { - if (At == BlockEnd) - throw std::string("Ran out of data reading vbr_uint!"); - Result |= (unsigned)((*At++) & 0x7F) << Shift; - Shift += 7; - } while (At[-1] & 0x80); - if (reportVBR) - handler->handleVBR32(At-Save); - return Result; -} - -inline uint64_t AbstractBytecodeParser::read_vbr_uint64() { - unsigned Shift = 0; - uint64_t Result = 0; - BufPtr Save = At; - - do { - if (At == BlockEnd) - throw std::string("Ran out of data reading vbr_uint64!"); - Result |= (uint64_t)((*At++) & 0x7F) << Shift; - Shift += 7; - } while (At[-1] & 0x80); - if (reportVBR) - handler->handleVBR64(At-Save); - return Result; -} - -inline int64_t AbstractBytecodeParser::read_vbr_int64() { - uint64_t R = read_vbr_uint64(); - if (R & 1) { - if (R != 1) - return -(int64_t)(R >> 1); - else // There is no such thing as -0 with integers. "-0" really means - // 0x8000000000000000. - return 1LL << 63; - } else - return (int64_t)(R >> 1); -} - -inline std::string AbstractBytecodeParser::read_str() { - unsigned Size = read_vbr_uint(); - const unsigned char *OldAt = At; - At += Size; - if (At > BlockEnd) // Size invalid? - throw std::string("Ran out of data reading a string!"); - return std::string((char*)OldAt, Size); -} - -inline void AbstractBytecodeParser::read_data(void *Ptr, void *End) { - unsigned char *Start = (unsigned char *)Ptr; - unsigned Amount = (unsigned char *)End - Start; - if (At+Amount > BlockEnd) - throw std::string("Ran out of data!"); - std::copy(At, At+Amount, Start); - At += Amount; -} - -inline void AbstractBytecodeParser::readBlock(unsigned &Type, unsigned &Size) { - Type = read_uint(); - Size = read_uint(); - BlockStart = At; - if ( At + Size > BlockEnd ) - throw std::string("Attempt to size a block past end of memory"); - BlockEnd = At + Size; - if ( reportBlocks ) { - handler->handleBlock( Type, BlockStart, Size ); - } -} - -const Type *AbstractBytecodeParser::getType(unsigned ID) { -//cerr << "Looking up Type ID: " << ID << "\n"; - -if (ID < Type::FirstDerivedTyID) - if (const Type *T = Type::getPrimitiveType((Type::TypeID)ID)) - return T; // Asked for a primitive type... - -// Otherwise, derived types need offset... -ID -= Type::FirstDerivedTyID; - -if (!CompactionTypeTable.empty()) { - if (ID >= CompactionTypeTable.size()) - PARSE_ERROR("Type ID out of range for compaction table!"); - return CompactionTypeTable[ID]; -} - -// Is it a module-level type? - if (ID < ModuleTypes.size()) - return ModuleTypes[ID].get(); - - // Nope, is it a function-level type? - ID -= ModuleTypes.size(); - if (ID < FunctionTypes.size()) - return FunctionTypes[ID].get(); - - PARSE_ERROR("Illegal type reference!"); - return Type::VoidTy; -} - -bool AbstractBytecodeParser::ParseInstruction(std::vector &Operands) { - BufPtr SaveAt = At; - Operands.clear(); - unsigned iType = 0; - unsigned Opcode = 0; - unsigned Op = read_uint(); - - // bits Instruction format: Common to all formats - // -------------------------- - // 01-00: Opcode type, fixed to 1. - // 07-02: Opcode - Opcode = (Op >> 2) & 63; - Operands.resize((Op >> 0) & 03); - - switch (Operands.size()) { - case 1: - // bits Instruction format: - // -------------------------- - // 19-08: Resulting type plane - // 31-20: Operand #1 (if set to (2^12-1), then zero operands) - // - iType = (Op >> 8) & 4095; - Operands[0] = (Op >> 20) & 4095; - if (Operands[0] == 4095) // Handle special encoding for 0 operands... - Operands.resize(0); - break; - case 2: - // bits Instruction format: - // -------------------------- - // 15-08: Resulting type plane - // 23-16: Operand #1 - // 31-24: Operand #2 - // - iType = (Op >> 8) & 255; - Operands[0] = (Op >> 16) & 255; - Operands[1] = (Op >> 24) & 255; - break; - case 3: - // bits Instruction format: - // -------------------------- - // 13-08: Resulting type plane - // 19-14: Operand #1 - // 25-20: Operand #2 - // 31-26: Operand #3 - // - iType = (Op >> 8) & 63; - Operands[0] = (Op >> 14) & 63; - Operands[1] = (Op >> 20) & 63; - Operands[2] = (Op >> 26) & 63; - break; - case 0: - At -= 4; // Hrm, try this again... - Opcode = read_vbr_uint(); - Opcode >>= 2; - iType = read_vbr_uint(); - - unsigned NumOperands = read_vbr_uint(); - Operands.resize(NumOperands); - - if (NumOperands == 0) - PARSE_ERROR("Zero-argument instruction found; this is invalid."); - - for (unsigned i = 0; i != NumOperands; ++i) - Operands[i] = read_vbr_uint(); - align32(); - break; - } - - return handler->handleInstruction(Opcode, getType(iType), Operands, At-SaveAt); -} - -/// ParseBasicBlock - In LLVM 1.0 bytecode files, we used to output one -/// basicblock at a time. This method reads in one of the basicblock packets. -void AbstractBytecodeParser::ParseBasicBlock( unsigned BlockNo) { - handler->handleBasicBlockBegin( BlockNo ); - - std::vector Args; - bool is_terminating = false; - while ( moreInBlock() ) - is_terminating = ParseInstruction(Args); - - if ( ! is_terminating ) - PARSE_ERROR("Non-terminated basic block found!"); - - handler->handleBasicBlockEnd( BlockNo ); -} - -/// ParseInstructionList - Parse all of the BasicBlock's & Instruction's in the -/// body of a function. In post 1.0 bytecode files, we no longer emit basic -/// block individually, in order to avoid per-basic-block overhead. -unsigned AbstractBytecodeParser::ParseInstructionList() { - unsigned BlockNo = 0; - std::vector Args; - - while ( moreInBlock() ) { - handler->handleBasicBlockBegin( BlockNo ); - - // Read instructions into this basic block until we get to a terminator - bool is_terminating = false; - while (moreInBlock() && !is_terminating ) - is_terminating = ParseInstruction(Args ) ; - - if (!is_terminating) - PARSE_ERROR( "Non-terminated basic block found!"); - - handler->handleBasicBlockEnd( BlockNo ); - ++BlockNo; - } - return BlockNo; -} - -void AbstractBytecodeParser::ParseSymbolTable() { - handler->handleSymbolTableBegin(); - - while ( moreInBlock() ) { - // Symtab block header: [num entries][type id number] - unsigned NumEntries = read_vbr_uint(); - unsigned Typ = read_vbr_uint(); - const Type *Ty = getType(Typ); - - handler->handleSymbolTablePlane( Typ, NumEntries, Ty ); - - for (unsigned i = 0; i != NumEntries; ++i) { - // Symtab entry: [def slot #][name] - unsigned slot = read_vbr_uint(); - std::string Name = read_str(); - - if (Typ == Type::TypeTyID) - handler->handleSymbolTableType( i, slot, Name ); - else - handler->handleSymbolTableValue( i, slot, Name ); - } - } - checkPastBlockEnd("Symbol Table"); - - handler->handleSymbolTableEnd(); -} - -void AbstractBytecodeParser::ParseFunctionLazily() { - if (FunctionSignatureList.empty()) - throw std::string("FunctionSignatureList empty!"); - - Function *Func = FunctionSignatureList.back(); - FunctionSignatureList.pop_back(); - - // Save the information for future reading of the function - LazyFunctionLoadMap[Func] = LazyFunctionInfo(BlockStart, BlockEnd); - - // Pretend we've `parsed' this function - At = BlockEnd; -} - -void AbstractBytecodeParser::ParseNextFunction(Function* Func) { - // Find {start, end} pointers and slot in the map. If not there, we're done. - LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.find(Func); - - // Make sure we found it - if ( Fi == LazyFunctionLoadMap.end() ) { - PARSE_ERROR("Unrecognized function of type " << Func->getType()->getDescription()); - return; - } - - BlockStart = At = Fi->second.Buf; - BlockEnd = Fi->second.Buf; - assert(Fi->first == Func); - - LazyFunctionLoadMap.erase(Fi); - - this->ParseFunctionBody( Func ); -} - -void AbstractBytecodeParser::ParseAllFunctionBodies() { - LazyFunctionMap::iterator Fi = LazyFunctionLoadMap.begin(); - LazyFunctionMap::iterator Fe = LazyFunctionLoadMap.end(); - - while ( Fi != Fe ) { - Function* Func = Fi->first; - BlockStart = At = Fi->second.Buf; - BlockEnd = Fi->second.EndBuf; - this->ParseFunctionBody(Func); - ++Fi; - } -} - -void AbstractBytecodeParser::ParseFunctionBody(Function* Func ) { - - unsigned FuncSize = BlockEnd - At; - GlobalValue::LinkageTypes Linkage = GlobalValue::ExternalLinkage; - - unsigned LinkageType = read_vbr_uint(); - switch (LinkageType) { - case 0: Linkage = GlobalValue::ExternalLinkage; break; - case 1: Linkage = GlobalValue::WeakLinkage; break; - case 2: Linkage = GlobalValue::AppendingLinkage; break; - case 3: Linkage = GlobalValue::InternalLinkage; break; - case 4: Linkage = GlobalValue::LinkOnceLinkage; break; - default: - PARSE_ERROR("Invalid linkage type for Function."); - Linkage = GlobalValue::InternalLinkage; - break; - } - - Func->setLinkage( Linkage ); - handler->handleFunctionBegin(Func,FuncSize); - - // Keep track of how many basic blocks we have read in... - unsigned BlockNum = 0; - bool InsertedArguments = false; - - BufPtr MyEnd = BlockEnd; - while ( At < MyEnd ) { - unsigned Type, Size; - BufPtr OldAt = At; - readBlock(Type, Size); - - switch (Type) { - case BytecodeFormat::ConstantPool: - ParseConstantPool(FunctionTypes ); - break; - - case BytecodeFormat::CompactionTable: - ParseCompactionTable(); - break; - - case BytecodeFormat::BasicBlock: - ParseBasicBlock(BlockNum++); - break; - - case BytecodeFormat::InstructionList: - if (BlockNum) - PARSE_ERROR("InstructionList must come before basic blocks!"); - BlockNum = ParseInstructionList(); - break; - - case BytecodeFormat::SymbolTable: - ParseSymbolTable(); - break; - - default: - At += Size; - if (OldAt > At) - PARSE_ERROR("Wrapped around reading bytecode"); - break; - } - BlockEnd = MyEnd; - - // Malformed bc file if read past end of block. - align32(); - } - - handler->handleFunctionEnd(Func); - - // Clear out function-level types... - FunctionTypes.clear(); - CompactionTypeTable.clear(); -} - -void AbstractBytecodeParser::ParseCompactionTable() { - - handler->handleCompactionTableBegin(); - - while ( moreInBlock() ) { - unsigned NumEntries = read_vbr_uint(); - unsigned Ty; - - if ((NumEntries & 3) == 3) { - NumEntries >>= 2; - Ty = read_vbr_uint(); - } else { - Ty = NumEntries >> 2; - NumEntries &= 3; - } - - handler->handleCompactionTablePlane( Ty, NumEntries ); - - if (Ty == Type::TypeTyID) { - for (unsigned i = 0; i != NumEntries; ++i) { - unsigned TypeSlot = read_vbr_uint(); - const Type *Typ = getGlobalTableType(TypeSlot); - handler->handleCompactionTableType( i, TypeSlot, Typ ); - } - } else { - const Type *Typ = getType(Ty); - // Push the implicit zero - for (unsigned i = 0; i != NumEntries; ++i) { - unsigned ValSlot = read_vbr_uint(); - handler->handleCompactionTableValue( i, ValSlot, Typ ); - } - } - } - handler->handleCompactionTableEnd(); -} - -const Type *AbstractBytecodeParser::ParseTypeConstant() { - unsigned PrimType = read_vbr_uint(); - - const Type *Val = 0; - if ((Val = Type::getPrimitiveType((Type::TypeID)PrimType))) - return Val; - - switch (PrimType) { - case Type::FunctionTyID: { - const Type *RetType = getType(read_vbr_uint()); - - unsigned NumParams = read_vbr_uint(); - - std::vector Params; - while (NumParams--) - Params.push_back(getType(read_vbr_uint())); - - bool isVarArg = Params.size() && Params.back() == Type::VoidTy; - if (isVarArg) Params.pop_back(); - - Type* result = FunctionType::get(RetType, Params, isVarArg); - handler->handleType( result ); - return result; - } - case Type::ArrayTyID: { - unsigned ElTyp = read_vbr_uint(); - const Type *ElementType = getType(ElTyp); - - unsigned NumElements = read_vbr_uint(); - - BCR_TRACE(5, "Array Type Constant #" << ElTyp << " size=" - << NumElements << "\n"); - Type* result = ArrayType::get(ElementType, NumElements); - handler->handleType( result ); - return result; - } - case Type::StructTyID: { - std::vector Elements; - unsigned Typ = read_vbr_uint(); - while (Typ) { // List is terminated by void/0 typeid - Elements.push_back(getType(Typ)); - Typ = read_vbr_uint(); - } - - Type* result = StructType::get(Elements); - handler->handleType( result ); - return result; - } - case Type::PointerTyID: { - unsigned ElTyp = read_vbr_uint(); - BCR_TRACE(5, "Pointer Type Constant #" << ElTyp << "\n"); - Type* result = PointerType::get(getType(ElTyp)); - handler->handleType( result ); - return result; - } - - case Type::OpaqueTyID: { - Type* result = OpaqueType::get(); - handler->handleType( result ); - return result; - } - - default: - PARSE_ERROR("Don't know how to deserialize primitive type" << PrimType << "\n"); - return Val; - } -} - -// ParseTypeConstants - We have to use this weird code to handle recursive -// types. We know that recursive types will only reference the current slab of -// values in the type plane, but they can forward reference types before they -// have been read. For example, Type #0 might be '{ Ty#1 }' and Type #1 might -// be 'Ty#0*'. When reading Type #0, type number one doesn't exist. To fix -// this ugly problem, we pessimistically insert an opaque type for each type we -// are about to read. This means that forward references will resolve to -// something and when we reread the type later, we can replace the opaque type -// with a new resolved concrete type. -// -void AbstractBytecodeParser::ParseTypeConstants( - TypeListTy &Tab, unsigned NumEntries -) { - assert(Tab.size() == 0 && "should not have read type constants in before!"); - - // Insert a bunch of opaque types to be resolved later... - Tab.reserve(NumEntries); - for (unsigned i = 0; i != NumEntries; ++i) - Tab.push_back(OpaqueType::get()); - - // Loop through reading all of the types. Forward types will make use of the - // opaque types just inserted. - // - for (unsigned i = 0; i != NumEntries; ++i) { - const Type *NewTy = ParseTypeConstant(), *OldTy = Tab[i].get(); - if (NewTy == 0) throw std::string("Couldn't parse type!"); - BCR_TRACE(4, "#" << i << ": Read Type Constant: '" << NewTy << - "' Replacing: " << OldTy << "\n"); - - // Don't insertValue the new type... instead we want to replace the opaque - // type with the new concrete value... - // - - // Refine the abstract type to the new type. This causes all uses of the - // abstract type to use NewTy. This also will cause the opaque type to be - // deleted... - // - cast(const_cast(OldTy))->refineAbstractTypeTo(NewTy); - - // This should have replace the old opaque type with the new type in the - // value table... or with a preexisting type that was already in the system - assert(Tab[i] != OldTy && "refineAbstractType didn't work!"); - } - - BCR_TRACE(5, "Resulting types:\n"); - for (unsigned i = 0; i < NumEntries; ++i) { - BCR_TRACE(5, (void*)Tab[i].get() << " - " << Tab[i].get() << "\n"); - } -} - - -void AbstractBytecodeParser::ParseConstantValue(unsigned TypeID) { - - // We must check for a ConstantExpr before switching by type because - // a ConstantExpr can be of any type, and has no explicit value. - // - // 0 if not expr; numArgs if is expr - unsigned isExprNumArgs = read_vbr_uint(); - - if (isExprNumArgs) { - unsigned Opcode = read_vbr_uint(); - const Type* Typ = getType(TypeID); - - // FIXME: Encoding of constant exprs could be much more compact! - std::vector > ArgVec; - ArgVec.reserve(isExprNumArgs); - - // Read the slot number and types of each of the arguments - for (unsigned i = 0; i != isExprNumArgs; ++i) { - unsigned ArgValSlot = read_vbr_uint(); - unsigned ArgTypeSlot = read_vbr_uint(); - BCR_TRACE(4, "CE Arg " << i << ": Type: '" << *getType(ArgTypeSlot) - << "' slot: " << ArgValSlot << "\n"); - - // Get the arg value from its slot if it exists, otherwise a placeholder - ArgVec.push_back(std::make_pair(getType(ArgTypeSlot), ArgValSlot)); - } - - handler->handleConstantExpression( Opcode, Typ, ArgVec ); - return; - } - - // Ok, not an ConstantExpr. We now know how to read the given type... - const Type *Ty = getType(TypeID); - switch (Ty->getTypeID()) { - case Type::BoolTyID: { - unsigned Val = read_vbr_uint(); - if (Val != 0 && Val != 1) - PARSE_ERROR("Invalid boolean value read."); - - handler->handleConstantValue( ConstantBool::get(Val == 1)); - break; - } - - case Type::UByteTyID: // Unsigned integer types... - case Type::UShortTyID: - case Type::UIntTyID: { - unsigned Val = read_vbr_uint(); - if (!ConstantUInt::isValueValidForType(Ty, Val)) - throw std::string("Invalid unsigned byte/short/int read."); - handler->handleConstantValue( ConstantUInt::get(Ty, Val) ); - break; - } - - case Type::ULongTyID: { - handler->handleConstantValue( ConstantUInt::get(Ty, read_vbr_uint64()) ); - break; - } - - case Type::SByteTyID: // Signed integer types... - case Type::ShortTyID: - case Type::IntTyID: { - case Type::LongTyID: - int64_t Val = read_vbr_int64(); - if (!ConstantSInt::isValueValidForType(Ty, Val)) - throw std::string("Invalid signed byte/short/int/long read."); - handler->handleConstantValue( ConstantSInt::get(Ty, Val) ); - break; - } - - case Type::FloatTyID: { - float F; - read_data(&F, &F+1); - handler->handleConstantValue( ConstantFP::get(Ty, F) ); - break; - } - - case Type::DoubleTyID: { - double Val; - read_data(&Val, &Val+1); - handler->handleConstantValue( ConstantFP::get(Ty, Val) ); - break; - } - - case Type::TypeTyID: - PARSE_ERROR("Type constants shouldn't live in constant table!"); - break; - - case Type::ArrayTyID: { - const ArrayType *AT = cast(Ty); - unsigned NumElements = AT->getNumElements(); - std::vector Elements; - Elements.reserve(NumElements); - while (NumElements--) // Read all of the elements of the constant. - Elements.push_back(read_vbr_uint()); - - handler->handleConstantArray( AT, Elements ); - break; - } - - case Type::StructTyID: { - const StructType *ST = cast(Ty); - std::vector Elements; - Elements.reserve(ST->getNumElements()); - for (unsigned i = 0; i != ST->getNumElements(); ++i) - Elements.push_back(read_vbr_uint()); - handler->handleConstantStruct( ST, Elements ); - break; - } - - case Type::PointerTyID: { // ConstantPointerRef value... - const PointerType *PT = cast(Ty); - unsigned Slot = read_vbr_uint(); - handler->handleConstantPointer( PT, Slot ); - break; - } - - default: - PARSE_ERROR("Don't know how to deserialize constant value of type '"+ - Ty->getDescription()); - } -} - -void AbstractBytecodeParser::ParseGlobalTypes() { - ParseConstantPool(ModuleTypes); -} - -void AbstractBytecodeParser::ParseStringConstants(unsigned NumEntries ){ - for (; NumEntries; --NumEntries) { - unsigned Typ = read_vbr_uint(); - const Type *Ty = getType(Typ); - if (!isa(Ty)) - throw std::string("String constant data invalid!"); - - const ArrayType *ATy = cast(Ty); - if (ATy->getElementType() != Type::SByteTy && - ATy->getElementType() != Type::UByteTy) - throw std::string("String constant data invalid!"); - - // Read character data. The type tells us how long the string is. - char Data[ATy->getNumElements()]; - read_data(Data, Data+ATy->getNumElements()); - - std::vector Elements(ATy->getNumElements()); - if (ATy->getElementType() == Type::SByteTy) - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) - Elements[i] = ConstantSInt::get(Type::SByteTy, (signed char)Data[i]); - else - for (unsigned i = 0, e = ATy->getNumElements(); i != e; ++i) - Elements[i] = ConstantUInt::get(Type::UByteTy, (unsigned char)Data[i]); - - // Create the constant, inserting it as needed. - ConstantArray *C = cast( ConstantArray::get(ATy, Elements) ); - handler->handleConstantString( C ); - } -} - - -void AbstractBytecodeParser::ParseConstantPool( TypeListTy &TypeTab) { - while ( moreInBlock() ) { - unsigned NumEntries = read_vbr_uint(); - unsigned Typ = read_vbr_uint(); - if (Typ == Type::TypeTyID) { - ParseTypeConstants(TypeTab, NumEntries); - } else if (Typ == Type::VoidTyID) { - ParseStringConstants(NumEntries); - } else { - BCR_TRACE(3, "Type: '" << *getType(Typ) << "' NumEntries: " - << NumEntries << "\n"); - - for (unsigned i = 0; i < NumEntries; ++i) { - ParseConstantValue(Typ); - } - } - } - - checkPastBlockEnd("Constant Pool"); -} - -void AbstractBytecodeParser::ParseModuleGlobalInfo() { - - handler->handleModuleGlobalsBegin(); - - // Read global variables... - unsigned VarType = read_vbr_uint(); - while (VarType != Type::VoidTyID) { // List is terminated by Void - // VarType Fields: bit0 = isConstant, bit1 = hasInitializer, bit2,3,4 = - // Linkage, bit4+ = slot# - unsigned SlotNo = VarType >> 5; - unsigned LinkageID = (VarType >> 2) & 7; - bool isConstant = VarType & 1; - bool hasInitializer = VarType & 2; - GlobalValue::LinkageTypes Linkage; - - switch (LinkageID) { - case 0: Linkage = GlobalValue::ExternalLinkage; break; - case 1: Linkage = GlobalValue::WeakLinkage; break; - case 2: Linkage = GlobalValue::AppendingLinkage; break; - case 3: Linkage = GlobalValue::InternalLinkage; break; - case 4: Linkage = GlobalValue::LinkOnceLinkage; break; - default: - PARSE_ERROR("Unknown linkage type: " << LinkageID); - Linkage = GlobalValue::InternalLinkage; - break; - } - - const Type *Ty = getType(SlotNo); - if ( !Ty ) { - PARSE_ERROR("Global has no type! SlotNo=" << SlotNo); - } - - if ( !isa(Ty)) { - PARSE_ERROR("Global not a pointer type! Ty= " << Ty->getDescription()); - } - - const Type *ElTy = cast(Ty)->getElementType(); - - // Create the global variable... - if (hasInitializer) { - unsigned initSlot = read_vbr_uint(); - handler->handleInitializedGV( ElTy, isConstant, Linkage, initSlot ); - } else - handler->handleGlobalVariable( ElTy, isConstant, Linkage ); - - // Get next item - VarType = read_vbr_uint(); - } - - // Read the function objects for all of the functions that are coming - unsigned FnSignature = read_vbr_uint(); - while (FnSignature != Type::VoidTyID) { // List is terminated by Void - const Type *Ty = getType(FnSignature); - if (!isa(Ty) || - !isa(cast(Ty)->getElementType())) { - PARSE_ERROR( "Function not a pointer to function type! Ty = " + - Ty->getDescription()); - // FIXME: what should Ty be if handler continues? - } - - // We create functions by passing the underlying FunctionType to create... - const FunctionType* FTy = - cast(cast(Ty)->getElementType()); - Function* Func = new Function(FTy, GlobalValue::ExternalLinkage); - - // Save this for later so we know type of lazily instantiated functions - FunctionSignatureList.push_back(Func); - - handler->handleFunctionDeclaration(Func, FTy); - - // Get Next function signature - FnSignature = read_vbr_uint(); - } - - if (hasInconsistentModuleGlobalInfo) - align32(); - - // Now that the function signature list is set up, reverse it so that we can - // remove elements efficiently from the back of the vector. - std::reverse(FunctionSignatureList.begin(), FunctionSignatureList.end()); - - // This is for future proofing... in the future extra fields may be added that - // we don't understand, so we transparently ignore them. - // - At = BlockEnd; - - handler->handleModuleGlobalsEnd(); -} - -void AbstractBytecodeParser::ParseVersionInfo() { - unsigned Version = read_vbr_uint(); - - // Unpack version number: low four bits are for flags, top bits = version - Module::Endianness Endianness; - Module::PointerSize PointerSize; - Endianness = (Version & 1) ? Module::BigEndian : Module::LittleEndian; - PointerSize = (Version & 2) ? Module::Pointer64 : Module::Pointer32; - - bool hasNoEndianness = Version & 4; - bool hasNoPointerSize = Version & 8; - - RevisionNum = Version >> 4; - - // Default values for the current bytecode version - hasInconsistentModuleGlobalInfo = false; - hasExplicitPrimitiveZeros = false; - hasRestrictedGEPTypes = false; - - switch (RevisionNum) { - case 0: // LLVM 1.0, 1.1 release version - // Base LLVM 1.0 bytecode format. - hasInconsistentModuleGlobalInfo = true; - hasExplicitPrimitiveZeros = true; - // FALL THROUGH - case 1: // LLVM 1.2 release version - // LLVM 1.2 added explicit support for emitting strings efficiently. - - // Also, it fixed the problem where the size of the ModuleGlobalInfo block - // included the size for the alignment at the end, where the rest of the - // blocks did not. - - // LLVM 1.2 and before required that GEP indices be ubyte constants for - // structures and longs for sequential types. - hasRestrictedGEPTypes = true; - - // FALL THROUGH - case 2: // LLVM 1.3 release version - break; - - default: - PARSE_ERROR("Unknown bytecode version number: " << RevisionNum); - } - - if (hasNoEndianness) Endianness = Module::AnyEndianness; - if (hasNoPointerSize) PointerSize = Module::AnyPointerSize; - - handler->handleVersionInfo(RevisionNum, Endianness, PointerSize ); -} - -void AbstractBytecodeParser::ParseModule() { - unsigned Type, Size; - - FunctionSignatureList.clear(); // Just in case... - - // Read into instance variables... - ParseVersionInfo(); - align32(); /// FIXME: Is this redundant? VI is first and 4 bytes! - - bool SeenModuleGlobalInfo = false; - bool SeenGlobalTypePlane = false; - BufPtr MyEnd = BlockEnd; - while (At < MyEnd) { - BufPtr OldAt = At; - readBlock(Type, Size); - - switch (Type) { - - case BytecodeFormat::GlobalTypePlane: - if ( SeenGlobalTypePlane ) - PARSE_ERROR("Two GlobalTypePlane Blocks Encountered!"); - - ParseGlobalTypes(); - SeenGlobalTypePlane = true; - break; - - case BytecodeFormat::ModuleGlobalInfo: - if ( SeenModuleGlobalInfo ) - PARSE_ERROR("Two ModuleGlobalInfo Blocks Encountered!"); - ParseModuleGlobalInfo(); - SeenModuleGlobalInfo = true; - break; - - case BytecodeFormat::ConstantPool: - ParseConstantPool(ModuleTypes); - break; - - case BytecodeFormat::Function: - ParseFunctionLazily(); - break; - - case BytecodeFormat::SymbolTable: - ParseSymbolTable(); - break; - - default: - At += Size; - if (OldAt > At) { - PARSE_ERROR("Unexpected Block of Type" << Type << "encountered!" ); - } - break; - } - BlockEnd = MyEnd; - align32(); - } - - /// Make sure we pulled them all out. If we didn't then there's a declaration - /// but a missing body. That's not allowed. - if (!FunctionSignatureList.empty()) - throw std::string( - "Function declared, but bytecode stream ended before definition"); -} - -void AbstractBytecodeParser::ParseBytecode( - BufPtr b, unsigned Length, - const std::string &ModuleID) { - - At = MemStart = BlockStart = b; - MemEnd = BlockEnd = b + Length; - handler->handleStart(); - - // Read and check signature... - unsigned Sig = read_uint(); - if (Sig != ('l' | ('l' << 8) | ('v' << 16) | ('m' << 24))) { - PARSE_ERROR("Invalid bytecode signature: " << Sig); - } - - handler->handleModuleBegin(ModuleID); - - unsigned Type, Size; - readBlock(Type, Size); - if ( Type != BytecodeFormat::Module ) { - PARSE_ERROR("Expected Module Block! At: " << unsigned(intptr_t(At)) - << ", Type:" << Type << ", Size:" << Size); - } - if ( At + Size != MemEnd ) { - PARSE_ERROR("Invalid Top Level Block Length! At: " - << unsigned(intptr_t(At)) << ", Type:" << Type << ", Size:" << Size); - } - this->ParseModule(); - - handler->handleModuleEnd(ModuleID); - - handler->handleFinish(); -} - -//===----------------------------------------------------------------------===// -//=== Default Implementations of Handler Methods -//===----------------------------------------------------------------------===// - -bool BytecodeHandler::handleError(const std::string& str ) { return false; } -void BytecodeHandler::handleStart() { } -void BytecodeHandler::handleFinish() { } -void BytecodeHandler::handleModuleBegin(const std::string& id) { } -void BytecodeHandler::handleModuleEnd(const std::string& id) { } -void BytecodeHandler::handleVersionInfo( unsigned char RevisionNum, - Module::Endianness Endianness, Module::PointerSize PointerSize) { } -void BytecodeHandler::handleModuleGlobalsBegin() { } -void BytecodeHandler::handleGlobalVariable( - const Type* ElemType, bool isConstant, GlobalValue::LinkageTypes ) { } -void BytecodeHandler::handleInitializedGV( - const Type* ElemType, bool isConstant, GlobalValue::LinkageTypes, - unsigned initSlot) {} -void BytecodeHandler::handleType( const Type* Ty ) {} -void BytecodeHandler::handleFunctionDeclaration( - Function* Func, const FunctionType* FuncType) {} -void BytecodeHandler::handleModuleGlobalsEnd() { } -void BytecodeHandler::handleCompactionTableBegin() { } -void BytecodeHandler::handleCompactionTablePlane( unsigned Ty, - unsigned NumEntries) {} -void BytecodeHandler::handleCompactionTableType( unsigned i, unsigned TypSlot, - const Type* ) {} -void BytecodeHandler::handleCompactionTableValue( unsigned i, unsigned ValSlot, - const Type* ) {} -void BytecodeHandler::handleCompactionTableEnd() { } -void BytecodeHandler::handleSymbolTableBegin() { } -void BytecodeHandler::handleSymbolTablePlane( unsigned Ty, unsigned NumEntries, - const Type* Typ) { } -void BytecodeHandler::handleSymbolTableType( unsigned i, unsigned slot, - const std::string& name ) { } -void BytecodeHandler::handleSymbolTableValue( unsigned i, unsigned slot, - const std::string& name ) { } -void BytecodeHandler::handleSymbolTableEnd() { } -void BytecodeHandler::handleFunctionBegin( Function* Func, - unsigned Size ) {} -void BytecodeHandler::handleFunctionEnd( Function* Func) { } -void BytecodeHandler::handleBasicBlockBegin( unsigned blocknum) { } -bool BytecodeHandler::handleInstruction( unsigned Opcode, const Type* iType, - std::vector& Operands, unsigned Size) { - return Instruction::isTerminator(Opcode); - } -void BytecodeHandler::handleBasicBlockEnd(unsigned blocknum) { } -void BytecodeHandler::handleGlobalConstantsBegin() { } -void BytecodeHandler::handleConstantExpression( unsigned Opcode, - const Type* Typ, std::vector > ArgVec ) { } -void BytecodeHandler::handleConstantValue( Constant * c ) { } -void BytecodeHandler::handleConstantArray( const ArrayType* AT, - std::vector& Elements ) { } -void BytecodeHandler::handleConstantStruct( const StructType* ST, - std::vector& ElementSlots) { } -void BytecodeHandler::handleConstantPointer( - const PointerType* PT, unsigned Slot) { } -void BytecodeHandler::handleConstantString( const ConstantArray* CA ) {} -void BytecodeHandler::handleGlobalConstantsEnd() {} -void BytecodeHandler::handleAlignment(unsigned numBytes) {} -void BytecodeHandler::handleBlock( - unsigned BType, const unsigned char* StartPtr, unsigned Size) {} -void BytecodeHandler::handleVBR32(unsigned Size ) {} -void BytecodeHandler::handleVBR64(unsigned Size ) {} - -// vim: sw=2 diff --git a/lib/Bytecode/Analyzer/Parser.h b/lib/Bytecode/Analyzer/Parser.h deleted file mode 100644 index 59023980b69..00000000000 --- a/lib/Bytecode/Analyzer/Parser.h +++ /dev/null @@ -1,544 +0,0 @@ -//===-- Parser.h - Abstract Interface To Bytecode Parsing -------*- C++ -*-===// -// -// 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 header file defines the interface to the Bytecode Parser and the -// Bytecode Handler interface that it calls. -// -//===----------------------------------------------------------------------===// - -#ifndef BYTECODE_PARSER_H -#define BYTECODE_PARSER_H - -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/GlobalValue.h" -#include "llvm/Module.h" -#include -#include -#include - -namespace llvm { - -class BytecodeHandler; ///< Forward declare the handler interface - -/// This class defines the interface for parsing a buffer of bytecode. The -/// parser itself takes no action except to call the various functions of -/// the handler interface. The parser's sole responsibility is the correct -/// interpretation of the bytecode buffer. The handler is responsible for -/// instantiating and keeping track of all values. As a convenience, the parser -/// is responsible for materializing types and will pass them through the -/// handler interface as necessary. -/// @see BytecodeHandler -/// @brief Abstract Bytecode Parser interface -class AbstractBytecodeParser { - -/// @name Constructors -/// @{ -public: - AbstractBytecodeParser( - BytecodeHandler* h, - bool repAlignment = false, - bool repBlocks = false, - bool repVBR = false - ) { - handler = h; - reportAlignment = repAlignment; - reportBlocks = repBlocks; - reportVBR = repVBR; - } - - ~AbstractBytecodeParser() { } - -/// @} -/// @name Types -/// @{ -public: - /// @brief A convenience type for the buffer pointer - typedef const unsigned char* BufPtr; - - /// @brief The type used for vector of potentially abstract types - typedef std::vector TypeListTy; - - /// @brief - -/// @} -/// @name Methods -/// @{ -public: - - /// @brief Main interface to parsing a bytecode buffer. - void ParseBytecode(const unsigned char *Buf, unsigned Length, - const std::string &ModuleID); - - /// The ParseBytecode method lazily parses functions. Use this - /// method to cause the parser to actually parse all the function bodies - /// in the bytecode buffer. - /// @see ParseBytecode - /// @brief Parse all function bodies - void ParseAllFunctionBodies (); - - /// The Parsebytecode method lazily parses functions. Use this - /// method to casue the parser to parse the next function of a given - /// types. Note that this will remove the function from what is to be - /// included by ParseAllFunctionBodies. - /// @see ParseAllFunctionBodies - /// @see ParseBytecode - /// @brief Parse the next function of specific type - void ParseNextFunction (Function* Func) ; - -/// @} -/// @name Parsing Units For Subclasses -/// @{ -protected: - /// @brief Parse whole module scope - void ParseModule (); - - /// @brief Parse the version information block - void ParseVersionInfo (); - - /// @brief Parse the ModuleGlobalInfo block - void ParseModuleGlobalInfo (); - - /// @brief Parse a symbol table - void ParseSymbolTable (); - - /// This function parses LLVM functions lazily. It obtains the type of the - /// function and records where the body of the function is in the bytecode - /// buffer. The caller can then use the ParseNextFunction and - /// ParseAllFunctionBodies to get handler events for the functions. - /// @brief Parse functions lazily. - void ParseFunctionLazily (); - - /// @brief Parse a function body - void ParseFunctionBody (Function* Func); - - /// @brief Parse a compaction table - void ParseCompactionTable (); - - /// @brief Parse global types - void ParseGlobalTypes (); - - /// @brief Parse a basic block (for LLVM 1.0 basic block blocks) - void ParseBasicBlock (unsigned BlockNo); - - /// @brief parse an instruction list (for post LLVM 1.0 instruction lists - /// with blocks differentiated by terminating instructions. - unsigned ParseInstructionList(); - - /// @brief Parse an instruction. - bool ParseInstruction (std::vector& Args); - - /// @brief Parse a constant pool - void ParseConstantPool (TypeListTy& List); - - /// @brief Parse a constant value - void ParseConstantValue (unsigned TypeID); - - /// @brief Parse a block of types. - void ParseTypeConstants (TypeListTy &Tab, unsigned NumEntries); - - /// @brief Parse a single type. - const Type *ParseTypeConstant(); - - /// @brief Parse a string constants block - void ParseStringConstants (unsigned NumEntries); - -/// @} -/// @name Data -/// @{ -private: - BufPtr MemStart; ///< Start of the memory buffer - BufPtr MemEnd; ///< End of the memory buffer - BufPtr BlockStart; ///< Start of current block being parsed - BufPtr BlockEnd; ///< End of current block being parsed - BufPtr At; ///< Where we're currently parsing at - - bool reportAlignment; ///< Parser should report alignment? - bool reportBlocks; ///< Parser should report blocks? - bool reportVBR; ///< Report VBR compression events - - // Information about the module, extracted from the bytecode revision number. - unsigned char RevisionNum; // The rev # itself - - // Flags to distinguish LLVM 1.0 & 1.1 bytecode formats (revision #0) - - // Revision #0 had an explicit alignment of data only for the ModuleGlobalInfo - // block. This was fixed to be like all other blocks in 1.2 - bool hasInconsistentModuleGlobalInfo; - - // Revision #0 also explicitly encoded zero values for primitive types like - // int/sbyte/etc. - bool hasExplicitPrimitiveZeros; - - // Flags to control features specific the LLVM 1.2 and before (revision #1) - - // LLVM 1.2 and earlier required that getelementptr structure indices were - // ubyte constants and that sequential type indices were longs. - bool hasRestrictedGEPTypes; - - - /// CompactionTable - If a compaction table is active in the current function, - /// this is the mapping that it contains. - std::vector CompactionTypeTable; - - // ConstantFwdRefs - This maintains a mapping between 's and - // forward references to constants. Such values may be referenced before they - // are defined, and if so, the temporary object that they represent is held - // here. - // - typedef std::map, Constant*> ConstantRefsType; - ConstantRefsType ConstantFwdRefs; - - // TypesLoaded - This vector mirrors the Values[TypeTyID] plane. It is used - // to deal with forward references to types. - // - TypeListTy ModuleTypes; - TypeListTy FunctionTypes; - - // When the ModuleGlobalInfo section is read, we create a FunctionType object - // for each function in the module. When the function is loaded, this type is - // used to instantiate the actual function object. - - std::vector FunctionSignatureList; - - // Constant values are read in after global variables. Because of this, we - // must defer setting the initializers on global variables until after module - // level constants have been read. In the mean time, this list keeps track of - // what we must do. - // - std::vector > GlobalInits; - -/// @} -/// @name Implementation Details -/// @{ -private: - /// This stores the parser's handler. It makes virtual function calls through - /// the BytecodeHandler to notify the handler of parsing events. What the - /// handler does with the events is completely orthogonal to the business of - /// parsing the bytecode. - /// @brief The handler of bytecode parsing events. - BytecodeHandler* handler; - - /// For lazy reading-in of functions, we need to save away several pieces of - /// information about each function: its begin and end pointer in the buffer - /// and its FunctionSlot. - struct LazyFunctionInfo { - const unsigned char *Buf, *EndBuf; - LazyFunctionInfo(const unsigned char *B = 0, const unsigned char *EB = 0) - : Buf(B), EndBuf(EB) {} - }; - typedef std::map LazyFunctionMap; - LazyFunctionMap LazyFunctionLoadMap; - -private: - - /// Is there more to parse in the current block? - inline bool moreInBlock(); - - /// Have we read past the end of the block - inline void checkPastBlockEnd(const char * block_name); - - /// Align to 32 bits - inline void align32(); - - /// Reader interface - inline unsigned read_uint(); - inline unsigned read_vbr_uint(); - inline uint64_t read_vbr_uint64(); - inline int64_t read_vbr_int64(); - inline std::string read_str(); - inline void read_data(void *Ptr, void *End); - - /// Read a block header - inline void readBlock(unsigned &Type, unsigned &Size); - - const Type *AbstractBytecodeParser::getType(unsigned ID); - /// getGlobalTableType - This is just like getType, but when a compaction - /// table is in use, it is ignored. Also, no forward references or other - /// fancy features are supported. - const Type *getGlobalTableType(unsigned Slot) { - if (Slot < Type::FirstDerivedTyID) { - const Type *Ty = Type::getPrimitiveType((Type::TypeID)Slot); - assert(Ty && "Not a primitive type ID?"); - return Ty; - } - Slot -= Type::FirstDerivedTyID; - if (Slot >= ModuleTypes.size()) - throw std::string("Illegal compaction table type reference!"); - return ModuleTypes[Slot]; - } - - unsigned getGlobalTableTypeSlot(const Type *Ty) { - if (Ty->isPrimitiveType()) - return Ty->getTypeID(); - TypeListTy::iterator I = find(ModuleTypes.begin(), - ModuleTypes.end(), Ty); - if (I == ModuleTypes.end()) - throw std::string("Didn't find type in ModuleTypes."); - return Type::FirstDerivedTyID + (&*I - &ModuleTypes[0]); - } - - AbstractBytecodeParser(const AbstractBytecodeParser &); // DO NOT IMPLEMENT - void operator=(const AbstractBytecodeParser &); // DO NOT IMPLEMENT - -/// @} -}; - -/// This class provides the interface for the handling bytecode events during -/// parsing. The methods on this interface are invoked by the -/// AbstractBytecodeParser as it discovers the content of a bytecode stream. -/// This class provides a a clear separation of concerns between recognizing -/// the semantic units of a bytecode file and deciding what to do with them. -/// The AbstractBytecodeParser recognizes the content of the bytecode file and -/// calls the BytecodeHandler methods to determine what should be done. This -/// arrangement allows Bytecode files to be read and handled for a number of -/// purposes simply by creating a subclass of BytecodeHandler. None of the -/// parsing details need to be understood, only the meaning of the calls -/// made on this interface. -/// -/// Another paradigm that uses this design pattern is the XML SAX Parser. The -/// ContentHandler for SAX plays the same role as the BytecodeHandler here. -/// @see AbstractbytecodeParser -/// @brief Handle Bytecode Parsing Events -class BytecodeHandler { - -/// @name Constructors And Operators -/// @{ -public: - /// @brief Default constructor (empty) - BytecodeHandler() {} - /// @brief Virtual destructor (empty) - virtual ~BytecodeHandler() {} - -private: - BytecodeHandler(const BytecodeHandler &); // DO NOT IMPLEMENT - void operator=(const BytecodeHandler &); // DO NOT IMPLEMENT - -/// @} -/// @name Handler Methods -/// @{ -public: - - /// This method is called whenever the parser detects an error in the - /// bytecode formatting. Returning true will cause the parser to keep - /// going, however this is inadvisable in most cases. Returning false will - /// cause the parser to throw the message as a std::string. - /// @brief Handle parsing errors. - virtual bool handleError(const std::string& str ); - - /// This method is called at the beginning of a parse before anything is - /// read in order to give the handler a chance to initialize. - /// @brief Handle the start of a bytecode parse - virtual void handleStart(); - - /// This method is called at the end of a parse after everything has been - /// read in order to give the handler a chance to terminate. - /// @brief Handle the end of a bytecode parse - virtual void handleFinish(); - - /// This method is called at the start of a module to indicate that a - /// module is being parsed. - /// @brief Handle the start of a module. - virtual void handleModuleBegin(const std::string& id); - - /// This method is called at the end of a module to indicate that the module - /// previously being parsed has concluded. - /// @brief Handle the end of a module. - virtual void handleModuleEnd(const std::string& id); - - /// This method is called once the version information has been parsed. It - /// provides the information about the version of the bytecode file being - /// read. - /// @brief Handle the bytecode prolog - virtual void handleVersionInfo( - unsigned char RevisionNum, ///< Byte code revision number - Module::Endianness Endianness, ///< Endianness indicator - Module::PointerSize PointerSize ///< PointerSize indicator - ); - - /// This method is called at the start of a module globals block which - /// contains the global variables and the function placeholders - virtual void handleModuleGlobalsBegin(); - - /// This method is called when a non-initialized global variable is - /// recognized. Its type, constness, and linkage type are provided. - /// @brief Handle a non-initialized global variable - virtual void handleGlobalVariable( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes ///< The linkage type of the GV - ); - - /// This method is called when an initialized global variable is recognized. - /// Its type constness, linkage type, and the slot number of the initializer - /// are provided. - /// @brief Handle an intialized global variable. - virtual void handleInitializedGV( - const Type* ElemType, ///< The type of the global variable - bool isConstant, ///< Whether the GV is constant or not - GlobalValue::LinkageTypes,///< The linkage type of the GV - unsigned initSlot ///< Slot number of GV's initializer - ); - - /// This method is called when a new type is recognized. The type is - /// converted from the bytecode and passed to this method. - /// @brief Handle a type - virtual void handleType( const Type* Ty ); - - /// This method is called when the function prototype for a function is - /// encountered in the module globals block. - virtual void handleFunctionDeclaration( - Function* Func, - const FunctionType* FuncType ///< The type of the function - ); - - /// This method is called at the end of the module globals block. - /// @brief Handle end of module globals block. - virtual void handleModuleGlobalsEnd(); - - /// This method is called at the beginning of a compaction table. - /// @brief Handle start of compaction table. - virtual void handleCompactionTableBegin(); - - /// @brief Handle start of a compaction table plane - virtual void handleCompactionTablePlane( - unsigned Ty, - unsigned NumEntries - ); - - - /// @brief Handle a type entry in the compaction table - virtual void handleCompactionTableType( - unsigned i, - unsigned TypSlot, - const Type* - ); - - /// @brief Handle a value entry in the compaction table - virtual void handleCompactionTableValue( - unsigned i, - unsigned ValSlot, - const Type* - ); - - /// @brief Handle end of a compaction table - virtual void handleCompactionTableEnd(); - - /// @brief Handle start of a symbol table - virtual void handleSymbolTableBegin(); - - /// @brief Handle start of a symbol table plane - virtual void handleSymbolTablePlane( - unsigned Ty, - unsigned NumEntries, - const Type* Ty - ); - - /// @brief Handle a named type in the symbol table - virtual void handleSymbolTableType( - unsigned i, - unsigned slot, - const std::string& name - ); - - /// @brief Handle a named value in the symbol table - virtual void handleSymbolTableValue( - unsigned i, - unsigned slot, - const std::string& name - ); - - /// @brief Handle the end of a symbol table - virtual void handleSymbolTableEnd(); - - /// @brief Handle the beginning of a function body - virtual void handleFunctionBegin( - Function* Func, unsigned Size - ); - - /// @brief Handle the end of a function body - virtual void handleFunctionEnd( - Function* Func - ); - - /// @brief Handle the beginning of a basic block - virtual void handleBasicBlockBegin( - unsigned blocknum - ); - - /// This method is called for each instruction that is parsed. - /// @returns true if the instruction is a block terminating instruction - /// @brief Handle an instruction - virtual bool handleInstruction( - unsigned Opcode, - const Type* iType, - std::vector& Operands, - unsigned Length - ); - - /// @brief Handle the end of a basic block - virtual void handleBasicBlockEnd(unsigned blocknum); - - /// @brief Handle start of global constants block. - virtual void handleGlobalConstantsBegin(); - - /// @brief Handle a constant expression - virtual void handleConstantExpression( - unsigned Opcode, - const Type* Typ, - std::vector > ArgVec - ); - - /// @brief Handle a constant array - virtual void handleConstantArray( - const ArrayType* AT, - std::vector& ElementSlots - ); - - /// @brief Handle a constant structure - virtual void handleConstantStruct( - const StructType* ST, - std::vector& ElementSlots - ); - - /// @brief Handle a constant pointer - virtual void handleConstantPointer( - const PointerType* PT, - unsigned Slot - ); - - /// @brief Handle a constant strings (array special case) - virtual void handleConstantString( - const ConstantArray* CA - ); - - /// @brief Handle a primitive constant value - virtual void handleConstantValue( Constant * c ); - - /// @brief Handle the end of the global constants - virtual void handleGlobalConstantsEnd(); - - /// @brief Handle an alignment event - virtual void handleAlignment(unsigned numBytes); - - virtual void handleBlock( - unsigned BType, ///< The type of block - const unsigned char* StartPtr, ///< The start of the block - unsigned Size ///< The size of the block - ); - virtual void handleVBR32(unsigned Size ); - virtual void handleVBR64(unsigned Size ); -/// @} - -}; - -} // End llvm namespace - -// vim: sw=2 -#endif