@@ -118,7 +118,13 @@ void AsynchronousSymbolQuery::notifySymbolMetRequiredState(
118
118
assert (I != ResolvedSymbols.end () &&
119
119
" Resolving symbol outside the requested set" );
120
120
assert (I->second .getAddress () == 0 && " Redundantly resolving symbol Name" );
121
- I->second = std::move (Sym);
121
+
122
+ // If this is a materialization-side-effects-only symbol then drop it,
123
+ // otherwise update its map entry with its resolved address.
124
+ if (Sym.getFlags ().hasMaterializationSideEffectsOnly ())
125
+ ResolvedSymbols.erase (I);
126
+ else
127
+ I->second = std::move (Sym);
122
128
--OutstandingSymbolsCount;
123
129
}
124
130
@@ -159,6 +165,14 @@ void AsynchronousSymbolQuery::removeQueryDependence(
159
165
QueryRegistrations.erase (QRI);
160
166
}
161
167
168
+ void AsynchronousSymbolQuery::dropSymbol (const SymbolStringPtr &Name) {
169
+ auto I = ResolvedSymbols.find (Name);
170
+ assert (I != ResolvedSymbols.end () &&
171
+ " Redundant removal of weakly-referenced symbol" );
172
+ ResolvedSymbols.erase (I);
173
+ --OutstandingSymbolsCount;
174
+ }
175
+
162
176
void AsynchronousSymbolQuery::detach () {
163
177
ResolvedSymbols.clear ();
164
178
OutstandingSymbolsCount = 0 ;
@@ -186,6 +200,8 @@ Error MaterializationResponsibility::notifyResolved(const SymbolMap &Symbols) {
186
200
auto I = SymbolFlags.find (KV.first );
187
201
assert (I != SymbolFlags.end () &&
188
202
" Resolving symbol outside this responsibility set" );
203
+ assert (!I->second .hasMaterializationSideEffectsOnly () &&
204
+ " Can't resolve materialization-side-effects-only symbol" );
189
205
assert ((KV.second .getFlags () & ~WeakFlags) == (I->second & ~WeakFlags) &&
190
206
" Resolving symbol with incorrect flags" );
191
207
}
@@ -398,11 +414,13 @@ void ReExportsMaterializationUnit::materialize(
398
414
SymbolAliasMap Aliases;
399
415
};
400
416
401
- // Build a list of queries to issue. In each round we build the largest set of
402
- // aliases that we can resolve without encountering a chain definition of the
403
- // form Foo -> Bar, Bar -> Baz. Such a form would deadlock as the query would
404
- // be waitin on a symbol that it itself had to resolve. Usually this will just
405
- // involve one round and a single query.
417
+ // Build a list of queries to issue. In each round we build a query for the
418
+ // largest set of aliases that we can resolve without encountering a chain of
419
+ // aliases (e.g. Foo -> Bar, Bar -> Baz). Such a chain would deadlock as the
420
+ // query would be waiting on a symbol that it itself had to resolve. Creating
421
+ // a new query for each link in such a chain eliminates the possibility of
422
+ // deadlock. In practice chains are likely to be rare, and this algorithm will
423
+ // usually result in a single query to issue.
406
424
407
425
std::vector<std::pair<SymbolLookupSet, std::shared_ptr<OnResolveInfo>>>
408
426
QueryInfos;
@@ -419,7 +437,10 @@ void ReExportsMaterializationUnit::materialize(
419
437
continue ;
420
438
421
439
ResponsibilitySymbols.insert (KV.first );
422
- QuerySymbols.add (KV.second .Aliasee );
440
+ QuerySymbols.add (KV.second .Aliasee ,
441
+ KV.second .AliasFlags .hasMaterializationSideEffectsOnly ()
442
+ ? SymbolLookupFlags::WeaklyReferencedSymbol
443
+ : SymbolLookupFlags::RequiredSymbol);
423
444
QueryAliases[KV.first ] = std::move (KV.second );
424
445
}
425
446
@@ -468,8 +489,13 @@ void ReExportsMaterializationUnit::materialize(
468
489
if (Result) {
469
490
SymbolMap ResolutionMap;
470
491
for (auto &KV : QueryInfo->Aliases ) {
471
- assert (Result->count (KV.second .Aliasee ) &&
492
+ assert ((KV.second .AliasFlags .hasMaterializationSideEffectsOnly () ||
493
+ Result->count (KV.second .Aliasee )) &&
472
494
" Result map missing entry?" );
495
+ // Don't try to resolve materialization-side-effects-only symbols.
496
+ if (KV.second .AliasFlags .hasMaterializationSideEffectsOnly ())
497
+ continue ;
498
+
473
499
ResolutionMap[KV.first ] = JITEvaluatedSymbol (
474
500
(*Result)[KV.second .Aliasee ].getAddress (), KV.second .AliasFlags );
475
501
}
@@ -906,7 +932,9 @@ Error JITDylib::emit(const SymbolFlagsMap &Emitted) {
906
932
auto &SymEntry = SymI->second ;
907
933
908
934
// Move symbol to the emitted state.
909
- assert (SymEntry.getState () == SymbolState::Resolved &&
935
+ assert (((SymEntry.getFlags ().hasMaterializationSideEffectsOnly () &&
936
+ SymEntry.getState () == SymbolState::Materializing) ||
937
+ SymEntry.getState () == SymbolState::Resolved) &&
910
938
" Emitting from state other than Resolved" );
911
939
SymEntry.setState (SymbolState::Emitted);
912
940
@@ -1311,6 +1339,12 @@ Error JITDylib::lodgeQueryImpl(MaterializationUnitList &MUs,
1311
1339
if (SymI == Symbols.end ())
1312
1340
return false ;
1313
1341
1342
+ // If we match against a materialization-side-effects only symbol then
1343
+ // make sure it is weakly-referenced. Otherwise bail out with an error.
1344
+ if (SymI->second .getFlags ().hasMaterializationSideEffectsOnly () &&
1345
+ SymLookupFlags != SymbolLookupFlags::WeaklyReferencedSymbol)
1346
+ return make_error<SymbolsNotFound>(SymbolNameVector ({Name}));
1347
+
1314
1348
// If this is a non exported symbol and we're matching exported symbols
1315
1349
// only then skip this symbol without removal.
1316
1350
if (!SymI->second .getFlags ().isExported () &&
@@ -1580,6 +1614,9 @@ JITDylib::JITDylib(ExecutionSession &ES, std::string Name)
1580
1614
}
1581
1615
1582
1616
Error JITDylib::defineImpl (MaterializationUnit &MU) {
1617
+
1618
+ LLVM_DEBUG ({ dbgs () << " " << MU.getSymbols () << " \n " ; });
1619
+
1583
1620
SymbolNameSet Duplicates;
1584
1621
std::vector<SymbolStringPtr> ExistingDefsOverridden;
1585
1622
std::vector<SymbolStringPtr> MUDefsOverridden;
@@ -1604,14 +1641,26 @@ Error JITDylib::defineImpl(MaterializationUnit &MU) {
1604
1641
}
1605
1642
1606
1643
// If there were any duplicate definitions then bail out.
1607
- if (!Duplicates.empty ())
1644
+ if (!Duplicates.empty ()) {
1645
+ LLVM_DEBUG (
1646
+ { dbgs () << " Error: Duplicate symbols " << Duplicates << " \n " ; });
1608
1647
return make_error<DuplicateDefinition>(std::string (**Duplicates.begin ()));
1648
+ }
1609
1649
1610
1650
// Discard any overridden defs in this MU.
1651
+ LLVM_DEBUG ({
1652
+ if (!MUDefsOverridden.empty ())
1653
+ dbgs () << " Defs in this MU overridden: " << MUDefsOverridden << " \n " ;
1654
+ });
1611
1655
for (auto &S : MUDefsOverridden)
1612
1656
MU.doDiscard (*this , S);
1613
1657
1614
1658
// Discard existing overridden defs.
1659
+ LLVM_DEBUG ({
1660
+ if (!ExistingDefsOverridden.empty ())
1661
+ dbgs () << " Existing defs overridden by this MU: " << MUDefsOverridden
1662
+ << " \n " ;
1663
+ });
1615
1664
for (auto &S : ExistingDefsOverridden) {
1616
1665
1617
1666
auto UMII = UnmaterializedInfos.find (S);
0 commit comments