Bitcode: Change the materializer interface to return llvm::Error.

Differential Revision: https://reviews.llvm.org/D26439

llvm-svn: 286382
This commit is contained in:
Peter Collingbourne 2016-11-09 17:49:19 +00:00
parent 9934c54cca
commit 7f00d0a125
19 changed files with 112 additions and 103 deletions

View File

@ -18,10 +18,10 @@
#ifndef LLVM_IR_GVMATERIALIZER_H
#define LLVM_IR_GVMATERIALIZER_H
#include <system_error>
#include <vector>
namespace llvm {
class Error;
class Function;
class GlobalValue;
class Module;
@ -36,13 +36,13 @@ public:
/// Make sure the given GlobalValue is fully read.
///
virtual std::error_code materialize(GlobalValue *GV) = 0;
virtual Error materialize(GlobalValue *GV) = 0;
/// Make sure the entire Module has been completely read.
///
virtual std::error_code materializeModule() = 0;
virtual Error materializeModule() = 0;
virtual std::error_code materializeMetadata() = 0;
virtual Error materializeMetadata() = 0;
virtual void setStripDebugInfo() = 0;
virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0;

View File

@ -21,11 +21,11 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/Support/MD5.h"
#include <system_error>
namespace llvm {
class Comdat;
class Error;
class GlobalObject;
class PointerType;
class Module;
@ -467,10 +467,8 @@ public:
/// function has been read in yet or not.
bool isMaterializable() const;
/// Make sure this GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
std::error_code materialize();
/// Make sure this GlobalValue is fully read.
Error materialize();
/// @}

View File

@ -26,10 +26,10 @@
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/DataTypes.h"
#include <system_error>
namespace llvm {
template <typename T> class Optional;
class Error;
class FunctionType;
class GVMaterializer;
class LLVMContext;
@ -454,16 +454,14 @@ public:
GVMaterializer *getMaterializer() const { return Materializer.get(); }
bool isMaterialized() const { return !getMaterializer(); }
/// Make sure the GlobalValue is fully read. If the module is corrupt, this
/// returns true and fills in the optional string with information about the
/// problem. If successful, this returns false.
std::error_code materialize(GlobalValue *GV);
/// Make sure the GlobalValue is fully read.
llvm::Error materialize(GlobalValue *GV);
/// Make sure all GlobalValues in this Module are fully read and clear the
/// Materializer.
std::error_code materializeAll();
llvm::Error materializeAll();
std::error_code materializeMetadata();
llvm::Error materializeMetadata();
/// @}
/// @name Direct access to the globals list, functions list, and symbol table

View File

@ -14,6 +14,7 @@
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/ModuleSummaryIndex.h"
#include "llvm/IR/PassManager.h"
#include "llvm/Support/Error.h"
#include <functional>
#include <map>
@ -53,8 +54,9 @@ public:
/// \p ForceImportReferencedDiscardableSymbols will set the ModuleLinker in
/// a mode where referenced discarable symbols in the source modules will be
/// imported as well even if they are not present in the ImportList.
bool importFunctions(Module &M, const ImportMapTy &ImportList,
bool ForceImportReferencedDiscardableSymbols = false);
Expected<bool>
importFunctions(Module &M, const ImportMapTy &ImportList,
bool ForceImportReferencedDiscardableSymbols = false);
private:
/// The summaries index used to trigger importing.

View File

@ -370,10 +370,8 @@ public:
Error materializeForwardReferencedFunctions();
std::error_code materialize(GlobalValue *GV) override;
Error materializeImpl(GlobalValue *GV);
std::error_code materializeModule() override;
Error materializeModuleImpl();
Error materialize(GlobalValue *GV) override;
Error materializeModule() override;
std::vector<StructType *> getIdentifiedStructTypes() const override;
/// \brief Main interface to parsing a bitcode buffer.
@ -394,8 +392,7 @@ public:
static uint64_t decodeSignRotatedValue(uint64_t V);
/// Materialize any deferred Metadata block.
std::error_code materializeMetadata() override;
Error materializeMetadataImpl();
Error materializeMetadata() override;
void setStripDebugInfo() override;
@ -677,7 +674,7 @@ Error BitcodeReader::materializeForwardReferencedFunctions() {
return error("Never resolved function from blockaddress");
// Try to materialize F.
if (Error Err = materializeImpl(F))
if (Error Err = materialize(F))
return Err;
}
assert(BasicBlockFwdRefs.empty() && "Function missing from queue");
@ -3580,11 +3577,7 @@ Error BitcodeReader::rememberAndSkipMetadata() {
return Error::success();
}
std::error_code BitcodeReader::materializeMetadata() {
return errorToErrorCodeAndEmitErrors(Context, materializeMetadataImpl());
}
Error BitcodeReader::materializeMetadataImpl() {
Error BitcodeReader::materializeMetadata() {
for (uint64_t BitPos : DeferredMetadataInfo) {
// Move the bit stream to the saved position.
Stream.JumpToBit(BitPos);
@ -5856,11 +5849,7 @@ Error BitcodeReader::findFunctionInStream(
// GVMaterializer implementation
//===----------------------------------------------------------------------===//
std::error_code BitcodeReader::materialize(GlobalValue *GV) {
return errorToErrorCodeAndEmitErrors(Context, materializeImpl(GV));
}
Error BitcodeReader::materializeImpl(GlobalValue *GV) {
Error BitcodeReader::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())
@ -5875,7 +5864,7 @@ Error BitcodeReader::materializeImpl(GlobalValue *GV) {
return Err;
// Materialize metadata before parsing any function bodies.
if (Error Err = materializeMetadataImpl())
if (Error Err = materializeMetadata())
return Err;
// Move the bit stream to the saved position of the deferred function body.
@ -5915,12 +5904,8 @@ Error BitcodeReader::materializeImpl(GlobalValue *GV) {
return materializeForwardReferencedFunctions();
}
std::error_code BitcodeReader::materializeModule() {
return errorToErrorCodeAndEmitErrors(Context, materializeModuleImpl());
}
Error BitcodeReader::materializeModuleImpl() {
if (Error Err = materializeMetadataImpl())
Error BitcodeReader::materializeModule() {
if (Error Err = materializeMetadata())
return Err;
// Promise to materialize all forward references.
@ -5929,7 +5914,7 @@ Error BitcodeReader::materializeModuleImpl() {
// Iterate over the module, deserializing any functions that are still on
// disk.
for (Function &F : *TheModule) {
if (Error Err = materializeImpl(&F))
if (Error Err = materialize(&F))
return Err;
}
// At this point, if there are any function bodies, parse the rest of
@ -6664,8 +6649,8 @@ getLazyBitcodeModuleImpl(MemoryBufferRef Buffer, LLVMContext &Context,
if (MaterializeAll) {
// Read in the entire module, and destroy the BitcodeReader.
if (std::error_code EC = M->materializeAll())
return EC;
if (Error Err = M->materializeAll())
return errorToErrorCodeAndEmitErrors(Context, std::move(Err));
} else {
// Resolve forward references from blockaddresses.
if (Error Err = R->materializeForwardReferencedFunctions())

View File

@ -35,9 +35,13 @@ extern "C" void LLVMLinkInInterpreter() { }
ExecutionEngine *Interpreter::create(std::unique_ptr<Module> M,
std::string *ErrStr) {
// Tell this Module to materialize everything and release the GVMaterializer.
if (std::error_code EC = M->materializeAll()) {
if (Error Err = M->materializeAll()) {
std::string Msg;
handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
Msg = EIB.message();
});
if (ErrStr)
*ErrStr = EC.message();
*ErrStr = Msg;
// We got an error, just return 0
return nullptr;
}

View File

@ -21,6 +21,7 @@
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
using namespace llvm;
@ -33,7 +34,7 @@ bool GlobalValue::isMaterializable() const {
return F->isMaterializable();
return false;
}
std::error_code GlobalValue::materialize() {
Error GlobalValue::materialize() {
return getParent()->materialize(this);
}

View File

@ -20,6 +20,7 @@
#include "llvm/Support/Chrono.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/Mutex.h"
@ -1377,8 +1378,9 @@ void FunctionPassManager::add(Pass *P) {
/// so, return true.
///
bool FunctionPassManager::run(Function &F) {
if (std::error_code EC = F.materialize())
report_fatal_error("Error reading bitcode file: " + EC.message());
handleAllErrors(F.materialize(), [&](ErrorInfoBase &EIB) {
report_fatal_error("Error reading bitcode file: " + EIB.message());
});
return FPM->run(F);
}

View File

@ -25,6 +25,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/RandomNumberGenerator.h"
@ -405,23 +406,23 @@ void Module::setMaterializer(GVMaterializer *GVM) {
Materializer.reset(GVM);
}
std::error_code Module::materialize(GlobalValue *GV) {
Error Module::materialize(GlobalValue *GV) {
if (!Materializer)
return std::error_code();
return Error::success();
return Materializer->materialize(GV);
}
std::error_code Module::materializeAll() {
Error Module::materializeAll() {
if (!Materializer)
return std::error_code();
return Error::success();
std::unique_ptr<GVMaterializer> M = std::move(Materializer);
return M->materializeModule();
}
std::error_code Module::materializeMetadata() {
Error Module::materializeMetadata() {
if (!Materializer)
return std::error_code();
return Error::success();
return Materializer->materializeMetadata();
}

View File

@ -350,7 +350,8 @@ Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
Module &M = Obj->getModule();
M.materializeMetadata();
if (Error Err = M.materializeMetadata())
return Err;
UpgradeDebugInfo(M);
SmallPtrSet<GlobalValue *, 8> Used;

View File

@ -359,7 +359,8 @@ Error lto::thinBackend(Config &Conf, unsigned Task, AddStreamFn AddStream,
};
FunctionImporter Importer(CombinedIndex, ModuleLoader);
Importer.importFunctions(Mod, ImportList);
if (Error Err = Importer.importFunctions(Mod, ImportList).takeError())
return Err;
if (Conf.PostImportModuleHook && !Conf.PostImportModuleHook(Task, Mod))
return Error();

View File

@ -152,7 +152,8 @@ crossImportIntoModule(Module &TheModule, const ModuleSummaryIndex &Index,
const FunctionImporter::ImportMapTy &ImportList) {
ModuleLoader Loader(TheModule.getContext(), ModuleMap);
FunctionImporter Importer(Index, Loader);
Importer.importFunctions(TheModule, ImportList);
if (!Importer.importFunctions(TheModule, ImportList))
report_fatal_error("importFunctions failed");
}
static void optimizeModule(Module &TheModule, TargetMachine &TM) {

View File

@ -963,8 +963,8 @@ Error IRLinker::linkFunctionBody(Function &Dst, Function &Src) {
assert(Dst.isDeclaration() && !Src.isDeclaration());
// Materialize if needed.
if (std::error_code EC = Src.materialize())
return errorCodeToError(EC);
if (Error Err = Src.materialize())
return Err;
// Link in the operands without remapping.
if (Src.hasPrefixData())
@ -1191,8 +1191,8 @@ static std::string mergeTriples(const Triple &SrcTriple,
Error IRLinker::run() {
// Ensure metadata materialized before value mapping.
if (SrcM->getMaterializer())
if (std::error_code EC = SrcM->getMaterializer()->materializeMetadata())
return errorCodeToError(EC);
if (Error Err = SrcM->getMaterializer()->materializeMetadata())
return Err;
// Inherit the target data from the source module if the destination module
// doesn't have one already.

View File

@ -606,7 +606,7 @@ void llvm::thinLTOInternalizeModule(Module &TheModule,
// Automatically import functions in Module \p DestModule based on the summaries
// index.
//
bool FunctionImporter::importFunctions(
Expected<bool> FunctionImporter::importFunctions(
Module &DestModule, const FunctionImporter::ImportMapTy &ImportList,
bool ForceImportReferencedDiscardableSymbols) {
DEBUG(dbgs() << "Starting import for Module "
@ -630,7 +630,8 @@ bool FunctionImporter::importFunctions(
// If modules were created with lazy metadata loading, materialize it
// now, before linking it (otherwise this will be a noop).
SrcModule->materializeMetadata();
if (Error Err = SrcModule->materializeMetadata())
return std::move(Err);
UpgradeDebugInfo(*SrcModule);
auto &ImportGUIDs = FunctionsToImportPerModule->second;
@ -645,7 +646,8 @@ bool FunctionImporter::importFunctions(
<< " " << F.getName() << " from "
<< SrcModule->getSourceFileName() << "\n");
if (Import) {
F.materialize();
if (Error Err = F.materialize())
return std::move(Err);
if (EnableImportMetadata) {
// Add 'thinlto_src_module' metadata for statistics and debugging.
F.setMetadata(
@ -667,7 +669,8 @@ bool FunctionImporter::importFunctions(
<< " " << GV.getName() << " from "
<< SrcModule->getSourceFileName() << "\n");
if (Import) {
GV.materialize();
if (Error Err = GV.materialize())
return std::move(Err);
GlobalsToImport.insert(&GV);
}
}
@ -693,9 +696,11 @@ bool FunctionImporter::importFunctions(
<< " " << GO->getName() << " from "
<< SrcModule->getSourceFileName() << "\n");
#endif
GO->materialize();
if (Error Err = GO->materialize())
return std::move(Err);
GlobalsToImport.insert(GO);
GA.materialize();
if (Error Err = GA.materialize())
return std::move(Err);
GlobalsToImport.insert(&GA);
}
}
@ -799,8 +804,17 @@ static bool doImportingForModule(Module &M, const ModuleSummaryIndex *Index) {
return loadFile(Identifier, M.getContext());
};
FunctionImporter Importer(*Index, ModuleLoader);
return Importer.importFunctions(M, ImportList,
!DontForceImportReferencedDiscardableSymbols);
Expected<bool> Result = Importer.importFunctions(
M, ImportList, !DontForceImportReferencedDiscardableSymbols);
// FIXME: Probably need to propagate Errors through the pass manager.
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(),
"Error importing module: ");
return false;
}
return *Result;
}
namespace {

View File

@ -418,11 +418,9 @@ int main(int argc, char **argv, char * const *envp) {
// If not jitting lazily, load the whole bitcode file eagerly too.
if (NoLazyCompilation) {
if (std::error_code EC = Mod->materializeAll()) {
errs() << argv[0] << ": bitcode didn't read correctly.\n";
errs() << "Reason: " << EC.message() << "\n";
exit(1);
}
ExitOnError ExitOnErr(std::string(argv[0]) +
": bitcode didn't read correctly: ");
ExitOnErr(Mod->materializeAll());
}
std::string ErrorMsg;

View File

@ -137,21 +137,19 @@ static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
exit(1);
}
static Expected<std::unique_ptr<Module>> openInputFile(LLVMContext &Context) {
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
MemoryBuffer::getFileOrSTDIN(InputFilename);
if (!MBOrErr)
return errorCodeToError(MBOrErr.getError());
ErrorOr<std::unique_ptr<Module>> MOrErr =
getOwningLazyBitcodeModule(std::move(*MBOrErr), Context,
/*ShouldLazyLoadMetadata=*/true);
if (!MOrErr)
return errorCodeToError(MOrErr.getError());
static ExitOnError ExitOnErr;
static std::unique_ptr<Module> openInputFile(LLVMContext &Context) {
std::unique_ptr<MemoryBuffer> MB =
ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(InputFilename)));
std::unique_ptr<Module> M = ExitOnErr(errorOrToExpected(
getOwningLazyBitcodeModule(std::move(MB), Context,
/*ShouldLazyLoadMetadata=*/true)));
if (MaterializeMetadata)
(*MOrErr)->materializeMetadata();
ExitOnErr(M->materializeMetadata());
else
(*MOrErr)->materializeAll();
return std::move(*MOrErr);
ExitOnErr(M->materializeAll());
return M;
}
int main(int argc, char **argv) {
@ -159,6 +157,8 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
ExitOnErr.setBanner(std::string(argv[0]) + ": error: ");
LLVMContext Context;
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.

View File

@ -22,6 +22,7 @@
#include "llvm/IRReader/IRReader.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/PrettyStackTrace.h"
@ -222,12 +223,9 @@ int main(int argc, char **argv) {
}
}
auto Materialize = [&](GlobalValue &GV) {
if (std::error_code EC = GV.materialize()) {
errs() << argv[0] << ": error reading input: " << EC.message() << "\n";
exit(1);
}
};
ExitOnError ExitOnErr(std::string(argv[0]) + ": error reading input: ");
auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); };
// Materialize requisite global values.
if (!DeleteFn) {
@ -251,7 +249,7 @@ int main(int argc, char **argv) {
// Now that we have all the GVs we want, mark the module as fully
// materialized.
// FIXME: should the GVExtractionPass handle this?
M->materializeAll();
ExitOnErr(M->materializeAll());
}
// In addition to deleting all other functions, we also want to spiff it

View File

@ -108,6 +108,8 @@ static cl::opt<bool> PreserveAssemblyUseListOrder(
cl::desc("Preserve use-list order when writing LLVM assembly."),
cl::init(false), cl::Hidden);
static ExitOnError ExitOnErr;
// Read the specified bitcode file in and return it. This routine searches the
// link path for the specified file to try to find it...
//
@ -129,7 +131,7 @@ static std::unique_ptr<Module> loadFile(const char *argv0,
}
if (MaterializeMetadata) {
Result->materializeMetadata();
ExitOnErr(Result->materializeMetadata());
UpgradeDebugInfo(*Result);
}
@ -264,7 +266,7 @@ static bool importFunctions(const char *argv0, LLVMContext &Context,
auto &Entry = ModuleToGlobalsToImportMap[SrcModule.getModuleIdentifier()];
Entry.insert(F);
F->materialize();
ExitOnErr(F->materialize());
}
// Do the actual import of globals now, one Module at a time
@ -277,7 +279,7 @@ static bool importFunctions(const char *argv0, LLVMContext &Context,
// If modules were created with lazy metadata loading, materialize it
// now, before linking it (otherwise this will be a noop).
SrcModule->materializeMetadata();
ExitOnErr(SrcModule->materializeMetadata());
UpgradeDebugInfo(*SrcModule);
// Linkage Promotion and renaming
@ -348,6 +350,8 @@ int main(int argc, char **argv) {
sys::PrintStackTraceOnErrorSignal(argv[0]);
PrettyStackTraceProgram X(argc, argv);
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
LLVMContext Context;
Context.setDiagnosticHandler(diagnosticHandlerWithContext, nullptr, true);

View File

@ -19,6 +19,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Verifier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "gtest/gtest.h"
@ -90,7 +91,7 @@ TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize h.
H->materialize();
ASSERT_FALSE(H->materialize());
EXPECT_TRUE(F->empty());
EXPECT_TRUE(G->empty());
EXPECT_FALSE(H->empty());
@ -98,7 +99,7 @@ TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize g.
G->materialize();
ASSERT_FALSE(G->materialize());
EXPECT_TRUE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());
@ -106,7 +107,7 @@ TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize j.
J->materialize();
ASSERT_FALSE(J->materialize());
EXPECT_TRUE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());
@ -114,7 +115,7 @@ TEST(BitReaderTest, MaterializeFunctionsOutOfOrder) {
EXPECT_FALSE(verifyModule(*M, &dbgs()));
// Materialize f.
F->materialize();
ASSERT_FALSE(F->materialize());
EXPECT_FALSE(F->empty());
EXPECT_FALSE(G->empty());
EXPECT_FALSE(H->empty());