mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[ORC] Add a fallback definition generator for VSOs.
If a VSO has a fallback definition generator attached it will be called during lookup (and lookupFlags) for any unresolved symbols. The definition generator can add new definitions to the VSO for any unresolved symbol. This allows VSOs to generate new definitions on demand. The immediate use case for this code is supporting VSOs that can import definitions found via dlsym on demand. llvm-svn: 334538
This commit is contained in:
parent
86330a7ffe
commit
814b934314
@ -476,6 +476,9 @@ class VSO {
|
||||
friend class ExecutionSession;
|
||||
friend class MaterializationResponsibility;
|
||||
public:
|
||||
using FallbackDefinitionGeneratorFunction =
|
||||
std::function<SymbolNameSet(VSO &Parent, const SymbolNameSet &Names)>;
|
||||
|
||||
using AsynchronousSymbolQuerySet =
|
||||
std::set<std::shared_ptr<AsynchronousSymbolQuery>>;
|
||||
|
||||
@ -495,6 +498,14 @@ public:
|
||||
/// Get a reference to the ExecutionSession for this VSO.
|
||||
ExecutionSessionBase &getExecutionSession() const { return ES; }
|
||||
|
||||
/// Set a fallback defenition generator. If set, lookup and lookupFlags will
|
||||
/// pass the unresolved symbols set to the fallback definition generator,
|
||||
/// allowing it to add a new definition to the VSO.
|
||||
void setFallbackDefinitionGenerator(
|
||||
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator) {
|
||||
this->FallbackDefinitionGenerator = std::move(FallbackDefinitionGenerator);
|
||||
}
|
||||
|
||||
/// Define all symbols provided by the materialization unit to be part
|
||||
/// of the given VSO.
|
||||
template <typename UniquePtrToMaterializationUnit>
|
||||
@ -567,9 +578,17 @@ private:
|
||||
SymbolMap Symbols;
|
||||
UnmaterializedInfosMap UnmaterializedInfos;
|
||||
MaterializingInfosMap MaterializingInfos;
|
||||
FallbackDefinitionGeneratorFunction FallbackDefinitionGenerator;
|
||||
|
||||
Error defineImpl(MaterializationUnit &MU);
|
||||
|
||||
SymbolNameSet lookupFlagsImpl(SymbolFlagsMap &Flags,
|
||||
const SymbolNameSet &Names);
|
||||
|
||||
void lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
|
||||
SymbolNameSet &Unresolved);
|
||||
|
||||
void detachQueryHelper(AsynchronousSymbolQuery &Q,
|
||||
const SymbolNameSet &QuerySymbols);
|
||||
|
||||
|
@ -639,10 +639,29 @@ void VSO::notifyFailed(const SymbolNameSet &FailedSymbols) {
|
||||
SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
|
||||
const SymbolNameSet &Names) {
|
||||
return ES.runSessionLocked([&, this]() {
|
||||
auto Unresolved = lookupFlagsImpl(Flags, Names);
|
||||
if (FallbackDefinitionGenerator && !Unresolved.empty()) {
|
||||
auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
|
||||
if (!FallbackDefs.empty()) {
|
||||
auto Unresolved2 = lookupFlagsImpl(Flags, FallbackDefs);
|
||||
(void)Unresolved2;
|
||||
assert(Unresolved2.empty() &&
|
||||
"All fallback defs should have been found by lookupFlagsImpl");
|
||||
for (auto &D : FallbackDefs)
|
||||
Unresolved.erase(D);
|
||||
}
|
||||
};
|
||||
return Unresolved;
|
||||
});
|
||||
}
|
||||
|
||||
SymbolNameSet VSO::lookupFlagsImpl(SymbolFlagsMap &Flags,
|
||||
const SymbolNameSet &Names) {
|
||||
SymbolNameSet Unresolved;
|
||||
|
||||
for (auto &Name : Names) {
|
||||
auto I = Symbols.find(Name);
|
||||
|
||||
if (I == Symbols.end()) {
|
||||
Unresolved.insert(Name);
|
||||
continue;
|
||||
@ -653,15 +672,43 @@ SymbolNameSet VSO::lookupFlags(SymbolFlagsMap &Flags,
|
||||
}
|
||||
|
||||
return Unresolved;
|
||||
});
|
||||
}
|
||||
|
||||
SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
|
||||
SymbolNameSet Names) {
|
||||
SymbolNameSet Unresolved = std::move(Names);
|
||||
std::vector<std::unique_ptr<MaterializationUnit>> MUs;
|
||||
|
||||
SymbolNameSet Unresolved = std::move(Names);
|
||||
ES.runSessionLocked([&, this]() {
|
||||
lookupImpl(Q, MUs, Unresolved);
|
||||
if (FallbackDefinitionGenerator && !Unresolved.empty()) {
|
||||
auto FallbackDefs = FallbackDefinitionGenerator(*this, Unresolved);
|
||||
if (!FallbackDefs.empty()) {
|
||||
for (auto &D : FallbackDefs)
|
||||
Unresolved.erase(D);
|
||||
lookupImpl(Q, MUs, FallbackDefs);
|
||||
assert(FallbackDefs.empty() &&
|
||||
"All fallback defs should have been found by lookupImpl");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (Q->isFullyResolved())
|
||||
Q->handleFullyResolved();
|
||||
|
||||
if (Q->isFullyReady())
|
||||
Q->handleFullyReady();
|
||||
|
||||
// Dispatch any required MaterializationUnits for materialization.
|
||||
for (auto &MU : MUs)
|
||||
ES.dispatchMaterialization(*this, std::move(MU));
|
||||
|
||||
return Unresolved;
|
||||
}
|
||||
|
||||
void VSO::lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
std::vector<std::unique_ptr<MaterializationUnit>> &MUs,
|
||||
SymbolNameSet &Unresolved) {
|
||||
for (auto I = Unresolved.begin(), E = Unresolved.end(); I != E;) {
|
||||
auto TmpI = I++;
|
||||
auto Name = *TmpI;
|
||||
@ -718,19 +765,6 @@ SymbolNameSet VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Q,
|
||||
MI.PendingQueries.push_back(Q);
|
||||
Q->addQueryDependence(*this, Name);
|
||||
}
|
||||
});
|
||||
|
||||
if (Q->isFullyResolved())
|
||||
Q->handleFullyResolved();
|
||||
|
||||
if (Q->isFullyReady())
|
||||
Q->handleFullyReady();
|
||||
|
||||
// Dispatch any required MaterializationUnits for materialization.
|
||||
for (auto &MU : MUs)
|
||||
ES.dispatchMaterialization(*this, std::move(MU));
|
||||
|
||||
return Unresolved;
|
||||
}
|
||||
|
||||
void VSO::dump(raw_ostream &OS) {
|
||||
|
@ -508,6 +508,33 @@ TEST(CoreAPIsTest, DefineMaterializingSymbol) {
|
||||
EXPECT_TRUE(BarResolved) << "Bar should have been resolved";
|
||||
}
|
||||
|
||||
TEST(CoreAPIsTest, FallbackDefinitionGeneratorTest) {
|
||||
constexpr JITTargetAddress FakeFooAddr = 0xdeadbeef;
|
||||
constexpr JITTargetAddress FakeBarAddr = 0xcafef00d;
|
||||
|
||||
ExecutionSession ES;
|
||||
auto Foo = ES.getSymbolStringPool().intern("foo");
|
||||
auto Bar = ES.getSymbolStringPool().intern("bar");
|
||||
|
||||
auto FooSym = JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
|
||||
auto BarSym = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported);
|
||||
|
||||
auto &V = ES.createVSO("V");
|
||||
|
||||
cantFail(V.define(absoluteSymbols({{Foo, FooSym}})));
|
||||
|
||||
V.setFallbackDefinitionGenerator([&](VSO &W, const SymbolNameSet &Names) {
|
||||
cantFail(W.define(absoluteSymbols({{Bar, BarSym}})));
|
||||
return SymbolNameSet({Bar});
|
||||
});
|
||||
|
||||
auto Result = cantFail(lookup({&V}, {Foo, Bar}));
|
||||
|
||||
EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'";
|
||||
EXPECT_EQ(Result[Bar].getAddress(), FakeBarAddr)
|
||||
<< "Expected address of fallback def for 'bar' to be " << FakeBarAddr;
|
||||
}
|
||||
|
||||
TEST(CoreAPIsTest, FailResolution) {
|
||||
ExecutionSession ES;
|
||||
auto Foo = ES.getSymbolStringPool().intern("foo");
|
||||
|
Loading…
Reference in New Issue
Block a user