mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 10:42:39 +01:00
[ORC] Change how non-exported symbols are matched during lookup.
In the new scheme the client passes a list of (JITDylib&, bool) pairs, rather than a list of JITDylibs. For each JITDylib the boolean indicates whether or not to match against non-exported symbols (true means that they should be found, false means that they should not). The MatchNonExportedInJD and MatchNonExported parameters on lookup are removed. The new scheme is more flexible, and easier to understand. This patch also updates JITDylib search orders to be lists of (JITDylib&, bool) pairs to match the new lookup scheme. Error handling is also plumbed through the LLJIT class to allow regression tests to fail predictably when a lookup from a lazy call-through fails. llvm-svn: 345077
This commit is contained in:
parent
5b2715d563
commit
bd85e5c88d
@ -40,6 +40,18 @@ class SymbolRef;
|
||||
/// Represents an address in the target process's address space.
|
||||
using JITTargetAddress = uint64_t;
|
||||
|
||||
/// Convert a JITTargetAddress to a pointer.
|
||||
template <typename T> T jitTargetAddressToPointer(JITTargetAddress Addr) {
|
||||
static_assert(std::is_pointer<T>::value, "T must be a pointer type");
|
||||
uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
|
||||
assert(IntPtr == Addr && "JITTargetAddress value out of range for uintptr_t");
|
||||
return reinterpret_cast<T>(IntPtr);
|
||||
}
|
||||
|
||||
template <typename T> JITTargetAddress pointerToJITTargetAddress(T *Ptr) {
|
||||
return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Ptr));
|
||||
}
|
||||
|
||||
/// Flags for symbols in the JIT.
|
||||
class JITSymbolFlags {
|
||||
public:
|
||||
|
@ -54,8 +54,8 @@ using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
|
||||
/// symbols to be obtained for logging.
|
||||
using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
|
||||
|
||||
/// A list of JITDylib pointers.
|
||||
using JITDylibList = std::vector<JITDylib *>;
|
||||
/// A list of (JITDylib*, bool) pairs.
|
||||
using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
|
||||
|
||||
/// Render a SymbolStringPtr.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
|
||||
@ -85,8 +85,8 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
|
||||
/// Render a MaterializationUnit.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
|
||||
|
||||
/// Render a JITDylibList.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs);
|
||||
/// Render a JITDylibSearchList.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
|
||||
|
||||
/// Callback to notify client that symbols have been resolved.
|
||||
using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
|
||||
@ -351,14 +351,15 @@ using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
|
||||
class ReExportsMaterializationUnit : public MaterializationUnit {
|
||||
public:
|
||||
/// SourceJD is allowed to be nullptr, in which case the source JITDylib is
|
||||
/// taken to be whatever JITDylib these definitions are materialized in. This
|
||||
/// is useful for defining aliases within a JITDylib.
|
||||
/// taken to be whatever JITDylib these definitions are materialized in (and
|
||||
/// MatchNonExported has no effect). This is useful for defining aliases
|
||||
/// within a JITDylib.
|
||||
///
|
||||
/// Note: Care must be taken that no sets of aliases form a cycle, as such
|
||||
/// a cycle will result in a deadlock when any symbol in the cycle is
|
||||
/// resolved.
|
||||
ReExportsMaterializationUnit(JITDylib *SourceJD, SymbolAliasMap Aliases,
|
||||
VModuleKey K);
|
||||
ReExportsMaterializationUnit(JITDylib *SourceJD, bool MatchNonExported,
|
||||
SymbolAliasMap Aliases, VModuleKey K);
|
||||
|
||||
StringRef getName() const override;
|
||||
|
||||
@ -368,6 +369,7 @@ private:
|
||||
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
|
||||
|
||||
JITDylib *SourceJD = nullptr;
|
||||
bool MatchNonExported = false;
|
||||
SymbolAliasMap Aliases;
|
||||
};
|
||||
|
||||
@ -385,16 +387,19 @@ private:
|
||||
inline std::unique_ptr<ReExportsMaterializationUnit>
|
||||
symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
|
||||
return llvm::make_unique<ReExportsMaterializationUnit>(
|
||||
nullptr, std::move(Aliases), std::move(K));
|
||||
nullptr, true, std::move(Aliases), std::move(K));
|
||||
}
|
||||
|
||||
/// Create a materialization unit for re-exporting symbols from another JITDylib
|
||||
/// with alternative names/flags.
|
||||
/// If MatchNonExported is true then non-exported symbols from SourceJD can be
|
||||
/// re-exported. If it is false, attempts to re-export a non-exported symbol
|
||||
/// will result in a "symbol not found" error.
|
||||
inline std::unique_ptr<ReExportsMaterializationUnit>
|
||||
reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
|
||||
VModuleKey K = VModuleKey()) {
|
||||
bool MatchNonExported = false, VModuleKey K = VModuleKey()) {
|
||||
return llvm::make_unique<ReExportsMaterializationUnit>(
|
||||
&SourceJD, std::move(Aliases), std::move(K));
|
||||
&SourceJD, MatchNonExported, std::move(Aliases), std::move(K));
|
||||
}
|
||||
|
||||
/// Build a SymbolAliasMap for the common case where you want to re-export
|
||||
@ -411,13 +416,14 @@ public:
|
||||
/// Create a reexports generator. If an Allow predicate is passed, only
|
||||
/// symbols for which the predicate returns true will be reexported. If no
|
||||
/// Allow predicate is passed, all symbols will be exported.
|
||||
ReexportsGenerator(JITDylib &SourceJD,
|
||||
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
|
||||
SymbolPredicate Allow = SymbolPredicate());
|
||||
|
||||
SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
|
||||
|
||||
private:
|
||||
JITDylib &SourceJD;
|
||||
bool MatchNonExported = false;
|
||||
SymbolPredicate Allow;
|
||||
};
|
||||
|
||||
@ -536,16 +542,18 @@ public:
|
||||
/// as the first in the search order (instead of this dylib) ensures that
|
||||
/// definitions within this dylib resolve to the lazy-compiling stubs,
|
||||
/// rather than immediately materializing the definitions in this dylib.
|
||||
void setSearchOrder(JITDylibList NewSearchOrder,
|
||||
bool SearchThisJITDylibFirst = true);
|
||||
void setSearchOrder(JITDylibSearchList NewSearchOrder,
|
||||
bool SearchThisJITDylibFirst = true,
|
||||
bool MatchNonExportedInThisDylib = true);
|
||||
|
||||
/// Add the given JITDylib to the search order for definitions in this
|
||||
/// JITDylib.
|
||||
void addToSearchOrder(JITDylib &JD);
|
||||
void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false);
|
||||
|
||||
/// Replace OldJD with NewJD in the search order if OldJD is present.
|
||||
/// Otherwise this operation is a no-op.
|
||||
void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD);
|
||||
void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
|
||||
bool MatchNonExported = false);
|
||||
|
||||
/// Remove the given JITDylib from the search order for this JITDylib if it is
|
||||
/// present. Otherwise this operation is a no-op.
|
||||
@ -554,7 +562,7 @@ public:
|
||||
/// Do something with the search order (run under the session lock).
|
||||
template <typename Func>
|
||||
auto withSearchOrderDo(Func &&F)
|
||||
-> decltype(F(std::declval<const JITDylibList &>()));
|
||||
-> decltype(F(std::declval<const JITDylibSearchList &>()));
|
||||
|
||||
/// Define all symbols provided by the materialization unit to be part of this
|
||||
/// JITDylib.
|
||||
@ -642,12 +650,12 @@ private:
|
||||
const SymbolNameSet &Names);
|
||||
|
||||
void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
|
||||
bool MatchNonExported, MaterializationUnitList &MUs);
|
||||
SymbolNameSet &Unresolved, bool MatchNonExported,
|
||||
MaterializationUnitList &MUs);
|
||||
|
||||
void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
|
||||
bool MatchNonExported, MaterializationUnitList &MUs);
|
||||
SymbolNameSet &Unresolved, bool MatchNonExported,
|
||||
MaterializationUnitList &MUs);
|
||||
|
||||
LookupImplActionFlags
|
||||
lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
@ -682,7 +690,7 @@ private:
|
||||
UnmaterializedInfosMap UnmaterializedInfos;
|
||||
MaterializingInfosMap MaterializingInfos;
|
||||
GeneratorFunction DefGenerator;
|
||||
JITDylibList SearchOrder;
|
||||
JITDylibSearchList SearchOrder;
|
||||
};
|
||||
|
||||
/// An ExecutionSession represents a running JIT program.
|
||||
@ -766,6 +774,10 @@ public:
|
||||
|
||||
/// Search the given JITDylib list for the given symbols.
|
||||
///
|
||||
/// SearchOrder lists the JITDylibs to search. For each dylib, the associated
|
||||
/// boolean indicates whether the search should match against non-exported
|
||||
/// (hidden visibility) symbols in that dylib (true means match against
|
||||
/// non-exported symbols, false means do not match).
|
||||
///
|
||||
/// The OnResolve callback will be called once all requested symbols are
|
||||
/// resolved, or if an error occurs prior to resolution.
|
||||
@ -782,19 +794,9 @@ public:
|
||||
/// dependenant symbols for this query (e.g. it is being made by a top level
|
||||
/// client to get an address to call) then the value NoDependenciesToRegister
|
||||
/// can be used.
|
||||
///
|
||||
/// If the MatchNonExportedInJD pointer is non-null, then the lookup will find
|
||||
/// non-exported symbols defined in the JITDylib pointed to by
|
||||
/// MatchNonExportedInJD.
|
||||
/// If MatchNonExported is true the lookup will find non-exported symbols in
|
||||
/// any JITDylib (setting MatchNonExportedInJD is redundant in such cases).
|
||||
/// If MatchNonExported is false and MatchNonExportedInJD is null,
|
||||
/// non-exported symbols will never be found.
|
||||
void lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
|
||||
void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
|
||||
SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
|
||||
RegisterDependenciesFunction RegisterDependencies,
|
||||
JITDylib *MatchNonExportedInJD = nullptr,
|
||||
bool MatchNonExported = false);
|
||||
RegisterDependenciesFunction RegisterDependencies);
|
||||
|
||||
/// Blocking version of lookup above. Returns the resolved symbol map.
|
||||
/// If WaitUntilReady is true (the default), will not return until all
|
||||
@ -803,24 +805,29 @@ public:
|
||||
/// or an error occurs. If WaitUntilReady is false and an error occurs
|
||||
/// after resolution, the function will return a success value, but the
|
||||
/// error will be reported via reportErrors.
|
||||
Expected<SymbolMap> lookup(const JITDylibList &JDs,
|
||||
Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
|
||||
const SymbolNameSet &Symbols,
|
||||
RegisterDependenciesFunction RegisterDependencies =
|
||||
NoDependenciesToRegister,
|
||||
bool WaitUntilReady = true,
|
||||
JITDylib *MatchNonExportedInJD = nullptr,
|
||||
bool MatchNonExported = false);
|
||||
bool WaitUntilReady = true);
|
||||
|
||||
/// Convenience version of blocking lookup.
|
||||
/// Performs a single-symbol lookup.
|
||||
Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs,
|
||||
SymbolStringPtr Symbol,
|
||||
bool MatchNonExported = false);
|
||||
/// Searches each of the JITDylibs in the search order in turn for the given
|
||||
/// symbol.
|
||||
Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder,
|
||||
SymbolStringPtr Symbol);
|
||||
|
||||
/// Convenience version of blocking lookup.
|
||||
/// Performs a single-symbol lookup, auto-interning the given symbol name.
|
||||
Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs, StringRef Symbol,
|
||||
bool MatchNonExported = false);
|
||||
/// Searches each of the JITDylibs in the search order in turn for the given
|
||||
/// symbol. The search will not find non-exported symbols.
|
||||
Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
|
||||
SymbolStringPtr Symbol);
|
||||
|
||||
/// Convenience version of blocking lookup.
|
||||
/// Searches each of the JITDylibs in the search order in turn for the given
|
||||
/// symbol. The search will not find non-exported symbols.
|
||||
Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
|
||||
StringRef Symbol);
|
||||
|
||||
/// Materialize the given unit.
|
||||
void dispatchMaterialization(JITDylib &JD,
|
||||
@ -866,7 +873,7 @@ private:
|
||||
|
||||
template <typename Func>
|
||||
auto JITDylib::withSearchOrderDo(Func &&F)
|
||||
-> decltype(F(std::declval<const JITDylibList &>())) {
|
||||
-> decltype(F(std::declval<const JITDylibSearchList &>())) {
|
||||
return ES.runSessionLocked([&]() { return F(SearchOrder); });
|
||||
}
|
||||
|
||||
|
@ -144,7 +144,7 @@ public:
|
||||
/// LLLazyJIT with the given number of compile threads.
|
||||
static Expected<std::unique_ptr<LLLazyJIT>>
|
||||
Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads = 0);
|
||||
JITTargetAddress ErrorAddr, unsigned NumCompileThreads = 0);
|
||||
|
||||
/// Set an IR transform (e.g. pass manager pipeline) to run on each function
|
||||
/// when it is compiled.
|
||||
|
@ -157,7 +157,7 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R,
|
||||
return;
|
||||
}
|
||||
|
||||
R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables)));
|
||||
R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables), true));
|
||||
R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
|
||||
std::move(Callables)));
|
||||
}
|
||||
@ -166,10 +166,17 @@ CompileOnDemandLayer::PerDylibResources &
|
||||
CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {
|
||||
auto I = DylibResources.find(&TargetD);
|
||||
if (I == DylibResources.end()) {
|
||||
auto &ImplD =
|
||||
getExecutionSession().createJITDylib(TargetD.getName() + ".impl");
|
||||
TargetD.withSearchOrderDo([&](const JITDylibList &TargetSearchOrder) {
|
||||
ImplD.setSearchOrder(TargetSearchOrder, false);
|
||||
auto &ImplD = getExecutionSession().createJITDylib(
|
||||
TargetD.getName() + ".impl", false);
|
||||
TargetD.withSearchOrderDo([&](const JITDylibSearchList &TargetSearchOrder) {
|
||||
auto NewSearchOrder = TargetSearchOrder;
|
||||
assert(!NewSearchOrder.empty() &&
|
||||
NewSearchOrder.front().first == &TargetD &&
|
||||
NewSearchOrder.front().second == true &&
|
||||
"TargetD must be at the front of its own search order and match "
|
||||
"non-exported symbol");
|
||||
NewSearchOrder.insert(std::next(NewSearchOrder.begin()), {&ImplD, true});
|
||||
ImplD.setSearchOrder(std::move(NewSearchOrder), false);
|
||||
});
|
||||
PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
|
||||
I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;
|
||||
|
@ -205,14 +205,16 @@ raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU) {
|
||||
return OS << ")";
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs) {
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs) {
|
||||
OS << "[";
|
||||
if (!JDs.empty()) {
|
||||
assert(JDs.front() && "JITDylibList entries must not be null");
|
||||
OS << " " << JDs.front()->getName();
|
||||
for (auto *JD : make_range(std::next(JDs.begin()), JDs.end())) {
|
||||
assert(JD && "JITDylibList entries must not be null");
|
||||
OS << ", " << JD->getName();
|
||||
assert(JDs.front().first && "JITDylibList entries must not be null");
|
||||
OS << " (\"" << JDs.front().first->getName() << "\", "
|
||||
<< (JDs.front().second ? "true" : "false") << ")";
|
||||
for (auto &KV : make_range(std::next(JDs.begin()), JDs.end())) {
|
||||
assert(KV.first && "JITDylibList entries must not be null");
|
||||
OS << ", (\"" << KV.first->getName() << "\", "
|
||||
<< (KV.second ? "true" : "false") << ")";
|
||||
}
|
||||
}
|
||||
OS << " ]";
|
||||
@ -526,9 +528,11 @@ AbsoluteSymbolsMaterializationUnit::extractFlags(const SymbolMap &Symbols) {
|
||||
}
|
||||
|
||||
ReExportsMaterializationUnit::ReExportsMaterializationUnit(
|
||||
JITDylib *SourceJD, SymbolAliasMap Aliases, VModuleKey K)
|
||||
JITDylib *SourceJD, bool MatchNonExported, SymbolAliasMap Aliases,
|
||||
VModuleKey K)
|
||||
: MaterializationUnit(extractFlags(Aliases), std::move(K)),
|
||||
SourceJD(SourceJD), Aliases(std::move(Aliases)) {}
|
||||
SourceJD(SourceJD), MatchNonExported(MatchNonExported),
|
||||
Aliases(std::move(Aliases)) {}
|
||||
|
||||
StringRef ReExportsMaterializationUnit::getName() const {
|
||||
return "<Reexports>";
|
||||
@ -556,7 +560,7 @@ void ReExportsMaterializationUnit::materialize(
|
||||
|
||||
if (!Aliases.empty()) {
|
||||
if (SourceJD)
|
||||
R.replace(reexports(*SourceJD, std::move(Aliases)));
|
||||
R.replace(reexports(*SourceJD, std::move(Aliases), MatchNonExported));
|
||||
else
|
||||
R.replace(symbolAliases(std::move(Aliases)));
|
||||
}
|
||||
@ -656,8 +660,8 @@ void ReExportsMaterializationUnit::materialize(
|
||||
|
||||
auto OnReady = [&ES](Error Err) { ES.reportError(std::move(Err)); };
|
||||
|
||||
ES.lookup({&SrcJD}, QuerySymbols, std::move(OnResolve), std::move(OnReady),
|
||||
std::move(RegisterDependencies), nullptr, true);
|
||||
ES.lookup({{&SrcJD, MatchNonExported}}, QuerySymbols, std::move(OnResolve),
|
||||
std::move(OnReady), std::move(RegisterDependencies));
|
||||
}
|
||||
}
|
||||
|
||||
@ -698,8 +702,10 @@ buildSimpleReexportsAliasMap(JITDylib &SourceJD, const SymbolNameSet &Symbols) {
|
||||
}
|
||||
|
||||
ReexportsGenerator::ReexportsGenerator(JITDylib &SourceJD,
|
||||
bool MatchNonExported,
|
||||
SymbolPredicate Allow)
|
||||
: SourceJD(SourceJD), Allow(std::move(Allow)) {}
|
||||
: SourceJD(SourceJD), MatchNonExported(MatchNonExported),
|
||||
Allow(std::move(Allow)) {}
|
||||
|
||||
SymbolNameSet ReexportsGenerator::operator()(JITDylib &JD,
|
||||
const SymbolNameSet &Names) {
|
||||
@ -716,7 +722,7 @@ SymbolNameSet ReexportsGenerator::operator()(JITDylib &JD,
|
||||
}
|
||||
|
||||
if (!Added.empty())
|
||||
cantFail(JD.define(reexports(SourceJD, AliasMap)));
|
||||
cantFail(JD.define(reexports(SourceJD, AliasMap, MatchNonExported)));
|
||||
|
||||
return Added;
|
||||
}
|
||||
@ -1041,30 +1047,41 @@ void JITDylib::notifyFailed(const SymbolNameSet &FailedSymbols) {
|
||||
Q->handleFailed(make_error<FailedToMaterialize>(FailedSymbols));
|
||||
}
|
||||
|
||||
void JITDylib::setSearchOrder(JITDylibList NewSearchOrder,
|
||||
bool SearchThisJITDylibFirst) {
|
||||
if (SearchThisJITDylibFirst && NewSearchOrder.front() != this)
|
||||
NewSearchOrder.insert(NewSearchOrder.begin(), this);
|
||||
void JITDylib::setSearchOrder(JITDylibSearchList NewSearchOrder,
|
||||
bool SearchThisJITDylibFirst,
|
||||
bool MatchNonExportedInThisDylib) {
|
||||
if (SearchThisJITDylibFirst && NewSearchOrder.front().first != this)
|
||||
NewSearchOrder.insert(NewSearchOrder.begin(),
|
||||
{this, MatchNonExportedInThisDylib});
|
||||
|
||||
ES.runSessionLocked([&]() { SearchOrder = std::move(NewSearchOrder); });
|
||||
}
|
||||
|
||||
void JITDylib::addToSearchOrder(JITDylib &JD) {
|
||||
ES.runSessionLocked([&]() { SearchOrder.push_back(&JD); });
|
||||
void JITDylib::addToSearchOrder(JITDylib &JD, bool MatchNonExported) {
|
||||
ES.runSessionLocked([&]() {
|
||||
SearchOrder.push_back({&JD, MatchNonExported});
|
||||
});
|
||||
}
|
||||
|
||||
void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD) {
|
||||
void JITDylib::replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
|
||||
bool MatchNonExported) {
|
||||
ES.runSessionLocked([&]() {
|
||||
auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &OldJD);
|
||||
auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(),
|
||||
[&](const JITDylibSearchList::value_type &KV) {
|
||||
return KV.first == &OldJD;
|
||||
});
|
||||
|
||||
if (I != SearchOrder.end())
|
||||
*I = &NewJD;
|
||||
*I = {&NewJD, MatchNonExported};
|
||||
});
|
||||
}
|
||||
|
||||
void JITDylib::removeFromSearchOrder(JITDylib &JD) {
|
||||
ES.runSessionLocked([&]() {
|
||||
auto I = std::find(SearchOrder.begin(), SearchOrder.end(), &JD);
|
||||
auto I = std::find_if(SearchOrder.begin(), SearchOrder.end(),
|
||||
[&](const JITDylibSearchList::value_type &KV) {
|
||||
return KV.first == &JD;
|
||||
});
|
||||
if (I != SearchOrder.end())
|
||||
SearchOrder.erase(I);
|
||||
});
|
||||
@ -1161,18 +1178,17 @@ SymbolNameSet JITDylib::lookupFlagsImpl(SymbolFlagsMap &Flags,
|
||||
}
|
||||
|
||||
void JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
SymbolNameSet &Unresolved,
|
||||
JITDylib *MatchNonExportedInJD, bool MatchNonExported,
|
||||
SymbolNameSet &Unresolved, bool MatchNonExported,
|
||||
MaterializationUnitList &MUs) {
|
||||
assert(Q && "Query can not be null");
|
||||
|
||||
lodgeQueryImpl(Q, Unresolved, MatchNonExportedInJD, MatchNonExported, MUs);
|
||||
lodgeQueryImpl(Q, Unresolved, MatchNonExported, MUs);
|
||||
if (DefGenerator && !Unresolved.empty()) {
|
||||
auto NewDefs = DefGenerator(*this, Unresolved);
|
||||
if (!NewDefs.empty()) {
|
||||
for (auto &D : NewDefs)
|
||||
Unresolved.erase(D);
|
||||
lodgeQueryImpl(Q, NewDefs, MatchNonExportedInJD, MatchNonExported, MUs);
|
||||
lodgeQueryImpl(Q, NewDefs, MatchNonExported, MUs);
|
||||
assert(NewDefs.empty() &&
|
||||
"All fallback defs should have been found by lookupImpl");
|
||||
}
|
||||
@ -1181,7 +1197,7 @@ void JITDylib::lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
|
||||
|
||||
void JITDylib::lodgeQueryImpl(
|
||||
std::shared_ptr<AsynchronousSymbolQuery> &Q, SymbolNameSet &Unresolved,
|
||||
JITDylib *MatchNonExportedInJD, bool MatchNonExported,
|
||||
bool MatchNonExported,
|
||||
std::vector<std::unique_ptr<MaterializationUnit>> &MUs) {
|
||||
|
||||
std::vector<SymbolStringPtr> ToRemove;
|
||||
@ -1191,12 +1207,9 @@ void JITDylib::lodgeQueryImpl(
|
||||
if (SymI == Symbols.end())
|
||||
continue;
|
||||
|
||||
// If this is a non-exported symbol, then check the values of
|
||||
// MatchNonExportedInJD and MatchNonExported. Skip if we should not match
|
||||
// against this symbol.
|
||||
if (!SymI->second.getFlags().isExported())
|
||||
if (!MatchNonExported && MatchNonExportedInJD != this)
|
||||
continue;
|
||||
// If this is a non exported symbol and we're skipping those then skip it.
|
||||
if (!SymI->second.getFlags().isExported() && !MatchNonExported)
|
||||
continue;
|
||||
|
||||
// If we matched against Name in JD, mark it to be removed from the Unresolved
|
||||
// set.
|
||||
@ -1382,8 +1395,9 @@ void JITDylib::dump(raw_ostream &OS) {
|
||||
<< "\" (ES: " << format("0x%016x", reinterpret_cast<uintptr_t>(&ES))
|
||||
<< "):\n"
|
||||
<< "Search order: [";
|
||||
for (auto *JD : SearchOrder)
|
||||
OS << " \"" << JD->getName() << "\"";
|
||||
for (auto &KV : SearchOrder)
|
||||
OS << " (\"" << KV.first->getName() << "\", "
|
||||
<< (KV.second ? "all" : "exported only") << ")";
|
||||
OS << " ]\n"
|
||||
<< "Symbol table:\n";
|
||||
|
||||
@ -1431,7 +1445,7 @@ void JITDylib::dump(raw_ostream &OS) {
|
||||
|
||||
JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
|
||||
: ES(ES), JITDylibName(std::move(Name)) {
|
||||
SearchOrder.push_back(this);
|
||||
SearchOrder.push_back({this, true});
|
||||
}
|
||||
|
||||
Error JITDylib::defineImpl(MaterializationUnit &MU) {
|
||||
@ -1724,12 +1738,10 @@ Expected<SymbolMap> ExecutionSession::legacyLookup(
|
||||
#endif
|
||||
}
|
||||
|
||||
void ExecutionSession::lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
|
||||
SymbolsResolvedCallback OnResolve,
|
||||
SymbolsReadyCallback OnReady,
|
||||
RegisterDependenciesFunction RegisterDependencies,
|
||||
JITDylib *MatchNonExportedInJD,
|
||||
bool MatchNonExported) {
|
||||
void ExecutionSession::lookup(
|
||||
const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
|
||||
SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
|
||||
RegisterDependenciesFunction RegisterDependencies) {
|
||||
|
||||
// lookup can be re-entered recursively if running on a single thread. Run any
|
||||
// outstanding MUs in case this query depends on them, otherwise this lookup
|
||||
@ -1745,12 +1757,14 @@ void ExecutionSession::lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
|
||||
bool QueryFailed = false;
|
||||
|
||||
runSessionLocked([&]() {
|
||||
for (auto *JD : JDs) {
|
||||
assert(JD && "JITDylibList entries must not be null");
|
||||
assert(!CollectedMUsMap.count(JD) &&
|
||||
for (auto &KV : SearchOrder) {
|
||||
assert(KV.first && "JITDylibList entries must not be null");
|
||||
assert(!CollectedMUsMap.count(KV.first) &&
|
||||
"JITDylibList should not contain duplicate entries");
|
||||
JD->lodgeQuery(Q, Unresolved, MatchNonExportedInJD, MatchNonExported,
|
||||
CollectedMUsMap[JD]);
|
||||
|
||||
auto &JD = *KV.first;
|
||||
auto MatchNonExported = KV.second;
|
||||
JD.lodgeQuery(Q, Unresolved, MatchNonExported, CollectedMUsMap[&JD]);
|
||||
}
|
||||
|
||||
if (Unresolved.empty()) {
|
||||
@ -1801,11 +1815,9 @@ void ExecutionSession::lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
|
||||
runOutstandingMUs();
|
||||
}
|
||||
|
||||
Expected<SymbolMap>
|
||||
ExecutionSession::lookup(const JITDylibList &JDs, const SymbolNameSet &Symbols,
|
||||
RegisterDependenciesFunction RegisterDependencies,
|
||||
bool WaitUntilReady, JITDylib *MatchNonExportedInJD,
|
||||
bool MatchNonExported) {
|
||||
Expected<SymbolMap> ExecutionSession::lookup(
|
||||
const JITDylibSearchList &SearchOrder, const SymbolNameSet &Symbols,
|
||||
RegisterDependenciesFunction RegisterDependencies, bool WaitUntilReady) {
|
||||
#if LLVM_ENABLE_THREADS
|
||||
// In the threaded case we use promises to return the results.
|
||||
std::promise<SymbolMap> PromisedResult;
|
||||
@ -1872,8 +1884,7 @@ ExecutionSession::lookup(const JITDylibList &JDs, const SymbolNameSet &Symbols,
|
||||
#endif
|
||||
|
||||
// Perform the asynchronous lookup.
|
||||
lookup(JDs, Symbols, OnResolve, OnReady, RegisterDependencies,
|
||||
MatchNonExportedInJD, MatchNonExported);
|
||||
lookup(SearchOrder, Symbols, OnResolve, OnReady, RegisterDependencies);
|
||||
|
||||
#if LLVM_ENABLE_THREADS
|
||||
auto ResultFuture = PromisedResult.get_future();
|
||||
@ -1916,14 +1927,13 @@ ExecutionSession::lookup(const JITDylibList &JDs, const SymbolNameSet &Symbols,
|
||||
#endif
|
||||
}
|
||||
|
||||
/// Look up a symbol by searching a list of JDs.
|
||||
Expected<JITEvaluatedSymbol> ExecutionSession::lookup(const JITDylibList &JDs,
|
||||
SymbolStringPtr Name,
|
||||
bool MatchNonExported) {
|
||||
Expected<JITEvaluatedSymbol>
|
||||
ExecutionSession::lookup(const JITDylibSearchList &SearchOrder,
|
||||
SymbolStringPtr Name) {
|
||||
SymbolNameSet Names({Name});
|
||||
|
||||
if (auto ResultMap = lookup(JDs, std::move(Names), NoDependenciesToRegister,
|
||||
true, nullptr, MatchNonExported)) {
|
||||
if (auto ResultMap = lookup(SearchOrder, std::move(Names),
|
||||
NoDependenciesToRegister, true)) {
|
||||
assert(ResultMap->size() == 1 && "Unexpected number of results");
|
||||
assert(ResultMap->count(Name) && "Missing result for symbol");
|
||||
return std::move(ResultMap->begin()->second);
|
||||
@ -1931,10 +1941,21 @@ Expected<JITEvaluatedSymbol> ExecutionSession::lookup(const JITDylibList &JDs,
|
||||
return ResultMap.takeError();
|
||||
}
|
||||
|
||||
Expected<JITEvaluatedSymbol> ExecutionSession::lookup(const JITDylibList &JDs,
|
||||
StringRef Name,
|
||||
bool MatchNonExported) {
|
||||
return lookup(JDs, intern(Name), MatchNonExported);
|
||||
Expected<JITEvaluatedSymbol>
|
||||
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder,
|
||||
SymbolStringPtr Name) {
|
||||
SymbolNameSet Names({Name});
|
||||
|
||||
JITDylibSearchList FullSearchOrder(SearchOrder.size());
|
||||
for (auto *JD : SearchOrder)
|
||||
FullSearchOrder.push_back({JD, false});
|
||||
|
||||
return lookup(FullSearchOrder, Name);
|
||||
}
|
||||
|
||||
Expected<JITEvaluatedSymbol>
|
||||
ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name) {
|
||||
return lookup(SearchOrder, intern(Name));
|
||||
}
|
||||
|
||||
void ExecutionSession::dump(raw_ostream &OS) {
|
||||
|
@ -129,9 +129,8 @@ Error CtorDtorRunner::run() {
|
||||
}
|
||||
|
||||
auto &ES = JD.getExecutionSession();
|
||||
if (auto CtorDtorMap =
|
||||
ES.lookup({&JD}, std::move(Names), NoDependenciesToRegister, true,
|
||||
nullptr, true)) {
|
||||
if (auto CtorDtorMap = ES.lookup({{&JD, true}}, std::move(Names),
|
||||
NoDependenciesToRegister, true)) {
|
||||
for (auto &KV : CtorDtorsByPriority) {
|
||||
for (auto &Name : KV.second) {
|
||||
assert(CtorDtorMap->count(Name) && "No entry for Name");
|
||||
|
@ -101,7 +101,7 @@ JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
|
||||
Name = I->second;
|
||||
}
|
||||
|
||||
if (auto Sym = ES.lookup({&CallbacksJD}, Name, true))
|
||||
if (auto Sym = ES.lookup({{&CallbacksJD, true}}, Name))
|
||||
return Sym->getAddress();
|
||||
else {
|
||||
llvm::dbgs() << "Didn't find callback.\n";
|
||||
|
@ -76,7 +76,7 @@ Error LLJIT::addObjectFile(JITDylib &JD, std::unique_ptr<MemoryBuffer> Obj) {
|
||||
|
||||
Expected<JITEvaluatedSymbol> LLJIT::lookupLinkerMangled(JITDylib &JD,
|
||||
StringRef Name) {
|
||||
return ES->lookup({&JD}, ES->intern(Name));
|
||||
return ES->lookup({{&JD, true}}, ES->intern(Name));
|
||||
}
|
||||
|
||||
LLJIT::LLJIT(std::unique_ptr<ExecutionSession> ES,
|
||||
@ -144,13 +144,13 @@ void LLJIT::recordCtorDtors(Module &M) {
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<LLLazyJIT>>
|
||||
LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
unsigned NumCompileThreads) {
|
||||
LLLazyJIT::Create(JITTargetMachineBuilder JTMB, DataLayout DL,
|
||||
JITTargetAddress ErrorAddr, unsigned NumCompileThreads) {
|
||||
auto ES = llvm::make_unique<ExecutionSession>();
|
||||
|
||||
const Triple &TT = JTMB.getTargetTriple();
|
||||
|
||||
auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, 0);
|
||||
auto LCTMgr = createLocalLazyCallThroughManager(TT, *ES, ErrorAddr);
|
||||
if (!LCTMgr)
|
||||
return LCTMgr.takeError();
|
||||
|
||||
|
@ -52,8 +52,8 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
|
||||
SymbolName = I->second.second;
|
||||
}
|
||||
|
||||
auto LookupResult = ES.lookup({SourceJD}, {SymbolName},
|
||||
NoDependenciesToRegister, true, nullptr, true);
|
||||
auto LookupResult = ES.lookup({{SourceJD, true}}, {SymbolName},
|
||||
NoDependenciesToRegister, true);
|
||||
|
||||
if (!LookupResult) {
|
||||
ES.reportError(LookupResult.takeError());
|
||||
|
@ -50,10 +50,11 @@ public:
|
||||
MR.addDependenciesForAll(Deps);
|
||||
};
|
||||
|
||||
MR.getTargetJITDylib().withSearchOrderDo([&](const JITDylibList &JDs) {
|
||||
ES.lookup(JDs, InternedSymbols, OnResolvedWithUnwrap, OnReady,
|
||||
RegisterDependencies, &MR.getTargetJITDylib());
|
||||
});
|
||||
JITDylibSearchList SearchOrder;
|
||||
MR.getTargetJITDylib().withSearchOrderDo(
|
||||
[&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
|
||||
ES.lookup(SearchOrder, InternedSymbols, OnResolvedWithUnwrap, OnReady,
|
||||
RegisterDependencies);
|
||||
}
|
||||
|
||||
Expected<LookupSet> getResponsibilitySet(const LookupSet &Symbols) {
|
||||
|
@ -0,0 +1,6 @@
|
||||
@bar = hidden global i32 0
|
||||
|
||||
define hidden i32 @foo() {
|
||||
entry:
|
||||
ret i32 0
|
||||
}
|
17
test/ExecutionEngine/OrcLazy/hidden-visibility.ll
Normal file
17
test/ExecutionEngine/OrcLazy/hidden-visibility.ll
Normal file
@ -0,0 +1,17 @@
|
||||
; RUN: lli -jit-kind=orc-lazy -extra-module %p/Inputs/hidden-definitions.ll %s
|
||||
; RUN: not lli -jit-kind=orc-lazy -jd libFoo -extra-module %p/Inputs/hidden-definitions.ll %s
|
||||
;
|
||||
; Check that hidden symbols in another module are visible when the module is
|
||||
; added to the same JITDylib, and not visible if it is added to a different
|
||||
; JITDylib.
|
||||
|
||||
@bar = external global i32
|
||||
declare i32 @foo()
|
||||
|
||||
define i32 @main(i32 %argc, i8** nocapture readnone %argv) {
|
||||
entry:
|
||||
%0 = call i32() @foo()
|
||||
%1 = load i32, i32* @bar
|
||||
%2 = add i32 %0, %1
|
||||
ret i32 %2
|
||||
}
|
@ -115,6 +115,11 @@ namespace {
|
||||
"rather than individual functions"),
|
||||
cl::init(false));
|
||||
|
||||
cl::list<std::string>
|
||||
JITDylibs("jd",
|
||||
cl::desc("Specifies the JITDylib to be used for any subsequent "
|
||||
"-extra-module arguments."));
|
||||
|
||||
// The MCJIT supports building for a target address space separate from
|
||||
// the JIT compilation process. Use a forked process and a copying
|
||||
// memory manager with IPC to execute using this functionality.
|
||||
@ -749,6 +754,8 @@ static orc::IRTransformLayer::TransformFunction createDebugDumper() {
|
||||
llvm_unreachable("Unknown DumpKind");
|
||||
}
|
||||
|
||||
static void exitOnLazyCallThroughFailure() { exit(1); }
|
||||
|
||||
int runOrcLazyJIT(const char *ProgName) {
|
||||
// Start setting up the JIT environment.
|
||||
|
||||
@ -778,7 +785,11 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
: None);
|
||||
|
||||
DataLayout DL = ExitOnErr(JTMB.getDefaultDataLayoutForTarget());
|
||||
auto J = ExitOnErr(orc::LLLazyJIT::Create(std::move(JTMB), DL, LazyJITCompileThreads));
|
||||
|
||||
auto J = ExitOnErr(orc::LLLazyJIT::Create(
|
||||
std::move(JTMB), DL,
|
||||
pointerToJITTargetAddress(exitOnLazyCallThroughFailure),
|
||||
LazyJITCompileThreads));
|
||||
|
||||
if (PerModuleLazy)
|
||||
J->setPartitionFunction(orc::CompileOnDemandLayer::compileWholeModule);
|
||||
@ -803,13 +814,32 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
// Add the main module.
|
||||
ExitOnErr(J->addLazyIRModule(std::move(MainModule)));
|
||||
|
||||
// Add any extra modules.
|
||||
for (auto &ModulePath : ExtraModules) {
|
||||
auto M = parseIRFile(ModulePath, Err, *TSCtx.getContext());
|
||||
if (!M)
|
||||
reportError(Err, ProgName);
|
||||
// Create JITDylibs and add any extra modules.
|
||||
{
|
||||
// Create JITDylibs, keep a map from argument index to dylib. We will use
|
||||
// -extra-module argument indexes to determine what dylib to use for each
|
||||
// -extra-module.
|
||||
std::map<unsigned, orc::JITDylib *> IdxToDylib;
|
||||
IdxToDylib[0] = &J->getMainJITDylib();
|
||||
for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();
|
||||
JDItr != JDEnd; ++JDItr) {
|
||||
IdxToDylib[JITDylibs.getPosition(JDItr - JITDylibs.begin())] =
|
||||
&J->createJITDylib(*JDItr);
|
||||
}
|
||||
|
||||
ExitOnErr(J->addLazyIRModule(orc::ThreadSafeModule(std::move(M), TSCtx)));
|
||||
for (auto EMItr = ExtraModules.begin(), EMEnd = ExtraModules.end();
|
||||
EMItr != EMEnd; ++EMItr) {
|
||||
auto M = parseIRFile(*EMItr, Err, *TSCtx.getContext());
|
||||
if (!M)
|
||||
reportError(Err, ProgName);
|
||||
|
||||
auto EMIdx = ExtraModules.getPosition(EMItr - ExtraModules.begin());
|
||||
assert(EMIdx != 0 && "ExtraModule should have index > 0");
|
||||
auto JDItr = std::prev(IdxToDylib.lower_bound(EMIdx));
|
||||
auto &JD = *JDItr->second;
|
||||
ExitOnErr(
|
||||
J->addLazyIRModule(JD, orc::ThreadSafeModule(std::move(M), TSCtx)));
|
||||
}
|
||||
}
|
||||
|
||||
// Add the objects.
|
||||
@ -837,6 +867,8 @@ int runOrcLazyJIT(const char *ProgName) {
|
||||
AltEntryThreads.push_back(std::thread([EntryPoint]() { EntryPoint(); }));
|
||||
}
|
||||
|
||||
J->getExecutionSession().dump(llvm::dbgs());
|
||||
|
||||
// Run main.
|
||||
auto MainSym = ExitOnErr(J->lookup("main"));
|
||||
typedef int (*MainFnPtr)(int, const char *[]);
|
||||
|
@ -48,7 +48,8 @@ TEST_F(CoreAPIsStandardTest, BasicSuccessfulLookup) {
|
||||
FooMR = std::make_shared<MaterializationResponsibility>(std::move(R));
|
||||
})));
|
||||
|
||||
ES.lookup({&JD}, {Foo}, OnResolution, OnReady, NoDependenciesToRegister);
|
||||
ES.lookup({{&JD, false}}, {Foo}, OnResolution, OnReady,
|
||||
NoDependenciesToRegister);
|
||||
|
||||
EXPECT_FALSE(OnResolutionRun) << "Should not have been resolved yet";
|
||||
EXPECT_FALSE(OnReadyRun) << "Should not have been marked ready yet";
|
||||
@ -101,7 +102,8 @@ TEST_F(CoreAPIsStandardTest, EmptyLookup) {
|
||||
OnReadyRun = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, {}, OnResolution, OnReady, NoDependenciesToRegister);
|
||||
ES.lookup({{&JD, false}}, {}, OnResolution, OnReady,
|
||||
NoDependenciesToRegister);
|
||||
|
||||
EXPECT_TRUE(OnResolvedRun) << "OnResolved was not run for empty query";
|
||||
EXPECT_TRUE(OnReadyRun) << "OnReady was not run for empty query";
|
||||
@ -148,7 +150,7 @@ TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
|
||||
|
||||
bool OnResolvedRun = false;
|
||||
bool OnReadyRun = false;
|
||||
ES.lookup({&JD}, {Foo, Baz},
|
||||
ES.lookup({{&JD, false}}, {Foo, Baz},
|
||||
[&](Expected<SymbolMap> Result) {
|
||||
EXPECT_TRUE(!!Result) << "OnResolved failed unexpectedly";
|
||||
consumeError(Result.takeError());
|
||||
@ -229,7 +231,8 @@ TEST_F(CoreAPIsStandardTest, LookupWithHiddenSymbols) {
|
||||
auto &JD2 = ES.createJITDylib("JD2");
|
||||
cantFail(JD2.define(absoluteSymbols({{Bar, QuxSym}})));
|
||||
|
||||
auto Result = cantFail(ES.lookup({&JD, &JD2}, {Foo, Bar}));
|
||||
/// Try a blocking lookup.
|
||||
auto Result = cantFail(ES.lookup({{&JD, false}, {&JD2, false}}, {Foo, Bar}));
|
||||
|
||||
EXPECT_EQ(Result.size(), 2U) << "Unexpected number of results";
|
||||
EXPECT_EQ(Result.count(Foo), 1U) << "Missing result for \"Foo\"";
|
||||
@ -275,7 +278,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicAliases) {
|
||||
{Qux, {Bar, JITSymbolFlags::Weak}}})));
|
||||
cantFail(JD.define(absoluteSymbols({{Qux, QuxSym}})));
|
||||
|
||||
auto Result = ES.lookup({&JD}, {Baz, Qux});
|
||||
auto Result = ES.lookup({{&JD, false}}, {Baz, Qux});
|
||||
EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
|
||||
EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
|
||||
EXPECT_EQ(Result->count(Qux), 1U) << "No result for \"qux\"";
|
||||
@ -290,7 +293,7 @@ TEST_F(CoreAPIsStandardTest, TestChainedAliases) {
|
||||
cantFail(JD.define(symbolAliases(
|
||||
{{Baz, {Bar, BazSym.getFlags()}}, {Bar, {Foo, BarSym.getFlags()}}})));
|
||||
|
||||
auto Result = ES.lookup({&JD}, {Bar, Baz});
|
||||
auto Result = ES.lookup({{&JD, false}}, {Bar, Baz});
|
||||
EXPECT_TRUE(!!Result) << "Unexpected lookup failure";
|
||||
EXPECT_EQ(Result->count(Bar), 1U) << "No result for \"bar\"";
|
||||
EXPECT_EQ(Result->count(Baz), 1U) << "No result for \"baz\"";
|
||||
@ -309,7 +312,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicReExports) {
|
||||
|
||||
cantFail(JD2.define(reexports(JD, {{Bar, {Foo, BarSym.getFlags()}}})));
|
||||
|
||||
auto Result = cantFail(ES.lookup({&JD2}, Bar));
|
||||
auto Result = cantFail(ES.lookup({{&JD2, false}}, Bar));
|
||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
|
||||
<< "Re-export Bar for symbol Foo should match FooSym's address";
|
||||
}
|
||||
@ -335,7 +338,7 @@ TEST_F(CoreAPIsStandardTest, TestThatReExportsDontUnnecessarilyMaterialize) {
|
||||
cantFail(JD2.define(reexports(
|
||||
JD, {{Baz, {Foo, BazSym.getFlags()}}, {Qux, {Bar, QuxSym.getFlags()}}})));
|
||||
|
||||
auto Result = cantFail(ES.lookup({&JD2}, Baz));
|
||||
auto Result = cantFail(ES.lookup({{&JD2, false}}, Baz));
|
||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
|
||||
<< "Re-export Baz for symbol Foo should match FooSym's address";
|
||||
|
||||
@ -350,13 +353,13 @@ TEST_F(CoreAPIsStandardTest, TestReexportsGenerator) {
|
||||
|
||||
auto Filter = [this](SymbolStringPtr Name) { return Name != Bar; };
|
||||
|
||||
JD.setGenerator(ReexportsGenerator(JD2, Filter));
|
||||
JD.setGenerator(ReexportsGenerator(JD2, false, Filter));
|
||||
|
||||
auto Flags = JD.lookupFlags({Foo, Bar, Baz});
|
||||
EXPECT_EQ(Flags.size(), 1U) << "Unexpected number of results";
|
||||
EXPECT_EQ(Flags[Foo], FooSym.getFlags()) << "Unexpected flags for Foo";
|
||||
|
||||
auto Result = cantFail(ES.lookup({&JD}, Foo));
|
||||
auto Result = cantFail(ES.lookup({{&JD, false}}, Foo));
|
||||
|
||||
EXPECT_EQ(Result.getAddress(), FooSym.getAddress())
|
||||
<< "Incorrect reexported symbol address";
|
||||
@ -377,7 +380,7 @@ TEST_F(CoreAPIsStandardTest, TestTrivialCircularDependency) {
|
||||
FooReady = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, {Foo}, std::move(OnResolution), std::move(OnReady),
|
||||
ES.lookup({{&JD, false}}, {Foo}, std::move(OnResolution), std::move(OnReady),
|
||||
NoDependenciesToRegister);
|
||||
|
||||
FooR->resolve({{Foo, FooSym}});
|
||||
@ -434,8 +437,8 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
|
||||
|
||||
// Issue a lookup for Foo. Use NoDependenciesToRegister: We're going to add
|
||||
// the dependencies manually below.
|
||||
ES.lookup({&JD}, {Foo}, std::move(OnFooResolution), std::move(OnFooReady),
|
||||
NoDependenciesToRegister);
|
||||
ES.lookup({{&JD, false}}, {Foo}, std::move(OnFooResolution),
|
||||
std::move(OnFooReady), NoDependenciesToRegister);
|
||||
|
||||
bool BarResolved = false;
|
||||
bool BarReady = false;
|
||||
@ -449,8 +452,8 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
|
||||
BarReady = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, {Bar}, std::move(OnBarResolution), std::move(OnBarReady),
|
||||
NoDependenciesToRegister);
|
||||
ES.lookup({{&JD, false}}, {Bar}, std::move(OnBarResolution),
|
||||
std::move(OnBarReady), NoDependenciesToRegister);
|
||||
|
||||
bool BazResolved = false;
|
||||
bool BazReady = false;
|
||||
@ -465,8 +468,8 @@ TEST_F(CoreAPIsStandardTest, TestCircularDependenceInOneJITDylib) {
|
||||
BazReady = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, {Baz}, std::move(OnBazResolution), std::move(OnBazReady),
|
||||
NoDependenciesToRegister);
|
||||
ES.lookup({{&JD, false}}, {Baz}, std::move(OnBazResolution),
|
||||
std::move(OnBazReady), NoDependenciesToRegister);
|
||||
|
||||
// Add a circular dependency: Foo -> Bar, Bar -> Baz, Baz -> Foo.
|
||||
FooR->addDependenciesForAll({{&JD, SymbolNameSet({Bar})}});
|
||||
@ -588,7 +591,7 @@ TEST_F(CoreAPIsStandardTest, AddAndMaterializeLazySymbol) {
|
||||
OnReadyRun = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, Names, std::move(OnResolution), std::move(OnReady),
|
||||
ES.lookup({{&JD, false}}, Names, std::move(OnResolution), std::move(OnReady),
|
||||
NoDependenciesToRegister);
|
||||
|
||||
EXPECT_TRUE(FooMaterialized) << "Foo was not materialized";
|
||||
@ -637,7 +640,7 @@ TEST_F(CoreAPIsStandardTest, TestBasicWeakSymbolMaterialization) {
|
||||
OnReadyRun = true;
|
||||
};
|
||||
|
||||
ES.lookup({&JD}, {Bar}, std::move(OnResolution), std::move(OnReady),
|
||||
ES.lookup({{&JD, false}}, {Bar}, std::move(OnResolution), std::move(OnReady),
|
||||
NoDependenciesToRegister);
|
||||
|
||||
EXPECT_TRUE(OnResolvedRun) << "OnResolved not run";
|
||||
@ -666,13 +669,13 @@ TEST_F(CoreAPIsStandardTest, DefineMaterializingSymbol) {
|
||||
});
|
||||
|
||||
cantFail(JD.define(MU));
|
||||
cantFail(ES.lookup({&JD}, Foo));
|
||||
cantFail(ES.lookup({{&JD, false}}, Foo));
|
||||
|
||||
// Assert that materialization is complete by now.
|
||||
ExpectNoMoreMaterialization = true;
|
||||
|
||||
// Look up bar to verify that no further materialization happens.
|
||||
auto BarResult = cantFail(ES.lookup({&JD}, Bar));
|
||||
auto BarResult = cantFail(ES.lookup({{&JD, false}}, Bar));
|
||||
EXPECT_EQ(BarResult.getAddress(), BarSym.getAddress())
|
||||
<< "Expected Bar == BarSym";
|
||||
}
|
||||
@ -685,7 +688,7 @@ TEST_F(CoreAPIsStandardTest, GeneratorTest) {
|
||||
return SymbolNameSet({Bar});
|
||||
});
|
||||
|
||||
auto Result = cantFail(ES.lookup({&JD}, {Foo, Bar}));
|
||||
auto Result = cantFail(ES.lookup({{&JD, false}}, {Foo, Bar}));
|
||||
|
||||
EXPECT_EQ(Result.count(Bar), 1U) << "Expected to find fallback def for 'bar'";
|
||||
EXPECT_EQ(Result[Bar].getAddress(), BarSym.getAddress())
|
||||
@ -701,7 +704,7 @@ TEST_F(CoreAPIsStandardTest, FailResolution) {
|
||||
cantFail(JD.define(MU));
|
||||
|
||||
SymbolNameSet Names({Foo, Bar});
|
||||
auto Result = ES.lookup({&JD}, Names);
|
||||
auto Result = ES.lookup({{&JD, false}}, Names);
|
||||
|
||||
EXPECT_FALSE(!!Result) << "Expected failure";
|
||||
if (!Result) {
|
||||
@ -733,7 +736,7 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithUnthreadedMaterialization) {
|
||||
|
||||
cantFail(JD.define(MU));
|
||||
|
||||
auto FooLookupResult = cantFail(ES.lookup({&JD}, Foo));
|
||||
auto FooLookupResult = cantFail(ES.lookup({{&JD, false}}, Foo));
|
||||
|
||||
EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
|
||||
<< "lookup returned an incorrect address";
|
||||
@ -754,7 +757,7 @@ TEST_F(CoreAPIsStandardTest, TestLookupWithThreadedMaterialization) {
|
||||
|
||||
cantFail(JD.define(absoluteSymbols({{Foo, FooSym}})));
|
||||
|
||||
auto FooLookupResult = cantFail(ES.lookup({&JD}, Foo));
|
||||
auto FooLookupResult = cantFail(ES.lookup({{&JD, false}}, Foo));
|
||||
|
||||
EXPECT_EQ(FooLookupResult.getAddress(), FooSym.getAddress())
|
||||
<< "lookup returned an incorrect address";
|
||||
@ -802,14 +805,14 @@ TEST_F(CoreAPIsStandardTest, TestGetRequestedSymbolsAndReplace) {
|
||||
EXPECT_FALSE(FooMaterialized) << "Foo should not be materialized yet";
|
||||
EXPECT_FALSE(BarMaterialized) << "Bar should not be materialized yet";
|
||||
|
||||
auto FooSymResult = cantFail(ES.lookup({&JD}, Foo));
|
||||
auto FooSymResult = cantFail(ES.lookup({{&JD, false}}, Foo));
|
||||
EXPECT_EQ(FooSymResult.getAddress(), FooSym.getAddress())
|
||||
<< "Address mismatch for Foo";
|
||||
|
||||
EXPECT_TRUE(FooMaterialized) << "Foo should be materialized now";
|
||||
EXPECT_FALSE(BarMaterialized) << "Bar still should not be materialized";
|
||||
|
||||
auto BarSymResult = cantFail(ES.lookup({&JD}, Bar));
|
||||
auto BarSymResult = cantFail(ES.lookup({{&JD, false}}, Bar));
|
||||
EXPECT_EQ(BarSymResult.getAddress(), BarSym.getAddress())
|
||||
<< "Address mismatch for Bar";
|
||||
EXPECT_TRUE(BarMaterialized) << "Bar should be materialized now";
|
||||
@ -829,7 +832,7 @@ TEST_F(CoreAPIsStandardTest, TestMaterializationResponsibilityDelegation) {
|
||||
|
||||
cantFail(JD.define(MU));
|
||||
|
||||
auto Result = ES.lookup({&JD}, {Foo, Bar});
|
||||
auto Result = ES.lookup({{&JD, false}}, {Foo, Bar});
|
||||
|
||||
EXPECT_TRUE(!!Result) << "Result should be a success value";
|
||||
EXPECT_EQ(Result->count(Foo), 1U) << "\"Foo\" entry missing";
|
||||
@ -861,7 +864,7 @@ TEST_F(CoreAPIsStandardTest, TestMaterializeWeakSymbol) {
|
||||
|
||||
auto OnReady = [](Error Err) { cantFail(std::move(Err)); };
|
||||
|
||||
ES.lookup({&JD}, {Foo}, std::move(OnResolution), std::move(OnReady),
|
||||
ES.lookup({{&JD, false}}, {Foo}, std::move(OnResolution), std::move(OnReady),
|
||||
NoDependenciesToRegister);
|
||||
|
||||
auto MU2 = llvm::make_unique<SimpleMaterializationUnit>(
|
||||
|
@ -66,7 +66,7 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
|
||||
|
||||
ObjLayer.setProcessAllSections(ProcessAllSections);
|
||||
cantFail(ObjLayer.add(JD, std::move(Obj), ES.allocateVModule()));
|
||||
ES.lookup({&JD}, {Foo}, OnResolveDoNothing, OnReadyDoNothing,
|
||||
ES.lookup({{&JD, false}}, {Foo}, OnResolveDoNothing, OnReadyDoNothing,
|
||||
NoDependenciesToRegister);
|
||||
return DebugSectionSeen;
|
||||
}
|
||||
@ -157,7 +157,8 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
|
||||
ObjLayer.setOverrideObjectFlagsWithResponsibilityFlags(true);
|
||||
|
||||
cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
|
||||
ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
|
||||
ES.lookup({{&JD, false}}, {Foo},
|
||||
[](Expected<SymbolMap> R) { cantFail(std::move(R)); },
|
||||
[](Error Err) { cantFail(std::move(Err)); },
|
||||
NoDependenciesToRegister);
|
||||
}
|
||||
@ -219,7 +220,8 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
|
||||
ObjLayer.setAutoClaimResponsibilityForObjectSymbols(true);
|
||||
|
||||
cantFail(CompileLayer.add(JD, std::move(M), ES.allocateVModule()));
|
||||
ES.lookup({&JD}, {Foo}, [](Expected<SymbolMap> R) { cantFail(std::move(R)); },
|
||||
ES.lookup({{&JD, false}}, {Foo},
|
||||
[](Expected<SymbolMap> R) { cantFail(std::move(R)); },
|
||||
[](Error Err) { cantFail(std::move(Err)); },
|
||||
NoDependenciesToRegister);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user