diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2016-11-16 21:44:45 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2016-11-16 21:44:45 +0000 |
commit | 7a74803abf1423854792987492fe25e975bae9f8 (patch) | |
tree | db665e0f7239b1a112eaac232f689a79da55cdda /llvm/lib/Bitcode/Reader/BitcodeReader.cpp | |
parent | a49c2019f14e5ea5de35d6db88da1b081312ea4a (diff) | |
download | bcm5719-llvm-7a74803abf1423854792987492fe25e975bae9f8.tar.gz bcm5719-llvm-7a74803abf1423854792987492fe25e975bae9f8.zip |
Bitcode: Introduce initial multi-module reader API.
Implement getLazyBitcodeModule() and parseBitcodeFile() in terms of it.
Differential Revision: https://reviews.llvm.org/D26719
llvm-svn: 287156
Diffstat (limited to 'llvm/lib/Bitcode/Reader/BitcodeReader.cpp')
-rw-r--r-- | llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 148 |
1 files changed, 99 insertions, 49 deletions
diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 94a3bcf8554..4bf8bbb8a22 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -607,7 +607,8 @@ class BitcodeReader : public BitcodeReaderBase, public GVMaterializer { std::vector<std::string> BundleTags; public: - BitcodeReader(BitstreamCursor Stream, LLVMContext &Context); + BitcodeReader(BitstreamCursor Stream, StringRef ProducerIdentification, + LLVMContext &Context); Error materializeForwardReferencedFunctions(); @@ -841,9 +842,13 @@ std::error_code llvm::errorToErrorCodeAndEmitErrors(LLVMContext &Ctx, return std::error_code(); } -BitcodeReader::BitcodeReader(BitstreamCursor Stream, LLVMContext &Context) - : BitcodeReaderBase(std::move(Stream)), Context(Context), ValueList(Context), - MetadataList(Context) {} +BitcodeReader::BitcodeReader(BitstreamCursor Stream, + StringRef ProducerIdentification, + LLVMContext &Context) + : BitcodeReaderBase(std::move(Stream)), Context(Context), + ValueList(Context), MetadataList(Context) { + this->ProducerIdentification = ProducerIdentification; +} Error BitcodeReader::materializeForwardReferencedFunctions() { if (WillMaterializeAllForwardRefs) @@ -4365,36 +4370,7 @@ Error BitcodeReader::parseModule(uint64_t ResumeBit, Error BitcodeReader::parseBitcodeInto(Module *M, bool ShouldLazyLoadMetadata) { TheModule = M; - - // We expect a number of well-defined blocks, though we don't necessarily - // need to understand them all. - while (true) { - if (Stream.AtEndOfStream()) { - // We didn't really read a proper Module. - return error("Malformed IR file"); - } - - BitstreamEntry Entry = - Stream.advance(BitstreamCursor::AF_DontAutoprocessAbbrevs); - - if (Entry.Kind != BitstreamEntry::SubBlock) - return error("Malformed block"); - - if (Entry.ID == bitc::IDENTIFICATION_BLOCK_ID) { - Expected<std::string> ProducerIdentificationOrErr = - readIdentificationBlock(Stream); - if (!ProducerIdentificationOrErr) - return ProducerIdentificationOrErr.takeError(); - ProducerIdentification = *ProducerIdentificationOrErr; - continue; - } - - if (Entry.ID == bitc::MODULE_BLOCK_ID) - return parseModule(0, ShouldLazyLoadMetadata); - - if (Stream.SkipBlock()) - return error("Invalid record"); - } + return parseModule(0, ShouldLazyLoadMetadata); } Error BitcodeReader::parseGlobalObjectAttachment(GlobalObject &GO, @@ -6566,26 +6542,76 @@ const std::error_category &llvm::BitcodeErrorCategory() { // External interface //===----------------------------------------------------------------------===// +Expected<std::vector<BitcodeModule>> +llvm::getBitcodeModuleList(MemoryBufferRef Buffer) { + Expected<BitstreamCursor> StreamOrErr = initStream(Buffer); + if (!StreamOrErr) + return StreamOrErr.takeError(); + BitstreamCursor &Stream = *StreamOrErr; + + uint64_t IdentificationBit = -1ull; + std::vector<BitcodeModule> Modules; + while (true) { + // We may be consuming bitcode from a client that leaves garbage at the end + // of the bitcode stream (e.g. Apple's ar tool). If we are close enough to + // the end that there cannot possibly be another module, stop looking. + if (Stream.getCurrentByteNo() + 8 >= Stream.getBitcodeBytes().size()) + return Modules; + + 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) + IdentificationBit = Stream.GetCurrentBitNo(); + else if (Entry.ID == bitc::MODULE_BLOCK_ID) + Modules.push_back({Stream.getBitcodeBytes(), + Buffer.getBufferIdentifier(), IdentificationBit, + Stream.GetCurrentBitNo()}); + + if (Stream.SkipBlock()) + return error("Malformed block"); + continue; + case BitstreamEntry::Record: + Stream.skipRecord(Entry.ID); + continue; + } + } +} + /// \brief Get a lazy one-at-time loading module from bitcode. /// /// This isn't always used in a lazy context. In particular, it's also used by -/// \a parseBitcodeFile(). If this is truly lazy, then we need to eagerly pull +/// \a parseModule(). If this is truly lazy, then we need to eagerly pull /// in forward-referenced functions from block address references. /// /// \param[in] MaterializeAll Set to \c true if we should materialize /// everything. -static Expected<std::unique_ptr<Module>> -getLazyBitcodeModuleImpl(MemoryBufferRef Buffer, LLVMContext &Context, - bool MaterializeAll, - bool ShouldLazyLoadMetadata = false) { - Expected<BitstreamCursor> StreamOrErr = initStream(Buffer); - if (!StreamOrErr) - return StreamOrErr.takeError(); +Expected<std::unique_ptr<Module>> +BitcodeModule::getModuleImpl(LLVMContext &Context, bool MaterializeAll, + bool ShouldLazyLoadMetadata) { + BitstreamCursor Stream(Buffer); - BitcodeReader *R = new BitcodeReader(std::move(*StreamOrErr), Context); + std::string ProducerIdentification; + if (IdentificationBit != -1ull) { + Stream.JumpToBit(IdentificationBit); + Expected<std::string> ProducerIdentificationOrErr = + readIdentificationBlock(Stream); + if (!ProducerIdentificationOrErr) + return ProducerIdentificationOrErr.takeError(); + + ProducerIdentification = *ProducerIdentificationOrErr; + } + + Stream.JumpToBit(ModuleBit); + auto *R = + new BitcodeReader(std::move(Stream), ProducerIdentification, Context); std::unique_ptr<Module> M = - llvm::make_unique<Module>(Buffer.getBufferIdentifier(), Context); + llvm::make_unique<Module>(ModuleIdentifier, Context); M->setMaterializer(R); // Delay parsing Metadata if ShouldLazyLoadMetadata is true. @@ -6605,10 +6631,22 @@ getLazyBitcodeModuleImpl(MemoryBufferRef Buffer, LLVMContext &Context, } Expected<std::unique_ptr<Module>> +BitcodeModule::getLazyModule(LLVMContext &Context, + bool ShouldLazyLoadMetadata) { + return getModuleImpl(Context, false, ShouldLazyLoadMetadata); +} + +Expected<std::unique_ptr<Module>> llvm::getLazyBitcodeModule(MemoryBufferRef Buffer, LLVMContext &Context, bool ShouldLazyLoadMetadata) { - return getLazyBitcodeModuleImpl(Buffer, Context, false, - ShouldLazyLoadMetadata); + Expected<std::vector<BitcodeModule>> MsOrErr = getBitcodeModuleList(Buffer); + if (!MsOrErr) + return MsOrErr.takeError(); + + if (MsOrErr->size() != 1) + return error("Expected a single module"); + + return (*MsOrErr)[0].getLazyModule(Context, ShouldLazyLoadMetadata); } Expected<std::unique_ptr<Module>> @@ -6621,13 +6659,25 @@ llvm::getOwningLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer, return MOrErr; } -Expected<std::unique_ptr<Module>> llvm::parseBitcodeFile(MemoryBufferRef Buffer, - LLVMContext &Context) { - return getLazyBitcodeModuleImpl(Buffer, Context, true); +Expected<std::unique_ptr<Module>> +BitcodeModule::parseModule(LLVMContext &Context) { + return getModuleImpl(Context, true, false); // TODO: Restore the use-lists to the in-memory state when the bitcode was // written. We must defer until the Module has been fully materialized. } +Expected<std::unique_ptr<Module>> llvm::parseBitcodeFile(MemoryBufferRef Buffer, + LLVMContext &Context) { + Expected<std::vector<BitcodeModule>> MsOrErr = getBitcodeModuleList(Buffer); + if (!MsOrErr) + return MsOrErr.takeError(); + + if (MsOrErr->size() != 1) + return error("Expected a single module"); + + return (*MsOrErr)[0].parseModule(Context); +} + Expected<std::string> llvm::getBitcodeTargetTriple(MemoryBufferRef Buffer) { Expected<BitstreamCursor> StreamOrErr = initStream(Buffer); if (!StreamOrErr) |