| 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;
|
| }
|
|
|