Skip to content

Commit d2fabd7

Browse files
committed
[ORC] Update lazyReexports to support aliases with different symbol names.
A bug in the existing implementation meant that lazyReexports would not work if the aliased name differed from the alias's name, i.e. all lazy reexports had to be of the form (lib1, name) -> (lib2, name). This patch fixes the issue by capturing the alias's name in the NotifyResolved callback. To simplify this capture, and the LazyCallThroughManager code in general, the NotifyResolved callback is updated to use llvm::unique_function rather than a custom class. No test case yet: This can only be tested at runtime, and the only in-tree client (lli) always uses aliases with matching names. I will add a new LLJIT example shortly that will directly test the lazyReexports API and the non-trivial alias use case.
1 parent 63b428e commit d2fabd7

File tree

3 files changed

+20
-63
lines changed

3 files changed

+20
-63
lines changed

llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h

Lines changed: 7 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#ifndef LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
1717
#define LLVM_EXECUTIONENGINE_ORC_LAZYREEXPORTS_H
1818

19+
#include "llvm/ADT/STLExtras.h"
1920
#include "llvm/ExecutionEngine/Orc/Core.h"
2021
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
2122
#include "llvm/ExecutionEngine/Orc/Speculation.h"
@@ -36,50 +37,14 @@ namespace orc {
3637
/// function.
3738
class LazyCallThroughManager {
3839
public:
39-
/// Clients will want to take some action on first resolution, e.g. updating
40-
/// a stub pointer. Instances of this class can be used to implement this.
41-
class NotifyResolvedFunction {
42-
public:
43-
virtual ~NotifyResolvedFunction() {}
44-
45-
/// Called the first time a lazy call through is executed and the target
46-
/// symbol resolved.
47-
virtual Error operator()(JITDylib &SourceJD,
48-
const SymbolStringPtr &SymbolName,
49-
JITTargetAddress ResolvedAddr) = 0;
50-
51-
private:
52-
virtual void anchor();
53-
};
54-
55-
template <typename NotifyResolvedImpl>
56-
class NotifyResolvedFunctionImpl : public NotifyResolvedFunction {
57-
public:
58-
NotifyResolvedFunctionImpl(NotifyResolvedImpl NotifyResolved)
59-
: NotifyResolved(std::move(NotifyResolved)) {}
60-
Error operator()(JITDylib &SourceJD, const SymbolStringPtr &SymbolName,
61-
JITTargetAddress ResolvedAddr) {
62-
return NotifyResolved(SourceJD, SymbolName, ResolvedAddr);
63-
}
64-
65-
private:
66-
NotifyResolvedImpl NotifyResolved;
67-
};
68-
69-
/// Create a shared NotifyResolvedFunction from a given type that is
70-
/// callable with the correct signature.
71-
template <typename NotifyResolvedImpl>
72-
static std::unique_ptr<NotifyResolvedFunction>
73-
createNotifyResolvedFunction(NotifyResolvedImpl NotifyResolved) {
74-
return std::make_unique<NotifyResolvedFunctionImpl<NotifyResolvedImpl>>(
75-
std::move(NotifyResolved));
76-
}
40+
using NotifyResolvedFunction =
41+
unique_function<Error(JITTargetAddress ResolvedAddr)>;
7742

7843
// Return a free call-through trampoline and bind it to look up and call
7944
// through to the given symbol.
80-
Expected<JITTargetAddress> getCallThroughTrampoline(
81-
JITDylib &SourceJD, SymbolStringPtr SymbolName,
82-
std::shared_ptr<NotifyResolvedFunction> NotifyResolved);
45+
Expected<JITTargetAddress>
46+
getCallThroughTrampoline(JITDylib &SourceJD, SymbolStringPtr SymbolName,
47+
NotifyResolvedFunction NotifyResolved);
8348

8449
protected:
8550
LazyCallThroughManager(ExecutionSession &ES,
@@ -96,8 +61,7 @@ class LazyCallThroughManager {
9661
using ReexportsMap =
9762
std::map<JITTargetAddress, std::pair<JITDylib *, SymbolStringPtr>>;
9863

99-
using NotifiersMap =
100-
std::map<JITTargetAddress, std::shared_ptr<NotifyResolvedFunction>>;
64+
using NotifiersMap = std::map<JITTargetAddress, NotifyResolvedFunction>;
10165

10266
std::mutex LCTMMutex;
10367
ExecutionSession &ES;
@@ -173,8 +137,6 @@ class LazyReexportsMaterializationUnit : public MaterializationUnit {
173137
IndirectStubsManager &ISManager;
174138
JITDylib &SourceJD;
175139
SymbolAliasMap CallableAliases;
176-
std::shared_ptr<LazyCallThroughManager::NotifyResolvedFunction>
177-
NotifyResolved;
178140
ImplSymbolMap *AliaseeTable;
179141
};
180142

llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,14 @@
1616
namespace llvm {
1717
namespace orc {
1818

19-
void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
20-
2119
LazyCallThroughManager::LazyCallThroughManager(
2220
ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
2321
std::unique_ptr<TrampolinePool> TP)
2422
: ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
2523

2624
Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
2725
JITDylib &SourceJD, SymbolStringPtr SymbolName,
28-
std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
26+
NotifyResolvedFunction NotifyResolved) {
2927
std::lock_guard<std::mutex> Lock(LCTMMutex);
3028
auto Trampoline = TP->getTrampoline();
3129

@@ -62,18 +60,18 @@ LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
6260

6361
auto ResolvedAddr = LookupResult->getAddress();
6462

65-
std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
63+
NotifyResolvedFunction NotifyResolved;
6664
{
6765
std::lock_guard<std::mutex> Lock(LCTMMutex);
6866
auto I = Notifiers.find(TrampolineAddr);
6967
if (I != Notifiers.end()) {
70-
NotifyResolved = I->second;
68+
NotifyResolved = std::move(I->second);
7169
Notifiers.erase(I);
7270
}
7371
}
7472

7573
if (NotifyResolved) {
76-
if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
74+
if (auto Err = NotifyResolved(ResolvedAddr)) {
7775
ES.reportError(std::move(Err));
7876
return ErrorHandlerAddr;
7977
}
@@ -128,11 +126,6 @@ LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
128126
: MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
129127
LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
130128
CallableAliases(std::move(CallableAliases)),
131-
NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
132-
[&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
133-
JITTargetAddress ResolvedAddr) {
134-
return ISManager.updatePointer(*SymbolName, ResolvedAddr);
135-
})),
136129
AliaseeTable(SrcJDLoc) {}
137130

138131
StringRef LazyReexportsMaterializationUnit::getName() const {
@@ -159,7 +152,11 @@ void LazyReexportsMaterializationUnit::materialize(
159152
for (auto &Alias : RequestedAliases) {
160153

161154
auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
162-
SourceJD, Alias.second.Aliasee, NotifyResolved);
155+
SourceJD, Alias.second.Aliasee,
156+
[&ISManager = this->ISManager,
157+
StubSym = Alias.first](JITTargetAddress ResolvedAddr) -> Error {
158+
return ISManager.updatePointer(*StubSym, ResolvedAddr);
159+
});
163160

164161
if (!CallThroughTrampoline) {
165162
SourceJD.getExecutionSession().reportError(

llvm/unittests/ExecutionEngine/Orc/LazyCallThroughAndReexportsTest.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,10 @@ TEST_F(LazyReexportsTest, BasicLocalCallThroughManagerOperation) {
5151
})));
5252

5353
unsigned NotifyResolvedCount = 0;
54-
auto NotifyResolved = LazyCallThroughManager::createNotifyResolvedFunction(
55-
[&](JITDylib &JD, const SymbolStringPtr &SymbolName,
56-
JITTargetAddress ResolvedAddr) {
57-
++NotifyResolvedCount;
58-
return Error::success();
59-
});
54+
auto NotifyResolved = [&](JITTargetAddress ResolvedAddr) {
55+
++NotifyResolvedCount;
56+
return Error::success();
57+
};
6058

6159
auto CallThroughTrampoline = cantFail((*LCTM)->getCallThroughTrampoline(
6260
JD, DummyTarget, std::move(NotifyResolved)));

0 commit comments

Comments
 (0)