TheModule(nullptr), Buffer(buffer), LazyStreamer(nullptr),
NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false),
- WillMaterializeAllForwardRefs(false) {}
+ WillMaterializeAllForwardRefs(false), IsMetadataMaterialized(false) {}
BitcodeReader::BitcodeReader(DataStreamer *streamer, LLVMContext &C,
DiagnosticHandlerFunction DiagnosticHandler)
TheModule(nullptr), Buffer(nullptr), LazyStreamer(streamer),
NextUnreadBit(0), SeenValueSymbolTable(false), ValueList(C),
MDValueList(C), SeenFirstFunctionBody(false), UseRelativeIDs(false),
- WillMaterializeAllForwardRefs(false) {}
+ WillMaterializeAllForwardRefs(false), IsMetadataMaterialized(false) {}
std::error_code BitcodeReader::materializeForwardReferencedFunctions() {
if (WillMaterializeAllForwardRefs)
std::vector<BasicBlock*>().swap(FunctionBBs);
std::vector<Function*>().swap(FunctionsWithBodies);
DeferredFunctionInfo.clear();
+ DeferredMetadataInfo.clear();
MDKindMap.clear();
assert(BasicBlockFwdRefs.empty() && "Unresolved blockaddress fwd references");
static int64_t unrotateSign(uint64_t U) { return U & 1 ? ~(U >> 1) : U >> 1; }
std::error_code BitcodeReader::ParseMetadata() {
+ IsMetadataMaterialized = true;
unsigned NextMDValueNo = MDValueList.size();
if (Stream.EnterSubBlock(bitc::METADATA_BLOCK_ID))
}
}
+/// When we see the block for metadata, remember where it is and then skip it.
+/// This lets us lazily deserialize the metadata.
+std::error_code BitcodeReader::rememberAndSkipMetadata() {
+ // Save the current stream state.
+ uint64_t CurBit = Stream.GetCurrentBitNo();
+ DeferredMetadataInfo.push_back(CurBit);
+
+ // Skip over the block for now.
+ if (Stream.SkipBlock())
+ return Error("Invalid record");
+ return std::error_code();
+}
+
+std::error_code BitcodeReader::materializeMetadata() {
+ for (uint64_t BitPos : DeferredMetadataInfo) {
+ // Move the bit stream to the saved position.
+ Stream.JumpToBit(BitPos);
+ if (std::error_code EC = ParseMetadata())
+ return EC;
+ }
+ DeferredMetadataInfo.clear();
+ return std::error_code();
+}
+
/// RememberAndSkipFunctionBody - When we see the block for a function body,
/// remember where it is and then skip it. This lets us lazily deserialize the
/// functions.
return std::error_code();
}
-std::error_code BitcodeReader::ParseModule(bool Resume) {
+std::error_code BitcodeReader::ParseModule(bool Resume,
+ bool ShouldLazyLoadMetadata) {
if (Resume)
Stream.JumpToBit(NextUnreadBit);
else if (Stream.EnterSubBlock(bitc::MODULE_BLOCK_ID))
return EC;
break;
case bitc::METADATA_BLOCK_ID:
+ if (ShouldLazyLoadMetadata && !IsMetadataMaterialized) {
+ if (std::error_code EC = rememberAndSkipMetadata())
+ return EC;
+ break;
+ }
+ assert(DeferredMetadataInfo.empty() && "Unexpected deferred metadata");
if (std::error_code EC = ParseMetadata())
return EC;
break;
}
}
-std::error_code BitcodeReader::ParseBitcodeInto(Module *M) {
+std::error_code BitcodeReader::ParseBitcodeInto(Module *M,
+ bool ShouldLazyLoadMetadata) {
TheModule = nullptr;
if (std::error_code EC = InitStream())
if (TheModule)
return Error("Invalid multiple blocks");
TheModule = M;
- if (std::error_code EC = ParseModule(false))
+ if (std::error_code EC = ParseModule(false, ShouldLazyLoadMetadata))
return EC;
if (LazyStreamer)
return std::error_code();
void BitcodeReader::releaseBuffer() { Buffer.release(); }
std::error_code BitcodeReader::materialize(GlobalValue *GV) {
+ if (std::error_code EC = materializeMetadata())
+ return EC;
+
Function *F = dyn_cast<Function>(GV);
// If it's not a function or is already material, ignore the request.
if (!F || !F->isMaterializable())
assert(M == TheModule &&
"Can only Materialize the Module this BitcodeReader is attached to.");
+ if (std::error_code EC = materializeMetadata())
+ return EC;
+
// Promise to materialize all forward references.
WillMaterializeAllForwardRefs = true;
static ErrorOr<Module *>
getLazyBitcodeModuleImpl(std::unique_ptr<MemoryBuffer> &&Buffer,
LLVMContext &Context, bool WillMaterializeAll,
- DiagnosticHandlerFunction DiagnosticHandler) {
+ DiagnosticHandlerFunction DiagnosticHandler,
+ bool ShouldLazyLoadMetadata = false) {
Module *M = new Module(Buffer->getBufferIdentifier(), Context);
BitcodeReader *R =
new BitcodeReader(Buffer.get(), Context, DiagnosticHandler);
return EC;
};
- if (std::error_code EC = R->ParseBitcodeInto(M))
+ // Delay parsing Metadata if ShouldLazyLoadMetadata is true.
+ if (std::error_code EC = R->ParseBitcodeInto(M, ShouldLazyLoadMetadata))
return cleanupOnError(EC);
if (!WillMaterializeAll)
ErrorOr<Module *>
llvm::getLazyBitcodeModule(std::unique_ptr<MemoryBuffer> &&Buffer,
LLVMContext &Context,
- DiagnosticHandlerFunction DiagnosticHandler) {
+ DiagnosticHandlerFunction DiagnosticHandler,
+ bool ShouldLazyLoadMetadata) {
return getLazyBitcodeModuleImpl(std::move(Buffer), Context, false,
- DiagnosticHandler);
+ DiagnosticHandler, ShouldLazyLoadMetadata);
}
ErrorOr<std::unique_ptr<Module>>
/// stream.
DenseMap<Function*, uint64_t> DeferredFunctionInfo;
+ /// When Metadata block is initially scanned when parsing the module, we may
+ /// choose to defer parsing of the metadata. This vector contains info about
+ /// which Metadata blocks are deferred.
+ std::vector<uint64_t> DeferredMetadataInfo;
+
/// These are basic blocks forward-referenced by block addresses. They are
/// inserted lazily into functions when they're loaded. The basic block ID is
/// its index into the vector.
/// Functions that have block addresses taken. This is usually empty.
SmallPtrSet<const Function *, 4> BlockAddressesTaken;
+ /// True if any Metadata block has been materialized.
+ bool IsMetadataMaterialized;
+
public:
std::error_code Error(BitcodeError E, const Twine &Message);
std::error_code Error(BitcodeError E);
/// @brief Main interface to parsing a bitcode buffer.
/// @returns true if an error occurred.
- std::error_code ParseBitcodeInto(Module *M);
+ std::error_code ParseBitcodeInto(Module *M,
+ bool ShouldLazyLoadMetadata = false);
/// @brief Cheap mechanism to just extract module triple
/// @returns true if an error occurred.
static uint64_t decodeSignRotatedValue(uint64_t V);
+ /// Materialize any deferred Metadata block.
+ std::error_code materializeMetadata();
+
private:
std::vector<StructType *> IdentifiedStructTypes;
StructType *createIdentifiedStructType(LLVMContext &Context, StringRef Name);
/// a corresponding error code.
std::error_code parseAlignmentValue(uint64_t Exponent, unsigned &Alignment);
std::error_code ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind);
- std::error_code ParseModule(bool Resume);
+ std::error_code ParseModule(bool Resume, bool ShouldLazyLoadMetadata = false);
std::error_code ParseAttributeBlock();
std::error_code ParseAttributeGroupBlock();
std::error_code ParseTypeTable();
std::error_code ParseValueSymbolTable();
std::error_code ParseConstants();
std::error_code RememberAndSkipFunctionBody();
+ /// Save the positions of the Metadata blocks and skip parsing the blocks.
+ std::error_code rememberAndSkipMetadata();
std::error_code ParseFunctionBody(Function *F);
std::error_code GlobalCleanup();
std::error_code ResolveGlobalAndAliasInits();