class SimpleRemoteEPC : public ExecutorProcessControl,
public SimpleRemoteEPCTransportClient {
public:
+ /// A setup object containing callbacks to construct a memory manager and
+ /// memory access object. Both are optional. If not specified,
+ /// EPCGenericJITLinkMemoryManager and EPCGenericMemoryAccess will be used.
+ struct Setup {
+ using CreateMemoryManagerFn =
+ Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>(
+ SimpleRemoteEPC &);
+ using CreateMemoryAccessFn =
+ Expected<std::unique_ptr<MemoryAccess>>(SimpleRemoteEPC &);
+
+ unique_function<CreateMemoryManagerFn> CreateMemoryManager;
+ unique_function<CreateMemoryAccessFn> CreateMemoryAccess;
+ };
+
/// Create a SimpleRemoteEPC using the given transport type and args.
template <typename TransportT, typename... TransportTCtorArgTs>
static Expected<std::unique_ptr<SimpleRemoteEPC>>
- Create(std::unique_ptr<TaskDispatcher> D,
+ Create(std::unique_ptr<TaskDispatcher> D, Setup S,
TransportTCtorArgTs &&...TransportTCtorArgs) {
std::unique_ptr<SimpleRemoteEPC> SREPC(
new SimpleRemoteEPC(std::make_shared<SymbolStringPool>(),
if (!T)
return T.takeError();
SREPC->T = std::move(*T);
- if (auto Err = SREPC->setup())
+ if (auto Err = SREPC->setup(std::move(S)))
return joinErrors(std::move(Err), SREPC->disconnect());
return std::move(SREPC);
}
void handleDisconnect(Error Err) override;
-protected:
- virtual Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
- createMemoryManager();
- virtual Expected<std::unique_ptr<MemoryAccess>> createMemoryAccess();
-
private:
SimpleRemoteEPC(std::shared_ptr<SymbolStringPool> SSP,
std::unique_ptr<TaskDispatcher> D)
: ExecutorProcessControl(std::move(SSP), std::move(D)) {}
+ static Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
+ createDefaultMemoryManager(SimpleRemoteEPC &SREPC);
+ static Expected<std::unique_ptr<MemoryAccess>>
+ createDefaultMemoryAccess(SimpleRemoteEPC &SREPC);
+
Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
Error handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes);
- Error setup();
+ Error setup(Setup S);
Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes);
}
Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
-SimpleRemoteEPC::createMemoryManager() {
+SimpleRemoteEPC::createDefaultMemoryManager(SimpleRemoteEPC &SREPC) {
EPCGenericJITLinkMemoryManager::SymbolAddrs SAs;
- if (auto Err = getBootstrapSymbols(
+ if (auto Err = SREPC.getBootstrapSymbols(
{{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
{SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
{SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
return std::move(Err);
- return std::make_unique<EPCGenericJITLinkMemoryManager>(*this, SAs);
+ return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
}
Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
-SimpleRemoteEPC::createMemoryAccess() {
-
+SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
return nullptr;
}
return Error::success();
}
-Error SimpleRemoteEPC::setup() {
+Error SimpleRemoteEPC::setup(Setup S) {
using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
else
return DM.takeError();
- if (auto MemMgr = createMemoryManager()) {
+ // Set a default CreateMemoryManager if none is specified.
+ if (!S.CreateMemoryManager)
+ S.CreateMemoryManager = createDefaultMemoryManager;
+
+ if (auto MemMgr = S.CreateMemoryManager(*this)) {
OwnedMemMgr = std::move(*MemMgr);
this->MemMgr = OwnedMemMgr.get();
} else
return MemMgr.takeError();
- if (auto MemAccess = createMemoryAccess()) {
+ // Set a default CreateMemoryAccess if none is specified.
+ if (!S.CreateMemoryAccess)
+ S.CreateMemoryAccess = createDefaultMemoryAccess;
+
+ if (auto MemAccess = S.CreateMemoryAccess(*this)) {
OwnedMemAccess = std::move(*MemAccess);
this->MemAccess = OwnedMemAccess.get();
} else
// Return a SimpleRemoteEPC instance connected to our end of the pipes.
return orc::SimpleRemoteEPC::Create<orc::FDSimpleRemoteEPCTransport>(
std::make_unique<llvm::orc::InPlaceTaskDispatcher>(),
- PipeFD[1][0], PipeFD[0][1]);
+ llvm::orc::SimpleRemoteEPC::Setup(), PipeFD[1][0], PipeFD[0][1]);
#endif
}
return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
std::make_unique<DynamicThreadPoolTaskDispatcher>(),
- FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
+ SimpleRemoteEPC::Setup(), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);
#endif
}
return SockFD.takeError();
return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(
- std::make_unique<DynamicThreadPoolTaskDispatcher>(), *SockFD, *SockFD);
+ std::make_unique<DynamicThreadPoolTaskDispatcher>(),
+ SimpleRemoteEPC::Setup(), *SockFD, *SockFD);
#endif
}