[ORC] Consolidate materialization errors, and generate them in VSO's

notifyFailed method rather than passing in an error generator.

VSO::notifyFailed is responsible for notifying queries that they will not
succeed due to error. In practice the queries don't care about the details
of the failure, just the fact that a failure occurred for some symbols.
Having VSO::notifyFailed take care of this simplifies the interface.

llvm-svn: 332666
This commit is contained in:
Lang Hames 2018-05-17 20:48:58 +00:00
parent 676e350789
commit ddc80b6937
3 changed files with 42 additions and 135 deletions

View File

@ -65,39 +65,15 @@ using SymbolDependenceMap = std::map<VSO *, SymbolNameSet>;
/// Render a SymbolDependendeMap.
raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
/// A base class for materialization failures that allows the failing
/// symbols to be obtained for logging.
/// Used to notify a VSO that the given set of symbols failed to materialize.
class FailedToMaterialize : public ErrorInfo<FailedToMaterialize> {
public:
static char ID;
virtual const SymbolNameSet &getSymbols() const = 0;
};
/// Used to notify a VSO that the given set of symbols failed to resolve.
class FailedToResolve : public ErrorInfo<FailedToResolve, FailedToMaterialize> {
public:
static char ID;
FailedToResolve(SymbolNameSet Symbols);
FailedToMaterialize(SymbolNameSet Symbols);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const SymbolNameSet &getSymbols() const override { return Symbols; }
private:
SymbolNameSet Symbols;
};
/// Used to notify a VSO that the given set of symbols failed to
/// finalize.
class FailedToFinalize
: public ErrorInfo<FailedToFinalize, FailedToMaterialize> {
public:
static char ID;
FailedToFinalize(SymbolNameSet Symbols);
std::error_code convertToErrorCode() const override;
void log(raw_ostream &OS) const override;
const SymbolNameSet &getSymbols() const override { return Symbols; }
const SymbolNameSet &getSymbols() const { return Symbols; }
private:
SymbolNameSet Symbols;
@ -145,7 +121,7 @@ public:
/// Notify all unfinalized symbols that an error has occurred.
/// This will remove all symbols covered by this MaterializationResponsibilty
/// from V, and send an error to any queries waiting on these symbols.
void failMaterialization(std::function<Error()> GenerateError);
void failMaterialization();
/// Transfers responsibility to the given MaterializationUnit for all
/// symbols defined by that MaterializationUnit. This allows
@ -552,8 +528,7 @@ public:
/// Fail to materialize the given symbols.
///
/// Returns the list of queries that fail as a consequence.
void notifyFailed(const SymbolFlagsMap &Failed,
std::function<Error()> GenerateError);
void notifyFailed(const SymbolNameSet &FailedSymbols);
/// Search the given VSO for the symbols in Symbols. If found, store
/// the flags for each symbol in Flags. Returns any unresolved symbols.

View File

@ -20,8 +20,6 @@ namespace llvm {
namespace orc {
char FailedToMaterialize::ID = 0;
char FailedToResolve::ID = 0;
char FailedToFinalize::ID = 0;
void MaterializationUnit::anchor() {}
void SymbolResolver::anchor() {}
@ -99,30 +97,17 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps) {
return OS;
}
FailedToResolve::FailedToResolve(SymbolNameSet Symbols)
FailedToMaterialize::FailedToMaterialize(SymbolNameSet Symbols)
: Symbols(std::move(Symbols)) {
assert(!this->Symbols.empty() && "Can not fail to resolve an empty set");
}
std::error_code FailedToResolve::convertToErrorCode() const {
std::error_code FailedToMaterialize::convertToErrorCode() const {
return orcError(OrcErrorCode::UnknownORCError);
}
void FailedToResolve::log(raw_ostream &OS) const {
OS << "Failed to resolve symbols: " << Symbols;
}
FailedToFinalize::FailedToFinalize(SymbolNameSet Symbols)
: Symbols(std::move(Symbols)) {
assert(!this->Symbols.empty() && "Can not fail to finalize an empty set");
}
std::error_code FailedToFinalize::convertToErrorCode() const {
return orcError(OrcErrorCode::UnknownORCError);
}
void FailedToFinalize::log(raw_ostream &OS) const {
OS << "Failed to finalize symbols: " << Symbols;
void FailedToMaterialize::log(raw_ostream &OS) const {
OS << "Failed to materialize symbols: " << Symbols;
}
void ExecutionSessionBase::failQuery(AsynchronousSymbolQuery &Q, Error Err) {
@ -266,9 +251,13 @@ Error MaterializationResponsibility::defineMaterializing(
return V.defineMaterializing(NewSymbolFlags);
}
void MaterializationResponsibility::failMaterialization(
std::function<Error()> GenerateError) {
V.notifyFailed(SymbolFlags, std::move(GenerateError));
void MaterializationResponsibility::failMaterialization() {
SymbolNameSet FailedSymbols;
for (auto &KV : SymbolFlags)
FailedSymbols.insert(KV.first);
V.notifyFailed(FailedSymbols);
SymbolFlags.clear();
}
@ -550,14 +539,14 @@ void VSO::finalize(const SymbolFlagsMap &Finalized) {
}
}
void VSO::notifyFailed(const SymbolFlagsMap &Failed,
std::function<Error()> GenerateError) {
void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) {
// FIXME: This should fail any transitively dependant symbols too.
auto FailedQueriesToNotify = ES.runSessionLocked([&, this]() {
AsynchronousSymbolQuerySet FailedQueries;
for (auto &KV : Failed) {
const auto &Name = KV.first;
for (auto &Name : FailedSymbols) {
auto I = Symbols.find(Name);
assert(I != Symbols.end() && "Symbol not present in this VSO");
Symbols.erase(I);
@ -589,7 +578,7 @@ void VSO::notifyFailed(const SymbolFlagsMap &Failed,
});
for (auto &Q : FailedQueriesToNotify)
Q->handleFailed(GenerateError());
Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
}
SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,

View File

@ -518,91 +518,34 @@ TEST(CoreAPIsTest, FailResolution) {
auto MU = llvm::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap(
{{Foo, JITSymbolFlags::Weak}, {Bar, JITSymbolFlags::Weak}}),
[&](MaterializationResponsibility R) {
R.failMaterialization(
[&]() { return make_error<FailedToResolve>(Names); });
});
auto &V = ES.createVSO("V");
cantFail(V.define(MU));
auto OnResolution = [&](Expected<AsynchronousSymbolQuery::ResolutionResult>
Result) {
handleAllErrors(Result.takeError(),
[&](FailedToResolve &F) {
EXPECT_EQ(F.getSymbols(), Names)
<< "Expected to fail on symbols in Names";
},
[](ErrorInfoBase &EIB) {
std::string ErrMsg;
{
raw_string_ostream ErrOut(ErrMsg);
EIB.log(ErrOut);
}
ADD_FAILURE()
<< "Expected a FailedToResolve error. Got:\n"
<< ErrMsg;
});
};
auto OnReady = [](Error Err) {
cantFail(std::move(Err));
ADD_FAILURE() << "OnReady should never be called";
};
auto Q =
std::make_shared<AsynchronousSymbolQuery>(Names, OnResolution, OnReady);
V.lookup(std::move(Q), Names);
}
TEST(CoreAPIsTest, FailFinalization) {
ExecutionSession ES;
auto Foo = ES.getSymbolStringPool().intern("foo");
auto Bar = ES.getSymbolStringPool().intern("bar");
SymbolNameSet Names({Foo, Bar});
auto MU = llvm::make_unique<SimpleMaterializationUnit>(
SymbolFlagsMap(
{{Foo, JITSymbolFlags::Exported}, {Bar, JITSymbolFlags::Exported}}),
[&](MaterializationResponsibility R) {
constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef;
constexpr JITTargetAddress FakeBarAddr = 0xcafef00d;
auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported);
R.resolve(SymbolMap({{Foo, FooSym}, {Bar, BarSym}}));
R.failMaterialization(
[&]() { return make_error<FailedToFinalize>(Names); });
});
[&](MaterializationResponsibility R) { R.failMaterialization(); });
auto &V = ES.createVSO("V");
cantFail(V.define(MU));
auto OnResolution =
[](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
cantFail(std::move(Result));
[&](Expected<AsynchronousSymbolQuery::ResolutionResult> Result) {
handleAllErrors(Result.takeError(),
[&](FailedToMaterialize &F) {
EXPECT_EQ(F.getSymbols(), Names)
<< "Expected to fail on symbols in Names";
},
[](ErrorInfoBase &EIB) {
std::string ErrMsg;
{
raw_string_ostream ErrOut(ErrMsg);
EIB.log(ErrOut);
}
ADD_FAILURE()
<< "Expected a FailedToResolve error. Got:\n"
<< ErrMsg;
});
};
auto OnReady = [&](Error Err) {
handleAllErrors(std::move(Err),
[&](FailedToFinalize &F) {
EXPECT_EQ(F.getSymbols(), Names)
<< "Expected to fail on symbols in Names";
},
[](ErrorInfoBase &EIB) {
std::string ErrMsg;
{
raw_string_ostream ErrOut(ErrMsg);
EIB.log(ErrOut);
}
ADD_FAILURE()
<< "Expected a FailedToFinalize error. Got:\n"
<< ErrMsg;
});
auto OnReady = [](Error Err) {
cantFail(std::move(Err));
ADD_FAILURE() << "OnReady should never be called";
};
auto Q =