//===- ReaderWrappers.cpp - Parse bytecode from file or buffer -----------===// // // 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 file implements loading and parsing a bytecode file and parsing a // bytecode module from a given buffer. // //===----------------------------------------------------------------------===// #include "llvm/Bytecode/Analyzer.h" #include "llvm/Bytecode/Reader.h" #include "Reader.h" #include "llvm/Module.h" #include "llvm/Instructions.h" #include "llvm/ADT/StringExtras.h" #include "llvm/System/MappedFile.h" #include "llvm/System/Program.h" #include #include using namespace llvm; //===----------------------------------------------------------------------===// // BytecodeFileReader - Read from an mmap'able file descriptor. // namespace { /// BytecodeFileReader - parses a bytecode file from a file /// class BytecodeFileReader : public BytecodeReader { private: std::string fileName; BCDecompressor_t *Decompressor; sys::MappedFile mapFile; BytecodeFileReader(const BytecodeFileReader&); // Do not implement void operator=(const BytecodeFileReader &BFR); // Do not implement public: BytecodeFileReader(const std::string &Filename, BCDecompressor_t *BCDC, llvm::BytecodeHandler* H=0); bool read(std::string* ErrMsg); void freeState() { BytecodeReader::freeState(); mapFile.close(); } }; } BytecodeFileReader::BytecodeFileReader(const std::string &Filename, BCDecompressor_t *BCDC, llvm::BytecodeHandler* H) : BytecodeReader(H), fileName(Filename), Decompressor(BCDC) { } bool BytecodeFileReader::read(std::string* ErrMsg) { if (mapFile.open(sys::Path(fileName), sys::MappedFile::READ_ACCESS, ErrMsg)) return true; if (!mapFile.map(ErrMsg)) { mapFile.close(); return true; } unsigned char* buffer = reinterpret_cast(mapFile.base()); return ParseBytecode(buffer, mapFile.size(), fileName, Decompressor, ErrMsg); } //===----------------------------------------------------------------------===// // BytecodeBufferReader - Read from a memory buffer // namespace { /// BytecodeBufferReader - parses a bytecode file from a buffer /// class BytecodeBufferReader : public BytecodeReader { private: const unsigned char *Buffer; const unsigned char *Buf; unsigned Length; std::string ModuleID; BCDecompressor_t *Decompressor; bool MustDelete; BytecodeBufferReader(const BytecodeBufferReader&); // Do not implement void operator=(const BytecodeBufferReader &BFR); // Do not implement public: BytecodeBufferReader(const unsigned char *Buf, unsigned Length, const std::string &ModuleID, BCDecompressor_t *BCDC, llvm::BytecodeHandler* Handler = 0); ~BytecodeBufferReader(); bool read(std::string* ErrMsg); }; } BytecodeBufferReader::BytecodeBufferReader(const unsigned char *buf, unsigned len, const std::string &modID, BCDecompressor_t *BCDC, llvm::BytecodeHandler *H) : BytecodeReader(H), Buffer(0), Buf(buf), Length(len), ModuleID(modID) , Decompressor(BCDC), MustDelete(false) { } BytecodeBufferReader::~BytecodeBufferReader() { if (MustDelete) delete [] Buffer; } bool BytecodeBufferReader::read(std::string* ErrMsg) { // If not aligned, allocate a new buffer to hold the bytecode... const unsigned char *ParseBegin = 0; if (reinterpret_cast(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; } if (ParseBytecode(ParseBegin, Length, ModuleID, Decompressor, ErrMsg)) { if (MustDelete) delete [] Buffer; return true; } return false; } //===----------------------------------------------------------------------===// // BytecodeStdinReader - Read bytecode from Standard Input // namespace { /// BytecodeStdinReader - parses a bytecode file from stdin /// class BytecodeStdinReader : public BytecodeReader { private: std::vector FileData; BCDecompressor_t *Decompressor; unsigned char *FileBuf; BytecodeStdinReader(const BytecodeStdinReader&); // Do not implement void operator=(const BytecodeStdinReader &BFR); // Do not implement public: BytecodeStdinReader(BCDecompressor_t *BCDC, llvm::BytecodeHandler* H = 0); bool read(std::string* ErrMsg); }; } BytecodeStdinReader::BytecodeStdinReader(BCDecompressor_t *BCDC, BytecodeHandler* H) : BytecodeReader(H), Decompressor(BCDC) { } bool BytecodeStdinReader::read(std::string* ErrMsg) { sys::Program::ChangeStdinToBinary(); char Buffer[4096*4]; // Read in all of the data from stdin, we cannot mmap stdin... while (cin.stream()->good()) { cin.stream()->read(Buffer, 4096*4); int BlockSize = cin.stream()->gcount(); if (0 >= BlockSize) break; FileData.insert(FileData.end(), Buffer, Buffer+BlockSize); } if (FileData.empty()) { if (ErrMsg) *ErrMsg = "Standard Input is empty!"; return true; } FileBuf = &FileData[0]; if (ParseBytecode(FileBuf, FileData.size(), "", Decompressor, ErrMsg)) return true; return false; } //===----------------------------------------------------------------------===// // Wrapper functions //===----------------------------------------------------------------------===// /// getBytecodeBufferModuleProvider - lazy function-at-a-time loading from a /// buffer ModuleProvider* llvm::getBytecodeBufferModuleProvider(const unsigned char *Buffer, unsigned Length, const std::string &ModuleID, BCDecompressor_t *BCDC, std::string *ErrMsg, BytecodeHandler *H) { BytecodeBufferReader *rdr = new BytecodeBufferReader(Buffer, Length, ModuleID, BCDC, H); if (rdr->read(ErrMsg)) return 0; return rdr; } /// ParseBytecodeBuffer - Parse a given bytecode buffer /// Module *llvm::ParseBytecodeBuffer(const unsigned char *Buffer, unsigned Length, const std::string &ModuleID, BCDecompressor_t *BCDC, std::string *ErrMsg) { ModuleProvider *MP = getBytecodeBufferModuleProvider(Buffer, Length, ModuleID, BCDC, ErrMsg, 0); if (!MP) return 0; Module *M = MP->releaseModule(ErrMsg); delete MP; return M; } /// getBytecodeModuleProvider - lazy function-at-a-time loading from a file /// ModuleProvider * llvm::getBytecodeModuleProvider(const std::string &Filename, BCDecompressor_t *BCDC, std::string* ErrMsg, BytecodeHandler* H) { // Read from a file if (Filename != std::string("-")) { BytecodeFileReader *rdr = new BytecodeFileReader(Filename, BCDC, H); if (rdr->read(ErrMsg)) return 0; return rdr; } // Read from stdin BytecodeStdinReader *rdr = new BytecodeStdinReader(BCDC, H); if (rdr->read(ErrMsg)) return 0; return rdr; } /// ParseBytecodeFile - Parse the given bytecode file /// Module *llvm::ParseBytecodeFile(const std::string &Filename, BCDecompressor_t *BCDC, std::string *ErrMsg) { ModuleProvider* MP = getBytecodeModuleProvider(Filename, BCDC, ErrMsg); if (!MP) return 0; Module *M = MP->releaseModule(ErrMsg); delete MP; return M; }