mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
[ORC] Introduce JITSymbolFlags::HasMaterializeSideEffectsOnly flag.
This flag can be used to mark a symbol as existing only for the purpose of enabling materialization. Such a symbol can be looked up to trigger materialization with the lookup returning only once materialization is complete. Symbols with this flag will never resolve however (to avoid permanently polluting the symbol table), and should only be looked up using the SymbolLookupFlags::WeaklyReferencedSymbol flag. The primary use case for this flag is initialization symbols.
This commit is contained in:
parent
c31e638b4f
commit
c9245d5323
@ -84,7 +84,9 @@ public:
|
||||
Absolute = 1U << 3,
|
||||
Exported = 1U << 4,
|
||||
Callable = 1U << 5,
|
||||
LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ Callable)
|
||||
MaterializationSideEffectsOnly = 1U << 6,
|
||||
LLVM_MARK_AS_BITMASK_ENUM( // LargestValue =
|
||||
MaterializationSideEffectsOnly)
|
||||
};
|
||||
|
||||
/// Default-construct a JITSymbolFlags instance.
|
||||
@ -146,6 +148,21 @@ public:
|
||||
/// Returns true if the given symbol is known to be callable.
|
||||
bool isCallable() const { return (Flags & Callable) == Callable; }
|
||||
|
||||
/// Returns true if this symbol is a materialization-side-effects-only
|
||||
/// symbol. Such symbols do not have a real address. They exist to trigger
|
||||
/// and support synchronization of materialization side effects, e.g. for
|
||||
/// collecting initialization information. These symbols will vanish from
|
||||
/// the symbol table immediately upon reaching the ready state, and will
|
||||
/// appear to queries as if they were never defined (except that query
|
||||
/// callback execution will be delayed until they reach the ready state).
|
||||
/// MaterializationSideEffectOnly symbols should only be queried using the
|
||||
/// SymbolLookupFlags::WeaklyReferencedSymbol flag (see
|
||||
/// llvm/include/llvm/ExecutionEngine/Orc/Core.h).
|
||||
bool hasMaterializationSideEffectsOnly() const {
|
||||
return (Flags & MaterializationSideEffectsOnly) ==
|
||||
MaterializationSideEffectsOnly;
|
||||
}
|
||||
|
||||
/// Get the underlying flags value as an integer.
|
||||
UnderlyingType getRawFlagsValue() const {
|
||||
return static_cast<UnderlyingType>(Flags);
|
||||
|
@ -483,6 +483,20 @@ public:
|
||||
/// callbacks, metadata).
|
||||
Error defineMaterializing(SymbolFlagsMap SymbolFlags);
|
||||
|
||||
/// Define the given symbols as non-existent, removing it from the symbol
|
||||
/// table and notifying any pending queries. Queries that lookup up the
|
||||
/// symbol using the SymbolLookupFlags::WeaklyReferencedSymbol flag will
|
||||
/// behave as if the symbol had not been matched in the first place. Queries
|
||||
/// that required this symbol will fail with a missing symbol definition
|
||||
/// error.
|
||||
///
|
||||
/// This method is intended to support cleanup of special symbols like
|
||||
/// initializer symbols: Queries using
|
||||
/// SymbolLookupFlags::WeaklyReferencedSymbol can be used to trigger their
|
||||
/// emission, and this method can be used to remove them from the JITDylib
|
||||
/// once materialization is complete.
|
||||
void defineNonExistent(ArrayRef<SymbolStringPtr> Symbols);
|
||||
|
||||
/// Notify all not-yet-emitted covered by this MaterializationResponsibility
|
||||
/// instance that an error has occurred.
|
||||
/// This will remove all symbols covered by this MaterializationResponsibilty
|
||||
@ -721,15 +735,6 @@ public:
|
||||
void notifySymbolMetRequiredState(const SymbolStringPtr &Name,
|
||||
JITEvaluatedSymbol Sym);
|
||||
|
||||
/// Remove a symbol from the query. This is used to drop weakly referenced
|
||||
/// symbols that are not found.
|
||||
void dropSymbol(const SymbolStringPtr &Name) {
|
||||
assert(ResolvedSymbols.count(Name) &&
|
||||
"Redundant removal of weakly-referenced symbol");
|
||||
ResolvedSymbols.erase(Name);
|
||||
--OutstandingSymbolsCount;
|
||||
}
|
||||
|
||||
/// Returns true if all symbols covered by this query have been
|
||||
/// resolved.
|
||||
bool isComplete() const { return OutstandingSymbolsCount == 0; }
|
||||
@ -747,6 +752,8 @@ private:
|
||||
|
||||
void removeQueryDependence(JITDylib &JD, const SymbolStringPtr &Name);
|
||||
|
||||
void dropSymbol(const SymbolStringPtr &Name);
|
||||
|
||||
bool canStillFail();
|
||||
|
||||
void handleFailed(Error Err);
|
||||
@ -1298,6 +1305,16 @@ auto JITDylib::withSearchOrderDo(Func &&F)
|
||||
template <typename MaterializationUnitType>
|
||||
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &&MU) {
|
||||
assert(MU && "Can not define with a null MU");
|
||||
|
||||
if (MU->getSymbols().empty()) {
|
||||
// Empty MUs are allowable but pathological, so issue a warning.
|
||||
DEBUG_WITH_TYPE("orc", {
|
||||
dbgs() << "Warning: Discarding empty MU " << MU->getName() << "\n";
|
||||
});
|
||||
return Error::success();
|
||||
} else
|
||||
DEBUG_WITH_TYPE("orc", dbgs() << "Defining MU " << MU->getName() << ":\n");
|
||||
|
||||
return ES.runSessionLocked([&, this]() -> Error {
|
||||
if (auto Err = defineImpl(*MU))
|
||||
return Err;
|
||||
@ -1320,6 +1337,15 @@ template <typename MaterializationUnitType>
|
||||
Error JITDylib::define(std::unique_ptr<MaterializationUnitType> &MU) {
|
||||
assert(MU && "Can not define with a null MU");
|
||||
|
||||
if (MU->getSymbols().empty()) {
|
||||
// Empty MUs are allowable but pathological, so issue a warning.
|
||||
DEBUG_WITH_TYPE("orc", {
|
||||
dbgs() << "Warning: Discarding empty MU " << MU->getName() << "\n";
|
||||
});
|
||||
return Error::success();
|
||||
} else
|
||||
DEBUG_WITH_TYPE("orc", dbgs() << "Defining MU " << MU->getName() << ":\n");
|
||||
|
||||
return ES.runSessionLocked([&, this]() -> Error {
|
||||
if (auto Err = defineImpl(*MU))
|
||||
return Err;
|
||||
|
@ -38,6 +38,9 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolNameSet &Symbols);
|
||||
/// Render a SymbolNameVector.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols);
|
||||
|
||||
/// Render an array of SymbolStringPtrs.
|
||||
raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols);
|
||||
|
||||
/// Render JITSymbolFlags.
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags);
|
||||
|
||||
|
@ -118,7 +118,13 @@ void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
|
||||
assert(I != ResolvedSymbols.end() &&
|
||||
"Resolving symbol outside the requested set");
|
||||
assert(I->second.getAddress() == 0 && "Redundantly resolving symbol Name");
|
||||
I->second = std::move(Sym);
|
||||
|
||||
// If this is a materialization-side-effects-only symbol then drop it,
|
||||
// otherwise update its map entry with its resolved address.
|
||||
if (Sym.getFlags().hasMaterializationSideEffectsOnly())
|
||||
ResolvedSymbols.erase(I);
|
||||
else
|
||||
I->second = std::move(Sym);
|
||||
--OutstandingSymbolsCount;
|
||||
}
|
||||
|
||||
@ -159,6 +165,14 @@ void AsynchronousSymbolQuery::removeQueryDependence(
|
||||
QueryRegistrations.erase(QRI);
|
||||
}
|
||||
|
||||
void AsynchronousSymbolQuery::dropSymbol(const SymbolStringPtr &Name) {
|
||||
auto I = ResolvedSymbols.find(Name);
|
||||
assert(I != ResolvedSymbols.end() &&
|
||||
"Redundant removal of weakly-referenced symbol");
|
||||
ResolvedSymbols.erase(I);
|
||||
--OutstandingSymbolsCount;
|
||||
}
|
||||
|
||||
void AsynchronousSymbolQuery::detach() {
|
||||
ResolvedSymbols.clear();
|
||||
OutstandingSymbolsCount = 0;
|
||||
@ -186,6 +200,8 @@ Error MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
|
||||
auto I = SymbolFlags.find(KV.first);
|
||||
assert(I != SymbolFlags.end() &&
|
||||
"Resolving symbol outside this responsibility set");
|
||||
assert(!I->second.hasMaterializationSideEffectsOnly() &&
|
||||
"Can't resolve materialization-side-effects-only symbol");
|
||||
assert((KV.second.getFlags() & ~WeakFlags) == (I->second & ~WeakFlags) &&
|
||||
"Resolving symbol with incorrect flags");
|
||||
}
|
||||
@ -398,11 +414,13 @@ void ReExportsMaterializationUnit::materialize(
|
||||
SymbolAliasMap Aliases;
|
||||
};
|
||||
|
||||
// Build a list of queries to issue. In each round we build the largest set of
|
||||
// aliases that we can resolve without encountering a chain definition of the
|
||||
// form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
|
||||
// be waitin on a symbol that it itself had to resolve. Usually this will just
|
||||
// involve one round and a single query.
|
||||
// Build a list of queries to issue. In each round we build a query for the
|
||||
// largest set of aliases that we can resolve without encountering a chain of
|
||||
// aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
|
||||
// query would be waiting on a symbol that it itself had to resolve. Creating
|
||||
// a new query for each link in such a chain eliminates the possibility of
|
||||
// deadlock. In practice chains are likely to be rare, and this algorithm will
|
||||
// usually result in a single query to issue.
|
||||
|
||||
std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
|
||||
QueryInfos;
|
||||
@ -419,7 +437,10 @@ void ReExportsMaterializationUnit::materialize(
|
||||
continue;
|
||||
|
||||
ResponsibilitySymbols.insert(KV.first);
|
||||
QuerySymbols.add(KV.second.Aliasee);
|
||||
QuerySymbols.add(KV.second.Aliasee,
|
||||
KV.second.AliasFlags.hasMaterializationSideEffectsOnly()
|
||||
? SymbolLookupFlags::WeaklyReferencedSymbol
|
||||
: SymbolLookupFlags::RequiredSymbol);
|
||||
QueryAliases[KV.first] = std::move(KV.second);
|
||||
}
|
||||
|
||||
@ -468,8 +489,13 @@ void ReExportsMaterializationUnit::materialize(
|
||||
if (Result) {
|
||||
SymbolMap ResolutionMap;
|
||||
for (auto &KV : QueryInfo->Aliases) {
|
||||
assert(Result->count(KV.second.Aliasee) &&
|
||||
assert((KV.second.AliasFlags.hasMaterializationSideEffectsOnly() ||
|
||||
Result->count(KV.second.Aliasee)) &&
|
||||
"Result map missing entry?");
|
||||
// Don't try to resolve materialization-side-effects-only symbols.
|
||||
if (KV.second.AliasFlags.hasMaterializationSideEffectsOnly())
|
||||
continue;
|
||||
|
||||
ResolutionMap[KV.first] = JITEvaluatedSymbol(
|
||||
(*Result)[KV.second.Aliasee].getAddress(), KV.second.AliasFlags);
|
||||
}
|
||||
@ -906,7 +932,9 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
|
||||
auto &SymEntry = SymI->second;
|
||||
|
||||
// Move symbol to the emitted state.
|
||||
assert(SymEntry.getState() == SymbolState::Resolved &&
|
||||
assert(((SymEntry.getFlags().hasMaterializationSideEffectsOnly() &&
|
||||
SymEntry.getState() == SymbolState::Materializing) ||
|
||||
SymEntry.getState() == SymbolState::Resolved) &&
|
||||
"Emitting from state other than Resolved");
|
||||
SymEntry.setState(SymbolState::Emitted);
|
||||
|
||||
@ -1311,6 +1339,12 @@ Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs,
|
||||
if (SymI == Symbols.end())
|
||||
return false;
|
||||
|
||||
// If we match against a materialization-side-effects only symbol then
|
||||
// make sure it is weakly-referenced. Otherwise bail out with an error.
|
||||
if (SymI->second.getFlags().hasMaterializationSideEffectsOnly() &&
|
||||
SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
|
||||
return make_error<SymbolsNotFound>(SymbolNameVector({Name}));
|
||||
|
||||
// If this is a non exported symbol and we're matching exported symbols
|
||||
// only then skip this symbol without removal.
|
||||
if (!SymI->second.getFlags().isExported() &&
|
||||
@ -1580,6 +1614,9 @@ JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
|
||||
}
|
||||
|
||||
Error JITDylib::defineImpl(MaterializationUnit &MU) {
|
||||
|
||||
LLVM_DEBUG({ dbgs() << " " << MU.getSymbols() << "\n"; });
|
||||
|
||||
SymbolNameSet Duplicates;
|
||||
std::vector<SymbolStringPtr> ExistingDefsOverridden;
|
||||
std::vector<SymbolStringPtr> MUDefsOverridden;
|
||||
@ -1604,14 +1641,26 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) {
|
||||
}
|
||||
|
||||
// If there were any duplicate definitions then bail out.
|
||||
if (!Duplicates.empty())
|
||||
if (!Duplicates.empty()) {
|
||||
LLVM_DEBUG(
|
||||
{ dbgs() << " Error: Duplicate symbols " << Duplicates << "\n"; });
|
||||
return make_error<DuplicateDefinition>(std::string(**Duplicates.begin()));
|
||||
}
|
||||
|
||||
// Discard any overridden defs in this MU.
|
||||
LLVM_DEBUG({
|
||||
if (!MUDefsOverridden.empty())
|
||||
dbgs() << " Defs in this MU overridden: " << MUDefsOverridden << "\n";
|
||||
});
|
||||
for (auto &S : MUDefsOverridden)
|
||||
MU.doDiscard(*this, S);
|
||||
|
||||
// Discard existing overridden defs.
|
||||
LLVM_DEBUG({
|
||||
if (!ExistingDefsOverridden.empty())
|
||||
dbgs() << " Existing defs overridden by this MU: " << MUDefsOverridden
|
||||
<< "\n";
|
||||
});
|
||||
for (auto &S : ExistingDefsOverridden) {
|
||||
|
||||
auto UMII = UnmaterializedInfos.find(S);
|
||||
|
@ -150,6 +150,10 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolNameVector &Symbols) {
|
||||
return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, ArrayRef<SymbolStringPtr> Symbols) {
|
||||
return OS << printSequence(Symbols, '[', ']', PrintAll<SymbolStringPtr>());
|
||||
}
|
||||
|
||||
raw_ostream &operator<<(raw_ostream &OS, const JITSymbolFlags &Flags) {
|
||||
if (Flags.hasError())
|
||||
OS << "[*ERROR*]";
|
||||
|
@ -176,7 +176,7 @@ public:
|
||||
|
||||
Error notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
|
||||
if (auto &InitSym = MU.getInitializerSymbol())
|
||||
InitSymbols[&JD].add(InitSym);
|
||||
InitSymbols[&JD].add(InitSym, SymbolLookupFlags::WeaklyReferencedSymbol);
|
||||
else {
|
||||
// If there's no identified init symbol attached, but there is a symbol
|
||||
// with the GenericIRPlatform::InitFunctionPrefix, then treat that as
|
||||
@ -185,7 +185,8 @@ public:
|
||||
// map (which holds the names of the symbols to execute).
|
||||
for (auto &KV : MU.getSymbols())
|
||||
if ((*KV.first).startswith(*InitFunctionPrefix)) {
|
||||
InitSymbols[&JD].add(KV.first);
|
||||
InitSymbols[&JD].add(KV.first,
|
||||
SymbolLookupFlags::WeaklyReferencedSymbol);
|
||||
InitFunctions[&JD].add(KV.first);
|
||||
}
|
||||
}
|
||||
|
@ -81,11 +81,19 @@ IRMaterializationUnit::IRMaterializationUnit(
|
||||
|
||||
// If we need an init symbol for this module then create one.
|
||||
if (!llvm::empty(getStaticInitGVs(M))) {
|
||||
std::string InitSymbolName;
|
||||
raw_string_ostream(InitSymbolName)
|
||||
<< "$." << M.getModuleIdentifier() << ".__inits";
|
||||
InitSymbol = ES.intern(InitSymbolName);
|
||||
SymbolFlags[InitSymbol] = JITSymbolFlags();
|
||||
size_t Counter = 0;
|
||||
|
||||
while (true) {
|
||||
std::string InitSymbolName;
|
||||
raw_string_ostream(InitSymbolName)
|
||||
<< "$." << M.getModuleIdentifier() << ".__inits." << Counter++;
|
||||
InitSymbol = ES.intern(InitSymbolName);
|
||||
if (SymbolFlags.count(InitSymbol))
|
||||
continue;
|
||||
SymbolFlags[InitSymbol] =
|
||||
JITSymbolFlags::MaterializationSideEffectsOnly;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -164,7 +164,8 @@ Error MachOPlatform::notifyAdding(JITDylib &JD, const MaterializationUnit &MU) {
|
||||
if (!InitSym)
|
||||
return Error::success();
|
||||
|
||||
RegisteredInitSymbols[&JD].add(InitSym);
|
||||
RegisteredInitSymbols[&JD].add(InitSym,
|
||||
SymbolLookupFlags::WeaklyReferencedSymbol);
|
||||
LLVM_DEBUG({
|
||||
dbgs() << "MachOPlatform: Registered init symbol " << *InitSym << " for MU "
|
||||
<< MU.getName() << "\n";
|
||||
|
@ -130,11 +130,19 @@ getObjectSymbolInfo(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
|
||||
for (auto &Sec : MachOObj.sections()) {
|
||||
auto SecType = MachOObj.getSectionType(Sec);
|
||||
if ((SecType & MachO::SECTION_TYPE) == MachO::S_MOD_INIT_FUNC_POINTERS) {
|
||||
std::string InitSymString;
|
||||
raw_string_ostream(InitSymString)
|
||||
<< "$." << ObjBuffer.getBufferIdentifier() << ".__inits";
|
||||
InitSymbol = ES.intern(InitSymString);
|
||||
SymbolFlags[InitSymbol] = JITSymbolFlags();
|
||||
size_t Counter = 0;
|
||||
while (true) {
|
||||
std::string InitSymString;
|
||||
raw_string_ostream(InitSymString)
|
||||
<< "$." << ObjBuffer.getBufferIdentifier() << ".__inits."
|
||||
<< Counter++;
|
||||
InitSymbol = ES.intern(InitSymString);
|
||||
if (SymbolFlags.count(InitSymbol))
|
||||
continue;
|
||||
SymbolFlags[InitSymbol] =
|
||||
JITSymbolFlags::MaterializationSideEffectsOnly;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -145,34 +145,50 @@ public:
|
||||
if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
|
||||
return notifyFailed(std::move(Err));
|
||||
|
||||
if (const auto &InitSym = MR.getInitializerSymbol())
|
||||
InternedResult[InitSym] = JITEvaluatedSymbol();
|
||||
|
||||
{
|
||||
|
||||
// Check that InternedResult matches up with MR.getSymbols().
|
||||
// This guards against faulty transformations / compilers / object caches.
|
||||
|
||||
if (InternedResult.size() > MR.getSymbols().size()) {
|
||||
SymbolNameVector ExtraSymbols;
|
||||
for (auto &KV : InternedResult)
|
||||
if (!MR.getSymbols().count(KV.first))
|
||||
// First check that there aren't any missing symbols.
|
||||
size_t NumMaterializationSideEffectsOnlySymbols = 0;
|
||||
SymbolNameVector ExtraSymbols;
|
||||
SymbolNameVector MissingSymbols;
|
||||
for (auto &KV : MR.getSymbols()) {
|
||||
|
||||
// If this is a materialization-side-effects only symbol then bump
|
||||
// the counter and make sure it's *not* defined, otherwise make
|
||||
// sure that it is defined.
|
||||
if (KV.second.hasMaterializationSideEffectsOnly()) {
|
||||
++NumMaterializationSideEffectsOnlySymbols;
|
||||
if (InternedResult.count(KV.first))
|
||||
ExtraSymbols.push_back(KV.first);
|
||||
ES.reportError(
|
||||
make_error<UnexpectedSymbolDefinitions>(G.getName(),
|
||||
std::move(ExtraSymbols)));
|
||||
continue;
|
||||
} else if (!InternedResult.count(KV.first))
|
||||
MissingSymbols.push_back(KV.first);
|
||||
}
|
||||
|
||||
// If there were missing symbols then report the error.
|
||||
if (!MissingSymbols.empty()) {
|
||||
ES.reportError(make_error<MissingSymbolDefinitions>(
|
||||
G.getName(), std::move(MissingSymbols)));
|
||||
MR.failMaterialization();
|
||||
return;
|
||||
}
|
||||
|
||||
SymbolNameVector MissingSymbols;
|
||||
for (auto &KV : MR.getSymbols())
|
||||
if (!InternedResult.count(KV.first))
|
||||
MissingSymbols.push_back(KV.first);
|
||||
// If there are more definitions than expected, add them to the
|
||||
// ExtraSymbols vector.
|
||||
if (InternedResult.size() >
|
||||
MR.getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
|
||||
for (auto &KV : InternedResult)
|
||||
if (!MR.getSymbols().count(KV.first))
|
||||
ExtraSymbols.push_back(KV.first);
|
||||
}
|
||||
|
||||
if (!MissingSymbols.empty()) {
|
||||
ES.reportError(
|
||||
make_error<MissingSymbolDefinitions>(G.getName(),
|
||||
std::move(MissingSymbols)));
|
||||
// If there were extra definitions then report the error.
|
||||
if (!ExtraSymbols.empty()) {
|
||||
ES.reportError(make_error<UnexpectedSymbolDefinitions>(
|
||||
G.getName(), std::move(ExtraSymbols)));
|
||||
MR.failMaterialization();
|
||||
return;
|
||||
}
|
||||
|
@ -258,9 +258,6 @@ Error RTDyldObjectLinkingLayer::onObjLoad(
|
||||
Symbols.erase(KV.first);
|
||||
}
|
||||
|
||||
if (const auto &InitSym = R.getInitializerSymbol())
|
||||
Symbols[InitSym] = JITEvaluatedSymbol();
|
||||
|
||||
if (auto Err = R.notifyResolved(Symbols)) {
|
||||
R.failMaterialization();
|
||||
return Err;
|
||||
|
@ -110,6 +110,43 @@ TEST_F(CoreAPIsStandardTest, ResolveUnrequestedSymbol) {
|
||||
EXPECT_TRUE(Result.count(Foo)) << "Expected result for \"Foo\"";
|
||||
}
|
||||
|
||||
TEST_F(CoreAPIsStandardTest, MaterializationSideEffctsOnlyTest) {
|
||||
// Test that basic materialization-side-effects-only symbols work as expected:
|
||||
// that they can be emitted without being resolved, that queries for them
|
||||
// don't return until they're emitted, and that they don't appear in query
|
||||
// results.
|
||||
|
||||
Optional<MaterializationResponsibility> FooR;
|
||||
Optional<SymbolMap> Result;
|
||||
|
||||
cantFail(JD.define(std::make_unique<SimpleMaterializationUnit>(
|
||||
SymbolFlagsMap(
|
||||
{{Foo, JITSymbolFlags::Exported |
|
||||
JITSymbolFlags::MaterializationSideEffectsOnly}}),
|
||||
[&](MaterializationResponsibility R) { FooR.emplace(std::move(R)); })));
|
||||
|
||||
ES.lookup(
|
||||
LookupKind::Static, makeJITDylibSearchOrder(&JD),
|
||||
SymbolLookupSet({Foo}, SymbolLookupFlags::WeaklyReferencedSymbol),
|
||||
SymbolState::Ready,
|
||||
[&](Expected<SymbolMap> LookupResult) {
|
||||
if (LookupResult)
|
||||
Result = std::move(*LookupResult);
|
||||
else
|
||||
ADD_FAILURE() << "Unexpected lookup error: "
|
||||
<< toString(LookupResult.takeError());
|
||||
},
|
||||
NoDependenciesToRegister);
|
||||
|
||||
EXPECT_FALSE(Result) << "Lookup returned unexpectedly";
|
||||
EXPECT_TRUE(FooR) << "Lookup failed to trigger materialization";
|
||||
EXPECT_THAT_ERROR(FooR->notifyEmitted(), Succeeded())
|
||||
<< "Emission of materialization-side-effects-only symbol failed";
|
||||
|
||||
EXPECT_TRUE(Result) << "Lookup failed to return";
|
||||
EXPECT_TRUE(Result->empty()) << "Lookup result contained unexpected value";
|
||||
}
|
||||
|
||||
TEST_F(CoreAPIsStandardTest, RemoveSymbolsTest) {
|
||||
// Test that:
|
||||
// (1) Missing symbols generate a SymbolsNotFound error.
|
||||
|
Loading…
x
Reference in New Issue
Block a user