Index: include/llvm/Bitcode/ReaderWriter.h =================================================================== --- include/llvm/Bitcode/ReaderWriter.h +++ include/llvm/Bitcode/ReaderWriter.h @@ -54,6 +54,13 @@ getBitcodeTargetTriple(MemoryBufferRef Buffer, LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr); + /// Read the header of the specified bitcode buffer and extract just the + /// producer string information. If successful, this returns a string. On + /// error, this returns "". + std::string getBitcodeProducerString( + MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler = nullptr); + /// Read the specified bitcode file, returning the module. ErrorOr> parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, Index: include/llvm/LTO/LTOModule.h =================================================================== --- include/llvm/LTO/LTOModule.h +++ include/llvm/LTO/LTOModule.h @@ -74,6 +74,11 @@ static bool isBitcodeForTarget(MemoryBuffer *memBuffer, StringRef triplePrefix); + /// Returns a string representing the producer identification stored in the + /// bitcode, or "" if the bitcode does not contains any. + /// + static std::string getProducerString(MemoryBuffer *Buffer); + /// Create a MemoryBuffer from a memory range with an optional name. static std::unique_ptr makeBuffer(const void *mem, size_t length, StringRef name = ""); Index: lib/Bitcode/Reader/BitcodeReader.cpp =================================================================== --- lib/Bitcode/Reader/BitcodeReader.cpp +++ lib/Bitcode/Reader/BitcodeReader.cpp @@ -271,6 +271,9 @@ /// \returns true if an error occurred. ErrorOr parseTriple(); + /// Cheap mechanism to just extract the identification block out of bitcode. + ErrorOr parseIdentificationBlock(); + static uint64_t decodeSignRotatedValue(uint64_t V); /// Materialize any deferred Metadata block. @@ -3729,6 +3732,41 @@ } } +ErrorOr BitcodeReader::parseIdentificationBlock() { + if (std::error_code EC = initStream(nullptr)) + return EC; + + // Sniff for the signature. + if (!hasValidBitcodeHeader(Stream)) + return error("Invalid bitcode signature"); + + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (1) { + BitstreamEntry Entry = Stream.advance(); + switch (Entry.Kind) { + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return std::error_code(); + + case BitstreamEntry::SubBlock: + if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { + if (std::error_code EC = parseBitcodeVersion()) + return EC; + return ProducerIdentification; + } + // Ignore other sub-blocks. + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + /// Parse metadata attachments. std::error_code BitcodeReader::parseMetadataAttachment(Function &F) { if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) @@ -5835,6 +5873,17 @@ return Triple.get(); } +std::string +llvm::getBitcodeProducerString(MemoryBufferRef Buffer, LLVMContext &Context, + DiagnosticHandlerFunction DiagnosticHandler) { + std::unique_ptr Buf = MemoryBuffer::getMemBuffer(Buffer, false); + BitcodeReader R(Buf.release(), Context, DiagnosticHandler); + ErrorOr ProducerString = R.parseIdentificationBlock(); + if (ProducerString.getError()) + return ""; + return ProducerString.get(); +} + // Parse the specified bitcode buffer, returning the function info index. // If IsLazy is false, parse the entire function summary into // the index. Otherwise skip the function summary section, and only create Index: lib/LTO/LTOModule.cpp =================================================================== --- lib/LTO/LTOModule.cpp +++ lib/LTO/LTOModule.cpp @@ -91,6 +91,15 @@ return StringRef(Triple).startswith(TriplePrefix); } +std::string LTOModule::getProducerString(MemoryBuffer *Buffer) { + ErrorOr BCOrErr = + IRObjectFile::findBitcodeInMemBuffer(Buffer->getMemBufferRef()); + if (!BCOrErr) + return ""; + LLVMContext Context; + return getBitcodeProducerString(*BCOrErr, Context); +} + LTOModule *LTOModule::createFromFile(const char *path, TargetOptions options, std::string &errMsg) { ErrorOr> BufferOrErr =