1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-23 19:23:23 +01:00

[ORC] Require ExecutorProcessControl when constructing an ExecutionSession.

Wrapper function call and dispatch handler helpers are moved to
ExecutionSession, and existing EPC-based tools are re-written to take an
ExecutionSession argument instead.

Requiring an ExecutorProcessControl instance simplifies existing EPC based
utilities (which only need to take an ES now), and should encourage more
utilities to use the EPC interface. It also simplifies process termination,
since the session can automatically call ExecutorProcessControl::disconnect
(previously this had to be done manually, and carefully ordered with the
rest of JIT tear-down to work correctly).
This commit is contained in:
Lang Hames 2021-07-27 13:50:19 +10:00
parent e9073c9b78
commit d08c2fabb8
34 changed files with 522 additions and 390 deletions

View File

@ -32,7 +32,6 @@ namespace orc {
class KaleidoscopeJIT {
private:
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
DataLayout DL;
@ -44,11 +43,9 @@ private:
JITDylib &MainJD;
public:
KaleidoscopeJIT(std::unique_ptr<ExecutorProcessControl> EPC,
std::unique_ptr<ExecutionSession> ES,
KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
JITTargetMachineBuilder JTMB, DataLayout DL)
: EPC(std::move(EPC)), ES(std::move(ES)), DL(std::move(DL)),
Mangle(*this->ES, this->DL),
: ES(std::move(ES)), DL(std::move(DL)), Mangle(*this->ES, this->DL),
ObjectLayer(*this->ES,
[]() { return std::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjectLayer,
@ -65,21 +62,21 @@ public:
}
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = SelfExecutorProcessControl::Create(SSP);
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(SSP));
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
JITTargetMachineBuilder JTMB((*EPC)->getTargetTriple());
JITTargetMachineBuilder JTMB(
ES->getExecutorProcessControl().getTargetTriple());
auto DL = JTMB.getDefaultDataLayoutForTarget();
if (!DL)
return DL.takeError();
return std::make_unique<KaleidoscopeJIT>(std::move(*EPC), std::move(ES),
std::move(JTMB), std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(JTMB),
std::move(*DL));
}
const DataLayout &getDataLayout() const { return DL; }

View File

@ -37,7 +37,6 @@ namespace orc {
class KaleidoscopeJIT {
private:
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
DataLayout DL;
@ -50,11 +49,9 @@ private:
JITDylib &MainJD;
public:
KaleidoscopeJIT(std::unique_ptr<ExecutorProcessControl> EPC,
std::unique_ptr<ExecutionSession> ES,
KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
JITTargetMachineBuilder JTMB, DataLayout DL)
: EPC(std::move(EPC)), ES(std::move(ES)), DL(std::move(DL)),
Mangle(*this->ES, this->DL),
: ES(std::move(ES)), DL(std::move(DL)), Mangle(*this->ES, this->DL),
ObjectLayer(*this->ES,
[]() { return std::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjectLayer,
@ -72,21 +69,21 @@ public:
}
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = SelfExecutorProcessControl::Create(SSP);
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(SSP));
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
JITTargetMachineBuilder JTMB((*EPC)->getTargetTriple());
JITTargetMachineBuilder JTMB(
ES->getExecutorProcessControl().getTargetTriple());
auto DL = JTMB.getDefaultDataLayoutForTarget();
if (!DL)
return DL.takeError();
return std::make_unique<KaleidoscopeJIT>(std::move(*EPC), std::move(ES),
std::move(JTMB), std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(JTMB),
std::move(*DL));
}
const DataLayout &getDataLayout() const { return DL; }

View File

@ -39,7 +39,6 @@ namespace orc {
class KaleidoscopeJIT {
private:
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
std::unique_ptr<EPCIndirectionUtils> EPCIU;
@ -59,12 +58,11 @@ private:
}
public:
KaleidoscopeJIT(std::unique_ptr<ExecutorProcessControl> EPC,
std::unique_ptr<ExecutionSession> ES,
KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
std::unique_ptr<EPCIndirectionUtils> EPCIU,
JITTargetMachineBuilder JTMB, DataLayout DL)
: EPC(std::move(EPC)), ES(std::move(ES)), EPCIU(std::move(EPCIU)),
DL(std::move(DL)), Mangle(*this->ES, this->DL),
: ES(std::move(ES)), EPCIU(std::move(EPCIU)), DL(std::move(DL)),
Mangle(*this->ES, this->DL),
ObjectLayer(*this->ES,
[]() { return std::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjectLayer,
@ -87,14 +85,13 @@ public:
}
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = SelfExecutorProcessControl::Create(SSP);
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(SSP));
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
auto EPCIU = EPCIndirectionUtils::Create(**EPC);
auto EPCIU = EPCIndirectionUtils::Create(ES->getExecutorProcessControl());
if (!EPCIU)
return EPCIU.takeError();
@ -104,15 +101,15 @@ public:
if (auto Err = setUpInProcessLCTMReentryViaEPCIU(**EPCIU))
return std::move(Err);
JITTargetMachineBuilder JTMB((*EPC)->getTargetTriple());
JITTargetMachineBuilder JTMB(
ES->getExecutorProcessControl().getTargetTriple());
auto DL = JTMB.getDefaultDataLayoutForTarget();
if (!DL)
return DL.takeError();
return std::make_unique<KaleidoscopeJIT>(std::move(*EPC), std::move(ES),
std::move(*EPCIU), std::move(JTMB),
std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(*EPCIU),
std::move(JTMB), std::move(*DL));
}
const DataLayout &getDataLayout() const { return DL; }

View File

@ -126,7 +126,6 @@ void KaleidoscopeASTMaterializationUnit::materialize(
class KaleidoscopeJIT {
private:
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
std::unique_ptr<EPCIndirectionUtils> EPCIU;
@ -146,12 +145,11 @@ private:
}
public:
KaleidoscopeJIT(std::unique_ptr<ExecutorProcessControl> EPC,
std::unique_ptr<ExecutionSession> ES,
KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
std::unique_ptr<EPCIndirectionUtils> EPCIU,
JITTargetMachineBuilder JTMB, DataLayout DL)
: EPC(std::move(EPC)), ES(std::move(ES)), EPCIU(std::move(EPCIU)),
DL(std::move(DL)), Mangle(*this->ES, this->DL),
: ES(std::move(ES)), EPCIU(std::move(EPCIU)), DL(std::move(DL)),
Mangle(*this->ES, this->DL),
ObjectLayer(*this->ES,
[]() { return std::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjectLayer,
@ -172,14 +170,13 @@ public:
}
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = SelfExecutorProcessControl::Create(SSP);
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(SSP));
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
auto EPCIU = EPCIndirectionUtils::Create(**EPC);
auto EPCIU = EPCIndirectionUtils::Create(ES->getExecutorProcessControl());
if (!EPCIU)
return EPCIU.takeError();
@ -195,9 +192,8 @@ public:
if (!DL)
return DL.takeError();
return std::make_unique<KaleidoscopeJIT>(std::move(*EPC), std::move(ES),
std::move(*EPCIU), std::move(JTMB),
std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(*EPCIU),
std::move(JTMB), std::move(*DL));
}
const DataLayout &getDataLayout() const { return DL; }

View File

@ -32,7 +32,6 @@ namespace orc {
class KaleidoscopeJIT {
private:
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
DataLayout DL;
@ -44,11 +43,9 @@ private:
JITDylib &MainJD;
public:
KaleidoscopeJIT(std::unique_ptr<ExecutorProcessControl> EPC,
std::unique_ptr<ExecutionSession> ES,
KaleidoscopeJIT(std::unique_ptr<ExecutionSession> ES,
JITTargetMachineBuilder JTMB, DataLayout DL)
: EPC(std::move(EPC)), ES(std::move(ES)), DL(std::move(DL)),
Mangle(*this->ES, this->DL),
: ES(std::move(ES)), DL(std::move(DL)), Mangle(*this->ES, this->DL),
ObjectLayer(*this->ES,
[]() { return std::make_unique<SectionMemoryManager>(); }),
CompileLayer(*this->ES, ObjectLayer,
@ -65,21 +62,21 @@ public:
}
static Expected<std::unique_ptr<KaleidoscopeJIT>> Create() {
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = SelfExecutorProcessControl::Create(SSP);
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(SSP));
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
JITTargetMachineBuilder JTMB((*EPC)->getTargetTriple());
JITTargetMachineBuilder JTMB(
ES->getExecutorProcessControl().getTargetTriple());
auto DL = JTMB.getDefaultDataLayoutForTarget();
if (!DL)
return DL.takeError();
return std::make_unique<KaleidoscopeJIT>(std::move(*EPC), std::move(ES),
std::move(JTMB), std::move(*DL));
return std::make_unique<KaleidoscopeJIT>(std::move(ES), std::move(JTMB),
std::move(*DL));
}
const DataLayout &getDataLayout() const { return DL; }

View File

@ -134,9 +134,9 @@ int main(int argc, char *argv[]) {
ExitOnErr.setBanner(std::string(argv[0]) + ": ");
// (1) Create LLJIT instance.
auto SSP = std::make_shared<SymbolStringPool>();
auto EPC = ExitOnErr(SelfExecutorProcessControl::Create(std::move(SSP)));
auto J = ExitOnErr(LLJITBuilder().setExecutorProcessControl(*EPC).create());
auto EPC = ExitOnErr(SelfExecutorProcessControl::Create());
auto J = ExitOnErr(
LLJITBuilder().setExecutorProcessControl(std::move(EPC)).create());
// (2) Install transform to print modules as they are compiled:
J->getIRTransformLayer().setTransform(
@ -154,7 +154,8 @@ int main(int argc, char *argv[]) {
J->getExecutionSession(), pointerToJITTargetAddress(&reportErrorAndExit));
auto ISM = EPCIU->createIndirectStubsManager();
J->getMainJITDylib().addGenerator(
ExitOnErr(EPCDynamicLibrarySearchGenerator::GetForTargetProcess(*EPC)));
ExitOnErr(EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
J->getExecutionSession())));
// (4) Add modules.
ExitOnErr(J->addIRModule(ExitOnErr(parseExampleModule(FooMod, "foo-mod"))));

View File

@ -49,7 +49,11 @@ public:
if (!DL)
return DL.takeError();
auto ES = std::make_unique<ExecutionSession>();
auto EPC = SelfExecutorProcessControl::Create();
if (!EPC)
return EPC.takeError();
auto ES = std::make_unique<ExecutionSession>(std::move(*EPC));
auto LCTMgr = createLocalLazyCallThroughManager(
JTMB->getTargetTriple(), *ES,

View File

@ -19,12 +19,14 @@
#include "llvm/ADT/IntrusiveRefCntPtr.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkDylib.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
#include "llvm/ExecutionEngine/OrcV1Deprecation.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ExtensibleRTTI.h"
#include <atomic>
#include <future>
#include <memory>
#include <vector>
@ -1286,19 +1288,30 @@ public:
/// For dispatching ORC tasks (typically materialization tasks).
using DispatchTaskFunction = unique_function<void(std::unique_ptr<Task> T)>;
/// Construct an ExecutionSession.
///
/// SymbolStringPools may be shared between ExecutionSessions.
ExecutionSession(std::shared_ptr<SymbolStringPool> SSP = nullptr);
/// An asynchronous wrapper-function callable from the executor via
/// jit-dispatch.
using JITDispatchHandlerFunction = unique_function<void(
ExecutorProcessControl::SendResultFunction SendResult,
const char *ArgData, size_t ArgSize)>;
/// A map associating tag names with asynchronous wrapper function
/// implementations in the JIT.
using JITDispatchHandlerAssociationMap =
DenseMap<SymbolStringPtr, JITDispatchHandlerFunction>;
/// Construct an ExecutionSession with the given ExecutorProcessControl
/// object.
ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC);
/// End the session. Closes all JITDylibs.
Error endSession();
/// Add a symbol name to the SymbolStringPool and return a pointer to it.
SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
/// Get the ExecutorProcessControl object associated with this
/// ExecutionSession.
ExecutorProcessControl &getExecutorProcessControl() { return *EPC; }
/// Returns a shared_ptr to the SymbolStringPool for this ExecutionSession.
std::shared_ptr<SymbolStringPool> getSymbolStringPool() const { return SSP; }
/// Add a symbol name to the SymbolStringPool and return a pointer to it.
SymbolStringPtr intern(StringRef SymName) { return EPC->intern(SymName); }
/// Set the Platform for this ExecutionSession.
void setPlatform(std::unique_ptr<Platform> P) { this->P = std::move(P); }
@ -1440,6 +1453,121 @@ public:
DispatchTask(std::move(T));
}
/// Run a wrapper function in the executor.
///
/// The wrapper function should be callable as:
///
/// \code{.cpp}
/// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
/// \endcode{.cpp}
///
/// The given OnComplete function will be called to return the result.
void callWrapperAsync(ExecutorProcessControl::SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) {
EPC->callWrapperAsync(std::move(OnComplete), WrapperFnAddr, ArgBuffer);
}
/// Run a wrapper function in the executor. The wrapper function should be
/// callable as:
///
/// \code{.cpp}
/// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
/// \endcode{.cpp}
shared::WrapperFunctionResult callWrapper(JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) {
std::promise<shared::WrapperFunctionResult> RP;
auto RF = RP.get_future();
callWrapperAsync(
[&](shared::WrapperFunctionResult R) { RP.set_value(std::move(R)); },
WrapperFnAddr, ArgBuffer);
return RF.get();
}
/// Run a wrapper function using SPS to serialize the arguments and
/// deserialize the results.
template <typename SPSSignature, typename SendResultT, typename... ArgTs>
void callSPSWrapperAsync(SendResultT &&SendResult,
JITTargetAddress WrapperFnAddr,
const ArgTs &...Args) {
shared::WrapperFunction<SPSSignature>::callAsync(
[this,
WrapperFnAddr](ExecutorProcessControl::SendResultFunction SendResult,
const char *ArgData, size_t ArgSize) {
callWrapperAsync(std::move(SendResult), WrapperFnAddr,
ArrayRef<char>(ArgData, ArgSize));
},
std::move(SendResult), Args...);
}
/// Run a wrapper function using SPS to serialize the arguments and
/// deserialize the results.
///
/// If SPSSignature is a non-void function signature then the second argument
/// (the first in the Args list) should be a reference to a return value.
template <typename SPSSignature, typename... WrapperCallArgTs>
Error callSPSWrapper(JITTargetAddress WrapperFnAddr,
WrapperCallArgTs &&...WrapperCallArgs) {
return shared::WrapperFunction<SPSSignature>::call(
[this, WrapperFnAddr](const char *ArgData, size_t ArgSize) {
return callWrapper(WrapperFnAddr, ArrayRef<char>(ArgData, ArgSize));
},
std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
}
/// Wrap a handler that takes concrete argument types (and a sender for a
/// concrete return type) to produce an AsyncHandlerWrapperFunction. Uses SPS
/// to unpack the arguments and pack the result.
///
/// This function is intended to support easy construction of
/// AsyncHandlerWrapperFunctions that can be associated with a tag
/// (using registerJITDispatchHandler) and called from the executor.
template <typename SPSSignature, typename HandlerT>
static JITDispatchHandlerFunction wrapAsyncWithSPS(HandlerT &&H) {
return [H = std::forward<HandlerT>(H)](
ExecutorProcessControl::SendResultFunction SendResult,
const char *ArgData, size_t ArgSize) mutable {
shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
std::move(SendResult));
};
}
/// Wrap a class method that takes concrete argument types (and a sender for
/// a concrete return type) to produce an AsyncHandlerWrapperFunction. Uses
/// SPS to unpack teh arguments and pack the result.
///
/// This function is intended to support easy construction of
/// AsyncHandlerWrapperFunctions that can be associated with a tag
/// (using registerJITDispatchHandler) and called from the executor.
template <typename SPSSignature, typename ClassT, typename... MethodArgTs>
static JITDispatchHandlerFunction
wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) {
return wrapAsyncWithSPS<SPSSignature>(
[Instance, Method](MethodArgTs &&...MethodArgs) {
(Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...);
});
}
/// For each tag symbol name, associate the corresponding
/// AsyncHandlerWrapperFunction with the address of that symbol. The
/// handler becomes callable from the executor using the ORC runtime
/// __orc_rt_jit_dispatch function and the given tag.
///
/// Tag symbols will be looked up in JD using LookupKind::Static,
/// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and
/// LookupFlags::WeaklyReferencedSymbol. Missing tag definitions will not
/// cause an error, the handler will simply be dropped.
Error registerJITDispatchHandlers(JITDylib &JD,
JITDispatchHandlerAssociationMap WFs);
/// Run a registered jit-side wrapper function.
/// This should be called by the ExecutorProcessControl instance in response
/// to incoming jit-dispatch requests from the executor.
void
runJITDispatchHandler(ExecutorProcessControl::SendResultFunction SendResult,
JITTargetAddress HandlerFnTagAddr,
ArrayRef<char> ArgBuffer);
/// Dump the state of all the JITDylibs in this session.
void dump(raw_ostream &OS);
@ -1523,7 +1651,7 @@ private:
mutable std::recursive_mutex SessionMutex;
bool SessionOpen = true;
std::shared_ptr<SymbolStringPool> SSP;
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<Platform> P;
ErrorReporter ReportError = logErrorsToStdErr;
DispatchTaskFunction DispatchTask = runOnCurrentThread;
@ -1538,6 +1666,10 @@ private:
std::vector<std::pair<std::unique_ptr<MaterializationUnit>,
std::unique_ptr<MaterializationResponsibility>>>
OutstandingMUs;
mutable std::mutex JITDispatchHandlersMutex;
DenseMap<JITTargetAddress, std::shared_ptr<JITDispatchHandlerFunction>>
JITDispatchHandlers;
};
inline ExecutionSession &MaterializationResponsibility::getExecutionSession() {

View File

@ -14,7 +14,7 @@
#define LLVM_EXECUTIONENGINE_ORC_EPCDEBUGOBJECTREGISTRAR_H
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/Memory.h"
@ -27,6 +27,8 @@ using namespace llvm::orc::shared;
namespace llvm {
namespace orc {
class ExecutionSession;
/// Abstract interface for registering debug objects in the executor process.
class DebugObjectRegistrar {
public:
@ -38,25 +40,20 @@ public:
/// executor process.
class EPCDebugObjectRegistrar : public DebugObjectRegistrar {
public:
EPCDebugObjectRegistrar(ExecutorProcessControl &EPC,
JITTargetAddress RegisterFn)
: EPC(EPC), RegisterFn(RegisterFn) {}
EPCDebugObjectRegistrar(ExecutionSession &ES, JITTargetAddress RegisterFn)
: ES(ES), RegisterFn(RegisterFn) {}
Error registerDebugObject(sys::MemoryBlock TargetMem) override {
return WrapperFunction<void(SPSExecutorAddress, uint64_t)>::call(
EPCCaller(EPC, RegisterFn), pointerToJITTargetAddress(TargetMem.base()),
static_cast<uint64_t>(TargetMem.allocatedSize()));
}
Error registerDebugObject(sys::MemoryBlock TargetMem) override;
private:
ExecutorProcessControl &EPC;
ExecutionSession &ES;
JITTargetAddress RegisterFn;
};
/// Create a ExecutorProcessControl-based DebugObjectRegistrar that emits debug
/// objects to the GDB JIT interface.
Expected<std::unique_ptr<EPCDebugObjectRegistrar>>
createJITLoaderGDBRegistrar(ExecutorProcessControl &EPC);
createJITLoaderGDBRegistrar(ExecutionSession &ES);
} // end namespace orc
} // end namespace llvm

View File

@ -15,11 +15,13 @@
#define LLVM_EXECUTIONENGINE_ORC_EPCDYNAMICLIBRARYSEARCHGENERATOR_H
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
namespace llvm {
namespace orc {
class ExecutorProcessControl;
class EPCDynamicLibrarySearchGenerator : public DefinitionGenerator {
public:
using SymbolPredicate = unique_function<bool(const SymbolStringPtr &)>;
@ -30,24 +32,24 @@ public:
/// If the Allow predicate is given then only symbols matching the predicate
/// will be searched for. If the predicate is not given then all symbols will
/// be searched for.
EPCDynamicLibrarySearchGenerator(ExecutorProcessControl &EPC,
EPCDynamicLibrarySearchGenerator(ExecutionSession &ES,
tpctypes::DylibHandle H,
SymbolPredicate Allow = SymbolPredicate())
: EPC(EPC), H(H), Allow(std::move(Allow)) {}
: EPC(ES.getExecutorProcessControl()), H(H), Allow(std::move(Allow)) {}
/// Permanently loads the library at the given path and, on success, returns
/// a DynamicLibrarySearchGenerator that will search it for symbol definitions
/// in the library. On failure returns the reason the library failed to load.
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
Load(ExecutorProcessControl &EPC, const char *LibraryPath,
Load(ExecutionSession &ES, const char *LibraryPath,
SymbolPredicate Allow = SymbolPredicate());
/// Creates a EPCDynamicLibrarySearchGenerator that searches for symbols in
/// the target process.
static Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
GetForTargetProcess(ExecutorProcessControl &EPC,
GetForTargetProcess(ExecutionSession &ES,
SymbolPredicate Allow = SymbolPredicate()) {
return Load(EPC, nullptr, std::move(Allow));
return Load(ES, nullptr, std::move(Allow));
}
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,

View File

@ -14,11 +14,12 @@
#define LLVM_EXECUTIONENGINE_ORC_EPCEHFRAMEREGISTRAR_H
#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
namespace llvm {
namespace orc {
class ExecutionSession;
/// Register/Deregisters EH frames in a remote process via a
/// ExecutorProcessControl instance.
class EPCEHFrameRegistrar : public jitlink::EHFrameRegistrar {
@ -27,14 +28,14 @@ public:
/// the EPC's lookupSymbols method to find the registration/deregistration
/// funciton addresses by name.
static Expected<std::unique_ptr<EPCEHFrameRegistrar>>
Create(ExecutorProcessControl &EPC);
Create(ExecutionSession &ES);
/// Create a EPCEHFrameRegistrar with the given ExecutorProcessControl
/// object and registration/deregistration function addresses.
EPCEHFrameRegistrar(ExecutorProcessControl &EPC,
EPCEHFrameRegistrar(ExecutionSession &ES,
JITTargetAddress RegisterEHFrameWrapperFnAddr,
JITTargetAddress DeregisterEHFRameWrapperFnAddr)
: EPC(EPC), RegisterEHFrameWrapperFnAddr(RegisterEHFrameWrapperFnAddr),
: ES(ES), RegisterEHFrameWrapperFnAddr(RegisterEHFrameWrapperFnAddr),
DeregisterEHFrameWrapperFnAddr(DeregisterEHFRameWrapperFnAddr) {}
Error registerEHFrames(JITTargetAddress EHFrameSectionAddr,
@ -43,7 +44,7 @@ public:
size_t EHFrameSectionSize) override;
private:
ExecutorProcessControl &EPC;
ExecutionSession &ES;
JITTargetAddress RegisterEHFrameWrapperFnAddr;
JITTargetAddress DeregisterEHFrameWrapperFnAddr;
};

View File

@ -17,10 +17,10 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
@ -31,22 +31,18 @@
namespace llvm {
namespace orc {
class ExecutionSession;
class SymbolLookupSet;
/// ExecutorProcessControl supports interaction with a JIT target process.
class ExecutorProcessControl {
friend class ExecutionSession;
public:
/// Sender to return the result of a WrapperFunction executed in the JIT.
using SendResultFunction =
unique_function<void(shared::WrapperFunctionResult)>;
/// An asynchronous wrapper-function.
using AsyncWrapperFunction = unique_function<void(
SendResultFunction SendResult, const char *ArgData, size_t ArgSize)>;
/// A map associating tag names with asynchronous wrapper function
/// implementations in the JIT.
using WrapperFunctionAssociationMap =
DenseMap<SymbolStringPtr, AsyncWrapperFunction>;
/// APIs for manipulating memory in the target process.
class MemoryAccess {
public:
@ -123,6 +119,13 @@ public:
virtual ~ExecutorProcessControl();
/// Return the ExecutionSession associated with this instance.
/// Not callable until the ExecutionSession has been associated.
ExecutionSession &getExecutionSession() {
assert(ES && "No ExecutionSession associated yet");
return *ES;
}
/// Intern a symbol name in the SymbolStringPool.
SymbolStringPtr intern(StringRef SymName) { return SSP->intern(SymName); }
@ -139,10 +142,16 @@ public:
const JITDispatchInfo &getJITDispatchInfo() const { return JDI; }
/// Return a MemoryAccess object for the target process.
MemoryAccess &getMemoryAccess() const { return *MemAccess; }
MemoryAccess &getMemoryAccess() const {
assert(MemAccess && "No MemAccess object set.");
return *MemAccess;
}
/// Return a JITLinkMemoryManager for the target process.
jitlink::JITLinkMemoryManager &getMemMgr() const { return *MemMgr; }
jitlink::JITLinkMemoryManager &getMemMgr() const {
assert(MemMgr && "No MemMgr object set");
return *MemMgr;
}
/// Load the dynamic library at the given path and return a handle to it.
/// If LibraryPath is null this function will return the global handle for
@ -163,7 +172,7 @@ public:
virtual Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
ArrayRef<std::string> Args) = 0;
/// Run a wrapper function in the executor (async version).
/// Run a wrapper function in the executor.
///
/// The wrapper function should be callable as:
///
@ -172,94 +181,9 @@ public:
/// \endcode{.cpp}
///
/// The given OnComplete function will be called to return the result.
virtual void runWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) = 0;
/// Run a wrapper function in the executor. The wrapper function should be
/// callable as:
///
/// \code{.cpp}
/// CWrapperFunctionResult fn(uint8_t *Data, uint64_t Size);
/// \endcode{.cpp}
shared::WrapperFunctionResult runWrapper(JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) {
std::promise<shared::WrapperFunctionResult> RP;
auto RF = RP.get_future();
runWrapperAsync(
[&](shared::WrapperFunctionResult R) { RP.set_value(std::move(R)); },
WrapperFnAddr, ArgBuffer);
return RF.get();
}
/// Run a wrapper function using SPS to serialize the arguments and
/// deserialize the results.
template <typename SPSSignature, typename SendResultT, typename... ArgTs>
void runSPSWrapperAsync(SendResultT &&SendResult,
JITTargetAddress WrapperFnAddr,
const ArgTs &...Args) {
shared::WrapperFunction<SPSSignature>::callAsync(
[this, WrapperFnAddr](SendResultFunction SendResult,
const char *ArgData, size_t ArgSize) {
runWrapperAsync(std::move(SendResult), WrapperFnAddr,
ArrayRef<char>(ArgData, ArgSize));
},
std::move(SendResult), Args...);
}
/// Run a wrapper function using SPS to serialize the arguments and
/// deserialize the results.
///
/// If SPSSignature is a non-void function signature then the second argument
/// (the first in the Args list) should be a reference to a return value.
template <typename SPSSignature, typename... WrapperCallArgTs>
Error runSPSWrapper(JITTargetAddress WrapperFnAddr,
WrapperCallArgTs &&...WrapperCallArgs) {
return shared::WrapperFunction<SPSSignature>::call(
[this, WrapperFnAddr](const char *ArgData, size_t ArgSize) {
return runWrapper(WrapperFnAddr, ArrayRef<char>(ArgData, ArgSize));
},
std::forward<WrapperCallArgTs>(WrapperCallArgs)...);
}
/// Wrap a handler that takes concrete argument types (and a sender for a
/// concrete return type) to produce an AsyncWrapperFunction. Uses SPS to
/// unpack the arguments and pack the result.
///
/// This function is usually used when building association maps.
template <typename SPSSignature, typename HandlerT>
static AsyncWrapperFunction wrapAsyncWithSPS(HandlerT &&H) {
return [H = std::forward<HandlerT>(H)](SendResultFunction SendResult,
const char *ArgData,
size_t ArgSize) mutable {
shared::WrapperFunction<SPSSignature>::handleAsync(ArgData, ArgSize, H,
std::move(SendResult));
};
}
template <typename SPSSignature, typename ClassT, typename... MethodArgTs>
static AsyncWrapperFunction
wrapAsyncWithSPS(ClassT *Instance, void (ClassT::*Method)(MethodArgTs...)) {
return wrapAsyncWithSPS<SPSSignature>(
[Instance, Method](MethodArgTs &&...MethodArgs) {
(Instance->*Method)(std::forward<MethodArgTs>(MethodArgs)...);
});
}
/// For each symbol name, associate the AsyncWrapperFunction implementation
/// value with the address of that symbol.
///
/// Symbols will be looked up using LookupKind::Static,
/// JITDylibLookupFlags::MatchAllSymbols (hidden tags will be found), and
/// LookupFlags::WeaklyReferencedSymbol (missing tags will not cause an
/// error, the implementations will simply be dropped).
Error associateJITSideWrapperFunctions(JITDylib &JD,
WrapperFunctionAssociationMap WFs);
/// Run a registered jit-side wrapper function.
void runJITSideWrapperFunction(SendResultFunction SendResult,
JITTargetAddress TagAddr,
ArrayRef<char> ArgBuffer);
virtual void callWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) = 0;
/// Disconnect from the target process.
///
@ -271,29 +195,49 @@ protected:
: SSP(std::move(SSP)) {}
std::shared_ptr<SymbolStringPool> SSP;
ExecutionSession *ES = nullptr;
Triple TargetTriple;
unsigned PageSize = 0;
JITDispatchInfo JDI;
MemoryAccess *MemAccess = nullptr;
jitlink::JITLinkMemoryManager *MemMgr = nullptr;
std::mutex TagToFuncMapMutex;
DenseMap<JITTargetAddress, std::shared_ptr<AsyncWrapperFunction>> TagToFunc;
};
/// Call a wrapper function via ExecutorProcessControl::runWrapper.
class EPCCaller {
/// A ExecutorProcessControl instance that asserts if any of its methods are
/// used. Suitable for use is unit tests, and by ORC clients who haven't moved
/// to ExecutorProcessControl-based APIs yet.
class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
public:
EPCCaller(ExecutorProcessControl &EPC, JITTargetAddress WrapperFnAddr)
: EPC(EPC), WrapperFnAddr(WrapperFnAddr) {}
shared::WrapperFunctionResult operator()(const char *ArgData,
size_t ArgSize) const {
return EPC.runWrapper(WrapperFnAddr, ArrayRef<char>(ArgData, ArgSize));
UnsupportedExecutorProcessControl(
std::shared_ptr<SymbolStringPool> SSP = nullptr,
const std::string &TT = "", unsigned PageSize = 0)
: ExecutorProcessControl(SSP ? std::move(SSP)
: std::make_shared<SymbolStringPool>()) {
this->TargetTriple = Triple(TT);
this->PageSize = PageSize;
}
private:
ExecutorProcessControl &EPC;
JITTargetAddress WrapperFnAddr;
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override {
llvm_unreachable("Unsupported");
}
Expected<std::vector<tpctypes::LookupResult>>
lookupSymbols(ArrayRef<LookupRequest> Request) override {
llvm_unreachable("Unsupported");
}
Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
ArrayRef<std::string> Args) override {
llvm_unreachable("Unsupported");
}
void callWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) override {
llvm_unreachable("Unsupported");
}
Error disconnect() override { return Error::success(); }
};
/// A ExecutorProcessControl implementation targeting the current process.
@ -305,11 +249,13 @@ public:
std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
/// Create a SelfExecutorProcessControl with the given memory manager.
/// Create a SelfExecutorProcessControl with the given symbol string pool and
/// memory manager.
/// If no symbol string pool is given then one will be created.
/// If no memory manager is given a jitlink::InProcessMemoryManager will
/// be used by default.
/// be created and used by default.
static Expected<std::unique_ptr<SelfExecutorProcessControl>>
Create(std::shared_ptr<SymbolStringPool> SSP,
Create(std::shared_ptr<SymbolStringPool> SSP = nullptr,
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr = nullptr);
Expected<tpctypes::DylibHandle> loadDylib(const char *DylibPath) override;
@ -320,9 +266,9 @@ public:
Expected<int32_t> runAsMain(JITTargetAddress MainFnAddr,
ArrayRef<std::string> Args) override;
void runWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) override;
void callWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) override;
Error disconnect() override;

View File

@ -260,6 +260,7 @@ public:
using PlatformSetupFunction = std::function<Error(LLJIT &J)>;
std::unique_ptr<ExecutorProcessControl> EPC;
std::unique_ptr<ExecutionSession> ES;
Optional<JITTargetMachineBuilder> JTMB;
Optional<DataLayout> DL;
@ -267,7 +268,6 @@ public:
CompileFunctionCreator CreateCompileFunction;
PlatformSetupFunction SetUpPlatform;
unsigned NumCompileThreads = 0;
ExecutorProcessControl *EPC = nullptr;
/// Called prior to JIT class construcion to fix up defaults.
Error prepareForConstruction();
@ -276,6 +276,17 @@ public:
template <typename JITType, typename SetterImpl, typename State>
class LLJITBuilderSetters {
public:
/// Set a ExecutorProcessControl for this instance.
/// This should not be called if ExecutionSession has already been set.
SetterImpl &
setExecutorProcessControl(std::unique_ptr<ExecutorProcessControl> EPC) {
assert(
!impl().ES &&
"setExecutorProcessControl should not be called if an ExecutionSession "
"has already been set");
impl().EPC = std::move(EPC);
return impl();
}
/// Set an ExecutionSession for this instance.
SetterImpl &setExecutionSession(std::unique_ptr<ExecutionSession> ES) {

View File

@ -97,13 +97,11 @@ public:
/// setting up all aliases (including the required ones).
static Expected<std::unique_ptr<MachOPlatform>>
Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
ExecutorProcessControl &EPC, JITDylib &PlatformJD,
const char *OrcRuntimePath,
JITDylib &PlatformJD, const char *OrcRuntimePath,
Optional<SymbolAliasMap> RuntimeAliases = None);
ExecutionSession &getExecutionSession() const { return ES; }
ObjectLinkingLayer &getObjectLinkingLayer() const { return ObjLinkingLayer; }
ExecutorProcessControl &getExecutorProcessControl() const { return EPC; }
Error setupJITDylib(JITDylib &JD) override;
Error notifyAdding(ResourceTracker &RT,
@ -193,7 +191,7 @@ private:
static bool supportedTarget(const Triple &TT);
MachOPlatform(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
ExecutorProcessControl &EPC, JITDylib &PlatformJD,
JITDylib &PlatformJD,
std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator,
Error &Err);
@ -228,7 +226,6 @@ private:
ExecutionSession &ES;
ObjectLinkingLayer &ObjLinkingLayer;
ExecutorProcessControl &EPC;
SymbolStringPtr MachOHeaderStartSymbol;
std::atomic<bool> RuntimeBootstrapped{false};

View File

@ -101,7 +101,11 @@ public:
using ReturnObjectBufferFunction =
std::function<void(std::unique_ptr<MemoryBuffer>)>;
/// Construct an ObjectLinkingLayer.
/// Construct an ObjectLinkingLayer using the ExecutorProcessControl
/// instance's memory manager.
ObjectLinkingLayer(ExecutionSession &ES);
/// Construct an ObjectLinkingLayer using a custom memory manager.
ObjectLinkingLayer(ExecutionSession &ES,
jitlink::JITLinkMemoryManager &MemMgr);

View File

@ -358,9 +358,9 @@ public:
return Result;
}
void runWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) override {
void callWrapperAsync(SendResultFunction OnComplete,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) override {
DEBUG_WITH_TYPE("orc", {
dbgs() << "Running as wrapper function "
<< formatv("{0:x16}", WrapperFnAddr) << " with "
@ -415,7 +415,7 @@ private:
std::function<Error(Expected<shared::WrapperFunctionResult>)> SendResult,
JITTargetAddress FunctionTag, std::vector<uint8_t> ArgBuffer) {
runJITSideWrapperFunction(
getExecutionSession().runJITDispatchHandler(
[this, SendResult = std::move(SendResult)](
Expected<shared::WrapperFunctionResult> R) {
if (auto Err = SendResult(std::move(R)))

View File

@ -1802,8 +1802,11 @@ void MaterializationTask::printDescription(raw_ostream &OS) {
void MaterializationTask::run() { MU->materialize(std::move(MR)); }
ExecutionSession::ExecutionSession(std::shared_ptr<SymbolStringPool> SSP)
: SSP(SSP ? std::move(SSP) : std::make_shared<SymbolStringPool>()) {}
ExecutionSession::ExecutionSession(std::unique_ptr<ExecutorProcessControl> EPC)
: EPC(std::move(EPC)) {
// Associated EPC and this.
this->EPC->ES = this;
}
Error ExecutionSession::endSession() {
LLVM_DEBUG(dbgs() << "Ending ExecutionSession " << this << "\n");
@ -1818,6 +1821,9 @@ Error ExecutionSession::endSession() {
Error Err = Error::success();
for (auto &JD : JITDylibsToClose)
Err = joinErrors(std::move(Err), JD->clear());
Err = joinErrors(std::move(Err), EPC->disconnect());
return Err;
}
@ -2048,6 +2054,58 @@ ExecutionSession::lookup(ArrayRef<JITDylib *> SearchOrder, StringRef Name,
return lookup(SearchOrder, intern(Name), RequiredState);
}
Error ExecutionSession::registerJITDispatchHandlers(
JITDylib &JD, JITDispatchHandlerAssociationMap WFs) {
auto TagAddrs = lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},
SymbolLookupSet::fromMapKeys(
WFs, SymbolLookupFlags::WeaklyReferencedSymbol));
if (!TagAddrs)
return TagAddrs.takeError();
// Associate tag addresses with implementations.
std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
for (auto &KV : *TagAddrs) {
auto TagAddr = KV.second.getAddress();
if (JITDispatchHandlers.count(TagAddr))
return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) +
" (for " + *KV.first +
") already registered",
inconvertibleErrorCode());
auto I = WFs.find(KV.first);
assert(I != WFs.end() && I->second &&
"JITDispatchHandler implementation missing");
JITDispatchHandlers[KV.second.getAddress()] =
std::make_shared<JITDispatchHandlerFunction>(std::move(I->second));
LLVM_DEBUG({
dbgs() << "Associated function tag \"" << *KV.first << "\" ("
<< formatv("{0:x}", KV.second.getAddress()) << ") with handler\n";
});
}
return Error::success();
}
void ExecutionSession::runJITDispatchHandler(
ExecutorProcessControl::SendResultFunction SendResult,
JITTargetAddress HandlerFnTagAddr, ArrayRef<char> ArgBuffer) {
std::shared_ptr<JITDispatchHandlerFunction> F;
{
std::lock_guard<std::mutex> Lock(JITDispatchHandlersMutex);
auto I = JITDispatchHandlers.find(HandlerFnTagAddr);
if (I != JITDispatchHandlers.end())
F = I->second;
}
if (F)
(*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size());
else
SendResult(shared::WrapperFunctionResult::createOutOfBandError(
("No function registered for tag " +
formatv("{0:x16}", HandlerFnTagAddr))
.str()));
}
void ExecutionSession::dump(raw_ostream &OS) {
runSessionLocked([this, &OS]() {
for (auto &JD : JDs)

View File

@ -9,6 +9,7 @@
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/Support/BinaryStreamWriter.h"
@ -16,7 +17,8 @@ namespace llvm {
namespace orc {
Expected<std::unique_ptr<EPCDebugObjectRegistrar>>
createJITLoaderGDBRegistrar(ExecutorProcessControl &EPC) {
createJITLoaderGDBRegistrar(ExecutionSession &ES) {
auto &EPC = ES.getExecutorProcessControl();
auto ProcessHandle = EPC.loadDylib(nullptr);
if (!ProcessHandle)
return ProcessHandle.takeError();
@ -37,7 +39,13 @@ createJITLoaderGDBRegistrar(ExecutorProcessControl &EPC) {
assert((*Result)[0].size() == 1 &&
"Unexpected number of addresses in result");
return std::make_unique<EPCDebugObjectRegistrar>(EPC, (*Result)[0][0]);
return std::make_unique<EPCDebugObjectRegistrar>(ES, (*Result)[0][0]);
}
Error EPCDebugObjectRegistrar::registerDebugObject(sys::MemoryBlock TargetMem) {
return ES.callSPSWrapper<void(SPSExecutorAddress, uint64_t)>(
RegisterFn, ExecutorAddress::fromPtr(TargetMem.base()),
static_cast<uint64_t>(TargetMem.allocatedSize()));
}
} // namespace orc

View File

@ -12,14 +12,14 @@ namespace llvm {
namespace orc {
Expected<std::unique_ptr<EPCDynamicLibrarySearchGenerator>>
EPCDynamicLibrarySearchGenerator::Load(ExecutorProcessControl &EPC,
EPCDynamicLibrarySearchGenerator::Load(ExecutionSession &ES,
const char *LibraryPath,
SymbolPredicate Allow) {
auto Handle = EPC.loadDylib(LibraryPath);
auto Handle = ES.getExecutorProcessControl().loadDylib(LibraryPath);
if (!Handle)
return Handle.takeError();
return std::make_unique<EPCDynamicLibrarySearchGenerator>(EPC, *Handle,
return std::make_unique<EPCDynamicLibrarySearchGenerator>(ES, *Handle,
std::move(Allow));
}

View File

@ -7,6 +7,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/Support/BinaryStreamWriter.h"
using namespace llvm::orc::shared;
@ -15,12 +17,13 @@ namespace llvm {
namespace orc {
Expected<std::unique_ptr<EPCEHFrameRegistrar>>
EPCEHFrameRegistrar::Create(ExecutorProcessControl &EPC) {
EPCEHFrameRegistrar::Create(ExecutionSession &ES) {
// FIXME: Proper mangling here -- we really need to decouple linker mangling
// from DataLayout.
// Find the addresses of the registration/deregistration functions in the
// executor process.
auto &EPC = ES.getExecutorProcessControl();
auto ProcessHandle = EPC.loadDylib(nullptr);
if (!ProcessHandle)
return ProcessHandle.takeError();
@ -48,22 +51,21 @@ EPCEHFrameRegistrar::Create(ExecutorProcessControl &EPC) {
auto RegisterEHFrameWrapperFnAddr = (*Result)[0][0];
auto DeregisterEHFrameWrapperFnAddr = (*Result)[0][1];
return std::make_unique<EPCEHFrameRegistrar>(
EPC, RegisterEHFrameWrapperFnAddr, DeregisterEHFrameWrapperFnAddr);
return std::make_unique<EPCEHFrameRegistrar>(ES, RegisterEHFrameWrapperFnAddr,
DeregisterEHFrameWrapperFnAddr);
}
Error EPCEHFrameRegistrar::registerEHFrames(JITTargetAddress EHFrameSectionAddr,
size_t EHFrameSectionSize) {
return WrapperFunction<void(SPSExecutorAddress, uint64_t)>::call(
EPCCaller(EPC, RegisterEHFrameWrapperFnAddr), EHFrameSectionAddr,
return ES.callSPSWrapper<void(SPSExecutorAddress, uint64_t)>(
RegisterEHFrameWrapperFnAddr, EHFrameSectionAddr,
static_cast<uint64_t>(EHFrameSectionSize));
}
Error EPCEHFrameRegistrar::deregisterEHFrames(
JITTargetAddress EHFrameSectionAddr, size_t EHFrameSectionSize) {
return WrapperFunction<void(SPSExecutorAddress, uint64_t)>::call(
EPCCaller(EPC, DeregisterEHFrameWrapperFnAddr), EHFrameSectionAddr,
return ES.callSPSWrapper<void(SPSExecutorAddress, uint64_t)>(
DeregisterEHFrameWrapperFnAddr, EHFrameSectionAddr,
static_cast<uint64_t>(EHFrameSectionSize));
}

View File

@ -23,60 +23,6 @@ ExecutorProcessControl::MemoryAccess::~MemoryAccess() {}
ExecutorProcessControl::~ExecutorProcessControl() {}
Error ExecutorProcessControl::associateJITSideWrapperFunctions(
JITDylib &JD, WrapperFunctionAssociationMap WFs) {
// Look up tag addresses.
auto &ES = JD.getExecutionSession();
auto TagAddrs =
ES.lookup({{&JD, JITDylibLookupFlags::MatchAllSymbols}},
SymbolLookupSet::fromMapKeys(
WFs, SymbolLookupFlags::WeaklyReferencedSymbol));
if (!TagAddrs)
return TagAddrs.takeError();
// Associate tag addresses with implementations.
std::lock_guard<std::mutex> Lock(TagToFuncMapMutex);
for (auto &KV : *TagAddrs) {
auto TagAddr = KV.second.getAddress();
if (TagToFunc.count(TagAddr))
return make_error<StringError>("Tag " + formatv("{0:x16}", TagAddr) +
" (for " + *KV.first +
") already registered",
inconvertibleErrorCode());
auto I = WFs.find(KV.first);
assert(I != WFs.end() && I->second &&
"AsyncWrapperFunction implementation missing");
TagToFunc[KV.second.getAddress()] =
std::make_shared<AsyncWrapperFunction>(std::move(I->second));
LLVM_DEBUG({
dbgs() << "Associated function tag \"" << *KV.first << "\" ("
<< formatv("{0:x}", KV.second.getAddress()) << ") with handler\n";
});
}
return Error::success();
}
void ExecutorProcessControl::runJITSideWrapperFunction(
SendResultFunction SendResult, JITTargetAddress TagAddr,
ArrayRef<char> ArgBuffer) {
std::shared_ptr<AsyncWrapperFunction> F;
{
std::lock_guard<std::mutex> Lock(TagToFuncMapMutex);
auto I = TagToFunc.find(TagAddr);
if (I != TagToFunc.end())
F = I->second;
}
if (F)
(*F)(std::move(SendResult), ArgBuffer.data(), ArgBuffer.size());
else
SendResult(shared::WrapperFunctionResult::createOutOfBandError(
("No function registered for tag " + formatv("{0:x16}", TagAddr))
.str()));
}
SelfExecutorProcessControl::SelfExecutorProcessControl(
std::shared_ptr<SymbolStringPool> SSP, Triple TargetTriple,
unsigned PageSize, std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
@ -100,6 +46,10 @@ Expected<std::unique_ptr<SelfExecutorProcessControl>>
SelfExecutorProcessControl::Create(
std::shared_ptr<SymbolStringPool> SSP,
std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
if (!SSP)
SSP = std::make_shared<SymbolStringPool>();
auto PageSize = sys::Process::getPageSize();
if (!PageSize)
return PageSize.takeError();
@ -159,9 +109,9 @@ SelfExecutorProcessControl::runAsMain(JITTargetAddress MainFnAddr,
return orc::runAsMain(jitTargetAddressToFunction<MainTy>(MainFnAddr), Args);
}
void SelfExecutorProcessControl::runWrapperAsync(SendResultFunction SendResult,
JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) {
void SelfExecutorProcessControl::callWrapperAsync(
SendResultFunction SendResult, JITTargetAddress WrapperFnAddr,
ArrayRef<char> ArgBuffer) {
using WrapperFnTy =
shared::detail::CWrapperFunctionResult (*)(const char *Data, size_t Size);
auto *WrapperFn = jitTargetAddressToFunction<WrapperFnTy>(WrapperFnAddr);
@ -217,12 +167,14 @@ SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
std::promise<shared::WrapperFunctionResult> ResultP;
auto ResultF = ResultP.get_future();
static_cast<SelfExecutorProcessControl *>(Ctx)->runJITSideWrapperFunction(
[ResultP =
std::move(ResultP)](shared::WrapperFunctionResult Result) mutable {
ResultP.set_value(std::move(Result));
},
pointerToJITTargetAddress(FnTag), {Data, Size});
static_cast<SelfExecutorProcessControl *>(Ctx)
->getExecutionSession()
.runJITDispatchHandler(
[ResultP = std::move(ResultP)](
shared::WrapperFunctionResult Result) mutable {
ResultP.set_value(std::move(Result));
},
pointerToJITTargetAddress(FnTag), {Data, Size});
return ResultF.get().release();
}

View File

@ -575,6 +575,22 @@ Error LLJITBuilderState::prepareForConstruction() {
dbgs() << "\n";
});
// If neither ES nor EPC has been set then create an EPC instance.
if (!ES && !EPC) {
LLVM_DEBUG({
dbgs() << "ExecutorProcessControl not specified, "
"Creating SelfExecutorProcessControl instance\n";
});
if (auto EPCOrErr = SelfExecutorProcessControl::Create())
EPC = std::move(*EPCOrErr);
else
return EPCOrErr.takeError();
} else
LLVM_DEBUG({
dbgs() << "Using explicitly specified ExecutorProcessControl instance "
<< EPC.get() << "\n";
});
// If the client didn't configure any linker options then auto-configure the
// JIT linker.
if (!CreateObjectLinkingLayer) {
@ -585,16 +601,9 @@ Error LLJITBuilderState::prepareForConstruction() {
JTMB->setRelocationModel(Reloc::PIC_);
JTMB->setCodeModel(CodeModel::Small);
CreateObjectLinkingLayer =
[EPC = this->EPC](
ExecutionSession &ES,
const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> {
std::unique_ptr<ObjectLinkingLayer> ObjLinkingLayer;
if (EPC)
ObjLinkingLayer =
std::make_unique<ObjectLinkingLayer>(ES, EPC->getMemMgr());
else
ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(
ES, std::make_unique<jitlink::InProcessMemoryManager>());
[](ExecutionSession &ES,
const Triple &) -> Expected<std::unique_ptr<ObjectLayer>> {
auto ObjLinkingLayer = std::make_unique<ObjectLinkingLayer>(ES);
ObjLinkingLayer->addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
ES, std::make_unique<jitlink::InProcessEHFrameRegistrar>()));
return std::move(ObjLinkingLayer);
@ -688,11 +697,25 @@ LLJIT::createCompileFunction(LLJITBuilderState &S,
}
LLJIT::LLJIT(LLJITBuilderState &S, Error &Err)
: ES(S.ES ? std::move(S.ES) : std::make_unique<ExecutionSession>()), Main(),
DL(""), TT(S.JTMB->getTargetTriple()) {
: DL(""), TT(S.JTMB->getTargetTriple()) {
ErrorAsOutParameter _(&Err);
assert(!(S.EPC && S.ES) && "EPC and ES should not both be set");
if (S.EPC) {
ES = std::make_unique<ExecutionSession>(std::move(S.EPC));
} else if (S.ES)
ES = std::move(S.ES);
else {
if (auto EPC = SelfExecutorProcessControl::Create()) {
ES = std::make_unique<ExecutionSession>(std::move(*EPC));
} else {
Err = EPC.takeError();
return;
}
}
if (auto MainOrErr = this->ES->createJITDylib("main"))
Main = &*MainOrErr;
else {

View File

@ -36,8 +36,10 @@ public:
void materialize(std::unique_ptr<MaterializationResponsibility> R) override {
unsigned PointerSize;
support::endianness Endianness;
const auto &TT =
MOP.getExecutionSession().getExecutorProcessControl().getTargetTriple();
switch (MOP.getExecutorProcessControl().getTargetTriple().getArch()) {
switch (TT.getArch()) {
case Triple::aarch64:
case Triple::x86_64:
PointerSize = 8;
@ -48,8 +50,8 @@ public:
}
auto G = std::make_unique<jitlink::LinkGraph>(
"<MachOHeaderMU>", MOP.getExecutorProcessControl().getTargetTriple(),
PointerSize, Endianness, jitlink::getGenericEdgeKindName);
"<MachOHeaderMU>", TT, PointerSize, Endianness,
jitlink::getGenericEdgeKindName);
auto &HeaderSection = G->createSection("__header", sys::Memory::MF_READ);
auto &HeaderBlock = createHeaderBlock(*G, HeaderSection);
@ -148,10 +150,11 @@ namespace orc {
Expected<std::unique_ptr<MachOPlatform>>
MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
ExecutorProcessControl &EPC, JITDylib &PlatformJD,
const char *OrcRuntimePath,
JITDylib &PlatformJD, const char *OrcRuntimePath,
Optional<SymbolAliasMap> RuntimeAliases) {
auto &EPC = ES.getExecutorProcessControl();
// If the target is not supported then bail out immediately.
if (!supportedTarget(EPC.getTargetTriple()))
return make_error<StringError>("Unsupported MachOPlatform triple: " +
@ -185,7 +188,7 @@ MachOPlatform::Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
// Create the instance.
Error Err = Error::success();
auto P = std::unique_ptr<MachOPlatform>(
new MachOPlatform(ES, ObjLinkingLayer, EPC, PlatformJD,
new MachOPlatform(ES, ObjLinkingLayer, PlatformJD,
std::move(*OrcRuntimeArchiveGenerator), Err));
if (Err)
return std::move(Err);
@ -273,9 +276,9 @@ bool MachOPlatform::supportedTarget(const Triple &TT) {
MachOPlatform::MachOPlatform(
ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
ExecutorProcessControl &EPC, JITDylib &PlatformJD,
JITDylib &PlatformJD,
std::unique_ptr<DefinitionGenerator> OrcRuntimeGenerator, Error &Err)
: ES(ES), ObjLinkingLayer(ObjLinkingLayer), EPC(EPC),
: ES(ES), ObjLinkingLayer(ObjLinkingLayer),
MachOHeaderStartSymbol(ES.intern("___dso_handle")) {
ErrorAsOutParameter _(&Err);
@ -309,27 +312,27 @@ MachOPlatform::MachOPlatform(
}
Error MachOPlatform::associateRuntimeSupportFunctions(JITDylib &PlatformJD) {
ExecutorProcessControl::WrapperFunctionAssociationMap WFs;
ExecutionSession::JITDispatchHandlerAssociationMap WFs;
using GetInitializersSPSSig =
SPSExpected<SPSMachOJITDylibInitializerSequence>(SPSString);
WFs[ES.intern("___orc_rt_macho_get_initializers_tag")] =
EPC.wrapAsyncWithSPS<GetInitializersSPSSig>(
ES.wrapAsyncWithSPS<GetInitializersSPSSig>(
this, &MachOPlatform::rt_getInitializers);
using GetDeinitializersSPSSig =
SPSExpected<SPSMachOJITDylibDeinitializerSequence>(SPSExecutorAddress);
WFs[ES.intern("___orc_rt_macho_get_deinitializers_tag")] =
EPC.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
ES.wrapAsyncWithSPS<GetDeinitializersSPSSig>(
this, &MachOPlatform::rt_getDeinitializers);
using LookupSymbolSPSSig =
SPSExpected<SPSExecutorAddress>(SPSExecutorAddress, SPSString);
WFs[ES.intern("___orc_rt_macho_symbol_lookup_tag")] =
EPC.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
&MachOPlatform::rt_lookupSymbol);
ES.wrapAsyncWithSPS<LookupSymbolSPSSig>(this,
&MachOPlatform::rt_lookupSymbol);
return EPC.associateJITSideWrapperFunctions(PlatformJD, std::move(WFs));
return ES.registerJITDispatchHandlers(PlatformJD, std::move(WFs));
}
void MachOPlatform::getInitializersBuildSequencePhase(
@ -520,7 +523,7 @@ Error MachOPlatform::bootstrapMachORuntime(JITDylib &PlatformJD) {
}
if (auto Err =
EPC.runSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue()))
ES.callSPSWrapper<void()>(orc_rt_macho_platform_bootstrap.getValue()))
return Err;
// FIXME: Ordering is fuzzy here. We're probably best off saying
@ -589,7 +592,7 @@ Error MachOPlatform::registerPerObjectSections(
inconvertibleErrorCode());
Error ErrResult = Error::success();
if (auto Err = EPC.runSPSWrapper<shared::SPSError(
if (auto Err = ES.callSPSWrapper<shared::SPSError(
SPSMachOPerObjectSectionsToRegister)>(
orc_rt_macho_register_object_sections.getValue(), ErrResult, POSR))
return Err;
@ -604,7 +607,7 @@ Expected<uint64_t> MachOPlatform::createPThreadKey() {
inconvertibleErrorCode());
Expected<uint64_t> Result(0);
if (auto Err = EPC.runSPSWrapper<SPSExpected<uint64_t>(void)>(
if (auto Err = ES.callSPSWrapper<SPSExpected<uint64_t>(void)>(
orc_rt_macho_create_pthread_key.getValue(), Result))
return std::move(Err);
return Result;

View File

@ -607,6 +607,11 @@ char ObjectLinkingLayer::ID;
using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
: BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
ES.registerResourceManager(*this);
}
ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
JITLinkMemoryManager &MemMgr)
: BaseT(ES), MemMgr(MemMgr) {

View File

@ -293,7 +293,8 @@ void LLVMOrcExecutionSessionSetErrorReporter(
LLVMOrcSymbolStringPoolRef
LLVMOrcExecutionSessionGetSymbolStringPool(LLVMOrcExecutionSessionRef ES) {
return wrap(unwrap(ES)->getSymbolStringPool().get());
return wrap(
unwrap(ES)->getExecutorProcessControl().getSymbolStringPool().get());
}
void LLVMOrcSymbolStringPoolClearDeadEntries(LLVMOrcSymbolStringPoolRef SSP) {

View File

@ -717,7 +717,8 @@ int main(int argc, char **argv, char * const *envp) {
}
// Create a remote target client running over the channel.
llvm::orc::ExecutionSession ES;
llvm::orc::ExecutionSession ES(
std::make_unique<orc::UnsupportedExecutorProcessControl>());
ES.setErrorReporter([&](Error Err) { ExitOnErr(std::move(Err)); });
typedef orc::remote::OrcRemoteTargetClient MyRemote;
auto R = ExitOnErr(MyRemote::Create(*C, ES));
@ -874,7 +875,8 @@ int runOrcJIT(const char *ProgName) {
// JIT builder to instantiate a default (which would fail with an error for
// unsupported architectures).
if (UseJITKind != JITKind::OrcLazy) {
auto ES = std::make_unique<orc::ExecutionSession>();
auto ES = std::make_unique<orc::ExecutionSession>(
ExitOnErr(orc::SelfExecutorProcessControl::Create()));
Builder.setLazyCallthroughManager(
std::make_unique<orc::LazyCallThroughManager>(*ES, 0, nullptr));
Builder.setExecutionSession(std::move(ES));
@ -934,9 +936,9 @@ int runOrcJIT(const char *ProgName) {
const Triple &) {
auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(*EPC))));
ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(*EPC))));
ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
return L;
});
}

View File

@ -621,7 +621,7 @@ static Error loadProcessSymbols(Session &S) {
};
S.MainJD->addGenerator(
ExitOnErr(orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(
*S.EPC, std::move(FilterMainEntryPoint))));
S.ES, std::move(FilterMainEntryPoint))));
return Error::success();
}
@ -630,7 +630,7 @@ static Error loadDylibs(Session &S) {
LLVM_DEBUG(dbgs() << "Loading dylibs...\n");
for (const auto &Dylib : Dylibs) {
LLVM_DEBUG(dbgs() << " " << Dylib << "\n");
auto G = orc::EPCDynamicLibrarySearchGenerator::Load(*S.EPC, Dylib.c_str());
auto G = orc::EPCDynamicLibrarySearchGenerator::Load(S.ES, Dylib.c_str());
if (!G)
return G.takeError();
S.MainJD->addGenerator(std::move(*G));
@ -880,13 +880,11 @@ Expected<std::unique_ptr<Session>> Session::Create(Triple TT) {
Session::~Session() {
if (auto Err = ES.endSession())
ES.reportError(std::move(Err));
if (auto Err = EPC->disconnect())
ES.reportError(std::move(Err));
}
Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
: EPC(std::move(EPC)), ES(this->EPC->getSymbolStringPool()),
ObjLayer(*this, this->EPC->getMemMgr()) {
: ES(std::move(EPC)),
ObjLayer(*this, ES.getExecutorProcessControl().getMemMgr()) {
/// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
/// Session.
@ -925,20 +923,20 @@ Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
ExitOnErr(loadDylibs(*this));
// Set up the platform.
if (this->EPC->getTargetTriple().isOSBinFormatMachO() && UseOrcRuntime) {
if (auto P = MachOPlatform::Create(ES, ObjLayer, *this->EPC, *MainJD,
auto &TT = ES.getExecutorProcessControl().getTargetTriple();
if (TT.isOSBinFormatMachO() && UseOrcRuntime) {
if (auto P = MachOPlatform::Create(ES, ObjLayer, *MainJD,
OrcRuntimePath.c_str()))
ES.setPlatform(std::move(*P));
else {
Err = P.takeError();
return;
}
} else if (!NoExec && !this->EPC->getTargetTriple().isOSWindows() &&
!this->EPC->getTargetTriple().isOSBinFormatMachO()) {
} else if (!NoExec && !TT.isOSWindows() && !TT.isOSBinFormatMachO()) {
ObjLayer.addPlugin(std::make_unique<EHFrameRegistrationPlugin>(
ES, ExitOnErr(EPCEHFrameRegistrar::Create(*this->EPC))));
ES, ExitOnErr(EPCEHFrameRegistrar::Create(this->ES))));
ObjLayer.addPlugin(std::make_unique<DebugObjectManagerPlugin>(
ES, ExitOnErr(createJITLoaderGDBRegistrar(*this->EPC))));
ES, ExitOnErr(createJITLoaderGDBRegistrar(this->ES))));
}
ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));
@ -985,10 +983,11 @@ void Session::modifyPassConfig(const Triple &TT,
PassConfiguration &PassConfig) {
if (!CheckFiles.empty())
PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {
if (EPC->getTargetTriple().getObjectFormat() == Triple::ELF)
auto &EPC = ES.getExecutorProcessControl();
if (EPC.getTargetTriple().getObjectFormat() == Triple::ELF)
return registerELFGraphInfo(*this, G);
if (EPC->getTargetTriple().getObjectFormat() == Triple::MachO)
if (EPC.getTargetTriple().getObjectFormat() == Triple::MachO)
return registerMachOGraphInfo(*this, G);
return make_error<StringError>("Unsupported object format for GOT/stub "
@ -1269,7 +1268,8 @@ static Error loadObjects(Session &S) {
if (Magic == file_magic::archive ||
Magic == file_magic::macho_universal_binary)
JD.addGenerator(ExitOnErr(StaticLibraryDefinitionGenerator::Load(
S.ObjLayer, InputFile.c_str(), S.EPC->getTargetTriple())));
S.ObjLayer, InputFile.c_str(),
S.ES.getExecutorProcessControl().getTargetTriple())));
else
ExitOnErr(S.ObjLayer.add(JD, std::move(ObjBuffer)));
}
@ -1316,13 +1316,14 @@ static Error loadObjects(Session &S) {
}
static Error runChecks(Session &S) {
const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
if (CheckFiles.empty())
return Error::success();
LLVM_DEBUG(dbgs() << "Running checks...\n");
auto TripleName = S.EPC->getTargetTriple().str();
auto TripleName = TT.str();
std::string ErrorStr;
const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, ErrorStr);
if (!TheTarget)
@ -1388,9 +1389,8 @@ static Error runChecks(Session &S) {
RuntimeDyldChecker Checker(
IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,
S.EPC->getTargetTriple().isLittleEndian() ? support::little
: support::big,
Disassembler.get(), InstPrinter.get(), dbgs());
TT.isLittleEndian() ? support::little : support::big, Disassembler.get(),
InstPrinter.get(), dbgs());
std::string CheckLineStart = "# " + CheckName + ":";
for (auto &CheckFile : CheckFiles) {
@ -1423,7 +1423,8 @@ static Expected<JITEvaluatedSymbol> getMainEntryPoint(Session &S) {
static Expected<JITEvaluatedSymbol> getOrcRuntimeEntryPoint(Session &S) {
std::string RuntimeEntryPoint = "__orc_rt_run_program_wrapper";
if (S.EPC->getTargetTriple().getObjectFormat() == Triple::MachO)
const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
if (TT.getObjectFormat() == Triple::MachO)
RuntimeEntryPoint = '_' + RuntimeEntryPoint;
return S.ES.lookup(S.JDSearchOrder, RuntimeEntryPoint);
}
@ -1431,13 +1432,14 @@ static Expected<JITEvaluatedSymbol> getOrcRuntimeEntryPoint(Session &S) {
static Expected<int> runWithRuntime(Session &S,
JITTargetAddress EntryPointAddress) {
StringRef DemangledEntryPoint = EntryPointName;
if (S.EPC->getTargetTriple().getObjectFormat() == Triple::MachO &&
const auto &TT = S.ES.getExecutorProcessControl().getTargetTriple();
if (TT.getObjectFormat() == Triple::MachO &&
DemangledEntryPoint.front() == '_')
DemangledEntryPoint = DemangledEntryPoint.drop_front();
using SPSRunProgramSig =
int64_t(SPSString, SPSString, SPSSequence<SPSString>);
int64_t Result;
if (auto Err = S.EPC->runSPSWrapper<SPSRunProgramSig>(
if (auto Err = S.ES.callSPSWrapper<SPSRunProgramSig>(
EntryPointAddress, Result, S.MainJD->getName(), DemangledEntryPoint,
static_cast<std::vector<std::string> &>(InputArgv)))
return std::move(Err);
@ -1446,7 +1448,8 @@ static Expected<int> runWithRuntime(Session &S,
static Expected<int> runWithoutRuntime(Session &S,
JITTargetAddress EntryPointAddress) {
return S.EPC->runAsMain(EntryPointAddress, InputArgv);
return S.ES.getExecutorProcessControl().runAsMain(EntryPointAddress,
InputArgv);
}
namespace {

View File

@ -109,7 +109,6 @@ private:
};
struct Session {
std::unique_ptr<orc::ExecutorProcessControl> EPC;
orc::ExecutionSession ES;
orc::JITDylib *MainJD = nullptr;
LLVMJITLinkObjectLinkingLayer ObjLayer;

View File

@ -16,7 +16,7 @@ set(LLVM_LINK_COMPONENTS
add_llvm_unittest(OrcJITTests
CoreAPIsTest.cpp
ExecutorProcessControlTest.cpp
ExecutionSessionWrapperFunctionCallsTest.cpp
IndirectionUtilsTest.cpp
JITTargetMachineBuilderTest.cpp
LazyCallThroughAndReexportsTest.cpp

View File

@ -1409,7 +1409,7 @@ TEST(JITDylibTest, GetDFSLinkOrderTree) {
// Test that DFS ordering behaves as expected when the linkage relationships
// form a tree.
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
auto &LibA = ES.createBareJITDylib("A");
auto &LibB = ES.createBareJITDylib("B");
@ -1450,7 +1450,7 @@ TEST(JITDylibTest, GetDFSLinkOrderDiamond) {
// Test that DFS ordering behaves as expected when the linkage relationships
// contain a diamond.
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
auto &LibA = ES.createBareJITDylib("A");
auto &LibB = ES.createBareJITDylib("B");
auto &LibC = ES.createBareJITDylib("C");
@ -1472,7 +1472,7 @@ TEST(JITDylibTest, GetDFSLinkOrderCycle) {
// Test that DFS ordering behaves as expected when the linkage relationships
// contain a cycle.
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
auto &LibA = ES.createBareJITDylib("A");
auto &LibB = ES.createBareJITDylib("B");
auto &LibC = ES.createBareJITDylib("C");

View File

@ -1,4 +1,4 @@
//===- ExecutorProcessControlTest.cpp - Test ExecutorProcessControl utils -===//
//===- ExecutionSessionWrapperFunctionCallsTest.cpp -- Test wrapper calls -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@ -6,8 +6,8 @@
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Testing/Support/Error.h"
#include "gtest/gtest.h"
@ -30,24 +30,22 @@ static void addAsyncWrapper(unique_function<void(int32_t)> SendResult,
SendResult(X + Y);
}
TEST(ExecutorProcessControl, RunWrapperTemplate) {
auto EPC = cantFail(
SelfExecutorProcessControl::Create(std::make_shared<SymbolStringPool>()));
TEST(ExecutionSessionWrapperFunctionCalls, RunWrapperTemplate) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
int32_t Result;
EXPECT_THAT_ERROR(EPC->runSPSWrapper<int32_t(int32_t, int32_t)>(
EXPECT_THAT_ERROR(ES.callSPSWrapper<int32_t(int32_t, int32_t)>(
pointerToJITTargetAddress(addWrapper), Result, 2, 3),
Succeeded());
EXPECT_EQ(Result, 5);
}
TEST(ExecutorProcessControl, RunWrapperAsyncTemplate) {
auto EPC = cantFail(
SelfExecutorProcessControl::Create(std::make_shared<SymbolStringPool>()));
TEST(ExecutionSessionWrapperFunctionCalls, RunWrapperAsyncTemplate) {
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
std::promise<MSVCPExpected<int32_t>> RP;
using Sig = int32_t(int32_t, int32_t);
EPC->runSPSWrapperAsync<Sig>(
ES.callSPSWrapperAsync<Sig>(
[&](Error SerializationErr, int32_t R) {
if (SerializationErr)
RP.set_value(std::move(SerializationErr));
@ -58,13 +56,11 @@ TEST(ExecutorProcessControl, RunWrapperAsyncTemplate) {
EXPECT_THAT_EXPECTED(Result, HasValue(5));
}
TEST(ExecutorProcessControl, RegisterAsyncHandlerAndRun) {
TEST(ExecutionSessionWrapperFunctionCalls, RegisterAsyncHandlerAndRun) {
constexpr JITTargetAddress AddAsyncTagAddr = 0x01;
auto EPC = cantFail(
SelfExecutorProcessControl::Create(std::make_shared<SymbolStringPool>()));
ExecutionSession ES(EPC->getSymbolStringPool());
ExecutionSession ES(cantFail(SelfExecutorProcessControl::Create()));
auto &JD = ES.createBareJITDylib("JD");
auto AddAsyncTag = ES.intern("addAsync_tag");
@ -72,12 +68,12 @@ TEST(ExecutorProcessControl, RegisterAsyncHandlerAndRun) {
{{AddAsyncTag,
JITEvaluatedSymbol(AddAsyncTagAddr, JITSymbolFlags::Exported)}})));
ExecutorProcessControl::WrapperFunctionAssociationMap Associations;
ExecutionSession::JITDispatchHandlerAssociationMap Associations;
Associations[AddAsyncTag] =
EPC->wrapAsyncWithSPS<int32_t(int32_t, int32_t)>(addAsyncWrapper);
ES.wrapAsyncWithSPS<int32_t(int32_t, int32_t)>(addAsyncWrapper);
cantFail(EPC->associateJITSideWrapperFunctions(JD, std::move(Associations)));
cantFail(ES.registerJITDispatchHandlers(JD, std::move(Associations)));
std::promise<int32_t> RP;
auto RF = RP.get_future();
@ -90,7 +86,7 @@ TEST(ExecutorProcessControl, RegisterAsyncHandlerAndRun) {
SPSOutputBuffer OB(ArgBufferData, ArgBufferSize);
EXPECT_TRUE(ArgSerialization::serialize(OB, 1, 2));
EPC->runJITSideWrapperFunction(
ES.runJITDispatchHandler(
[&](WrapperFunctionResult ResultBuffer) {
int32_t Result;
SPSInputBuffer IB(ResultBuffer.data(), ResultBuffer.size());

View File

@ -35,7 +35,7 @@ public:
}
protected:
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
JITDylib &JD = ES.createBareJITDylib("main");
ObjectLinkingLayer ObjLinkingLayer{
ES, std::make_unique<InProcessMemoryManager>()};

View File

@ -14,8 +14,9 @@
#ifndef LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
#define LLVM_UNITTESTS_EXECUTIONENGINE_ORC_ORCTESTCOMMON_H
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
@ -52,7 +53,7 @@ public:
protected:
std::shared_ptr<SymbolStringPool> SSP = std::make_shared<SymbolStringPool>();
ExecutionSession ES{SSP};
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>(SSP)};
JITDylib &JD = ES.createBareJITDylib("JD");
SymbolStringPtr Foo = ES.intern("foo");
SymbolStringPtr Bar = ES.intern("bar");

View File

@ -46,7 +46,7 @@ static bool testSetProcessAllSections(std::unique_ptr<MemoryBuffer> Obj,
bool NonAllocSectionSeen = false;
ExecutionSession ES;
ExecutionSession ES(std::make_unique<UnsupportedExecutorProcessControl>());
auto &JD = ES.createBareJITDylib("main");
auto Foo = ES.intern("foo");
@ -153,7 +153,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestOverrideObjectFlags) {
}
// Create a simple stack and set the override flags option.
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
auto &JD = ES.createBareJITDylib("main");
auto Foo = ES.intern("foo");
RTDyldObjectLinkingLayer ObjLayer(
@ -223,7 +223,7 @@ TEST(RTDyldObjectLinkingLayerTest, TestAutoClaimResponsibilityForSymbols) {
}
// Create a simple stack and set the override flags option.
ExecutionSession ES;
ExecutionSession ES{std::make_unique<UnsupportedExecutorProcessControl>()};
auto &JD = ES.createBareJITDylib("main");
auto Foo = ES.intern("foo");
RTDyldObjectLinkingLayer ObjLayer(