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,17 @@ /// 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 @@ -387,6 +387,8 @@ ErrorOr recordValue(SmallVectorImpl &Record, unsigned NameIndex, Triple &TT); + ErrorOr recordValue(SmallVectorImpl &Record, StringRef Name, + unsigned NameIndex, Triple &TT); std::error_code parseValueSymbolTable(uint64_t Offset = 0); std::error_code parseConstants(); std::error_code rememberAndSkipFunctionBodies(); @@ -1727,6 +1729,32 @@ return V; } +ErrorOr BitcodeReader::recordValue(SmallVectorImpl &Record, StringRef Name, + unsigned NameIndex, Triple &TT) { + if(Name.empty()) { + return recordValue(Record, NameIndex, TT); + } + unsigned ValueID = Record[0]; + if (ValueID >= ValueList.size() || !ValueList[ValueID]) + return error("Invalid record"); + Value *V = ValueList[ValueID]; + + if (Name.find_first_of(0) != StringRef::npos) + return error("Invalid value name"); + V->setName(Name); + auto *GO = dyn_cast(V); + if (GO) { + if (GO->getComdat() == reinterpret_cast(1)) { + if (TT.isOSBinFormatMachO()) + GO->setComdat(nullptr); + else + GO->setComdat(TheModule->getOrInsertComdat(V->getName())); + } + } + return V; +} + + /// Parse the value symbol table at either the current parsing location or /// at the given bit offset if provided. std::error_code BitcodeReader::parseValueSymbolTable(uint64_t Offset) { @@ -1792,11 +1820,12 @@ // Read a record. Record.clear(); - switch (Stream.readRecord(Entry.ID, Record)) { + StringRef Name; + switch (Stream.readRecord(Entry.ID, Record, &Name)) { default: // Default behavior: unknown type. break; case bitc::VST_CODE_ENTRY: { // VST_ENTRY: [valueid, namechar x N] - ErrorOr ValOrErr = recordValue(Record, 1, TT); + ErrorOr ValOrErr = recordValue(Record, Name, 1, TT); if (std::error_code EC = ValOrErr.getError()) return EC; ValOrErr.get(); @@ -1804,7 +1833,7 @@ } case bitc::VST_CODE_FNENTRY: { // VST_FNENTRY: [valueid, offset, namechar x N] - ErrorOr ValOrErr = recordValue(Record, 2, TT); + ErrorOr ValOrErr = recordValue(Record, Name, 2, TT); if (std::error_code EC = ValOrErr.getError()) return EC; Value *V = ValOrErr.get(); @@ -1832,13 +1861,16 @@ break; } case bitc::VST_CODE_BBENTRY: { - if (convertToString(Record, 1, ValueName)) - return error("Invalid record"); + if (Name.empty()) { + if(convertToString(Record, 1, ValueName)) + return error("Invalid record"); + Name = ValueName; + } BasicBlock *BB = getBasicBlock(Record[0]); if (!BB) return error("Invalid record"); - BB->setName(StringRef(ValueName.data(), ValueName.size())); + BB->setName(Name); ValueName.clear(); break; } @@ -2551,7 +2583,8 @@ // Read a record. Record.clear(); Value *V = nullptr; - unsigned BitCode = Stream.readRecord(Entry.ID, Record); + StringRef Blob; + unsigned BitCode = Stream.readRecord(Entry.ID, Record, &Blob); switch (BitCode) { default: // Default behavior: unknown constant case bitc::CST_CODE_UNDEF: // UNDEF @@ -2639,14 +2672,28 @@ } break; } - case bitc::CST_CODE_STRING: // STRING: [values] + case bitc::CST_CODE_STRING: { // STRING: [values] + if (!Blob.empty()) { + V = ConstantDataArray::getString(Context, Blob, false); + break; + } + if (Record.empty()) + return error("Invalid record"); + SmallString<16> Elts(Record.begin(), Record.end()); + V = ConstantDataArray::getString(Context, Elts, false); + break; + } case bitc::CST_CODE_CSTRING: { // CSTRING: [values] + if (!Blob.empty()) { + V = ConstantDataArray::getString(Context, Blob, true); + break; + } if (Record.empty()) return error("Invalid record"); SmallString<16> Elts(Record.begin(), Record.end()); - V = ConstantDataArray::getString(Context, Elts, - BitCode == bitc::CST_CODE_CSTRING); + Elts.push_back('\0'); + V = ConstantDataArray::getString(Context, Elts, false); break; } case bitc::CST_CODE_DATA: {// DATA: [n x value] Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -38,6 +38,9 @@ #include using namespace llvm; +static cl::opt OptSpeed("bc-optspeed", cl::init(false), + cl::desc("Optimize bitcode for speed.")); + /// These are manifest constants used by the bitcode writer. They do not need to /// be kept in sync with the reader, but need to be consistent within this file. enum { @@ -45,7 +48,9 @@ VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV, VST_ENTRY_7_ABBREV, VST_ENTRY_6_ABBREV, + VST_ENTRY_BLOB_ABBREV, VST_BBENTRY_6_ABBREV, + VST_BBENTRY_BLOB_ABBREV, // CONSTANTS_BLOCK abbrev id's. CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV, @@ -1487,8 +1492,10 @@ unsigned AggregateAbbrev = 0; unsigned String8Abbrev = 0; + unsigned StringBlobAbbrev = 0; unsigned CString7Abbrev = 0; unsigned CString6Abbrev = 0; + unsigned CStringBlobAbbrev = 0; // If this is a constant pool for the module, emit module-specific abbrevs. if (isGlobal) { // Abbrev for CST_CODE_AGGREGATE. @@ -1506,6 +1513,11 @@ String8Abbrev = Stream.EmitAbbrev(Abbv); // Abbrev for CST_CODE_CSTRING. Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + StringBlobAbbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); @@ -1516,6 +1528,11 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); CString6Abbrev = Stream.EmitAbbrev(Abbv); + // Abbrev for CST_CODE_CSTRING. + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + CStringBlobAbbrev = Stream.EmitAbbrev(Abbv); } SmallVector Record; @@ -1623,6 +1640,12 @@ AbbrevToUse = CString6Abbrev; else if (isCStr7) AbbrevToUse = CString7Abbrev; + if (OptSpeed) { + if (Code == bitc::CST_CODE_STRING) + AbbrevToUse = StringBlobAbbrev; + else + AbbrevToUse = CStringBlobAbbrev; + } } else if (const ConstantDataSequential *CDS = dyn_cast(C)) { Code = bitc::CST_CODE_DATA; @@ -2245,6 +2268,7 @@ unsigned FnEntry8BitAbbrev; unsigned FnEntry7BitAbbrev; unsigned FnEntry6BitAbbrev; + unsigned FnEntryBlobAbbrev; if (VSTOffsetPlaceholder > 0) { // 8-bit fixed-width VST_FNENTRY function strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); @@ -2272,6 +2296,13 @@ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6)); FnEntry6BitAbbrev = Stream.EmitAbbrev(Abbv); + + Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_FNENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // funcoffset + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + FnEntryBlobAbbrev = Stream.EmitAbbrev(Abbv); } // FIXME: Set up the abbrev, we know how many values there are! @@ -2303,6 +2334,8 @@ Code = bitc::VST_CODE_BBENTRY; if (Bits == SE_Char6) AbbrevToUse = VST_BBENTRY_6_ABBREV; + if (OptSpeed) + AbbrevToUse = VST_BBENTRY_BLOB_ABBREV; } else if (F && !F->isDeclaration()) { // Must be the module-level VST, where we pass in the Index and // have a VSTOffsetPlaceholder. The function-level VST should not @@ -2324,9 +2357,13 @@ AbbrevToUse = FnEntry6BitAbbrev; else if (Bits == SE_Fixed7) AbbrevToUse = FnEntry7BitAbbrev; + if (OptSpeed) + AbbrevToUse = FnEntryBlobAbbrev; } else { Code = bitc::VST_CODE_ENTRY; - if (Bits == SE_Char6) + if (OptSpeed) { + AbbrevToUse = VST_ENTRY_BLOB_ABBREV; + } else if (Bits == SE_Char6) AbbrevToUse = VST_ENTRY_6_ABBREV; else if (Bits == SE_Fixed7) AbbrevToUse = VST_ENTRY_7_ABBREV; @@ -2579,6 +2616,15 @@ Abbv) != VST_ENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } + { + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_ENTRY_BLOB_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } { // 6-bit char6 VST_BBENTRY strings. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY)); @@ -2589,8 +2635,15 @@ Abbv) != VST_BBENTRY_6_ABBREV) llvm_unreachable("Unexpected abbrev ordering!"); } - - + { // Blob VST_BBENTRY strings. + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); + Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID, + Abbv) != VST_BBENTRY_BLOB_ABBREV) + llvm_unreachable("Unexpected abbrev ordering!"); + } { // SETTYPE abbrev for CONSTANTS_BLOCK. BitCodeAbbrev *Abbv = new BitCodeAbbrev(); 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