Index: include/llvm/Bitcode/ReaderWriter.h =================================================================== --- include/llvm/Bitcode/ReaderWriter.h +++ include/llvm/Bitcode/ReaderWriter.h @@ -20,7 +20,7 @@ namespace llvm { class BitstreamWriter; class MemoryBuffer; - class DataStreamer; + class StreamingMemoryObject; class LLVMContext; class Module; class ModulePass; @@ -34,10 +34,11 @@ /// getStreamedBitcodeModule - Read the header of the specified stream /// and prepare for lazy deserialization and streaming of function bodies. + /// This takes ownership of 'Streamer' on both success and error. /// On error, this returns null, and fills in *ErrMsg with an error /// description if ErrMsg is non-null. Module *getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, + StreamingMemoryObject *Streamer, LLVMContext &Context, std::string *ErrMsg = nullptr); Index: include/llvm/Support/StreamableMemoryObject.h =================================================================== --- include/llvm/Support/StreamableMemoryObject.h +++ include/llvm/Support/StreamableMemoryObject.h @@ -98,13 +98,31 @@ virtual bool isObjectEnd(uint64_t address) const = 0; }; + /// StreamingMemoryObject - interface to data which is actually streamed from /// a DataStreamer. In addition to inherited members, it has the /// dropLeadingBytes and setKnownObjectSize methods which are not applicable /// to non-streamed objects. class StreamingMemoryObject : public StreamableMemoryObject { public: - StreamingMemoryObject(DataStreamer *streamer); + /// Drop s bytes from the front of the stream, pushing the positions of the + /// remaining bytes down by s. This is used to skip past the bitcode header, + /// since we don't know a priori if it's present, and we can't put bytes + /// back into the stream once we've read them. + virtual bool dropLeadingBytes(size_t s) = 0; + + /// If the data object size is known in advance, many of the operations can + /// be made more efficient, so this method should be called before reading + /// starts (although it can be called anytime). + virtual void setKnownObjectSize(size_t size) = 0; +}; + + +/// StreamingMemoryObjectImpl - An implementation of a StreamingMemoryObject. +class StreamingMemoryObjectImpl : public StreamingMemoryObject { +public: + /// Constructs a StreamingMemoryObject and takes ownership of DataStreamer. + StreamingMemoryObjectImpl(DataStreamer *streamer); uint64_t getBase() const override { return 0; } uint64_t getExtent() const override; int readByte(uint64_t address, uint8_t *ptr) const override; @@ -125,12 +143,12 @@ /// remaining bytes down by s. This is used to skip past the bitcode header, /// since we don't know a priori if it's present, and we can't put bytes /// back into the stream once we've read them. - bool dropLeadingBytes(size_t s); + bool dropLeadingBytes(size_t s) override; /// If the data object size is known in advance, many of the operations can /// be made more efficient, so this method should be called before reading /// starts (although it can be called anytime). - void setKnownObjectSize(size_t size); + void setKnownObjectSize(size_t size) override; private: const static uint32_t kChunkSize = 4096 * 4; @@ -166,8 +184,10 @@ return true; } - StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; - void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; + StreamingMemoryObjectImpl( + const StreamingMemoryObjectImpl&) LLVM_DELETED_FUNCTION; + void operator=( + const StreamingMemoryObjectImpl&) LLVM_DELETED_FUNCTION; }; StreamableMemoryObject *getNonStreamedMemoryObject( Index: lib/Bitcode/Reader/BitcodeReader.h =================================================================== --- lib/Bitcode/Reader/BitcodeReader.h +++ lib/Bitcode/Reader/BitcodeReader.h @@ -129,7 +129,7 @@ bool BufferOwned; std::unique_ptr StreamFile; BitstreamCursor Stream; - DataStreamer *LazyStreamer; + StreamingMemoryObject* LazyStreamer; // owned by StreamFile. uint64_t NextUnreadBit; bool SeenValueSymbolTable; @@ -229,9 +229,9 @@ ValueList(C), MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false) { } - explicit BitcodeReader(DataStreamer *streamer, LLVMContext &C) + explicit BitcodeReader(StreamingMemoryObject *Streamer, LLVMContext &C) : Context(C), TheModule(0), Buffer(0), BufferOwned(false), - LazyStreamer(streamer), NextUnreadBit(0), SeenValueSymbolTable(false), + LazyStreamer(Streamer), NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C), MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false) { } Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -3235,12 +3235,11 @@ error_code BitcodeReader::InitLazyStream() { // Check and strip off the bitcode wrapper; BitstreamReader expects never to // see it. - StreamingMemoryObject *Bytes = new StreamingMemoryObject(LazyStreamer); - StreamFile.reset(new BitstreamReader(Bytes)); + StreamFile.reset(new BitstreamReader(LazyStreamer)); Stream.init(*StreamFile); unsigned char buf[16]; - if (Bytes->readBytes(0, 16, buf) == -1) + if (LazyStreamer->readBytes(0, 16, buf) == -1) return Error(BitcodeStreamInvalidSize); if (!isBitcode(buf, buf + 16)) @@ -3250,8 +3249,8 @@ const unsigned char *bitcodeStart = buf; const unsigned char *bitcodeEnd = buf + 16; SkipBitcodeWrapperHeader(bitcodeStart, bitcodeEnd, false); - Bytes->dropLeadingBytes(bitcodeStart - buf); - Bytes->setKnownObjectSize(bitcodeEnd - bitcodeStart); + LazyStreamer->dropLeadingBytes(bitcodeStart - buf); + LazyStreamer->setKnownObjectSize(bitcodeEnd - bitcodeStart); } return error_code::success(); } @@ -3338,11 +3337,11 @@ Module *llvm::getStreamedBitcodeModule(const std::string &name, - DataStreamer *streamer, + StreamingMemoryObject *Streamer, LLVMContext &Context, std::string *ErrMsg) { Module *M = new Module(name, Context); - BitcodeReader *R = new BitcodeReader(streamer, Context); + BitcodeReader *R = new BitcodeReader(Streamer, Context); M->setMaterializer(R); if (error_code EC = R->ParseBitcodeInto(M)) { if (ErrMsg) Index: lib/Support/StreamableMemoryObject.cpp =================================================================== --- lib/Support/StreamableMemoryObject.cpp +++ lib/Support/StreamableMemoryObject.cpp @@ -80,18 +80,18 @@ namespace llvm { // If the bitcode has a header, then its size is known, and we don't have to // block until we actually want to read it. -bool StreamingMemoryObject::isValidAddress(uint64_t address) const { +bool StreamingMemoryObjectImpl::isValidAddress(uint64_t address) const { if (ObjectSize && address < ObjectSize) return true; return fetchToPos(address); } -bool StreamingMemoryObject::isObjectEnd(uint64_t address) const { +bool StreamingMemoryObjectImpl::isObjectEnd(uint64_t address) const { if (ObjectSize) return address == ObjectSize; fetchToPos(address); return address == ObjectSize && address != 0; } -uint64_t StreamingMemoryObject::getExtent() const { +uint64_t StreamingMemoryObjectImpl::getExtent() const { if (ObjectSize) return ObjectSize; size_t pos = BytesRead + kChunkSize; // keep fetching until we run out of bytes @@ -99,13 +99,13 @@ return ObjectSize; } -int StreamingMemoryObject::readByte(uint64_t address, uint8_t* ptr) const { +int StreamingMemoryObjectImpl::readByte(uint64_t address, uint8_t* ptr) const { if (!fetchToPos(address)) return -1; *ptr = Bytes[address + BytesSkipped]; return 0; } -int StreamingMemoryObject::readBytes(uint64_t address, +int StreamingMemoryObjectImpl::readBytes(uint64_t address, uint64_t size, uint8_t *buf) const { if (!fetchToPos(address + size - 1)) return -1; @@ -113,14 +113,14 @@ return 0; } -bool StreamingMemoryObject::dropLeadingBytes(size_t s) { +bool StreamingMemoryObjectImpl::dropLeadingBytes(size_t s) { if (BytesRead < s) return true; BytesSkipped = s; BytesRead -= s; return false; } -void StreamingMemoryObject::setKnownObjectSize(size_t size) { +void StreamingMemoryObjectImpl::setKnownObjectSize(size_t size) { ObjectSize = size; Bytes.reserve(size); } @@ -132,7 +132,8 @@ StreamableMemoryObject::~StreamableMemoryObject() { } -StreamingMemoryObject::StreamingMemoryObject(DataStreamer *streamer) : +StreamingMemoryObjectImpl::StreamingMemoryObjectImpl( + DataStreamer *streamer) : Bytes(kChunkSize), Streamer(streamer), BytesRead(0), BytesSkipped(0), ObjectSize(0), EOFReached(false) { BytesRead = streamer->GetBytes(&Bytes[0], kChunkSize); Index: tools/llvm-dis/llvm-dis.cpp =================================================================== --- tools/llvm-dis/llvm-dis.cpp +++ tools/llvm-dis/llvm-dis.cpp @@ -27,9 +27,9 @@ #include "llvm/Support/DataStream.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/PrettyStackTrace.h" #include "llvm/Support/Signals.h" +#include "llvm/Support/StreamableMemoryObject.h" #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/system_error.h" using namespace llvm; @@ -126,15 +126,17 @@ std::unique_ptr M; // Use the bitcode streaming interface - DataStreamer *streamer = getDataFileStreamer(InputFilename, &ErrorMessage); - if (streamer) { + DataStreamer *Streamer = getDataFileStreamer(InputFilename, &ErrorMessage); + if (Streamer) { + std::unique_ptr StreamBytes( + new StreamingMemoryObjectImpl(Streamer)); std::string DisplayFilename; if (InputFilename == "-") DisplayFilename = ""; else DisplayFilename = InputFilename; - M.reset(getStreamedBitcodeModule(DisplayFilename, streamer, Context, - &ErrorMessage)); + M.reset(getStreamedBitcodeModule(DisplayFilename, StreamBytes.release(), + Context, &ErrorMessage)); if(M.get() != 0) { if (error_code EC = M->materializeAllPermanently()) { ErrorMessage = EC.message();