#ifndef LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
#define LLVM_EXECUTIONENGINE_ORC_TARGETPROCESS_SIMPLEREMOTEEPCSERVER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/FunctionExtras.h"
#include "llvm/Config/llvm-config.h"
#include "llvm/ExecutionEngine/Orc/Shared/SimpleRemoteEPCUtils.h"
#include "llvm/ExecutionEngine/Orc/Shared/TargetProcessControlTypes.h"
#include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/ExecutorBootstrapService.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/SimpleExecutorDylibManager.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/Error.h"
#include <condition_variable>
#include <future>
#include <memory>
#include <mutex>
namespace llvm {
namespace orc {
class SimpleRemoteEPCServer : public SimpleRemoteEPCTransportClient {
public:
using ReportErrorFunction = unique_function<void(Error)>;
class Dispatcher {
public:
virtual ~Dispatcher();
virtual void dispatch(unique_function<void()> Work) = 0;
virtual void shutdown() = 0;
};
#if LLVM_ENABLE_THREADS
class ThreadDispatcher : public Dispatcher {
public:
void dispatch(unique_function<void()> Work) override;
void shutdown() override;
private:
std::mutex DispatchMutex;
bool Running = true;
size_t Outstanding = 0;
std::condition_variable OutstandingCV;
};
#endif
class Setup {
friend class SimpleRemoteEPCServer;
public:
SimpleRemoteEPCServer &server() { return S; }
StringMap<ExecutorAddr> &bootstrapSymbols() { return BootstrapSymbols; }
std::vector<std::unique_ptr<ExecutorBootstrapService>> &services() {
return Services;
}
void setDispatcher(std::unique_ptr<Dispatcher> D) { S.D = std::move(D); }
void setErrorReporter(unique_function<void(Error)> ReportError) {
S.ReportError = std::move(ReportError);
}
private:
Setup(SimpleRemoteEPCServer &S) : S(S) {}
SimpleRemoteEPCServer &S;
StringMap<ExecutorAddr> BootstrapSymbols;
std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
};
static StringMap<ExecutorAddr> defaultBootstrapSymbols();
template <typename TransportT, typename... TransportTCtorArgTs>
static Expected<std::unique_ptr<SimpleRemoteEPCServer>>
Create(unique_function<Error(Setup &S)> SetupFunction,
TransportTCtorArgTs &&...TransportTCtorArgs) {
auto Server = std::make_unique<SimpleRemoteEPCServer>();
Setup S(*Server);
if (auto Err = SetupFunction(S))
return std::move(Err);
if (!Server->ReportError)
Server->ReportError = [](Error Err) {
logAllUnhandledErrors(std::move(Err), errs(), "SimpleRemoteEPCServer ");
};
auto T = TransportT::Create(
*Server, std::forward<TransportTCtorArgTs>(TransportTCtorArgs)...);
if (!T)
return T.takeError();
Server->T = std::move(*T);
if (auto Err = Server->T->start())
return std::move(Err);
Server->Services = std::move(S.services());
Server->Services.push_back(
std::make_unique<rt_bootstrap::SimpleExecutorDylibManager>());
for (auto &Service : Server->Services)
Service->addBootstrapSymbols(S.bootstrapSymbols());
if (auto Err = Server->sendSetupMessage(std::move(S.BootstrapSymbols)))
return std::move(Err);
return std::move(Server);
}
void setErrorReporter(ReportErrorFunction ReportError) {
this->ReportError = std::move(ReportError);
}
Expected<HandleMessageAction>
handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes) override;
Error waitForDisconnect();
void handleDisconnect(Error Err) override;
private:
Error sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
ExecutorAddr TagAddr, ArrayRef<char> ArgBytes);
Error sendSetupMessage(StringMap<ExecutorAddr> BootstrapSymbols);
Error handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes);
void handleCallWrapper(uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
SimpleRemoteEPCArgBytesVector ArgBytes);
shared::WrapperFunctionResult
doJITDispatch(const void *FnTag, const char *ArgData, size_t ArgSize);
static shared::CWrapperFunctionResult jitDispatchEntry(void *DispatchCtx,
const void *FnTag,
const char *ArgData,
size_t ArgSize);
uint64_t getNextSeqNo() { return NextSeqNo++; }
void releaseSeqNo(uint64_t) {}
using PendingJITDispatchResultsMap =
DenseMap<uint64_t, std::promise<shared::WrapperFunctionResult> *>;
std::mutex ServerStateMutex;
std::condition_variable ShutdownCV;
enum { ServerRunning, ServerShuttingDown, ServerShutDown } RunState;
Error ShutdownErr = Error::success();
std::unique_ptr<SimpleRemoteEPCTransport> T;
std::unique_ptr<Dispatcher> D;
std::vector<std::unique_ptr<ExecutorBootstrapService>> Services;
ReportErrorFunction ReportError;
uint64_t NextSeqNo = 0;
PendingJITDispatchResultsMap PendingJITDispatchResults;
std::vector<sys::DynamicLibrary> Dylibs;
};
} }
#endif