From cd513a41c17a3591e764b1ff986ae501a28cc5f5 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Fri, 11 Nov 2016 19:50:24 +0000 Subject: [PATCH] Bitcode: Clean up error handling for certain bitcode query functions. The functions getBitcodeTargetTriple(), isBitcodeContainingObjCCategory(), getBitcodeProducerString() and hasGlobalValueSummary() now return errors via their return value rather than via the diagnostic handler. To make this work, re-implement these functions using non-member functions so that they can be used without the LLVMContext required by BitcodeReader. Differential Revision: https://reviews.llvm.org/D26532 llvm-svn: 286623 --- lld/ELF/Driver.cpp | 7 +- lld/ELF/Driver.h | 2 - lld/ELF/InputFiles.cpp | 4 +- llvm/include/llvm/Bitcode/BitcodeReader.h | 30 +- .../llvm/Object/ModuleSummaryIndexObjectFile.h | 6 - llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 567 +++++++++------------ llvm/lib/LTO/LTO.cpp | 6 +- llvm/lib/LTO/LTOModule.cpp | 26 +- llvm/lib/LTO/ThinLTOCodeGenerator.cpp | 15 +- llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp | 12 - llvm/tools/llvm-lto/llvm-lto.cpp | 10 +- llvm/tools/lto/lto.cpp | 4 +- 12 files changed, 318 insertions(+), 371 deletions(-) diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 8fd6137..2b1f746 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -24,6 +24,7 @@ #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include @@ -202,12 +203,6 @@ static void initLLVM(opt::InputArgList &Args) { InitializeAllAsmPrinters(); InitializeAllAsmParsers(); - // This is a flag to discard all but GlobalValue names. - // We want to enable it by default because it saves memory. - // Disable it only when a developer option (-save-temps) is given. - Driver->Context.setDiscardValueNames(!Config->SaveTemps); - Driver->Context.enableDebugTypeODRUniquing(); - // Parse and evaluate -mllvm options. std::vector V; V.push_back("lld (LLVM option parsing)"); diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h index 09b7e23..26da9d8 100644 --- a/lld/ELF/Driver.h +++ b/lld/ELF/Driver.h @@ -16,7 +16,6 @@ #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" -#include "llvm/IR/LLVMContext.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/raw_ostream.h" @@ -30,7 +29,6 @@ public: void main(ArrayRef Args, bool CanExitEarly); void addFile(StringRef Path); void addLibrary(StringRef Name); - llvm::LLVMContext Context; // to parse bitcode files std::unique_ptr Cpio; // for reproduce private: diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 87baa9d..6843618 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -653,14 +653,14 @@ template void SharedFile::parseRest() { } static ELFKind getBitcodeELFKind(MemoryBufferRef MB) { - Triple T(getBitcodeTargetTriple(MB, Driver->Context)); + Triple T(check(getBitcodeTargetTriple(MB))); if (T.isLittleEndian()) return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind; return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind; } static uint8_t getBitcodeMachineKind(MemoryBufferRef MB) { - Triple T(getBitcodeTargetTriple(MB, Driver->Context)); + Triple T(check(getBitcodeTargetTriple(MB))); switch (T.getArch()) { case Triple::aarch64: return EM_AARCH64; diff --git a/llvm/include/llvm/Bitcode/BitcodeReader.h b/llvm/include/llvm/Bitcode/BitcodeReader.h index 52759c1..25af17b 100644 --- a/llvm/include/llvm/Bitcode/BitcodeReader.h +++ b/llvm/include/llvm/Bitcode/BitcodeReader.h @@ -18,6 +18,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/MemoryBuffer.h" #include @@ -26,6 +27,22 @@ namespace llvm { class LLVMContext; class Module; + // These functions are for converting Expected/Error values to + // ErrorOr/std::error_code for compatibility with legacy clients. FIXME: + // Remove these functions once no longer needed by the C and libLTO APIs. + + std::error_code errorToErrorCodeAndEmitErrors(LLVMContext &Ctx, Error Err); + std::error_code + errorToErrorCodeAndEmitErrors(const DiagnosticHandlerFunction &DiagHandler, + Error Err); + + template + ErrorOr expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected Val) { + if (!Val) + return errorToErrorCodeAndEmitErrors(Ctx, Val.takeError()); + return std::move(*Val); + } + /// Read the header of the specified bitcode buffer and prepare for lazy /// deserialization of function bodies. If ShouldLazyLoadMetadata is true, /// lazily load metadata as well. @@ -44,28 +61,23 @@ namespace llvm { /// Read the header of the specified bitcode buffer and extract just the /// triple information. If successful, this returns a string. On error, this /// returns "". - std::string getBitcodeTargetTriple(MemoryBufferRef Buffer, - LLVMContext &Context); + Expected getBitcodeTargetTriple(MemoryBufferRef Buffer); /// Return true if \p Buffer contains a bitcode file with ObjC code (category /// or class) in it. - bool isBitcodeContainingObjCCategory(MemoryBufferRef Buffer, - LLVMContext &Context); + Expected isBitcodeContainingObjCCategory(MemoryBufferRef Buffer); /// 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); + Expected getBitcodeProducerString(MemoryBufferRef Buffer); /// Read the specified bitcode file, returning the module. ErrorOr> parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context); /// Check if the given bitcode buffer contains a summary block. - bool - hasGlobalValueSummary(MemoryBufferRef Buffer, - const DiagnosticHandlerFunction &DiagnosticHandler); + Expected hasGlobalValueSummary(MemoryBufferRef Buffer); /// Parse the specified bitcode buffer, returning the module summary index. ErrorOr> diff --git a/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h b/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h index d021fb2..8d30f77 100644 --- a/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h +++ b/llvm/include/llvm/Object/ModuleSummaryIndexObjectFile.h @@ -79,12 +79,6 @@ public: static ErrorOr findBitcodeInMemBuffer(MemoryBufferRef Object); - /// \brief Looks for summary sections in the given memory buffer, - /// returns true if found, else false. - static bool hasGlobalValueSummaryInMemBuffer( - MemoryBufferRef Object, - const DiagnosticHandlerFunction &DiagnosticHandler); - /// \brief Parse module summary index in the given memory buffer. /// Return new ModuleSummaryIndexObjectFile instance containing parsed module /// summary/index. diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 9256baa8..357f283 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -267,6 +267,228 @@ Expected initStream(MemoryBufferRef Buffer) { return std::move(Stream); } +/// Convert a string from a record into an std::string, return true on failure. +template +static bool convertToString(ArrayRef Record, unsigned Idx, + StrTy &Result) { + if (Idx > Record.size()) + return true; + + for (unsigned i = Idx, e = Record.size(); i != e; ++i) + Result += (char)Record[i]; + return false; +} + +/// Read the "IDENTIFICATION_BLOCK_ID" block, do some basic enforcement on the +/// "epoch" encoded in the bitcode, and return the producer name if any. +Expected readIdentificationBlock(BitstreamCursor &Stream) { + if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID)) + return error("Invalid record"); + + // Read all the records. + SmallVector Record; + + std::string ProducerIdentification; + + while (true) { + BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + default: + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return ProducerIdentification; + case BitstreamEntry::Record: + // The interesting case. + break; + } + + // Read a record. + Record.clear(); + unsigned BitCode = Stream.readRecord(Entry.ID, Record); + switch (BitCode) { + default: // Default behavior: reject + return error("Invalid value"); + case bitc::IDENTIFICATION_CODE_STRING: // IDENTIFICATION: [strchr x N] + convertToString(Record, 0, ProducerIdentification); + break; + case bitc::IDENTIFICATION_CODE_EPOCH: { // EPOCH: [epoch#] + unsigned epoch = (unsigned)Record[0]; + if (epoch != bitc::BITCODE_CURRENT_EPOCH) { + return error( + Twine("Incompatible epoch: Bitcode '") + Twine(epoch) + + "' vs current: '" + Twine(bitc::BITCODE_CURRENT_EPOCH) + "'"); + } + } + } + } +} + +Expected readIdentificationCode(BitstreamCursor &Stream) { + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (true) { + if (Stream.AtEndOfStream()) + return ""; + + BitstreamEntry Entry = Stream.advance(); + switch (Entry.Kind) { + case BitstreamEntry::EndBlock: + case BitstreamEntry::Error: + return error("Malformed block"); + + case BitstreamEntry::SubBlock: + if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) + return readIdentificationBlock(Stream); + + // Ignore other sub-blocks. + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + +Expected hasObjCCategoryInModule(BitstreamCursor &Stream) { + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return error("Invalid record"); + + SmallVector Record; + // Read all the records for this module. + + while (true) { + BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + + switch (Entry.Kind) { + case BitstreamEntry::SubBlock: // Handled for us already. + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return false; + case BitstreamEntry::Record: + // The interesting case. + break; + } + + // Read a record. + switch (Stream.readRecord(Entry.ID, Record)) { + default: + break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] + std::string S; + if (convertToString(Record, 0, S)) + return error("Invalid record"); + // Check for the i386 and other (x86_64, ARM) conventions + if (S.find("__DATA, __objc_catlist") != std::string::npos || + S.find("__OBJC,__category") != std::string::npos) + return true; + break; + } + } + Record.clear(); + } + llvm_unreachable("Exit infinite loop"); +} + +Expected hasObjCCategory(BitstreamCursor &Stream) { + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (true) { + BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return false; + + case BitstreamEntry::SubBlock: + if (Entry.ID == bitc::MODULE_BLOCK_ID) + return hasObjCCategoryInModule(Stream); + + // Ignore other sub-blocks. + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + +Expected readModuleTriple(BitstreamCursor &Stream) { + if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) + return error("Invalid record"); + + SmallVector Record; + + std::string Triple; + + // Read all the records for this module. + while (true) { + BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); + + switch (Entry.Kind) { + case BitstreamEntry::SubBlock: // Handled for us already. + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return Triple; + case BitstreamEntry::Record: + // The interesting case. + break; + } + + // Read a record. + switch (Stream.readRecord(Entry.ID, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] + std::string S; + if (convertToString(Record, 0, S)) + return error("Invalid record"); + Triple = S; + break; + } + } + Record.clear(); + } + llvm_unreachable("Exit infinite loop"); +} + +Expected readTriple(BitstreamCursor &Stream) { + // We expect a number of well-defined blocks, though we don't necessarily + // need to understand them all. + while (true) { + BitstreamEntry Entry = Stream.advance(); + + switch (Entry.Kind) { + case BitstreamEntry::Error: + return error("Malformed block"); + case BitstreamEntry::EndBlock: + return ""; + + case BitstreamEntry::SubBlock: + if (Entry.ID == bitc::MODULE_BLOCK_ID) + return readModuleTriple(Stream); + + // Ignore other sub-blocks. + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + class BitcodeReaderBase { protected: BitcodeReaderBase(BitstreamCursor Stream) : Stream(std::move(Stream)) { @@ -397,17 +619,6 @@ public: /// \returns true if an error occurred. Error parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata = false); - /// \brief Cheap mechanism to just extract module triple - /// \returns true if an error occurred. - Expected parseTriple(); - - /// Cheap mechanism to just extract the identification block out of bitcode. - Expected parseIdentificationBlock(); - - /// Peak at the module content and return true if any ObjC category or class - /// is found. - Expected hasObjCCategory(); - static uint64_t decodeSignRotatedValue(uint64_t V); /// Materialize any deferred Metadata block. @@ -416,11 +627,6 @@ public: void setStripDebugInfo() override; private: - /// Parse the "IDENTIFICATION_BLOCK_ID" block, populate the - // ProducerIdentification data member, and do some basic enforcement on the - // "epoch" encoded in the bitcode. - Error parseBitcodeVersion(); - std::vector IdentifiedStructTypes; StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name); StructType *createIdentifiedStructType(LLVMContext &Context); @@ -546,8 +752,6 @@ private: Error parseGlobalObjectAttachment(GlobalObject &GO, ArrayRef Record); Error parseMetadataAttachment(Function &F); - Expected parseModuleTriple(); - Expected hasObjCCategoryInModule(); Error parseUseLists(); Error findFunctionInStream( Function *F, @@ -622,7 +826,10 @@ private: bool IsOldProfileFormat, bool HasProfile); }; -std::error_code errorToErrorCodeAndEmitErrors(LLVMContext &Ctx, Error Err) { +} // end anonymous namespace + +std::error_code llvm::errorToErrorCodeAndEmitErrors(LLVMContext &Ctx, + Error Err) { if (Err) { std::error_code EC; handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { @@ -634,9 +841,8 @@ std::error_code errorToErrorCodeAndEmitErrors(LLVMContext &Ctx, Error Err) { return std::error_code(); } -std::error_code -errorToErrorCodeAndEmitErrors(const DiagnosticHandlerFunction &DiagHandler, - Error Err) { +std::error_code llvm::errorToErrorCodeAndEmitErrors( + const DiagnosticHandlerFunction &DiagHandler, Error Err) { if (Err) { std::error_code EC; handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) { @@ -648,24 +854,6 @@ errorToErrorCodeAndEmitErrors(const DiagnosticHandlerFunction &DiagHandler, return std::error_code(); } -template -ErrorOr expectedToErrorOrAndEmitErrors(LLVMContext &Ctx, Expected Val) { - if (!Val) - return errorToErrorCodeAndEmitErrors(Ctx, Val.takeError()); - return std::move(*Val); -} - -template -static ErrorOr -expectedToErrorOrAndEmitErrors(const DiagnosticHandlerFunction &DiagHandler, - Expected Val) { - if (!Val) - return errorToErrorCodeAndEmitErrors(DiagHandler, Val.takeError()); - return std::move(*Val); -} - -} // end anonymous namespace - BitcodeReader::BitcodeReader(BitstreamCursor Stream, LLVMContext &Context) : BitcodeReaderBase(std::move(Stream)), Context(Context), ValueList(Context), MetadataList(Context) {} @@ -707,18 +895,6 @@ Error BitcodeReader::materializeForwardReferencedFunctions() { // Helper functions to implement forward reference resolution, etc. //===----------------------------------------------------------------------===// -/// Convert a string from a record into an std::string, return true on failure. -template -static bool convertToString(ArrayRef Record, unsigned Idx, - StrTy &Result) { - if (Idx > Record.size()) - return true; - - for (unsigned i = Idx, e = Record.size(); i != e; ++i) - Result += (char)Record[i]; - return false; -} - static bool hasImplicitComdat(size_t Val) { switch (Val) { default: @@ -3713,50 +3889,6 @@ Error BitcodeReader::rememberAndSkipFunctionBodies() { } } -Error BitcodeReader::parseBitcodeVersion() { - if (Stream.EnterSubBlock(bitc::IDENTIFICATION_BLOCK_ID)) - return error("Invalid record"); - - // Read all the records. - SmallVector Record; - - while (true) { - BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - default: - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return Error::success(); - case BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - Record.clear(); - unsigned BitCode = Stream.readRecord(Entry.ID, Record); - switch (BitCode) { - default: // Default behavior: reject - return error("Invalid value"); - case bitc::IDENTIFICATION_CODE_STRING: { // IDENTIFICATION: [strchr x - // N] - convertToString(Record, 0, ProducerIdentification); - break; - } - case bitc::IDENTIFICATION_CODE_EPOCH: { // EPOCH: [epoch#] - unsigned epoch = (unsigned)Record[0]; - if (epoch != bitc::BITCODE_CURRENT_EPOCH) { - return error( - Twine("Incompatible epoch: Bitcode '") + Twine(epoch) + - "' vs current: '" + Twine(bitc::BITCODE_CURRENT_EPOCH) + "'"); - } - } - } - } -} - bool BitcodeReaderBase::readBlockInfo() { Optional NewBlockInfo = Stream.ReadBlockInfoBlock(); if (!NewBlockInfo) @@ -4259,8 +4391,11 @@ Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata) { return error("Malformed block"); if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { - if (Error Err = parseBitcodeVersion()) - return Err; + Expected ProducerIdentificationOrErr = + readIdentificationBlock(Stream); + if (!ProducerIdentificationOrErr) + return ProducerIdentificationOrErr.takeError(); + ProducerIdentification = *ProducerIdentificationOrErr; continue; } @@ -4272,107 +4407,6 @@ Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata) { } } -Expected BitcodeReader::parseModuleTriple() { - if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) - return error("Invalid record"); - - SmallVector Record; - - std::string Triple; - - // Read all the records for this module. - while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); - - switch (Entry.Kind) { - case BitstreamEntry::SubBlock: // Handled for us already. - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return Triple; - case BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - switch (Stream.readRecord(Entry.ID, Record)) { - default: break; // Default behavior, ignore unknown content. - case bitc::MODULE_CODE_TRIPLE: { // TRIPLE: [strchr x N] - std::string S; - if (convertToString(Record, 0, S)) - return error("Invalid record"); - Triple = S; - break; - } - } - Record.clear(); - } - llvm_unreachable("Exit infinite loop"); -} - -Expected BitcodeReader::parseTriple() { - // We expect a number of well-defined blocks, though we don't necessarily - // need to understand them all. - while (true) { - BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return ""; - - case BitstreamEntry::SubBlock: - if (Entry.ID == bitc::MODULE_BLOCK_ID) - return parseModuleTriple(); - - // Ignore other sub-blocks. - if (Stream.SkipBlock()) - return error("Malformed block"); - continue; - - case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; - } - } -} - -Expected BitcodeReader::parseIdentificationBlock() { - // We expect a number of well-defined blocks, though we don't necessarily - // need to understand them all. - while (true) { - // This loop iterates at the top-level: since there is no enclosing block - // we need to make sure we aren't at the end of the stream before calling - // advance, otherwise we'll get an error. - if (Stream.AtEndOfStream()) - return ""; - - BitstreamEntry Entry = Stream.advance(); - switch (Entry.Kind) { - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return ""; - - case BitstreamEntry::SubBlock: - if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { - if (Error Err = parseBitcodeVersion()) - return std::move(Err); - return ProducerIdentification; - } - // Ignore other sub-blocks. - if (Stream.SkipBlock()) - return error("Malformed block"); - continue; - case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; - } - } -} - Error BitcodeReader::parseGlobalObjectAttachment(GlobalObject &GO, ArrayRef Record) { assert(Record.size() % 2 == 0); @@ -4388,75 +4422,6 @@ Error BitcodeReader::parseGlobalObjectAttachment(GlobalObject &GO, return Error::success(); } -Expected BitcodeReader::hasObjCCategory() { - // We expect a number of well-defined blocks, though we don't necessarily - // need to understand them all. - while (true) { - BitstreamEntry Entry = Stream.advance(); - - switch (Entry.Kind) { - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return false; - - case BitstreamEntry::SubBlock: - if (Entry.ID == bitc::MODULE_BLOCK_ID) - return hasObjCCategoryInModule(); - - // Ignore other sub-blocks. - if (Stream.SkipBlock()) - return error("Malformed block"); - continue; - - case BitstreamEntry::Record: - Stream.skipRecord(Entry.ID); - continue; - } - } -} - -Expected BitcodeReader::hasObjCCategoryInModule() { - if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID)) - return error("Invalid record"); - - SmallVector Record; - // Read all the records for this module. - - while (true) { - BitstreamEntry Entry = Stream.advanceSkippingSubblocks(); - - switch (Entry.Kind) { - case BitstreamEntry::SubBlock: // Handled for us already. - case BitstreamEntry::Error: - return error("Malformed block"); - case BitstreamEntry::EndBlock: - return false; - case BitstreamEntry::Record: - // The interesting case. - break; - } - - // Read a record. - switch (Stream.readRecord(Entry.ID, Record)) { - default: - break; // Default behavior, ignore unknown content. - case bitc::MODULE_CODE_SECTIONNAME: { // SECTIONNAME: [strchr x N] - std::string S; - if (convertToString(Record, 0, S)) - return error("Invalid record"); - // Check for the i386 and other (x86_64, ARM) conventions - if (S.find("__DATA, __objc_catlist") != std::string::npos || - S.find("__OBJC,__category") != std::string::npos) - return true; - break; - } - } - Record.clear(); - } - llvm_unreachable("Exit infinite loop"); -} - /// Parse metadata attachments. Error BitcodeReader::parseMetadataAttachment(Function &F) { if (Stream.EnterSubBlock(bitc::METADATA_ATTACHMENT_ID)) @@ -6673,49 +6638,28 @@ ErrorOr> llvm::parseBitcodeFile(MemoryBufferRef Buffer, // written. We must defer until the Module has been fully materialized. } -std::string llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer, - LLVMContext &Context) { - ErrorOr StreamOrErr = - expectedToErrorOrAndEmitErrors(Context, initStream(Buffer)); +Expected llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer) { + Expected StreamOrErr = initStream(Buffer); if (!StreamOrErr) - return ""; - - BitcodeReader R(std::move(*StreamOrErr), Context); - ErrorOr Triple = - expectedToErrorOrAndEmitErrors(Context, R.parseTriple()); - if (Triple.getError()) - return ""; - return Triple.get(); + return StreamOrErr.takeError(); + + return readTriple(*StreamOrErr); } -bool llvm::isBitcodeContainingObjCCategory(MemoryBufferRef Buffer, - LLVMContext &Context) { - ErrorOr StreamOrErr = - expectedToErrorOrAndEmitErrors(Context, initStream(Buffer)); +Expected llvm::isBitcodeContainingObjCCategory(MemoryBufferRef Buffer) { + Expected StreamOrErr = initStream(Buffer); if (!StreamOrErr) - return false; + return StreamOrErr.takeError(); - BitcodeReader R(std::move(*StreamOrErr), Context); - ErrorOr hasObjCCategory = - expectedToErrorOrAndEmitErrors(Context, R.hasObjCCategory()); - if (hasObjCCategory.getError()) - return false; - return hasObjCCategory.get(); + return hasObjCCategory(*StreamOrErr); } -std::string llvm::getBitcodeProducerString(MemoryBufferRef Buffer, - LLVMContext &Context) { - ErrorOr StreamOrErr = - expectedToErrorOrAndEmitErrors(Context, initStream(Buffer)); +Expected llvm::getBitcodeProducerString(MemoryBufferRef Buffer) { + Expected StreamOrErr = initStream(Buffer); if (!StreamOrErr) - return ""; - - BitcodeReader R(std::move(*StreamOrErr), Context); - ErrorOr ProducerString = - expectedToErrorOrAndEmitErrors(Context, R.parseIdentificationBlock()); - if (ProducerString.getError()) - return ""; - return ProducerString.get(); + return StreamOrErr.takeError(); + + return readIdentificationCode(*StreamOrErr); } // Parse the specified bitcode buffer, returning the function info index. @@ -6740,19 +6684,16 @@ ErrorOr> llvm::getModuleSummaryIndex( } // Check if the given bitcode buffer contains a global value summary block. -bool llvm::hasGlobalValueSummary( - MemoryBufferRef Buffer, - const DiagnosticHandlerFunction &DiagnosticHandler) { - ErrorOr StreamOrErr = expectedToErrorOrAndEmitErrors( - DiagnosticHandler, initStream(Buffer)); +Expected llvm::hasGlobalValueSummary(MemoryBufferRef Buffer) { + Expected StreamOrErr = initStream(Buffer); if (!StreamOrErr) - return false; + return StreamOrErr.takeError(); ModuleSummaryIndexBitcodeReader R(std::move(*StreamOrErr), true); - if (errorToErrorCodeAndEmitErrors( - DiagnosticHandler, - R.parseSummaryIndexInto(nullptr, Buffer.getBufferIdentifier()))) - return false; + + if (Error Err = + R.parseSummaryIndexInto(nullptr, Buffer.getBufferIdentifier())) + return std::move(Err); return R.foundGlobalValSummary(); } diff --git a/llvm/lib/LTO/LTO.cpp b/llvm/lib/LTO/LTO.cpp index 1e5ab58..4ff1bfb 100644 --- a/llvm/lib/LTO/LTO.cpp +++ b/llvm/lib/LTO/LTO.cpp @@ -328,9 +328,11 @@ Error LTO::add(std::unique_ptr Input, M.setTargetTriple(Conf.DefaultTriple); MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef(); - bool HasThinLTOSummary = hasGlobalValueSummary(MBRef, Conf.DiagHandler); + Expected HasThinLTOSummary = hasGlobalValueSummary(MBRef); + if (!HasThinLTOSummary) + return HasThinLTOSummary.takeError(); - if (HasThinLTOSummary) + if (*HasThinLTOSummary) return addThinLTO(std::move(Input), Res); else return addRegularLTO(std::move(Input), Res); diff --git a/llvm/lib/LTO/LTOModule.cpp b/llvm/lib/LTO/LTOModule.cpp index 039dbf2..ef1c93a 100644 --- a/llvm/lib/LTO/LTOModule.cpp +++ b/llvm/lib/LTO/LTOModule.cpp @@ -76,13 +76,12 @@ bool LTOModule::isBitcodeFile(StringRef Path) { bool LTOModule::isThinLTO() { // Right now the detection is only based on the summary presence. We may want // to add a dedicated flag at some point. - return hasGlobalValueSummary(IRFile->getMemoryBufferRef(), - [](const DiagnosticInfo &DI) { - DiagnosticPrinterRawOStream DP(errs()); - DI.print(DP); - errs() << '\n'; - return; - }); + Expected Result = hasGlobalValueSummary(IRFile->getMemoryBufferRef()); + if (!Result) { + logAllUnhandledErrors(Result.takeError(), errs(), ""); + return false; + } + return *Result; } bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, @@ -92,8 +91,11 @@ bool LTOModule::isBitcodeForTarget(MemoryBuffer *Buffer, if (!BCOrErr) return false; LLVMContext Context; - std::string Triple = getBitcodeTargetTriple(*BCOrErr, Context); - return StringRef(Triple).startswith(TriplePrefix); + ErrorOr TripleOrErr = + expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(*BCOrErr)); + if (!TripleOrErr) + return false; + return StringRef(*TripleOrErr).startswith(TriplePrefix); } std::string LTOModule::getProducerString(MemoryBuffer *Buffer) { @@ -102,7 +104,11 @@ std::string LTOModule::getProducerString(MemoryBuffer *Buffer) { if (!BCOrErr) return ""; LLVMContext Context; - return getBitcodeProducerString(*BCOrErr, Context); + ErrorOr ProducerOrErr = expectedToErrorOrAndEmitErrors( + Context, getBitcodeProducerString(*BCOrErr)); + if (!ProducerOrErr) + return ""; + return *ProducerOrErr; } ErrorOr> diff --git a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp index 400b80d..77f1d34 100644 --- a/llvm/lib/LTO/ThinLTOCodeGenerator.cpp +++ b/llvm/lib/LTO/ThinLTOCodeGenerator.cpp @@ -453,14 +453,23 @@ void ThinLTOCodeGenerator::addModule(StringRef Identifier, StringRef Data) { if (Modules.empty()) { // First module added, so initialize the triple and some options LLVMContext Context; - Triple TheTriple(getBitcodeTargetTriple(Buffer, Context)); + StringRef TripleStr; + ErrorOr TripleOrErr = + expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(Buffer)); + if (TripleOrErr) + TripleStr = *TripleOrErr; + Triple TheTriple(TripleStr); initTMBuilder(TMBuilder, Triple(TheTriple)); } #ifndef NDEBUG else { LLVMContext Context; - assert(TMBuilder.TheTriple.str() == - getBitcodeTargetTriple(Buffer, Context) && + StringRef TripleStr; + ErrorOr TripleOrErr = + expectedToErrorOrAndEmitErrors(Context, getBitcodeTargetTriple(Buffer)); + if (TripleOrErr) + TripleStr = *TripleOrErr; + assert(TMBuilder.TheTriple.str() == TripleStr && "ThinLTO modules with different triple not supported"); } #endif diff --git a/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp b/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp index 780324d..e597fc2 100644 --- a/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp +++ b/llvm/lib/Object/ModuleSummaryIndexObjectFile.cpp @@ -67,18 +67,6 @@ ModuleSummaryIndexObjectFile::findBitcodeInMemBuffer(MemoryBufferRef Object) { } } -// Looks for module summary index in the given memory buffer. -// returns true if found, else false. -bool ModuleSummaryIndexObjectFile::hasGlobalValueSummaryInMemBuffer( - MemoryBufferRef Object, - const DiagnosticHandlerFunction &DiagnosticHandler) { - ErrorOr BCOrErr = findBitcodeInMemBuffer(Object); - if (!BCOrErr) - return false; - - return hasGlobalValueSummary(BCOrErr.get(), DiagnosticHandler); -} - // Parse module summary index in the given memory buffer. // Return new ModuleSummaryIndexObjectFile instance containing parsed // module summary/index. diff --git a/llvm/tools/llvm-lto/llvm-lto.cpp b/llvm/tools/llvm-lto/llvm-lto.cpp index 50c5f23..d883f3c 100644 --- a/llvm/tools/llvm-lto/llvm-lto.cpp +++ b/llvm/tools/llvm-lto/llvm-lto.cpp @@ -773,12 +773,12 @@ int main(int argc, char **argv) { if (CheckHasObjC) { for (auto &Filename : InputFilenames) { - ErrorOr> BufferOrErr = - MemoryBuffer::getFile(Filename); - error(BufferOrErr, "error loading file '" + Filename + "'"); + ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" + + Filename + "': "); + std::unique_ptr BufferOrErr = + ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename))); auto Buffer = std::move(BufferOrErr.get()); - LLVMContext Ctx; - if (llvm::isBitcodeContainingObjCCategory(*Buffer, Ctx)) + if (ExitOnErr(llvm::isBitcodeContainingObjCCategory(*Buffer))) outs() << "Bitcode " << Filename << " contains ObjC\n"; else outs() << "Bitcode " << Filename << " does not contain ObjC\n"; diff --git a/llvm/tools/lto/lto.cpp b/llvm/tools/lto/lto.cpp index 2763b1f..2f0dd26 100644 --- a/llvm/tools/lto/lto.cpp +++ b/llvm/tools/lto/lto.cpp @@ -187,7 +187,9 @@ bool lto_module_has_objc_category(const void *mem, size_t length) { if (!Buffer) return false; LLVMContext Ctx; - return llvm::isBitcodeContainingObjCCategory(*Buffer, Ctx); + ErrorOr Result = expectedToErrorOrAndEmitErrors( + Ctx, llvm::isBitcodeContainingObjCCategory(*Buffer)); + return Result && *Result; } bool lto_module_is_object_file_in_memory(const void* mem, size_t length) { -- 2.7.4