20#define DEBUG_TYPE "orc"
27 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
28 assert(Disconnected &&
"Destroyed without disconnection");
51 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
52 SeqNo = getNextSeqNo();
53 assert(!PendingCallWrapperResults.count(SeqNo) &&
"SeqNo already in use");
54 PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
58 WrapperFnAddr, ArgBuffer)) {
67 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
68 auto I = PendingCallWrapperResults.find(SeqNo);
69 if (
I != PendingCallWrapperResults.end()) {
70 H = std::move(
I->second);
71 PendingCallWrapperResults.erase(
I);
101 bool SendHangup =
false;
103 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
104 SendHangup = !LocalHangup && !RemoteHangup;
116 {Payload.data(), Payload.size()}))
122 std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
123 DisconnectCV.wait(Lock, [
this] {
return Disconnected; });
124 return std::move(DisconnectErr);
133 dbgs() <<
"SimpleRemoteEPC::handleMessage: opc = ";
137 assert(SeqNo == 0 &&
"Non-zero SeqNo for Setup?");
138 assert(!TagAddr &&
"Non-zero TagAddr for Setup?");
142 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
143 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
149 dbgs() <<
"CallWrapper";
152 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
153 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
157 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
164 if (
auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
165 return std::move(Err);
170 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
173 if (
auto Err = handleHangup(std::move(ArgBytes)))
174 return std::move(Err);
177 if (
auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
178 return std::move(Err);
181 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
189 dbgs() <<
"SimpleRemoteEPC::handleDisconnect: "
190 << (Err ?
"failure" :
"success") <<
"\n";
193 PendingCallWrapperResultsMap TmpPending;
196 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
197 std::swap(TmpPending, PendingCallWrapperResults);
200 for (
auto &KV : TmpPending)
204 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
217 Error DisconnectReason =
218 (!Err && !LocalHangup && !RemoteHangup)
224 joinErrors(std::move(DisconnectErr), std::move(DisconnectReason));
226 DisconnectCV.notify_all();
233 "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
236 dbgs() <<
"SimpleRemoteEPC::sendMessage: opc = ";
240 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
241 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
247 dbgs() <<
"CallWrapper";
252 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
253 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
256 auto Err =
T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
259 dbgs() <<
" \\--> SimpleRemoteEPC::sendMessage failed\n";
274 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
275 auto I = PendingCallWrapperResults.find(0);
276 assert(PendingCallWrapperResults.size() == 1 &&
277 I != PendingCallWrapperResults.end() &&
278 "Setup message handler not connectly set up");
279 auto SetupMsgHandler = std::move(
I->second);
280 PendingCallWrapperResults.erase(
I);
284 SetupMsgHandler(std::move(WFR));
288Error SimpleRemoteEPC::setup() {
289 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
291 std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
292 auto EIF = EIP.get_future();
295 PendingCallWrapperResults[0] =
297 [&](shared::WrapperFunctionBuffer SetupMsgBytes) {
298 if (
const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
304 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
305 shared::SPSInputBuffer
IB(SetupMsgBytes.data(), SetupMsgBytes.size());
306 SimpleRemoteEPCExecutorInfo EI;
307 if (SPSSerialize::deserialize(IB, EI))
315 if (
auto Err = T->start())
322 return EI.takeError();
326 dbgs() <<
"SimpleRemoteEPC received setup message:\n"
327 <<
" Triple: " << EI->TargetTriple <<
"\n"
328 <<
" Page size: " << EI->PageSize <<
"\n"
329 <<
" Bootstrap map" << (EI->BootstrapMap.empty() ?
" empty" :
":")
331 for (
const auto &KV : EI->BootstrapMap)
332 dbgs() <<
" " << KV.first() <<
": " << KV.second.size()
333 <<
"-byte SPS encoded buffer\n";
334 dbgs() <<
" Bootstrap symbols"
335 << (EI->BootstrapSymbols.empty() ?
" empty" :
":") <<
"\n";
336 for (
const auto &KV : EI->BootstrapSymbols)
337 dbgs() <<
" " << KV.first() <<
": " << KV.second <<
"\n";
359 return WFR.takeError();
362 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
363 auto I = PendingCallWrapperResults.find(SeqNo);
364 if (
I == PendingCallWrapperResults.end())
368 SendResult = std::move(
I->second);
369 PendingCallWrapperResults.erase(
I);
373 SendResult(std::move(*WFR));
377void SimpleRemoteEPC::handleCallWrapper(
380 assert(
ES &&
"No ExecutionSession attached");
382 [
this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]()
mutable {
383 ES->runJITDispatchHandler(
384 [
this, RemoteSeqNo](shared::WrapperFunctionBuffer WFR) {
388 ResultTag, {Payload.data(), Payload.size()}))
391 TagAddr, std::move(ArgBytes));
393 "callWrapper task"));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
void reportError(Error Err)
Report a error for this execution session.
Represents an address in the executor process.
A handler or incoming WrapperFunctionBuffers – either return values from callWrapper* calls,...
Constructs an IncomingWFRHandler from a function object that is callable as void(shared::WrapperFunct...
std::unique_ptr< TaskDispatcher > D
const Triple & getTargetTriple() const
Return the Triple for the target process.
StringMap< ExecutorAddr > BootstrapSymbols
StringMap< std::vector< char > > BootstrapMap
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
void handleDisconnect(Error Err) override
Handle a disconnection from the underlying transport.
Expected< std::unique_ptr< MemoryAccess > > createDefaultMemoryAccess() override
Create a default MemoryAccess for the target process.
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.
Expected< std::unique_ptr< jitlink::JITLinkMemoryManager > > createDefaultMemoryManager() override
Create a default JITLinkMemoryManager for the target process.
Expected< HandleMessageAction > handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, shared::WrapperFunctionBuffer ArgBytes) override
Handle receipt of a message.
~SimpleRemoteEPC() override
Expected< std::unique_ptr< DylibManager > > createDefaultDylibMgr() override
Create a default DylibManager for the target process.
Error disconnect() override
Disconnect from the target process.
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
C++ wrapper function buffer: Same as CWrapperFunctionBuffer but auto-releases memory.
static WrapperFunctionBuffer copyFrom(const char *Source, size_t Size)
Copy from the given char range.
size_t size() const
Returns the size of the data contained in this instance.
static WrapperFunctionBuffer createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI const char * DispatchFnName
LLVM_ABI const char * ExecutorSessionObjectName
LLVM_ABI const SymbolNameSpec DispatchCtxName
LLVM_ABI const SymbolNameSpec DispatchName
LLVM_ABI Expected< std::unique_ptr< EPCGenericJITLinkMemoryManager > > createEPCGenericJITLinkMemoryManager(JITDylib &JD)
Create an EPCGenericJITLinkMemoryManager for the ORC runtime's SimpleNativeMemoryMap interface,...
LLVM_ABI Expected< std::unique_ptr< EPCGenericDylibManager > > createEPCGenericDylibManager(JITDylib &JD)
Create an EPCGenericDylibManager for the ORC runtime's NativeDylibManager interface,...
LLVM_ABI Expected< std::unique_ptr< EPCGenericMemoryAccess > > createEPCGenericMemoryAccess(JITDylib &JD)
Create an EPCGenericMemoryAccess that reaches the memory-access wrappers in the given JITDylib via th...
LookupPrepareFn recordProxy(Proxy< FnT > *P, typename Proxy< FnT >::DispatchFn Dispatch, SymbolNameSpec Name, SymbolLookupFlags LF=SymbolLookupFlags::RequiredSymbol)
Builds P over the symbol with the given name, dispatching through Dispatch.
LLVM_ABI shared::WrapperFunctionBuffer encodeHangupPayload(Error Err)
Encode an Error as the payload of a Hangup message.
LLVM_ABI std::pair< ExecutorAddr, shared::WrapperFunctionBuffer > encodeResultMessage(shared::WrapperFunctionBuffer ResultBytes)
Encode a wrapper function result as the TagAddr and payload of a Result message.
std::unique_ptr< GenericNamedTask > makeGenericNamedTask(FnT &&Fn, std::string Desc)
Create a generic named task from a std::string description.
LLVM_ABI void lookupAndApply(unique_function< void(Error)> OnApplied, LookupKind K, const JITDylibSearchOrder &SearchOrder, ArrayRef< LookupPrepareFn > PrepareFns)
Resolve the symbols contributed by every prepare function with a single lookup, then let each of thei...
LLVM_ABI Error decodeHangupPayload(shared::WrapperFunctionBuffer Payload)
Decode a Hangup payload produced by encodeHangupPayload.
LLVM_ABI Expected< shared::WrapperFunctionBuffer > decodeResultMessage(ExecutorAddr TagAddr, shared::WrapperFunctionBuffer Payload)
Decode a Result message produced by encodeResultMessage, returning the result to complete the pending...
This is an optimization pass for GlobalISel generic memory operations.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(bool Validate, const char *Fmt, Ts &&...Vals)
Error joinErrors(Error E1, Error E2)
Concatenate errors.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Error make_error(ArgTs &&... Args)
Make a Error instance representing failure using the given error info type.
void consumeError(Error Err)
Consume a Error without doing anything.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.