Skip to content

Commit 841796d

Browse files
committed
[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
1 parent 5ac28a0 commit 841796d

File tree

15 files changed

+277
-170
lines changed

15 files changed

+277
-170
lines changed

llvm/include/llvm/ExecutionEngine/JITSymbol.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,18 @@ class SymbolRef;
4040
/// Represents an address in the target process's address space.
4141
using JITTargetAddress = uint64_t;
4242

43+
/// Convert a JITTargetAddress to a pointer.
44+
template <typename T> T jitTargetAddressToPointer(JITTargetAddress Addr) {
45+
static_assert(std::is_pointer<T>::value, "T must be a pointer type");
46+
uintptr_t IntPtr = static_cast<uintptr_t>(Addr);
47+
assert(IntPtr == Addr && "JITTargetAddress value out of range for uintptr_t");
48+
return reinterpret_cast<T>(IntPtr);
49+
}
50+
51+
template <typename T> JITTargetAddress pointerToJITTargetAddress(T *Ptr) {
52+
return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Ptr));
53+
}
54+
4355
/// Flags for symbols in the JIT.
4456
class JITSymbolFlags {
4557
public:

llvm/include/llvm/ExecutionEngine/Orc/Core.h

Lines changed: 53 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,8 @@ using SymbolFlagsMap = DenseMap<SymbolStringPtr, JITSymbolFlags>;
5454
/// symbols to be obtained for logging.
5555
using SymbolDependenceMap = DenseMap<JITDylib *, SymbolNameSet>;
5656

57-
/// A list of JITDylib pointers.
58-
using JITDylibList = std::vector<JITDylib *>;
57+
/// A list of (JITDylib*, bool) pairs.
58+
using JITDylibSearchList = std::vector<std::pair<JITDylib *, bool>>;
5959

6060
/// Render a SymbolStringPtr.
6161
raw_ostream &operator<<(raw_ostream &OS, const SymbolStringPtr &Sym);
@@ -85,8 +85,8 @@ raw_ostream &operator<<(raw_ostream &OS, const SymbolDependenceMap &Deps);
8585
/// Render a MaterializationUnit.
8686
raw_ostream &operator<<(raw_ostream &OS, const MaterializationUnit &MU);
8787

88-
/// Render a JITDylibList.
89-
raw_ostream &operator<<(raw_ostream &OS, const JITDylibList &JDs);
88+
/// Render a JITDylibSearchList.
89+
raw_ostream &operator<<(raw_ostream &OS, const JITDylibSearchList &JDs);
9090

9191
/// Callback to notify client that symbols have been resolved.
9292
using SymbolsResolvedCallback = std::function<void(Expected<SymbolMap>)>;
@@ -351,14 +351,15 @@ using SymbolAliasMap = DenseMap<SymbolStringPtr, SymbolAliasMapEntry>;
351351
class ReExportsMaterializationUnit : public MaterializationUnit {
352352
public:
353353
/// SourceJD is allowed to be nullptr, in which case the source JITDylib is
354-
/// taken to be whatever JITDylib these definitions are materialized in. This
355-
/// is useful for defining aliases within a JITDylib.
354+
/// taken to be whatever JITDylib these definitions are materialized in (and
355+
/// MatchNonExported has no effect). This is useful for defining aliases
356+
/// within a JITDylib.
356357
///
357358
/// Note: Care must be taken that no sets of aliases form a cycle, as such
358359
/// a cycle will result in a deadlock when any symbol in the cycle is
359360
/// resolved.
360-
ReExportsMaterializationUnit(JITDylib *SourceJD, SymbolAliasMap Aliases,
361-
VModuleKey K);
361+
ReExportsMaterializationUnit(JITDylib *SourceJD, bool MatchNonExported,
362+
SymbolAliasMap Aliases, VModuleKey K);
362363

363364
StringRef getName() const override;
364365

@@ -368,6 +369,7 @@ class ReExportsMaterializationUnit : public MaterializationUnit {
368369
static SymbolFlagsMap extractFlags(const SymbolAliasMap &Aliases);
369370

370371
JITDylib *SourceJD = nullptr;
372+
bool MatchNonExported = false;
371373
SymbolAliasMap Aliases;
372374
};
373375

@@ -385,16 +387,19 @@ class ReExportsMaterializationUnit : public MaterializationUnit {
385387
inline std::unique_ptr<ReExportsMaterializationUnit>
386388
symbolAliases(SymbolAliasMap Aliases, VModuleKey K = VModuleKey()) {
387389
return llvm::make_unique<ReExportsMaterializationUnit>(
388-
nullptr, std::move(Aliases), std::move(K));
390+
nullptr, true, std::move(Aliases), std::move(K));
389391
}
390392

391393
/// Create a materialization unit for re-exporting symbols from another JITDylib
392394
/// with alternative names/flags.
395+
/// If MatchNonExported is true then non-exported symbols from SourceJD can be
396+
/// re-exported. If it is false, attempts to re-export a non-exported symbol
397+
/// will result in a "symbol not found" error.
393398
inline std::unique_ptr<ReExportsMaterializationUnit>
394399
reexports(JITDylib &SourceJD, SymbolAliasMap Aliases,
395-
VModuleKey K = VModuleKey()) {
400+
bool MatchNonExported = false, VModuleKey K = VModuleKey()) {
396401
return llvm::make_unique<ReExportsMaterializationUnit>(
397-
&SourceJD, std::move(Aliases), std::move(K));
402+
&SourceJD, MatchNonExported, std::move(Aliases), std::move(K));
398403
}
399404

400405
/// Build a SymbolAliasMap for the common case where you want to re-export
@@ -411,13 +416,14 @@ class ReexportsGenerator {
411416
/// Create a reexports generator. If an Allow predicate is passed, only
412417
/// symbols for which the predicate returns true will be reexported. If no
413418
/// Allow predicate is passed, all symbols will be exported.
414-
ReexportsGenerator(JITDylib &SourceJD,
419+
ReexportsGenerator(JITDylib &SourceJD, bool MatchNonExported = false,
415420
SymbolPredicate Allow = SymbolPredicate());
416421

417422
SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
418423

419424
private:
420425
JITDylib &SourceJD;
426+
bool MatchNonExported = false;
421427
SymbolPredicate Allow;
422428
};
423429

@@ -536,16 +542,18 @@ class JITDylib {
536542
/// as the first in the search order (instead of this dylib) ensures that
537543
/// definitions within this dylib resolve to the lazy-compiling stubs,
538544
/// rather than immediately materializing the definitions in this dylib.
539-
void setSearchOrder(JITDylibList NewSearchOrder,
540-
bool SearchThisJITDylibFirst = true);
545+
void setSearchOrder(JITDylibSearchList NewSearchOrder,
546+
bool SearchThisJITDylibFirst = true,
547+
bool MatchNonExportedInThisDylib = true);
541548

542549
/// Add the given JITDylib to the search order for definitions in this
543550
/// JITDylib.
544-
void addToSearchOrder(JITDylib &JD);
551+
void addToSearchOrder(JITDylib &JD, bool MatcNonExported = false);
545552

546553
/// Replace OldJD with NewJD in the search order if OldJD is present.
547554
/// Otherwise this operation is a no-op.
548-
void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD);
555+
void replaceInSearchOrder(JITDylib &OldJD, JITDylib &NewJD,
556+
bool MatchNonExported = false);
549557

550558
/// Remove the given JITDylib from the search order for this JITDylib if it is
551559
/// present. Otherwise this operation is a no-op.
@@ -554,7 +562,7 @@ class JITDylib {
554562
/// Do something with the search order (run under the session lock).
555563
template <typename Func>
556564
auto withSearchOrderDo(Func &&F)
557-
-> decltype(F(std::declval<const JITDylibList &>()));
565+
-> decltype(F(std::declval<const JITDylibSearchList &>()));
558566

559567
/// Define all symbols provided by the materialization unit to be part of this
560568
/// JITDylib.
@@ -642,12 +650,12 @@ class JITDylib {
642650
const SymbolNameSet &Names);
643651

644652
void lodgeQuery(std::shared_ptr<AsynchronousSymbolQuery> &Q,
645-
SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
646-
bool MatchNonExported, MaterializationUnitList &MUs);
653+
SymbolNameSet &Unresolved, bool MatchNonExported,
654+
MaterializationUnitList &MUs);
647655

648656
void lodgeQueryImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
649-
SymbolNameSet &Unresolved, JITDylib *MatchNonExportedInJD,
650-
bool MatchNonExported, MaterializationUnitList &MUs);
657+
SymbolNameSet &Unresolved, bool MatchNonExported,
658+
MaterializationUnitList &MUs);
651659

652660
LookupImplActionFlags
653661
lookupImpl(std::shared_ptr<AsynchronousSymbolQuery> &Q,
@@ -682,7 +690,7 @@ class JITDylib {
682690
UnmaterializedInfosMap UnmaterializedInfos;
683691
MaterializingInfosMap MaterializingInfos;
684692
GeneratorFunction DefGenerator;
685-
JITDylibList SearchOrder;
693+
JITDylibSearchList SearchOrder;
686694
};
687695

688696
/// An ExecutionSession represents a running JIT program.
@@ -766,6 +774,10 @@ class ExecutionSession {
766774

767775
/// Search the given JITDylib list for the given symbols.
768776
///
777+
/// SearchOrder lists the JITDylibs to search. For each dylib, the associated
778+
/// boolean indicates whether the search should match against non-exported
779+
/// (hidden visibility) symbols in that dylib (true means match against
780+
/// non-exported symbols, false means do not match).
769781
///
770782
/// The OnResolve callback will be called once all requested symbols are
771783
/// resolved, or if an error occurs prior to resolution.
@@ -782,19 +794,9 @@ class ExecutionSession {
782794
/// dependenant symbols for this query (e.g. it is being made by a top level
783795
/// client to get an address to call) then the value NoDependenciesToRegister
784796
/// can be used.
785-
///
786-
/// If the MatchNonExportedInJD pointer is non-null, then the lookup will find
787-
/// non-exported symbols defined in the JITDylib pointed to by
788-
/// MatchNonExportedInJD.
789-
/// If MatchNonExported is true the lookup will find non-exported symbols in
790-
/// any JITDylib (setting MatchNonExportedInJD is redundant in such cases).
791-
/// If MatchNonExported is false and MatchNonExportedInJD is null,
792-
/// non-exported symbols will never be found.
793-
void lookup(const JITDylibList &JDs, SymbolNameSet Symbols,
797+
void lookup(const JITDylibSearchList &SearchOrder, SymbolNameSet Symbols,
794798
SymbolsResolvedCallback OnResolve, SymbolsReadyCallback OnReady,
795-
RegisterDependenciesFunction RegisterDependencies,
796-
JITDylib *MatchNonExportedInJD = nullptr,
797-
bool MatchNonExported = false);
799+
RegisterDependenciesFunction RegisterDependencies);
798800

799801
/// Blocking version of lookup above. Returns the resolved symbol map.
800802
/// If WaitUntilReady is true (the default), will not return until all
@@ -803,24 +805,29 @@ class ExecutionSession {
803805
/// or an error occurs. If WaitUntilReady is false and an error occurs
804806
/// after resolution, the function will return a success value, but the
805807
/// error will be reported via reportErrors.
806-
Expected<SymbolMap> lookup(const JITDylibList &JDs,
808+
Expected<SymbolMap> lookup(const JITDylibSearchList &SearchOrder,
807809
const SymbolNameSet &Symbols,
808810
RegisterDependenciesFunction RegisterDependencies =
809811
NoDependenciesToRegister,
810-
bool WaitUntilReady = true,
811-
JITDylib *MatchNonExportedInJD = nullptr,
812-
bool MatchNonExported = false);
812+
bool WaitUntilReady = true);
813+
814+
/// Convenience version of blocking lookup.
815+
/// Searches each of the JITDylibs in the search order in turn for the given
816+
/// symbol.
817+
Expected<JITEvaluatedSymbol> lookup(const JITDylibSearchList &SearchOrder,
818+
SymbolStringPtr Symbol);
813819

814820
/// Convenience version of blocking lookup.
815-
/// Performs a single-symbol lookup.
816-
Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs,
817-
SymbolStringPtr Symbol,
818-
bool MatchNonExported = false);
821+
/// Searches each of the JITDylibs in the search order in turn for the given
822+
/// symbol. The search will not find non-exported symbols.
823+
Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
824+
SymbolStringPtr Symbol);
819825

820826
/// Convenience version of blocking lookup.
821-
/// Performs a single-symbol lookup, auto-interning the given symbol name.
822-
Expected<JITEvaluatedSymbol> lookup(const JITDylibList &JDs, StringRef Symbol,
823-
bool MatchNonExported = false);
827+
/// Searches each of the JITDylibs in the search order in turn for the given
828+
/// symbol. The search will not find non-exported symbols.
829+
Expected<JITEvaluatedSymbol> lookup(ArrayRef<JITDylib *> SearchOrder,
830+
StringRef Symbol);
824831

825832
/// Materialize the given unit.
826833
void dispatchMaterialization(JITDylib &JD,
@@ -866,7 +873,7 @@ class ExecutionSession {
866873

867874
template <typename Func>
868875
auto JITDylib::withSearchOrderDo(Func &&F)
869-
-> decltype(F(std::declval<const JITDylibList &>())) {
876+
-> decltype(F(std::declval<const JITDylibSearchList &>())) {
870877
return ES.runSessionLocked([&]() { return F(SearchOrder); });
871878
}
872879

llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class LLLazyJIT : public LLJIT {
144144
/// LLLazyJIT with the given number of compile threads.
145145
static Expected<std::unique_ptr<LLLazyJIT>>
146146
Create(JITTargetMachineBuilder JTMB, DataLayout DL,
147-
unsigned NumCompileThreads = 0);
147+
JITTargetAddress ErrorAddr, unsigned NumCompileThreads = 0);
148148

149149
/// Set an IR transform (e.g. pass manager pipeline) to run on each function
150150
/// when it is compiled.

llvm/lib/ExecutionEngine/Orc/CompileOnDemandLayer.cpp

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ void CompileOnDemandLayer::emit(MaterializationResponsibility R,
157157
return;
158158
}
159159

160-
R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables)));
160+
R.replace(reexports(PDR.getImplDylib(), std::move(NonCallables), true));
161161
R.replace(lazyReexports(LCTMgr, PDR.getISManager(), PDR.getImplDylib(),
162162
std::move(Callables)));
163163
}
@@ -166,10 +166,17 @@ CompileOnDemandLayer::PerDylibResources &
166166
CompileOnDemandLayer::getPerDylibResources(JITDylib &TargetD) {
167167
auto I = DylibResources.find(&TargetD);
168168
if (I == DylibResources.end()) {
169-
auto &ImplD =
170-
getExecutionSession().createJITDylib(TargetD.getName() + ".impl");
171-
TargetD.withSearchOrderDo([&](const JITDylibList &TargetSearchOrder) {
172-
ImplD.setSearchOrder(TargetSearchOrder, false);
169+
auto &ImplD = getExecutionSession().createJITDylib(
170+
TargetD.getName() + ".impl", false);
171+
TargetD.withSearchOrderDo([&](const JITDylibSearchList &TargetSearchOrder) {
172+
auto NewSearchOrder = TargetSearchOrder;
173+
assert(!NewSearchOrder.empty() &&
174+
NewSearchOrder.front().first == &TargetD &&
175+
NewSearchOrder.front().second == true &&
176+
"TargetD must be at the front of its own search order and match "
177+
"non-exported symbol");
178+
NewSearchOrder.insert(std::next(NewSearchOrder.begin()), {&ImplD, true});
179+
ImplD.setSearchOrder(std::move(NewSearchOrder), false);
173180
});
174181
PerDylibResources PDR(ImplD, BuildIndirectStubsManager());
175182
I = DylibResources.insert(std::make_pair(&TargetD, std::move(PDR))).first;

0 commit comments

Comments
 (0)