Index: include/llvm/Bitcode/LLVMBitCodes.h =================================================================== --- include/llvm/Bitcode/LLVMBitCodes.h +++ include/llvm/Bitcode/LLVMBitCodes.h @@ -34,7 +34,9 @@ CONSTANTS_BLOCK_ID, FUNCTION_BLOCK_ID, - UNUSED_ID1, + // Block intended to contains a single string identifying the bitcode + // producer. Can be used to debug error while parsing the bitcode. + IDENTIFICATION_BLOCK_ID, VALUE_SYMTAB_BLOCK_ID, METADATA_BLOCK_ID, Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -152,6 +152,8 @@ uint64_t LastFunctionBlockBit = 0; bool SeenValueSymbolTable = false; unsigned VSTOffset = 0; + // Contains an arbitrary and optional string identifying the bitcode producer + std::string ProducerIdentification; std::vector TypeList; BitcodeReaderValueList ValueList; @@ -273,6 +275,10 @@ void setStripDebugInfo() override; private: + /// Parse the "IDENTIFICATION_BLOCK_ID" block and populate the + /// ProducerIdentification data member. + std::error_code parseBitcodeVersion(); + std::vector IdentifiedStructTypes; StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name); StructType *createIdentifiedStructType(LLVMContext &Context); @@ -518,10 +524,19 @@ } std::error_code BitcodeReader::error(BitcodeError E, const Twine &Message) { + if (!ProducerIdentification.empty()) { + Twine MsgWithID = Message + " (Producer: " + ProducerIdentification + ")"; + return ::error(DiagnosticHandler, make_error_code(E), MsgWithID); + } return ::error(DiagnosticHandler, make_error_code(E), Message); } std::error_code BitcodeReader::error(const Twine &Message) { + if (!ProducerIdentification.empty()) { + Twine MsgWithID = Message + " (Producer: " + ProducerIdentification + ")"; + return ::error(DiagnosticHandler, + make_error_code(BitcodeError::CorruptedBitcode), MsgWithID); + } return ::error(DiagnosticHandler, make_error_code(BitcodeError::CorruptedBitcode), Message); } @@ -3061,6 +3076,19 @@ } } +std::error_code BitcodeReader::parseBitcodeVersion() { + if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID)) + return error("Invalid record"); + + // Get the version string + Stream.Read(Stream.getAbbrevIDWidth()); + SmallVector Record; + Stream.readRecord(bitc::UNABBREV_RECORD, Record, nullptr); + convertToString(Record, 0, ProducerIdentification); + Stream.advance(); + return std::error_code(); +} + std::error_code BitcodeReader::parseModule(uint64_t ResumeBit, bool ShouldLazyLoadMetadata) { if (ResumeBit) @@ -3552,6 +3580,11 @@ if (Entry.Kind != BitstreamEntry::SubBlock) return error("Malformed block"); + if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { + parseBitcodeVersion(); + continue; + } + if (Entry.ID == bitc::MODULE_BLOCK_ID) return parseModule(0, ShouldLazyLoadMetadata); Index: lib/Bitcode/Writer/BitcodeWriter.cpp =================================================================== --- lib/Bitcode/Writer/BitcodeWriter.cpp +++ lib/Bitcode/Writer/BitcodeWriter.cpp @@ -2830,6 +2830,14 @@ Stream.ExitBlock(); } +// Create the "IDENTIFICATION_BLOCK_ID" containing a single string with the +// current llvm version. +static void WriteIdentificationBlock(const Module *M, BitstreamWriter &Stream) { + Stream.EnterSubblock(bitc::IDENTIFICATION_BLOCK_ID, 5); + WriteStringRecord(/* code */ 0, "LLVM " LLVM_VERSION_STRING, 0, Stream); + Stream.ExitBlock(); +} + /// WriteModule - Emit the specified module to the bitstream. static void WriteModule(const Module *M, BitstreamWriter &Stream, bool ShouldPreserveUseListOrder, @@ -3001,6 +3009,8 @@ // Emit the file header. WriteBitcodeHeader(Stream); + WriteIdentificationBlock(M, Stream); + // Emit the module. WriteModule(M, Stream, ShouldPreserveUseListOrder, BitcodeStartBit, EmitFunctionSummary); Index: test/Bitcode/identification.ll =================================================================== --- /dev/null +++ test/Bitcode/identification.ll @@ -0,0 +1,3 @@ +; Check that a block "IDENTIFICATION_BLOCK_ID" is emitted. +;RUN: llvm-as < %s | llvm-bcanalyzer -dump | FileCheck %s +;CHECK: IDENTIFICATION_BLOCK_ID Index: tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp =================================================================== --- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -110,6 +110,8 @@ case bitc::TYPE_BLOCK_ID_NEW: return "TYPE_BLOCK_ID"; case bitc::CONSTANTS_BLOCK_ID: return "CONSTANTS_BLOCK"; case bitc::FUNCTION_BLOCK_ID: return "FUNCTION_BLOCK"; + case bitc::IDENTIFICATION_BLOCK_ID: + return "IDENTIFICATION_BLOCK_ID"; case bitc::VALUE_SYMTAB_BLOCK_ID: return "VALUE_SYMTAB"; case bitc::METADATA_BLOCK_ID: return "METADATA_BLOCK"; case bitc::METADATA_ATTACHMENT_ID: return "METADATA_ATTACHMENT_BLOCK";