std::forward<LookupFlagsFn>(LookupFlags), std::forward<LookupFn>(Lookup));
}
-/// @brief Represents a source of symbol definitions which may be materialized
-/// (turned into data / code through some materialization process) or
-/// discarded (if the definition is overridden by a stronger one).
+/// @brief A MaterializationUnit represents a set of symbol definitions that can
+/// be materialized as a group, or individually discarded (when
+/// overriding definitions are encountered).
///
-/// SymbolSources are used when providing lazy definitions of symbols to VSOs.
-/// The VSO will call materialize when the address of a symbol is requested via
-/// the lookup method. The VSO will call discard if a stronger definition is
-/// added or already present.
-class SymbolSource {
+/// MaterializationUnits are used when providing lazy definitions of symbols to
+/// VSOs. The VSO will call materialize when the address of a symbol is
+/// requested via the lookup method. The VSO will call discard if a stronger
+/// definition is added or already present.
+class MaterializationUnit {
public:
- virtual ~SymbolSource() {}
+ virtual ~MaterializationUnit() {}
- /// @brief Implementations of this method should materialize the given
- /// symbols (plus any additional symbols required) by adding a
- /// Materializer to the ExecutionSession's MaterializationQueue.
- virtual Error materialize(VSO &V, SymbolNameSet Symbols) = 0;
+ /// @brief Return the set of symbols that this source provides.
+ virtual SymbolFlagsMap getSymbols() = 0;
+
+ /// @brief Implementations of this method should materialize all symbols
+ /// in the materialzation unit, except for those that have been
+ /// previously discarded.
+ virtual Error materialize(VSO &V) = 0;
/// @brief Implementations of this method should discard the given symbol
/// from the source (e.g. if the source is an LLVM IR Module and the
using SetDefinitionsResult =
std::map<SymbolStringPtr, RelativeLinkageStrength>;
- using SourceWorkMap = std::map<std::shared_ptr<SymbolSource>, SymbolNameSet>;
+
+ using MaterializationUnitList =
+ std::vector<std::unique_ptr<MaterializationUnit>>;
struct LookupResult {
- SourceWorkMap MaterializationWork;
+ MaterializationUnitList MaterializationUnits;
SymbolNameSet UnresolvedSymbols;
};
Error define(SymbolMap NewSymbols);
/// @brief Adds the given symbols to the mapping as lazy symbols.
- Error defineLazy(const SymbolFlagsMap &NewSymbols,
- std::shared_ptr<SymbolSource> Source);
+ Error defineLazy(std::unique_ptr<MaterializationUnit> Source);
/// @brief Add the given symbol/address mappings to the dylib, but do not
/// mark the symbols as finalized yet.
private:
class MaterializationInfo {
public:
- MaterializationInfo(JITSymbolFlags Flags,
- std::shared_ptr<SymbolSource> Query);
- JITSymbolFlags getFlags() const;
- JITTargetAddress getAddress() const;
- void replaceWithSource(VSO &V, SymbolStringPtr Name,
- JITSymbolFlags NewFlags,
- std::shared_ptr<SymbolSource> NewSource);
- std::shared_ptr<SymbolSource>
- query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
- void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
- void finalize();
+ using QueryList = std::vector<std::shared_ptr<AsynchronousSymbolQuery>>;
- private:
- JITSymbolFlags Flags;
- JITTargetAddress Address = 0;
- std::shared_ptr<SymbolSource> Source;
- std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingResolution;
- std::vector<std::shared_ptr<AsynchronousSymbolQuery>> PendingFinalization;
+ MaterializationInfo(size_t SymbolsRemaining,
+ std::unique_ptr<MaterializationUnit> MU);
+
+ uint64_t SymbolsRemaining;
+ std::unique_ptr<MaterializationUnit> MU;
+ SymbolMap Symbols;
+ std::map<SymbolStringPtr, QueryList> PendingResolution;
+ std::map<SymbolStringPtr, QueryList> PendingFinalization;
};
+ using MaterializationInfoSet = std::set<std::unique_ptr<MaterializationInfo>>;
+
+ using MaterializationInfoIterator = MaterializationInfoSet::iterator;
+
class SymbolTableEntry {
public:
- SymbolTableEntry(JITSymbolFlags Flags,
- std::shared_ptr<SymbolSource> Source);
+ SymbolTableEntry(JITSymbolFlags SymbolFlags,
+ MaterializationInfoIterator MaterializationInfoItr);
SymbolTableEntry(JITEvaluatedSymbol Sym);
SymbolTableEntry(SymbolTableEntry &&Other);
~SymbolTableEntry();
+
+ SymbolTableEntry &operator=(JITEvaluatedSymbol Sym);
+
JITSymbolFlags getFlags() const;
- void replaceWithSource(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
- std::shared_ptr<SymbolSource> NewSource);
- std::shared_ptr<SymbolSource>
+ void replaceWith(VSO &V, SymbolStringPtr Name, JITSymbolFlags Flags,
+ MaterializationInfoIterator NewMaterializationInfoItr);
+ std::unique_ptr<MaterializationUnit>
query(SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query);
void resolve(VSO &V, SymbolStringPtr Name, JITEvaluatedSymbol Sym);
- void finalize();
+ void finalize(VSO &V, SymbolStringPtr Name);
+ void discard(VSO &V, SymbolStringPtr Name);
private:
+ void destroy();
+
JITSymbolFlags Flags;
+ MaterializationInfoIterator MII;
union {
JITTargetAddress Address;
- std::unique_ptr<MaterializationInfo> MatInfo;
+ MaterializationInfoIterator MaterializationInfoItr;
};
};
std::map<SymbolStringPtr, SymbolTableEntry> Symbols;
+ MaterializationInfoSet MaterializationInfos;
};
/// @brief An ExecutionSession represents a running JIT program.
ErrorReporter ReportError = logErrorsToStdErr;
};
-/// Runs SymbolSource materializations on the current thread and reports errors
-/// to the given ExecutionSession.
+/// Runs Materializers on the current thread and reports errors to the given
+/// ExecutionSession.
class MaterializeOnCurrentThread {
public:
MaterializeOnCurrentThread(ExecutionSession &ES) : ES(ES) {}
- void operator()(VSO &V, std::shared_ptr<SymbolSource> Source,
- SymbolNameSet Names) {
- if (auto Err = Source->materialize(V, std::move(Names)))
+ void operator()(VSO &V, std::unique_ptr<MaterializationUnit> MU) {
+ if (auto Err = MU->materialize(V))
ES.reportError(std::move(Err));
}
};
/// Materialization function object wrapper for the lookup method.
-using MaterializationDispatcher = std::function<void(
- VSO &V, std::shared_ptr<SymbolSource> S, SymbolNameSet Names)>;
+using MaterializationDispatcher =
+ std::function<void(VSO &V, std::unique_ptr<MaterializationUnit> S)>;
/// @brief Look up a set of symbols by searching a list of VSOs.
///
-//===--------- Core.cpp - Core ORC APIs (SymbolSource, VSO, etc.) ---------===//
+//===----- Core.cpp - Core ORC APIs (MaterializationUnit, VSO, etc.) ------===//
//
// The LLVM Compiler Infrastructure
//
namespace llvm {
namespace orc {
+void MaterializationUnit::anchor() {}
void SymbolResolver::anchor() {}
-void SymbolSource::anchor() {}
AsynchronousSymbolQuery::AsynchronousSymbolQuery(
const SymbolNameSet &Symbols, SymbolsResolvedCallback NotifySymbolsResolved,
}
VSO::MaterializationInfo::MaterializationInfo(
- JITSymbolFlags Flags, std::shared_ptr<SymbolSource> Source)
- : Flags(std::move(Flags)), Source(std::move(Source)) {}
+ size_t SymbolsRemaining, std::unique_ptr<MaterializationUnit> MU)
+ : SymbolsRemaining(SymbolsRemaining), MU(std::move(MU)) {}
-JITSymbolFlags VSO::MaterializationInfo::getFlags() const { return Flags; }
-
-JITTargetAddress VSO::MaterializationInfo::getAddress() const {
- return Address;
-}
-
-void VSO::MaterializationInfo::replaceWithSource(
- VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags,
- std::shared_ptr<SymbolSource> NewSource) {
- assert(Address == 0 && PendingResolution.empty() &&
- PendingFinalization.empty() &&
- "Cannot replace source during or after materialization");
- Source->discard(V, Name);
- Flags = std::move(NewFlags);
- Source = std::move(NewSource);
-}
-
-std::shared_ptr<SymbolSource> VSO::MaterializationInfo::query(
- SymbolStringPtr Name, std::shared_ptr<AsynchronousSymbolQuery> Query) {
- if (Address == 0) {
- PendingResolution.push_back(std::move(Query));
- auto S = std::move(Source);
- Source = nullptr;
- return S;
- }
-
- Query->setDefinition(Name, JITEvaluatedSymbol(Address, Flags));
- PendingFinalization.push_back(std::move(Query));
- return nullptr;
-}
-
-void VSO::MaterializationInfo::resolve(VSO &V, SymbolStringPtr Name,
- JITEvaluatedSymbol Sym) {
- if (Source) {
- Source->discard(V, Name);
- Source = nullptr;
- }
-
- // FIXME: Sanity check flags?
- Flags = Sym.getFlags();
- Address = Sym.getAddress();
- for (auto &Query : PendingResolution) {
- Query->setDefinition(Name, std::move(Sym));
- PendingFinalization.push_back(std::move(Query));
- }
- PendingResolution = {};
-}
-
-void VSO::MaterializationInfo::finalize() {
- for (auto &Query : PendingFinalization)
- Query->notifySymbolFinalized();
- PendingFinalization = {};
-}
-
-VSO::SymbolTableEntry::SymbolTableEntry(JITSymbolFlags Flags,
- std::shared_ptr<SymbolSource> Source)
+VSO::SymbolTableEntry::SymbolTableEntry(
+ JITSymbolFlags Flags, MaterializationInfoIterator MaterializationInfoItr)
: Flags(JITSymbolFlags::FlagNames(Flags | JITSymbolFlags::NotMaterialized)),
- MatInfo(
- llvm::make_unique<MaterializationInfo>(Flags, std::move(Source))) {
+ MaterializationInfoItr(std::move(MaterializationInfoItr)) {
// FIXME: Assert flag sanity.
}
if (Flags.isMaterialized())
Address = Other.Address;
else
- MatInfo = std::move(Other.MatInfo);
+ MaterializationInfoItr = std::move(Other.MaterializationInfoItr);
}
-VSO::SymbolTableEntry::~SymbolTableEntry() {
+VSO::SymbolTableEntry::~SymbolTableEntry() { destroy(); }
+
+VSO::SymbolTableEntry &VSO::SymbolTableEntry::
+operator=(JITEvaluatedSymbol Sym) {
+ destroy();
+ Flags = Sym.getFlags();
+ Address = Sym.getAddress();
+ return *this;
+}
+
+void VSO::SymbolTableEntry::destroy() {
if (!Flags.isMaterialized())
- MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr();
+ MaterializationInfoItr
+ .MaterializationInfoIterator::~MaterializationInfoIterator();
}
JITSymbolFlags VSO::SymbolTableEntry::getFlags() const { return Flags; }
-void VSO::SymbolTableEntry::replaceWithSource(
+void VSO::SymbolTableEntry::replaceWith(
VSO &V, SymbolStringPtr Name, JITSymbolFlags NewFlags,
- std::shared_ptr<SymbolSource> NewSource) {
- bool ReplaceExisting = !Flags.isMaterialized();
+ MaterializationInfoIterator NewMaterializationInfoItr) {
+ bool ReplaceExistingLazyDefinition = !Flags.isMaterialized();
Flags = NewFlags;
- if (ReplaceExisting)
- MatInfo->replaceWithSource(V, Name, Flags, std::move(NewSource));
- else
- new (&MatInfo) std::unique_ptr<MaterializationInfo>(
- llvm::make_unique<MaterializationInfo>(Flags, std::move(NewSource)));
+ if (ReplaceExistingLazyDefinition) {
+ // If we are replacing an existing lazy definition with a stronger one,
+ // we need to notify the old lazy definition to discard its definition.
+ assert((*MaterializationInfoItr)->MU != nullptr &&
+ (*MaterializationInfoItr)->Symbols.count(Name) == 0 &&
+ (*MaterializationInfoItr)->PendingResolution.count(Name) == 0 &&
+ (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+ "Attempt to replace materializer during materialization");
+
+ if (--(*MaterializationInfoItr)->SymbolsRemaining == 0)
+ V.MaterializationInfos.erase(MaterializationInfoItr);
+ }
+ MaterializationInfoItr = std::move(NewMaterializationInfoItr);
}
-std::shared_ptr<SymbolSource>
+std::unique_ptr<MaterializationUnit>
VSO::SymbolTableEntry::query(SymbolStringPtr Name,
std::shared_ptr<AsynchronousSymbolQuery> Query) {
if (Flags.isMaterialized()) {
Query->setDefinition(std::move(Name), JITEvaluatedSymbol(Address, Flags));
Query->notifySymbolFinalized();
return nullptr;
- } else
- return MatInfo->query(std::move(Name), std::move(Query));
+ } else {
+ if ((*MaterializationInfoItr)->MU) {
+ assert((*MaterializationInfoItr)->PendingResolution.count(Name) == 0 &&
+ (*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+ "Materializer should have been activated on first query");
+ (*MaterializationInfoItr)
+ ->PendingResolution[Name]
+ .push_back(std::move(Query));
+ return std::move((*MaterializationInfoItr)->MU);
+ } else {
+ assert((*MaterializationInfoItr)->MU == nullptr &&
+ "Materializer should have been activated on first query");
+ auto SymValueItr = (*MaterializationInfoItr)->Symbols.find(Name);
+ if (SymValueItr == (*MaterializationInfoItr)->Symbols.end()) {
+ // Symbol has not been resolved yet.
+ (*MaterializationInfoItr)
+ ->PendingResolution[Name]
+ .push_back(std::move(Query));
+ return nullptr;
+ } else {
+ // Symbol has already resolved, is just waiting on finalization.
+ Query->setDefinition(Name, SymValueItr->second);
+ (*MaterializationInfoItr)
+ ->PendingFinalization[Name]
+ .push_back(std::move(Query));
+ return nullptr;
+ }
+ }
+ }
}
void VSO::SymbolTableEntry::resolve(VSO &V, SymbolStringPtr Name,
// in VSO?
Flags = Sym.getFlags();
Address = Sym.getAddress();
- } else
- MatInfo->resolve(V, std::move(Name), std::move(Sym));
+ } else {
+ assert((*MaterializationInfoItr)->MU == nullptr &&
+ "Can not resolve a symbol that has not been materialized");
+ assert((*MaterializationInfoItr)->Symbols.count(Name) == 0 &&
+ "Symbol resolved more than once");
+
+ // Add the symbol to the MaterializationInfo Symbols table.
+ (*MaterializationInfoItr)->Symbols[Name] = Sym;
+
+ // If there are any queries waiting on this symbol then notify them that it
+ // has been resolved, then move them to the PendingFinalization list.
+ auto I = (*MaterializationInfoItr)->PendingResolution.find(Name);
+ if (I != (*MaterializationInfoItr)->PendingResolution.end()) {
+ assert((*MaterializationInfoItr)->PendingFinalization.count(Name) == 0 &&
+ "Queries already pending finalization on newly resolved symbol");
+ auto &PendingFinalization =
+ (*MaterializationInfoItr)->PendingFinalization[Name];
+
+ for (auto &Query : I->second) {
+ Query->setDefinition(Name, Sym);
+ PendingFinalization.push_back(Query);
+ }
+
+ // Clear the PendingResolution list for this symbol.
+ (*MaterializationInfoItr)->PendingResolution.erase(I);
+ }
+ }
}
-void VSO::SymbolTableEntry::finalize() {
+void VSO::SymbolTableEntry::finalize(VSO &V, SymbolStringPtr Name) {
if (!Flags.isMaterialized()) {
- auto TmpMatInfo = std::move(MatInfo);
- MatInfo.std::unique_ptr<MaterializationInfo>::~unique_ptr();
- // FIXME: Assert flag sanity?
- Flags = TmpMatInfo->getFlags();
- Address = TmpMatInfo->getAddress();
- TmpMatInfo->finalize();
+ auto SymI = (*MaterializationInfoItr)->Symbols.find(Name);
+ assert(SymI != (*MaterializationInfoItr)->Symbols.end() &&
+ "Finalizing an unresolved symbol");
+ auto Sym = SymI->second;
+ (*MaterializationInfoItr)->Symbols.erase(SymI);
+ auto I = (*MaterializationInfoItr)->PendingFinalization.find(Name);
+ if (I != (*MaterializationInfoItr)->PendingFinalization.end()) {
+ for (auto &Query : I->second)
+ Query->notifySymbolFinalized();
+ (*MaterializationInfoItr)->PendingFinalization.erase(I);
+ }
+
+ if (--(*MaterializationInfoItr)->SymbolsRemaining == 0)
+ V.MaterializationInfos.erase(MaterializationInfoItr);
+
+ // Destruct the iterator and re-define this entry using the final symbol
+ // value.
+ MaterializationInfoItr
+ .MaterializationInfoIterator::~MaterializationInfoIterator();
+ Flags = Sym.getFlags();
+ Address = Sym.getAddress();
}
assert(Flags.isMaterialized() && "Trying to finalize not-emitted symbol");
}
+void VSO::SymbolTableEntry::discard(VSO &V, SymbolStringPtr Name) {
+ assert((*MaterializationInfoItr)->MU != nullptr &&
+ "Can not override a symbol after it has been materialized");
+ (*MaterializationInfoItr)->MU->discard(V, Name);
+ --(*MaterializationInfoItr)->SymbolsRemaining;
+}
+
VSO::RelativeLinkageStrength VSO::compareLinkage(Optional<JITSymbolFlags> Old,
JITSymbolFlags New) {
if (Old == None)
}
if (I != Symbols.end()) {
- I->second.resolve(*this, KV.first, std::move(KV.second));
- I->second.finalize();
+ // This is an override -- discard the overridden definition and overwrite.
+ I->second.discard(*this, KV.first);
+ I->second = std::move(KV.second);
} else
Symbols.insert(std::make_pair(KV.first, std::move(KV.second)));
}
return Err;
}
-Error VSO::defineLazy(const SymbolFlagsMap &NewSymbols,
- std::shared_ptr<SymbolSource> Source) {
+Error VSO::defineLazy(std::unique_ptr<MaterializationUnit> MU) {
+
+ auto NewSymbols = MU->getSymbols();
+
+ auto MaterializationInfoItr =
+ MaterializationInfos
+ .insert(llvm::make_unique<MaterializationInfo>(NewSymbols.size(),
+ std::move(MU)))
+ .first;
+
Error Err = Error::success();
for (auto &KV : NewSymbols) {
auto I = Symbols.find(KV.first);
KV.second);
// Discard weaker definitions.
- if (LinkageResult == ExistingDefinitionIsStronger)
- Source->discard(*this, KV.first);
+ if (LinkageResult == ExistingDefinitionIsStronger) {
+ (*MaterializationInfoItr)->MU->discard(*this, KV.first);
+ assert((*MaterializationInfoItr)->SymbolsRemaining > 0 &&
+ "Discarding non-existant symbols?");
+ --(*MaterializationInfoItr)->SymbolsRemaining;
+ continue;
+ }
// Report duplicate definition errors.
if (LinkageResult == DuplicateDefinition) {
Err = joinErrors(std::move(Err),
make_error<orc::DuplicateDefinition>(*KV.first));
+ // Duplicate definitions are discarded, so remove the duplicates from
+ // materializer.
+ assert((*MaterializationInfoItr)->SymbolsRemaining > 0 &&
+ "Discarding non-existant symbols?");
+ --(*MaterializationInfoItr)->SymbolsRemaining;
continue;
}
if (I != Symbols.end())
- I->second.replaceWithSource(*this, KV.first, KV.second, Source);
+ I->second.replaceWith(*this, KV.first, KV.second, MaterializationInfoItr);
else
- Symbols.emplace(
- std::make_pair(KV.first, SymbolTableEntry(KV.second, Source)));
+ Symbols.emplace(std::make_pair(
+ KV.first, SymbolTableEntry(KV.second, MaterializationInfoItr)));
}
+
+ // If we ended up overriding all definitions in this materializer then delete
+ // it.
+ if ((*MaterializationInfoItr)->SymbolsRemaining == 0)
+ MaterializationInfos.erase(MaterializationInfoItr);
+
return Err;
}
for (auto &S : SymbolsToFinalize) {
auto I = Symbols.find(S);
assert(I != Symbols.end() && "Finalizing symbol not present in this dylib");
- I->second.finalize();
+ I->second.finalize(*this, S);
}
}
VSO::LookupResult VSO::lookup(std::shared_ptr<AsynchronousSymbolQuery> Query,
SymbolNameSet Names) {
- SourceWorkMap MaterializationWork;
+ MaterializationUnitList MaterializationUnits;
for (SymbolNameSet::iterator I = Names.begin(), E = Names.end(); I != E;) {
auto Tmp = I++;
// Forward the query to the given SymbolTableEntry, and if it return a
// layer to perform materialization with, add that to the
// MaterializationWork map.
- if (auto Source = SymI->second.query(SymI->first, Query))
- MaterializationWork[Source].insert(SymI->first);
+ if (auto MU = SymI->second.query(SymI->first, Query))
+ MaterializationUnits.push_back(std::move(MU));
}
- return {std::move(MaterializationWork), std::move(Names)};
+ return {std::move(MaterializationUnits), std::move(Names)};
}
Expected<SymbolMap> lookup(const std::vector<VSO *> &VSOs, SymbolNameSet Names,
Names, std::move(OnResolve), std::move(OnReady));
SymbolNameSet UnresolvedSymbols(std::move(Names));
- for (auto *VSO : VSOs) {
+ for (auto *V : VSOs) {
if (UnresolvedSymbols.empty())
break;
- assert(VSO && "VSO pointers in VSOs list should be non-null");
- auto LR = VSO->lookup(Query, UnresolvedSymbols);
+ assert(V && "VSO pointers in VSOs list should be non-null");
+ auto LR = V->lookup(Query, UnresolvedSymbols);
UnresolvedSymbols = std::move(LR.UnresolvedSymbols);
- for (auto I = LR.MaterializationWork.begin(),
- E = LR.MaterializationWork.end();
- I != E;) {
- auto Tmp = I++;
- std::shared_ptr<SymbolSource> Source = Tmp->first;
- SymbolNameSet Names = std::move(Tmp->second);
- LR.MaterializationWork.erase(Tmp);
- DispatchMaterialization(*VSO, std::move(Source), std::move(Names));
- }
+ for (auto &MU : LR.MaterializationUnits)
+ DispatchMaterialization(*V, std::move(MU));
}
#if LLVM_ENABLE_THREADS
namespace {
-class SimpleSource : public SymbolSource {
+class SimpleMaterializationUnit : public MaterializationUnit {
public:
- using MaterializeFunction = std::function<Error(VSO &, SymbolNameSet)>;
+ using GetSymbolsFunction = std::function<SymbolFlagsMap()>;
+ using MaterializeFunction = std::function<Error(VSO &)>;
using DiscardFunction = std::function<void(VSO &, SymbolStringPtr)>;
- SimpleSource(MaterializeFunction Materialize, DiscardFunction Discard)
- : Materialize(std::move(Materialize)), Discard(std::move(Discard)) {}
+ SimpleMaterializationUnit(GetSymbolsFunction GetSymbols,
+ MaterializeFunction Materialize,
+ DiscardFunction Discard)
+ : GetSymbols(std::move(GetSymbols)), Materialize(std::move(Materialize)),
+ Discard(std::move(Discard)) {}
- Error materialize(VSO &V, SymbolNameSet Symbols) override {
- return Materialize(V, std::move(Symbols));
- }
+ SymbolFlagsMap getSymbols() override { return GetSymbols(); }
+
+ Error materialize(VSO &V) override { return Materialize(V); }
void discard(VSO &V, SymbolStringPtr Name) override {
Discard(V, std::move(Name));
}
private:
+ GetSymbolsFunction GetSymbols;
MaterializeFunction Materialize;
DiscardFunction Discard;
};
auto Bar = SP.intern("bar");
auto Baz = SP.intern("baz");
+ JITSymbolFlags FooFlags = JITSymbolFlags::Exported;
+ JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>(
+ JITSymbolFlags::Exported | JITSymbolFlags::Weak);
+
VSO V;
- auto Source = std::make_shared<SimpleSource>(
- [](VSO &V, SymbolNameSet Symbols) -> Error {
+ auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+ [=]() {
+ return SymbolFlagsMap({{Bar, BarFlags}});
+ },
+ [](VSO &V) -> Error {
llvm_unreachable("Symbol materialized on flags lookup");
},
[](VSO &V, SymbolStringPtr Name) -> Error {
llvm_unreachable("Symbol finalized on flags lookup");
});
- JITSymbolFlags FooFlags = JITSymbolFlags::Exported;
- JITSymbolFlags BarFlags = static_cast<JITSymbolFlags::FlagNames>(
- JITSymbolFlags::Exported | JITSymbolFlags::Weak);
-
SymbolMap InitialDefs;
InitialDefs[Foo] = JITEvaluatedSymbol(0xdeadbeef, FooFlags);
cantFail(V.define(std::move(InitialDefs)));
- SymbolFlagsMap InitialLazyDefs({{Bar, BarFlags}});
- cantFail(V.defineLazy(InitialLazyDefs, Source));
+ cantFail(V.defineLazy(std::move(MU)));
SymbolNameSet Names({Foo, Bar, Baz});
VSO V;
- auto Source = std::make_shared<SimpleSource>(
- [&](VSO &V, SymbolNameSet Symbols) {
- EXPECT_EQ(Symbols.size(), 1U)
- << "Expected Symbols set size to be 1 ({ Foo })";
- EXPECT_EQ(*Symbols.begin(), Foo) << "Expected Symbols == { Foo }";
-
+ auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+ [=]() {
+ return SymbolFlagsMap(
+ {{Foo, JITSymbolFlags::Exported},
+ {Bar, static_cast<JITSymbolFlags::FlagNames>(
+ JITSymbolFlags::Exported | JITSymbolFlags::Weak)}});
+ },
+ [&](VSO &V) {
+ assert(BarDiscarded && "Bar should have been discarded by this point");
SymbolMap SymbolsToResolve;
SymbolsToResolve[Foo] =
JITEvaluatedSymbol(FakeFooAddr, JITSymbolFlags::Exported);
BarDiscarded = true;
});
- SymbolFlagsMap InitialSymbols(
- {{Foo, JITSymbolFlags::Exported},
- {Bar, static_cast<JITSymbolFlags::FlagNames>(JITSymbolFlags::Exported |
- JITSymbolFlags::Weak)}});
- cantFail(V.defineLazy(InitialSymbols, Source));
+ cantFail(V.defineLazy(std::move(MU)));
SymbolMap BarOverride;
BarOverride[Bar] = JITEvaluatedSymbol(FakeBarAddr, JITSymbolFlags::Exported);
auto LR = V.lookup(std::move(Q), Names);
- for (auto &SWKV : LR.MaterializationWork)
- cantFail(SWKV.first->materialize(V, std::move(SWKV.second)));
+ for (auto &SWKV : LR.MaterializationUnits)
+ cantFail(SWKV->materialize(V));
EXPECT_TRUE(LR.UnresolvedSymbols.empty()) << "Could not find Foo in dylib";
EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
},
[&](std::shared_ptr<AsynchronousSymbolQuery> Q, SymbolNameSet Symbols) {
auto LR = V.lookup(std::move(Q), Symbols);
- assert(LR.MaterializationWork.empty() &&
- "Test generated unexpected materialization "
- "work?");
+ assert(LR.MaterializationUnits.empty() &&
+ "Test generated unexpected materialization work?");
return std::move(LR.UnresolvedSymbols);
});
SymbolStringPool SSP;
auto Foo = SSP.intern("foo");
- auto Source = std::make_shared<SimpleSource>(
- [&](VSO &V, SymbolNameSet Symbols) -> Error {
+ auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+ [=]() {
+ return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
+ },
+ [&](VSO &V) -> Error {
V.resolve({{Foo, FooSym}});
V.finalize({Foo});
return Error::success();
VSO V;
- SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}});
- cantFail(V.defineLazy(InitialSymbols, Source));
+ cantFail(V.defineLazy(std::move(MU)));
ExecutionSession ES(SSP);
auto FooLookupResult =
SymbolStringPool SSP;
auto Foo = SSP.intern("foo");
- auto Source = std::make_shared<SimpleSource>(
- [&](VSO &V, SymbolNameSet Symbols) -> Error {
+ auto MU = llvm::make_unique<SimpleMaterializationUnit>(
+ [=]() {
+ return SymbolFlagsMap({{Foo, JITSymbolFlags::Exported}});
+ },
+ [&](VSO &V) -> Error {
V.resolve({{Foo, FooSym}});
V.finalize({Foo});
return Error::success();
VSO V;
- SymbolFlagsMap InitialSymbols({{Foo, JITSymbolFlags::Exported}});
- cantFail(V.defineLazy(InitialSymbols, Source));
+ cantFail(V.defineLazy(std::move(MU)));
ExecutionSession ES(SSP);
- auto MaterializeOnNewThread =
- [&ES](VSO &V, std::shared_ptr<SymbolSource> Source, SymbolNameSet Names) {
- std::thread(
- [&ES, &V, Source, Names]() {
- if (auto Err = Source->materialize(V, std::move(Names)))
- ES.reportError(std::move(Err));
- }).detach();
- };
+ auto MaterializeOnNewThread = [&ES](VSO &V,
+ std::unique_ptr<MaterializationUnit> MU) {
+ // FIXME: Use move capture once we move to C++14.
+ std::shared_ptr<MaterializationUnit> SharedMU = std::move(MU);
+ std::thread([&ES, &V, SharedMU]() {
+ if (auto Err = SharedMU->materialize(V))
+ ES.reportError(std::move(Err));
+ })
+ .detach();
+ };
auto FooLookupResult =
cantFail(lookup({&V}, Foo, MaterializeOnNewThread));