Index: lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
diff --git a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
index c08c62d57be507704fb0ce438d2794ba8f43ff01..d356985c8e51ed97cf536a086969d964243dd464 100644 |
--- a/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
+++ b/lib/Bitcode/NaCl/Reader/NaClBitcodeReader.cpp |
@@ -1026,6 +1026,7 @@ std::error_code NaClBitcodeReader::ParseModule(bool Resume) { |
// If this is a function with a body, remember the prototype we are |
// creating now, so that we can match up the body with them later. |
if (!isProto) { |
+ Func->setIsMaterializable(true); |
FunctionsWithBodies.push_back(Func); |
if (LazyStreamer) DeferredFunctionInfo[Func] = 0; |
} |
@@ -1731,15 +1732,7 @@ std::error_code NaClBitcodeReader::FindFunctionInStream( |
void NaClBitcodeReader::releaseBuffer() { Buffer.release(); } |
-bool NaClBitcodeReader::isMaterializable(const GlobalValue *GV) const { |
- if (const Function *F = dyn_cast<Function>(GV)) { |
- return F->isDeclaration() && |
- DeferredFunctionInfo.count(const_cast<Function*>(F)); |
- } |
- return false; |
-} |
- |
-std::error_code NaClBitcodeReader::Materialize(GlobalValue *GV) { |
+std::error_code NaClBitcodeReader::materialize(GlobalValue *GV) { |
Function *F = dyn_cast<Function>(GV); |
// If it's not a function or is already material, ignore the request. |
if (!F || !F->isMaterializable()) |
@@ -1760,6 +1753,7 @@ std::error_code NaClBitcodeReader::Materialize(GlobalValue *GV) { |
if (std::error_code EC = ParseFunctionBody(F)) |
return EC; |
+ F->setIsMaterializable(false); |
// Upgrade any old intrinsic calls in the function. |
for (UpgradedIntrinsicMap::iterator I = UpgradedIntrinsics.begin(), |
@@ -1793,6 +1787,7 @@ void NaClBitcodeReader::Dematerialize(GlobalValue *GV) { |
// Just forget the function body, we can remat it later. |
F->dropAllReferences(); |
+ F->setIsMaterializable(true); |
} |
@@ -1804,7 +1799,7 @@ std::error_code NaClBitcodeReader::MaterializeModule(Module *M) { |
for (Module::iterator F = TheModule->begin(), E = TheModule->end(); |
F != E; ++F) { |
if (F->isMaterializable()) { |
- if (std::error_code EC = Materialize(F)) |
+ if (std::error_code EC = materialize(F)) |
return EC; |
} |
} |
@@ -1878,21 +1873,30 @@ std::error_code NaClBitcodeReader::InitLazyStream() { |
// External interface |
//===----------------------------------------------------------------------===// |
-/// getNaClLazyBitcodeModule - lazy function-at-a-time loading from a file. |
+/// \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 NaClParseBitcodeFile(). Compared to the upstream LLVM bitcode reader, |
+/// NaCl does not support BlockAddresses, so it does not need to materialize |
+/// forward-referenced functions from block address references. |
ErrorOr<Module *> llvm::getNaClLazyBitcodeModule( |
- MemoryBuffer *Buffer, LLVMContext& Context, raw_ostream *Verbose, |
- bool AcceptSupportedOnly) { |
+ std::unique_ptr<MemoryBuffer> &&Buffer, LLVMContext& Context, |
+ raw_ostream *Verbose, bool AcceptSupportedOnly) { |
Module *M = new Module(Buffer->getBufferIdentifier(), Context); |
NaClBitcodeReader *R = |
- new NaClBitcodeReader(Buffer, Context, Verbose, AcceptSupportedOnly); |
+ new NaClBitcodeReader(Buffer.get(), Context, Verbose, AcceptSupportedOnly); |
M->setMaterializer(R); |
- if (std::error_code EC = R->ParseBitcodeInto(M)) { |
+ |
+ auto cleanupOnError = [&](std::error_code EC) { |
R->releaseBuffer(); // Never take ownership on error. |
delete M; // Also deletes R. |
return EC; |
- } |
+ }; |
+ |
+ if (std::error_code EC = R->ParseBitcodeInto(M)) |
+ return cleanupOnError(EC); |
+ Buffer.release(); // The BitcodeReader owns it now. |
return M; |
} |
@@ -1918,23 +1922,17 @@ Module *llvm::getNaClStreamedBitcodeModule(const std::string &name, |
return M; |
} |
-/// NaClParseBitcodeFile - Read the specified bitcode file, returning the module. |
-/// If an error occurs, return null and fill in *ErrMsg if non-null. |
ErrorOr<Module *> llvm::NaClParseBitcodeFile( |
- MemoryBuffer *Buffer, LLVMContext& Context, raw_ostream *Verbose, |
+ MemoryBufferRef Buffer, LLVMContext& Context, raw_ostream *Verbose, |
bool AcceptSupportedOnly){ |
+ std::unique_ptr<MemoryBuffer> Buf = MemoryBuffer::getMemBuffer(Buffer, false); |
ErrorOr<Module *> ModuleOrErr = |
- getNaClLazyBitcodeModule(Buffer, Context, Verbose, AcceptSupportedOnly); |
+ getNaClLazyBitcodeModule(std::move(Buf), Context, Verbose, AcceptSupportedOnly); |
if (!ModuleOrErr) |
return ModuleOrErr; |
Module *M = ModuleOrErr.get(); |
// Read in the entire module, and destroy the NaClBitcodeReader. |
- if (std::error_code EC = M->materializeAllPermanently(true)) { |
- // Be sure the input buffer is released on error |
- // (materalializeAllPermanently doesn't release the buffer on error). |
- // TODO(kschimpf) Revisit this when we merge to tip of LLVM. |
- if (GVMaterializer *Materializer = M->getMaterializer()) |
- Materializer->releaseBuffer(); |
+ if (std::error_code EC = M->materializeAllPermanently()) { |
delete M; |
return EC; |
} |