Index: include/llvm/Support/StreamingMemoryObject.h =================================================================== --- include/llvm/Support/StreamingMemoryObject.h +++ include/llvm/Support/StreamingMemoryObject.h @@ -10,6 +10,7 @@ #ifndef LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H #define LLVM_SUPPORT_STREAMINGMEMORYOBJECT_H +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataStream.h" #include "llvm/Support/ErrorHandling.h" @@ -23,19 +24,18 @@ /// addition to inherited members, it has the dropLeadingBytes and /// setKnownObjectSize methods which are not applicable to non-streamed objects. class StreamingMemoryObject : public MemoryObject { + /// Buffer for temporary storage if getPointer() is used + mutable SmallVector Buffer; + public: StreamingMemoryObject(std::unique_ptr Streamer); uint64_t getExtent() const override; uint64_t readBytes(uint8_t *Buf, uint64_t Size, uint64_t Address) const override; - const uint8_t *getPointer(uint64_t address, uint64_t size) const override { - // FIXME: This could be fixed by ensuring the bytes are fetched and - // making a copy, requiring that the bitcode size be known, or - // otherwise ensuring that the memory doesn't go away/get reallocated, - // but it's not currently necessary. Users that need the pointer (any - // that need Blobs) don't stream. - report_fatal_error("getPointer in streaming memory objects not allowed"); - return nullptr; + const uint8_t *getPointer(uint64_t Address, uint64_t Size) const override { + Buffer.resize(Size); + readBytes(&Buffer[0], Size, Address); + return &Buffer[0]; } bool isValidAddress(uint64_t address) const override; Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -1948,9 +1948,12 @@ } // Read a record. + StringRef Blob; // Optional blob that readRecord can supply. Record.clear(); - unsigned Code = Stream.readRecord(Entry.ID, Record); + unsigned Code = Stream.readRecord(Entry.ID, Record, &Blob); bool IsDistinct = false; + assert((Blob.empty() || Code == bitc::METADATA_STRING) && + "Unexpected Blob for non-METADATA_STRING record"); switch (Code) { default: // Default behavior: ignore. break; @@ -2384,10 +2387,16 @@ break; } case bitc::METADATA_STRING: { - std::string String(Record.begin(), Record.end()); - llvm::UpgradeMDStringConstant(String); - Metadata *MD = MDString::get(Context, String); - MetadataList.assignValue(MD, NextMetadataNo++); + if (!Blob.empty()) { + Metadata *MD = MDString::get(Context, Blob); + MetadataList.assignValue(MD, NextMetadataNo++); + } else { + // Old bitcode didn't use blob here. + std::string String(Record.begin(), Record.end()); + llvm::UpgradeMDStringConstant(String); + Metadata *MD = MDString::get(Context, String); + MetadataList.assignValue(MD, NextMetadataNo++); + } break; } case bitc::METADATA_KIND: { Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -1316,8 +1316,7 @@ // Abbrev for METADATA_STRING. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::METADATA_STRING)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); - Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); MDSAbbrev = Stream.EmitAbbrev(Abbv); } Index: test/Bitcode/invalid.test =================================================================== --- test/Bitcode/invalid.test +++ test/Bitcode/invalid.test @@ -168,11 +168,6 @@ INVALID-ARGUMENT-TYPE: Invalid function argument type -RUN: not llvm-dis -disable-output %p/Inputs/invalid-fixme-streaming-blob.bc 2>&1 | \ -RUN: FileCheck --check-prefix=STREAMING-BLOB %s - -STREAMING-BLOB: getPointer in streaming memory objects not allowed - RUN: not llvm-dis -disable-output %p/Inputs/invalid-function-comdat-id.bc 2>&1 | \ RUN: FileCheck --check-prefix=INVALID-FCOMDAT-ID %s