Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@
namespace llvm::orc {

class ObjectLinkingLayer;
class LazyReexportsManager;
class LazyCallThroughManager;
class RedirectableSymbolManager;

class LazyObjectLinkingLayer : public ObjectLayer {
public:
LazyObjectLinkingLayer(ObjectLinkingLayer &BaseLayer,
LazyReexportsManager &LRMgr);
LazyCallThroughManager &LCTMgr,
RedirectableSymbolManager &RSMgr);

llvm::Error add(llvm::orc::ResourceTrackerSP RT,
std::unique_ptr<llvm::MemoryBuffer> O,
Expand All @@ -37,7 +38,8 @@ class LazyObjectLinkingLayer : public ObjectLayer {
class RenamerPlugin;

ObjectLinkingLayer &BaseLayer;
LazyReexportsManager &LRMgr;
LazyCallThroughManager &LCTMgr;
RedirectableSymbolManager &RSMgr;
};

} // namespace llvm::orc
Expand Down
64 changes: 0 additions & 64 deletions llvm/include/llvm/ExecutionEngine/Orc/LazyReexports.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,70 +173,6 @@ lazyReexports(LazyCallThroughManager &LCTManager,
LCTManager, RSManager, SourceJD, std::move(CallableAliases), SrcJDLoc);
}

class LazyReexportsManager {

friend std::unique_ptr<MaterializationUnit>
lazyReexports(LazyReexportsManager &, SymbolAliasMap);

public:
using OnTrampolinesReadyFn = unique_function<void(
Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
using EmitTrampolinesFn =
unique_function<void(ResourceTrackerSP RT, size_t NumTrampolines,
OnTrampolinesReadyFn OnTrampolinesReady)>;

/// Create a LazyReexportsManager that uses the ORC runtime for reentry.
/// This will work both in-process and out-of-process.
static Expected<std::unique_ptr<LazyReexportsManager>>
Create(EmitTrampolinesFn EmitTrampolines, RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD);

LazyReexportsManager(LazyReexportsManager &&) = delete;
LazyReexportsManager &operator=(LazyReexportsManager &&) = delete;

private:
struct CallThroughInfo {
SymbolStringPtr Name;
SymbolStringPtr BodyName;
JITDylibSP JD;
};

class MU;
class Plugin;

using ResolveSendResultFn =
unique_function<void(Expected<ExecutorSymbolDef>)>;

LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
RedirectableSymbolManager &RSMgr, JITDylib &PlatformJD,
Error &Err);

std::unique_ptr<MaterializationUnit>
createLazyReexports(SymbolAliasMap Reexports);

void emitReentryTrampolines(std::unique_ptr<MaterializationResponsibility> MR,
SymbolAliasMap Reexports);
void emitRedirectableSymbols(
std::unique_ptr<MaterializationResponsibility> MR,
SymbolAliasMap Reexports,
Expected<std::vector<ExecutorSymbolDef>> ReentryPoints);
void resolve(ResolveSendResultFn SendResult, ExecutorAddr ReentryStubAddr);

EmitTrampolinesFn EmitTrampolines;
RedirectableSymbolManager &RSMgr;

std::mutex M;
DenseMap<ExecutorAddr, CallThroughInfo> CallThroughs;
};

/// Define lazy-reexports based on the given SymbolAliasMap. Each lazy re-export
/// is a callable symbol that will look up and dispatch to the given aliasee on
/// first call. All subsequent calls will go directly to the aliasee.
inline std::unique_ptr<MaterializationUnit>
lazyReexports(LazyReexportsManager &LRM, SymbolAliasMap Reexports) {
return LRM.createLazyReexports(std::move(Reexports));
}

} // End namespace orc
} // End namespace llvm

Expand Down
5 changes: 0 additions & 5 deletions llvm/include/llvm/ExecutionEngine/Orc/MachOPlatform.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,6 @@ class MachOPlatform : public Platform {
static ArrayRef<std::pair<const char *, const char *>>
standardRuntimeUtilityAliases();

/// Returns a list of aliases required to enable lazy compilation via the
/// ORC runtime.
static ArrayRef<std::pair<const char *, const char *>>
standardLazyCompilationAliases();

private:
using SymbolTableVector = SmallVector<
std::tuple<ExecutorAddr, ExecutorAddr, MachOExecutorSymbolFlags>>;
Expand Down
1 change: 0 additions & 1 deletion llvm/include/llvm/ExecutionEngine/Orc/RedirectionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ namespace orc {
class RedirectionManager {
public:
virtual ~RedirectionManager() = default;

/// Change the redirection destination of given symbols to new destination
/// symbols.
virtual Error redirect(JITDylib &JD, const SymbolMap &NewDests) = 0;
Expand Down
5 changes: 0 additions & 5 deletions llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,6 @@ const char PointerJumpStubContent[12] = {
0x00, 0x02, 0x1f, (char)0xd6u // BR x16
};

const char ReentryTrampolineContent[8] = {
(char)0xfd, 0x7b, (char)0xbf, (char)0xa9, // STP x30, [sp, #-8]
0x00, 0x00, 0x00, (char)0x94 // BL
};

const char *getEdgeKindName(Edge::Kind R) {
switch (R) {
case Pointer64:
Expand Down
1 change: 0 additions & 1 deletion llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ add_llvm_component_library(LLVMOrcJIT
IRTransformLayer.cpp
IRPartitionLayer.cpp
JITTargetMachineBuilder.cpp
JITLinkReentryTrampolines.cpp
LazyObjectLinkingLayer.cpp
LazyReexports.cpp
Layer.cpp
Expand Down
21 changes: 0 additions & 21 deletions llvm/lib/ExecutionEngine/Orc/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -178,27 +178,6 @@ void UnexpectedSymbolDefinitions::log(raw_ostream &OS) const {
<< ": " << Symbols;
}

void SymbolInstance::lookupAsync(LookupAsyncOnCompleteFn OnComplete) const {
JD->getExecutionSession().lookup(
LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},
SymbolLookupSet(Name), SymbolState::Ready,
[OnComplete = std::move(OnComplete)
#ifndef NDEBUG
,
Name = this->Name // Captured for the assert below only.
#endif // NDEBUG
](Expected<SymbolMap> Result) mutable {
if (Result) {
assert(Result->size() == 1 && "Unexpected number of results");
assert(Result->count(Name) &&
"Result does not contain expected symbol");
OnComplete(Result->begin()->second);
} else
OnComplete(Result.takeError());
},
NoDependenciesToRegister);
}

AsynchronousSymbolQuery::AsynchronousSymbolQuery(
const SymbolLookupSet &Symbols, SymbolState RequiredState,
SymbolsResolvedCallback NotifyComplete)
Expand Down
184 changes: 0 additions & 184 deletions llvm/lib/ExecutionEngine/Orc/JITLinkReentryTrampolines.cpp

This file was deleted.

8 changes: 5 additions & 3 deletions llvm/lib/ExecutionEngine/Orc/LazyObjectLinkingLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,10 @@ class LazyObjectLinkingLayer::RenamerPlugin
};

LazyObjectLinkingLayer::LazyObjectLinkingLayer(ObjectLinkingLayer &BaseLayer,
LazyReexportsManager &LRMgr)
LazyCallThroughManager &LCTMgr,
RedirectableSymbolManager &RSMgr)
: ObjectLayer(BaseLayer.getExecutionSession()), BaseLayer(BaseLayer),
LRMgr(LRMgr) {
LCTMgr(LCTMgr), RSMgr(RSMgr) {
BaseLayer.addPlugin(std::make_unique<RenamerPlugin>());
}

Expand All @@ -100,7 +101,8 @@ Error LazyObjectLinkingLayer::add(ResourceTrackerSP RT,
return Err;

auto &JD = RT->getJITDylib();
return JD.define(lazyReexports(LRMgr, std::move(LazySymbols)), std::move(RT));
return JD.define(lazyReexports(LCTMgr, RSMgr, JD, std::move(LazySymbols)),
std::move(RT));
}

void LazyObjectLinkingLayer::emit(
Expand Down
164 changes: 0 additions & 164 deletions llvm/lib/ExecutionEngine/Orc/LazyReexports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

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

#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
#include "llvm/TargetParser/Triple.h"

#define DEBUG_TYPE "orc"
Expand Down Expand Up @@ -231,167 +229,5 @@ LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
return MaterializationUnit::Interface(std::move(SymbolFlags), nullptr);
}

class LazyReexportsManager::MU : public MaterializationUnit {
public:
MU(LazyReexportsManager &LRMgr, SymbolAliasMap Reexports)
: MaterializationUnit(getInterface(Reexports)), LRMgr(LRMgr),
Reexports(std::move(Reexports)) {}

private:
Interface getInterface(const SymbolAliasMap &Reexports) {
SymbolFlagsMap SF;
for (auto &[Alias, AI] : Reexports)
SF[Alias] = AI.AliasFlags;
return {std::move(SF), nullptr};
}

StringRef getName() const override { return "LazyReexportsManager::MU"; }

void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
LRMgr.emitReentryTrampolines(std::move(R), std::move(Reexports));
}

void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
Reexports.erase(Name);
}

LazyReexportsManager &LRMgr;
SymbolAliasMap Reexports;
};

class LazyReexportsManager::Plugin : public ObjectLinkingLayer::Plugin {
public:
void modifyPassConfig(MaterializationResponsibility &MR,
jitlink::LinkGraph &G,
jitlink::PassConfiguration &Config) override {}

Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}

Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
return Error::success();
}

void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
ResourceKey SrcKey) override {}

private:
std::mutex M;
};

Expected<std::unique_ptr<LazyReexportsManager>>
LazyReexportsManager::Create(EmitTrampolinesFn EmitTrampolines,
RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD) {
Error Err = Error::success();
std::unique_ptr<LazyReexportsManager> LRM(new LazyReexportsManager(
std::move(EmitTrampolines), RSMgr, PlatformJD, Err));
if (Err)
return std::move(Err);
return std::move(LRM);
}

LazyReexportsManager::LazyReexportsManager(EmitTrampolinesFn EmitTrampolines,
RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD, Error &Err)
: EmitTrampolines(std::move(EmitTrampolines)), RSMgr(RSMgr) {

using namespace shared;

ErrorAsOutParameter _(&Err);

auto &ES = PlatformJD.getExecutionSession();
ExecutionSession::JITDispatchHandlerAssociationMap WFs;

WFs[ES.intern("__orc_rt_resolve_tag")] =
ES.wrapAsyncWithSPS<SPSExpected<SPSExecutorSymbolDef>(SPSExecutorAddr)>(
this, &LazyReexportsManager::resolve);

Err = ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
}

std::unique_ptr<MaterializationUnit>
LazyReexportsManager::createLazyReexports(SymbolAliasMap Reexports) {
return std::make_unique<MU>(*this, std::move(Reexports));
}

void LazyReexportsManager::emitReentryTrampolines(
std::unique_ptr<MaterializationResponsibility> MR,
SymbolAliasMap Reexports) {
size_t NumTrampolines = Reexports.size();
auto RT = MR->getResourceTracker();
EmitTrampolines(
std::move(RT), NumTrampolines,
[this, MR = std::move(MR), Reexports = std::move(Reexports)](
Expected<std::vector<ExecutorSymbolDef>> ReentryPoints) mutable {
emitRedirectableSymbols(std::move(MR), std::move(Reexports),
std::move(ReentryPoints));
});
}

void LazyReexportsManager::emitRedirectableSymbols(
std::unique_ptr<MaterializationResponsibility> MR, SymbolAliasMap Reexports,
Expected<std::vector<ExecutorSymbolDef>> ReentryPoints) {

if (!ReentryPoints) {
MR->getExecutionSession().reportError(ReentryPoints.takeError());
MR->failMaterialization();
return;
}

assert(Reexports.size() == ReentryPoints->size() &&
"Number of reentry points doesn't match number of reexports");

// Bind entry points to names.
SymbolMap Redirs;
{
std::lock_guard<std::mutex> Lock(M);
size_t I = 0;
for (auto &[Name, AI] : Reexports) {
const auto &ReentryPoint = (*ReentryPoints)[I++];
Redirs[Name] = ReentryPoint;
CallThroughs[ReentryPoint.getAddress()] = {Name, AI.Aliasee,
&MR->getTargetJITDylib()};
}
}

RSMgr.emitRedirectableSymbols(std::move(MR), std::move(Redirs));
}

void LazyReexportsManager::resolve(ResolveSendResultFn SendResult,
ExecutorAddr ReentryStubAddr) {

CallThroughInfo LandingInfo;

{
std::lock_guard<std::mutex> Lock(M);

auto I = CallThroughs.find(ReentryStubAddr);
if (I == CallThroughs.end())
return SendResult(make_error<StringError>(
"Reentry address " + formatv("{0:x}", ReentryStubAddr) +
" not registered",
inconvertibleErrorCode()));
LandingInfo = I->second;
}

SymbolInstance LandingSym(LandingInfo.JD, std::move(LandingInfo.BodyName));
LandingSym.lookupAsync([this, JD = std::move(LandingInfo.JD),
ReentryName = std::move(LandingInfo.Name),
SendResult = std::move(SendResult)](
Expected<ExecutorSymbolDef> Result) mutable {
if (Result) {
// FIXME: Make RedirectionManager operations async, then use the async
// APIs here.
if (auto Err = RSMgr.redirect(*JD, ReentryName, *Result))
SendResult(std::move(Err));
else
SendResult(std::move(Result));
} else
SendResult(std::move(Result));
});
}

} // End namespace orc.
} // End namespace llvm.
12 changes: 0 additions & 12 deletions llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,6 @@ SymbolAliasMap MachOPlatform::standardPlatformAliases(ExecutionSession &ES) {
SymbolAliasMap Aliases;
addAliases(ES, Aliases, requiredCXXAliases());
addAliases(ES, Aliases, standardRuntimeUtilityAliases());
addAliases(ES, Aliases, standardLazyCompilationAliases());
return Aliases;
}

Expand Down Expand Up @@ -437,17 +436,6 @@ MachOPlatform::standardRuntimeUtilityAliases() {
StandardRuntimeUtilityAliases);
}

ArrayRef<std::pair<const char *, const char *>>
MachOPlatform::standardLazyCompilationAliases() {
static const std::pair<const char *, const char *>
StandardLazyCompilationAliases[] = {
{"__orc_rt_reentry", "__orc_rt_sysv_reentry"},
{"__orc_rt_resolve_tag", "___orc_rt_resolve_tag"}};

return ArrayRef<std::pair<const char *, const char *>>(
StandardLazyCompilationAliases);
}

bool MachOPlatform::supportedTarget(const Triple &TT) {
switch (TT.getArch()) {
case Triple::aarch64:
Expand Down
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@
; referenced by main, should be linked (despite being passed with -lazy).
;
; RUN: rm -rf %t && mkdir -p %t
; RUN: %clang -c -o %t/foo.o %S/Inputs/foo-ret-42.ll
; RUN: %clang -c -o %t/x.o %S/Inputs/var-x-42.ll
; RUN: %clang -c -o %t/main.o %s
; RUN: %llvm_jitlink -noexec -show-linked-files %t/main.o -lazy %t/foo.o \
; RUN: llc -filetype=obj -o %t/foo.o %S/Inputs/foo-ret-42.ll
; RUN: llc -filetype=obj -o %t/x.o %S/Inputs/var-x-42.ll
; RUN: llc -filetype=obj -o %t/main.o %s
; RUN: llvm-jitlink -noexec -show-linked-files %t/main.o -lazy %t/foo.o \
; RUN: -lazy %t/x.o | FileCheck %s
;
; UNSUPPORTED: system-windows
; REQUIRES: target={{(arm|aarch)64.*}}
; UNSUPPORTED: system-windows, target={{arm[^6][^4].*}}, target=powerpc64{{.*}}
;
; CHECK: Linking {{.*}}main.o
; CHECK-DAG: Linking <indirect stubs graph #1>
Expand Down
56 changes: 35 additions & 21 deletions llvm/tools/llvm-jitlink/llvm-jitlink.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"
#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
#include "llvm/ExecutionEngine/Orc/MachO.h"
Expand Down Expand Up @@ -950,18 +949,41 @@ class PhonyExternalsGenerator : public DefinitionGenerator {
}
};

static void handleLazyCallFailure() {
dbgs() << "ERROR: failure to materialize lazy call-through target.\n";
exit(1);
}

static void *reenter(void *Ctx, void *TrampolineAddr) {
std::promise<void *> LandingAddressP;
auto LandingAddressF = LandingAddressP.get_future();

auto *EPCIU = static_cast<EPCIndirectionUtils *>(Ctx);
EPCIU->getLazyCallThroughManager().resolveTrampolineLandingAddress(
ExecutorAddr::fromPtr(TrampolineAddr), [&](ExecutorAddr LandingAddress) {
LandingAddressP.set_value(LandingAddress.toPtr<void *>());
});
return LandingAddressF.get();
}

Expected<std::unique_ptr<Session::LazyLinkingSupport>>
createLazyLinkingSupport(ObjectLinkingLayer &OLL, JITDylib &PlatformJD) {
createLazyLinkingSupport(ObjectLinkingLayer &OLL) {
auto EPCIU = EPCIndirectionUtils::Create(OLL.getExecutionSession());
if (!EPCIU)
return EPCIU.takeError();
if (auto Err = (*EPCIU)
->writeResolverBlock(ExecutorAddr::fromPtr(&reenter),
ExecutorAddr::fromPtr(EPCIU->get()))
.takeError())
return Err;
(*EPCIU)->createLazyCallThroughManager(
OLL.getExecutionSession(), ExecutorAddr::fromPtr(handleLazyCallFailure));
auto RSMgr = JITLinkRedirectableSymbolManager::Create(OLL);
if (!RSMgr)
return RSMgr.takeError();

auto LRMgr = createJITLinkLazyReexportsManager(OLL, **RSMgr, PlatformJD);
if (!LRMgr)
return LRMgr.takeError();

return std::make_unique<Session::LazyLinkingSupport>(std::move(*RSMgr),
std::move(*LRMgr), OLL);
return std::make_unique<Session::LazyLinkingSupport>(std::move(*EPCIU),
std::move(*RSMgr), OLL);
}

Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
Expand Down Expand Up @@ -998,8 +1020,7 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
S->Features = std::move(Features);

if (lazyLinkingRequested()) {
if (auto LazyLinking =
createLazyLinkingSupport(S->ObjLayer, *S->PlatformJD))
if (auto LazyLinking = createLazyLinkingSupport(S->ObjLayer))
S->LazyLinking = std::move(*LazyLinking);
else
return LazyLinking.takeError();
Expand Down Expand Up @@ -1621,17 +1642,10 @@ static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {
OutOfProcessExecutor = OOPExecutorPath.str().str();
}

// If lazy linking is requested then check compatibility with other options.
if (lazyLinkingRequested()) {
if (OrcRuntime.empty())
return make_error<StringError>("Lazy linking requries the ORC runtime",
inconvertibleErrorCode());

if (!TestHarnesses.empty())
return make_error<StringError>(
"Lazy linking cannot be used with -harness mode",
inconvertibleErrorCode());
}
if (lazyLinkingRequested() && !TestHarnesses.empty())
return make_error<StringError>(
"Lazy linking cannot be used with -harness mode",
inconvertibleErrorCode());

return Error::success();
}
Expand Down
20 changes: 13 additions & 7 deletions llvm/tools/llvm-jitlink/llvm-jitlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@

#include "llvm/ADT/StringSet.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/LazyObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/RedirectionManager.h"
#include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
Expand All @@ -33,14 +33,20 @@ namespace llvm {
struct Session {

struct LazyLinkingSupport {
LazyLinkingSupport(std::unique_ptr<orc::RedirectableSymbolManager> RSMgr,
std::unique_ptr<orc::LazyReexportsManager> LRMgr,
LazyLinkingSupport(std::unique_ptr<orc::EPCIndirectionUtils> EPCIU,
std::unique_ptr<orc::RedirectableSymbolManager> RSMgr,
orc::ObjectLinkingLayer &ObjLinkingLayer)
: RSMgr(std::move(RSMgr)), LRMgr(std::move(LRMgr)),
LazyObjLinkingLayer(ObjLinkingLayer, *this->LRMgr) {}

: EPCIU(std::move(EPCIU)), RSMgr(std::move(RSMgr)),
LazyObjLinkingLayer(ObjLinkingLayer,
this->EPCIU->getLazyCallThroughManager(),
*this->RSMgr) {}
~LazyLinkingSupport() {
if (auto Err = EPCIU->cleanup())
LazyObjLinkingLayer.getExecutionSession().reportError(std::move(Err));
}

std::unique_ptr<orc::EPCIndirectionUtils> EPCIU;
std::unique_ptr<orc::RedirectableSymbolManager> RSMgr;
std::unique_ptr<orc::LazyReexportsManager> LRMgr;
orc::LazyObjectLinkingLayer LazyObjLinkingLayer;
};

Expand Down