Revert "Reapply "[ORC] Introduce LazyReexportsManager, … (#118923)" with fixes"

This reverts commit 41652c6c92 while I investigate
more bot failures.
This commit is contained in:
Lang Hames
2024-12-09 12:38:59 +11:00
parent f145ff3f70
commit 74e8a37ff3
28 changed files with 79 additions and 834 deletions

View File

@@ -3,11 +3,10 @@
# ORC runtime library common implementation files.
set(ORC_COMMON_SOURCES
debug.cpp
dlfcn_wrapper.cpp
extensible_rtti.cpp
log_error_to_stderr.cpp
run_program_wrapper.cpp
resolve.cpp
dlfcn_wrapper.cpp
)
# Common implementation headers will go here.
@@ -52,7 +51,6 @@ if (APPLE)
set(ORC_ASM_SOURCES
macho_tlv.x86-64.S
macho_tlv.arm64.S
sysv_reentry.arm64.S
)
set(ORC_IMPL_HEADERS
@@ -118,7 +116,6 @@ else() # not Apple
elfnix_tls.x86-64.S
elfnix_tls.aarch64.S
elfnix_tls.ppc64.S
sysv_reentry.arm64.S
)
endif()

View File

@@ -1,102 +0,0 @@
//===-- sysv_reentry.arm64.s ------------------------------------*- ASM -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file is a part of the ORC runtime support library.
//
//===----------------------------------------------------------------------===//
// The content of this file is arm64-only
#if defined(__arm64__) || defined(__aarch64__)
.text
// Saves GPRs, calls __orc_rt_sysv_resolve
.globl __orc_rt_sysv_reentry
__orc_rt_sysv_reentry:
// Save register state, set up new stack frome.
stp x27, x28, [sp, #-16]!
stp x25, x26, [sp, #-16]!
stp x23, x24, [sp, #-16]!
stp x21, x22, [sp, #-16]!
stp x19, x20, [sp, #-16]!
stp x14, x15, [sp, #-16]!
stp x12, x13, [sp, #-16]!
stp x10, x11, [sp, #-16]!
stp x8, x9, [sp, #-16]!
stp x6, x7, [sp, #-16]!
stp x4, x5, [sp, #-16]!
stp x2, x3, [sp, #-16]!
stp x0, x1, [sp, #-16]!
stp q30, q31, [sp, #-32]!
stp q28, q29, [sp, #-32]!
stp q26, q27, [sp, #-32]!
stp q24, q25, [sp, #-32]!
stp q22, q23, [sp, #-32]!
stp q20, q21, [sp, #-32]!
stp q18, q19, [sp, #-32]!
stp q16, q17, [sp, #-32]!
stp q14, q15, [sp, #-32]!
stp q12, q13, [sp, #-32]!
stp q10, q11, [sp, #-32]!
stp q8, q9, [sp, #-32]!
stp q6, q7, [sp, #-32]!
stp q4, q5, [sp, #-32]!
stp q2, q3, [sp, #-32]!
stp q0, q1, [sp, #-32]!
// Look up the return address and subtract 8 from it (on the
// assumption that it's a standard arm64 reentry trampoline) to get
// back the trampoline's address.
sub x0, x30, #8
// Call __orc_rt_sysv_resolve to look up the implementation
// corresponding to the calling stub, then store this in x17 (which
// we'll return to below.
#if !defined(__APPLE__)
bl __orc_rt_resolve
#else
bl ___orc_rt_resolve
#endif
mov x17, x0
// Restore the register state.
ldp q0, q1, [sp], #32
ldp q2, q3, [sp], #32
ldp q4, q5, [sp], #32
ldp q6, q7, [sp], #32
ldp q8, q9, [sp], #32
ldp q10, q11, [sp], #32
ldp q12, q13, [sp], #32
ldp q14, q15, [sp], #32
ldp q16, q17, [sp], #32
ldp q18, q19, [sp], #32
ldp q20, q21, [sp], #32
ldp q22, q23, [sp], #32
ldp q24, q25, [sp], #32
ldp q26, q27, [sp], #32
ldp q28, q29, [sp], #32
ldp q30, q31, [sp], #32
ldp x0, x1, [sp], #16
ldp x2, x3, [sp], #16
ldp x4, x5, [sp], #16
ldp x6, x7, [sp], #16
ldp x8, x9, [sp], #16
ldp x10, x11, [sp], #16
ldp x12, x13, [sp], #16
ldp x14, x15, [sp], #16
ldp x19, x20, [sp], #16
ldp x21, x22, [sp], #16
ldp x23, x24, [sp], #16
ldp x25, x26, [sp], #16
ldp x27, x28, [sp], #16
ldp x29, x30, [sp], #16
// Return to the function implementation (rather than the stub).
ret x17
#endif // defined(__arm64__) || defined(__aarch64__)

View File

@@ -1,49 +0,0 @@
//===- sysv_resolve.cpp ---------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file contains a generic "resolver" function compatible with the SysV
// ABI.
//
//===----------------------------------------------------------------------===//
#include "executor_symbol_def.h"
#include "jit_dispatch.h"
#include "wrapper_function_utils.h"
#include <stdio.h>
#define DEBUG_TYPE "sysv_resolve"
using namespace orc_rt;
// Declare function tags for functions in the JIT process.
ORC_RT_JIT_DISPATCH_TAG(__orc_rt_resolve_tag)
// FIXME: Make this configurable via an alias.
static void __orc_rt_sysv_fail(void *Caller, const char *ErrMsg) {
fprintf(stderr, "error resolving implementation for stub %p: %s\n", Caller,
ErrMsg);
abort();
}
extern "C" ORC_RT_HIDDEN void *__orc_rt_resolve(void *Caller) {
Expected<ExecutorSymbolDef> Result((ExecutorSymbolDef()));
if (auto Err = WrapperFunction<SPSExpected<SPSExecutorSymbolDef>(
SPSExecutorAddr)>::call(JITDispatch(&__orc_rt_resolve_tag), Result,
ExecutorAddr::fromPtr(Caller))) {
__orc_rt_sysv_fail(Caller, toString(std::move(Err)).c_str());
return nullptr; // Unreachable.
}
if (!Result) {
__orc_rt_sysv_fail(Caller, toString(Result.takeError()).c_str());
return nullptr; // Unreachable.
}
return Result->getAddress().toPtr<void *>();
}

View File

@@ -0,0 +1,6 @@
// Test that the orc-remote-executor tool errors out as expected when called
// with no arguments.
//
// RUN: not %orc_rt_executor 2>&1 | FileCheck %s
// CHECK: usage: orc-rt-executor [help] [<mode>] <program arguments>...

View File

@@ -16,11 +16,6 @@ if config.host_arch == "x86_64h" and config.target_arch == "x86_64":
host_arch_compatible = True
if host_arch_compatible:
config.available_features.add("host-arch-compatible")
# If the target OS hasn't been set then assume host.
if not config.target_os:
config.target_os = config.host_os
config.test_target_is_host_executable = (
config.target_os == config.host_os and host_arch_compatible
)

View File

@@ -755,32 +755,6 @@ inline Symbol &createAnonymousPointerJumpStub(LinkGraph &G,
sizeof(PointerJumpStubContent), true, false);
}
/// AArch64 reentry trampoline.
///
/// Contains the instruction sequence for a trampoline that stores its return
/// address on the stack and passes its own address in x0:
/// STP x29, x30, [sp, #-16]!
/// BL <reentry-symbol>
extern const char ReentryTrampolineContent[8];
/// Create a block of N reentry trampolines.
inline Block &createReentryTrampolineBlock(LinkGraph &G,
Section &TrampolineSection,
Symbol &ReentrySymbol) {
auto &B = G.createContentBlock(TrampolineSection, ReentryTrampolineContent,
orc::ExecutorAddr(~uint64_t(7)), 4, 0);
B.addEdge(Branch26PCRel, 4, ReentrySymbol, 0);
return B;
}
inline Symbol &createAnonymousReentryTrampoline(LinkGraph &G,
Section &TrampolineSection,
Symbol &ReentrySymbol) {
return G.addAnonymousSymbol(
createReentryTrampolineBlock(G, TrampolineSection, ReentrySymbol), 0,
sizeof(ReentryTrampolineContent), true, false);
}
/// Global Offset Table Builder.
class GOTTableManager : public TableManager<GOTTableManager> {
public:

View File

@@ -51,26 +51,6 @@ enum class SymbolState : uint8_t;
using ResourceTrackerSP = IntrusiveRefCntPtr<ResourceTracker>;
using JITDylibSP = IntrusiveRefCntPtr<JITDylib>;
/// A definition of a Symbol within a JITDylib.
class SymbolInstance {
public:
using LookupAsyncOnCompleteFn =
unique_function<void(Expected<ExecutorSymbolDef>)>;
SymbolInstance(JITDylibSP JD, SymbolStringPtr Name)
: JD(std::move(JD)), Name(std::move(Name)) {}
const JITDylib &getJITDylib() const { return *JD; }
const SymbolStringPtr &getName() const { return Name; }
Expected<ExecutorSymbolDef> lookup() const;
void lookupAsync(LookupAsyncOnCompleteFn OnComplete) const;
private:
JITDylibSP JD;
SymbolStringPtr Name;
};
using ResourceKey = uintptr_t;
/// API to remove / transfer ownership of JIT resources.
@@ -570,9 +550,6 @@ public:
/// emitted or notified of an error.
~MaterializationResponsibility();
/// Return the ResourceTracker associated with this instance.
const ResourceTrackerSP &getResourceTracker() const { return RT; }
/// Runs the given callback under the session lock, passing in the associated
/// ResourceKey. This is the safe way to associate resources with trackers.
template <typename Func> Error withResourceKeyDo(Func &&F) const {
@@ -1771,10 +1748,6 @@ private:
JITDispatchHandlers;
};
inline Expected<ExecutorSymbolDef> SymbolInstance::lookup() const {
return JD->getExecutionSession().lookup({JD.get()}, Name);
}
template <typename Func> Error ResourceTracker::withResourceKeyDo(Func &&F) {
return getJITDylib().getExecutionSession().runSessionLocked([&]() -> Error {
if (isDefunct())

View File

@@ -138,11 +138,6 @@ public:
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:
// Data needed for bootstrap only.
struct BootstrapInfo {

View File

@@ -1,26 +0,0 @@
//===- JITLinkLazyCallThroughManager.h - JITLink based laziness -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Redirectable Symbol Manager implementation using JITLink
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_JITLINKLAZYCALLTHROUGHMANAGER_H
#define LLVM_EXECUTIONENGINE_ORC_JITLINKLAZYCALLTHROUGHMANAGER_H
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/Orc/RedirectionManager.h"
#include "llvm/Support/StringSaver.h"
#include <atomic>
namespace llvm {
namespace orc {} // namespace orc
} // namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_JITLINKLAZYCALLTHROUGHMANAGER_H

View File

@@ -39,6 +39,12 @@ public:
ObjLinkingLayer, AnonymousPtrCreator, PtrJumpStubCreator));
}
void emitRedirectableSymbols(std::unique_ptr<MaterializationResponsibility> R,
SymbolMap InitialDests) override;
Error redirect(JITDylib &JD, const SymbolMap &NewDests) override;
private:
JITLinkRedirectableSymbolManager(
ObjectLinkingLayer &ObjLinkingLayer,
jitlink::AnonymousPointerCreator &AnonymousPtrCreator,
@@ -47,14 +53,6 @@ public:
AnonymousPtrCreator(std::move(AnonymousPtrCreator)),
PtrJumpStubCreator(std::move(PtrJumpStubCreator)) {}
ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
void emitRedirectableSymbols(std::unique_ptr<MaterializationResponsibility> R,
SymbolMap InitialDests) override;
Error redirect(JITDylib &JD, const SymbolMap &NewDests) override;
private:
ObjectLinkingLayer &ObjLinkingLayer;
jitlink::AnonymousPointerCreator AnonymousPtrCreator;
jitlink::PointerJumpStubCreator PtrJumpStubCreator;

View File

@@ -1,72 +0,0 @@
//===- JITLinkReentryTrampolines.h -- JITLink-based trampolines -*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Emit reentry trampolines via JITLink.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_EXECUTIONENGINE_ORC_JITLINKREENTRYTRAMPOLINES_H
#define LLVM_EXECUTIONENGINE_ORC_JITLINKREENTRYTRAMPOLINES_H
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/LazyReexports.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorSymbolDef.h"
#include "llvm/Support/Error.h"
namespace llvm::jitlink {
class Block;
class LinkGraph;
class Section;
class Symbol;
} // namespace llvm::jitlink
namespace llvm::orc {
class ObjectLinkingLayer;
class RedirectableSymbolManager;
/// Produces trampolines on request using JITLink.
class JITLinkReentryTrampolines {
public:
using EmitTrampolineFn = unique_function<jitlink::Symbol &(
jitlink::LinkGraph &G, jitlink::Section &Sec,
jitlink::Symbol &ReentrySym)>;
using OnTrampolinesReadyFn = unique_function<void(
Expected<std::vector<ExecutorSymbolDef>> EntryAddrs)>;
/// Create trampolines using the default reentry trampoline function for
/// the session triple.
static Expected<std::unique_ptr<JITLinkReentryTrampolines>>
Create(ObjectLinkingLayer &ObjLinkingLayer);
JITLinkReentryTrampolines(ObjectLinkingLayer &ObjLinkingLayer,
EmitTrampolineFn EmitTrampoline);
JITLinkReentryTrampolines(JITLinkReentryTrampolines &&) = delete;
JITLinkReentryTrampolines &operator=(JITLinkReentryTrampolines &&) = delete;
void emit(ResourceTrackerSP RT, size_t NumTrampolines,
OnTrampolinesReadyFn OnTrampolinesReady);
private:
class TrampolineAddrScraperPlugin;
ObjectLinkingLayer &ObjLinkingLayer;
TrampolineAddrScraperPlugin *TrampolineAddrScraper = nullptr;
EmitTrampolineFn EmitTrampoline;
std::atomic<size_t> ReentryGraphIdx{0};
};
Expected<std::unique_ptr<LazyReexportsManager>>
createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD);
} // namespace llvm::orc
#endif // LLVM_EXECUTIONENGINE_ORC_JITLINKREENTRYTRAMPOLINES_H

View File

@@ -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,
@@ -37,7 +38,8 @@ private:
class RenamerPlugin;
ObjectLinkingLayer &BaseLayer;
LazyReexportsManager &LRMgr;
LazyCallThroughManager &LCTMgr;
RedirectableSymbolManager &RSMgr;
};
} // namespace llvm::orc

View File

@@ -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

View File

@@ -176,11 +176,6 @@ public:
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>>;

View File

@@ -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;

View File

@@ -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:

View File

@@ -29,7 +29,6 @@ add_llvm_component_library(LLVMOrcJIT
IRTransformLayer.cpp
IRPartitionLayer.cpp
JITTargetMachineBuilder.cpp
JITLinkReentryTrampolines.cpp
LazyObjectLinkingLayer.cpp
LazyReexports.cpp
Layer.cpp

View File

@@ -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)
@@ -1476,9 +1455,10 @@ void JITDylib::installMaterializationUnit(
void JITDylib::detachQueryHelper(AsynchronousSymbolQuery &Q,
const SymbolNameSet &QuerySymbols) {
for (auto &QuerySymbol : QuerySymbols) {
auto MII = MaterializingInfos.find(QuerySymbol);
if (MII != MaterializingInfos.end())
MII->second.removeQuery(Q);
assert(MaterializingInfos.count(QuerySymbol) &&
"QuerySymbol does not have MaterializingInfo");
auto &MI = MaterializingInfos[QuerySymbol];
MI.removeQuery(Q);
}
}

View File

@@ -349,7 +349,6 @@ ELFNixPlatform::standardPlatformAliases(ExecutionSession &ES,
SymbolAliasMap Aliases;
addAliases(ES, Aliases, requiredCXXAliases());
addAliases(ES, Aliases, standardRuntimeUtilityAliases());
addAliases(ES, Aliases, standardLazyCompilationAliases());
return Aliases;
}
@@ -378,16 +377,6 @@ ELFNixPlatform::standardRuntimeUtilityAliases() {
StandardRuntimeUtilityAliases);
}
ArrayRef<std::pair<const char *, const char *>>
ELFNixPlatform::standardLazyCompilationAliases() {
static const std::pair<const char *, const char *>
StandardLazyCompilationAliases[] = {
{"__orc_rt_reentry", "__orc_rt_sysv_reentry"}};
return ArrayRef<std::pair<const char *, const char *>>(
StandardLazyCompilationAliases);
}
bool ELFNixPlatform::supportedTarget(const Triple &TT) {
switch (TT.getArch()) {
case Triple::x86_64:

View File

@@ -1,184 +0,0 @@
//===----- JITLinkReentryTrampolines.cpp -- JITLink-based trampoline- -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include <memory>
#define DEBUG_TYPE "orc"
using namespace llvm;
using namespace llvm::jitlink;
namespace {
constexpr StringRef ReentryFnName = "__orc_rt_reentry";
constexpr StringRef ReentrySectionName = "__orc_stubs";
} // namespace
namespace llvm::orc {
class JITLinkReentryTrampolines::TrampolineAddrScraperPlugin
: public ObjectLinkingLayer::Plugin {
public:
void modifyPassConfig(MaterializationResponsibility &MR,
jitlink::LinkGraph &G,
jitlink::PassConfiguration &Config) override {
Config.PreFixupPasses.push_back(
[this](LinkGraph &G) { return recordTrampolineAddrs(G); });
}
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 {}
void registerGraph(LinkGraph &G,
std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs) {
std::lock_guard<std::mutex> Lock(M);
assert(!PendingAddrs.count(&G) && "Duplicate registration");
PendingAddrs[&G] = std::move(Addrs);
}
Error recordTrampolineAddrs(LinkGraph &G) {
std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs;
{
std::lock_guard<std::mutex> Lock(M);
auto I = PendingAddrs.find(&G);
if (I == PendingAddrs.end())
return Error::success();
Addrs = std::move(I->second);
PendingAddrs.erase(I);
}
auto *Sec = G.findSectionByName(ReentrySectionName);
assert(Sec && "Reentry graph missing reentry section");
assert(!Sec->empty() && "Reentry graph is empty");
for (auto *Sym : Sec->symbols())
if (!Sym->hasName())
Addrs->push_back({Sym->getAddress(), JITSymbolFlags()});
return Error::success();
}
private:
std::mutex M;
DenseMap<LinkGraph *, std::shared_ptr<std::vector<ExecutorSymbolDef>>>
PendingAddrs;
};
Expected<std::unique_ptr<JITLinkReentryTrampolines>>
JITLinkReentryTrampolines::Create(ObjectLinkingLayer &ObjLinkingLayer) {
EmitTrampolineFn EmitTrampoline;
switch (ObjLinkingLayer.getExecutionSession().getTargetTriple().getArch()) {
case Triple::aarch64:
EmitTrampoline = aarch64::createAnonymousReentryTrampoline;
break;
default:
return make_error<StringError>("Architecture not supported",
inconvertibleErrorCode());
}
return std::make_unique<JITLinkReentryTrampolines>(ObjLinkingLayer,
std::move(EmitTrampoline));
}
JITLinkReentryTrampolines::JITLinkReentryTrampolines(
ObjectLinkingLayer &ObjLinkingLayer, EmitTrampolineFn EmitTrampoline)
: ObjLinkingLayer(ObjLinkingLayer),
EmitTrampoline(std::move(EmitTrampoline)) {
auto TAS = std::make_shared<TrampolineAddrScraperPlugin>();
TrampolineAddrScraper = TAS.get();
ObjLinkingLayer.addPlugin(std::move(TAS));
}
void JITLinkReentryTrampolines::emit(ResourceTrackerSP RT,
size_t NumTrampolines,
OnTrampolinesReadyFn OnTrampolinesReady) {
if (NumTrampolines == 0)
return OnTrampolinesReady(std::vector<ExecutorSymbolDef>());
JITDylibSP JD(&RT->getJITDylib());
auto &ES = ObjLinkingLayer.getExecutionSession();
Triple TT = ES.getTargetTriple();
auto ReentryGraphSym =
ES.intern(("__orc_reentry_graph_#" + Twine(++ReentryGraphIdx)).str());
auto G = std::make_unique<jitlink::LinkGraph>(
(*ReentryGraphSym).str(), ES.getSymbolStringPool(), TT,
TT.isArch64Bit() ? 8 : 4,
TT.isLittleEndian() ? endianness::little : endianness::big,
jitlink::getGenericEdgeKindName);
auto &ReentryFnSym = G->addExternalSymbol(ReentryFnName, 0, false);
auto &ReentrySection =
G->createSection(ReentrySectionName, MemProt::Exec | MemProt::Read);
for (size_t I = 0; I != NumTrampolines; ++I)
EmitTrampoline(*G, ReentrySection, ReentryFnSym).setLive(true);
auto &FirstBlock = **ReentrySection.blocks().begin();
G->addDefinedSymbol(FirstBlock, 0, *ReentryGraphSym, FirstBlock.getSize(),
Linkage::Strong, Scope::SideEffectsOnly, true, true);
auto TrampolineAddrs = std::make_shared<std::vector<ExecutorSymbolDef>>();
TrampolineAddrScraper->registerGraph(*G, TrampolineAddrs);
// Add Graph via object linking layer.
if (auto Err = ObjLinkingLayer.add(std::move(RT), std::move(G)))
return OnTrampolinesReady(std::move(Err));
// Trigger graph emission.
ES.lookup(
LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},
SymbolLookupSet(ReentryGraphSym,
SymbolLookupFlags::WeaklyReferencedSymbol),
SymbolState::Ready,
[OnTrampolinesReady = std::move(OnTrampolinesReady),
TrampolineAddrs =
std::move(TrampolineAddrs)](Expected<SymbolMap> Result) mutable {
if (Result)
OnTrampolinesReady(std::move(*TrampolineAddrs));
else
OnTrampolinesReady(Result.takeError());
},
NoDependenciesToRegister);
}
Expected<std::unique_ptr<LazyReexportsManager>>
createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD) {
auto JLT = JITLinkReentryTrampolines::Create(ObjLinkingLayer);
if (!JLT)
return JLT.takeError();
return LazyReexportsManager::Create(
[JLT = std::move(*JLT)](ResourceTrackerSP RT, size_t NumTrampolines,
LazyReexportsManager::OnTrampolinesReadyFn
OnTrampolinesReady) mutable {
JLT->emit(std::move(RT), NumTrampolines, std::move(OnTrampolinesReady));
},
RSMgr, PlatformJD);
}
} // namespace llvm::orc

View File

@@ -71,9 +71,10 @@ private:
};
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>());
}
@@ -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(

View File

@@ -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"
@@ -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.

View File

@@ -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;
}
@@ -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:

View File

@@ -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>

View File

@@ -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"
@@ -950,18 +949,41 @@ public:
}
};
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,
@@ -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();
@@ -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();
}

View File

@@ -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"
@@ -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;
};