15#define DEBUG_TYPE "orc"
22 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
23 assert(Disconnected &&
"Destroyed without disconnection");
29 return DylibMgr->open(DylibPath, 0);
38 std::vector<tpctypes::LookupResult>
Result,
41 return Complete(std::move(
Result));
43 auto &Element = Request.
front();
44 DylibMgr.
lookupAsync(Element.Handle, Element.Symbols,
45 [&DylibMgr, Request, Complete = std::move(Complete),
48 return Complete(R.takeError());
50 Result.back().reserve(R->size());
68 if (
auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
69 RunAsMainAddr, Result, MainFnAddr, Args))
70 return std::move(Err);
76 if (
auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
77 RunAsVoidFunctionAddr, Result, VoidFnAddr))
78 return std::move(Err);
85 if (
auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
86 RunAsIntFunctionAddr, Result, IntFnAddr, Arg))
87 return std::move(Err);
96 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
97 SeqNo = getNextSeqNo();
98 assert(!PendingCallWrapperResults.count(SeqNo) &&
"SeqNo already in use");
99 PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
102 if (
auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
103 WrapperFnAddr, ArgBuffer)) {
112 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
113 auto I = PendingCallWrapperResults.find(SeqNo);
114 if (
I != PendingCallWrapperResults.end()) {
115 H = std::move(
I->second);
116 PendingCallWrapperResults.erase(
I);
121 H(shared::WrapperFunctionResult::createOutOfBandError(
"disconnecting"));
123 getExecutionSession().reportError(std::move(Err));
127Error SimpleRemoteEPC::disconnect() {
130 std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
131 DisconnectCV.wait(Lock, [
this] {
return Disconnected; });
132 return std::move(DisconnectErr);
141 dbgs() <<
"SimpleRemoteEPC::handleMessage: opc = ";
143 case SimpleRemoteEPCOpcode::Setup:
145 assert(SeqNo == 0 &&
"Non-zero SeqNo for Setup?");
146 assert(!TagAddr &&
"Non-zero TagAddr for Setup?");
148 case SimpleRemoteEPCOpcode::Hangup:
150 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
151 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
153 case SimpleRemoteEPCOpcode::Result:
155 assert(!TagAddr &&
"Non-zero TagAddr for Result?");
157 case SimpleRemoteEPCOpcode::CallWrapper:
158 dbgs() <<
"CallWrapper";
161 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
162 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
166 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
167 if (
static_cast<UT
>(OpC) >
static_cast<UT
>(SimpleRemoteEPCOpcode::LastOpC))
168 return make_error<StringError>(
"Unexpected opcode",
172 case SimpleRemoteEPCOpcode::Setup:
173 if (
auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
174 return std::move(Err);
176 case SimpleRemoteEPCOpcode::Hangup:
178 if (
auto Err = handleHangup(std::move(ArgBytes)))
179 return std::move(Err);
181 case SimpleRemoteEPCOpcode::Result:
182 if (
auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
183 return std::move(Err);
185 case SimpleRemoteEPCOpcode::CallWrapper:
186 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
189 return ContinueSession;
192void SimpleRemoteEPC::handleDisconnect(
Error Err) {
194 dbgs() <<
"SimpleRemoteEPC::handleDisconnect: "
195 << (Err ?
"failure" :
"success") <<
"\n";
201 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
202 std::swap(TmpPending, PendingCallWrapperResults);
205 for (
auto &KV : TmpPending)
207 shared::WrapperFunctionResult::createOutOfBandError(
"disconnecting"));
209 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
210 DisconnectErr =
joinErrors(std::move(DisconnectErr), std::move(Err));
212 DisconnectCV.notify_all();
219 {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
220 {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
221 {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
223 rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
224 return std::move(Err);
226 return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
229Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
230SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
234Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC,
uint64_t SeqNo,
235 ExecutorAddr TagAddr,
236 ArrayRef<char> ArgBytes) {
237 assert(OpC != SimpleRemoteEPCOpcode::Setup &&
238 "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
241 dbgs() <<
"SimpleRemoteEPC::sendMessage: opc = ";
243 case SimpleRemoteEPCOpcode::Hangup:
245 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
246 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
248 case SimpleRemoteEPCOpcode::Result:
250 assert(!TagAddr &&
"Non-zero TagAddr for Result?");
252 case SimpleRemoteEPCOpcode::CallWrapper:
253 dbgs() <<
"CallWrapper";
258 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
259 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.size())
262 auto Err =
T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
265 dbgs() <<
" \\--> SimpleRemoteEPC::sendMessage failed\n";
270Error SimpleRemoteEPC::handleSetup(
uint64_t SeqNo, ExecutorAddr TagAddr,
271 SimpleRemoteEPCArgBytesVector ArgBytes) {
273 return make_error<StringError>(
"Setup packet SeqNo not zero",
277 return make_error<StringError>(
"Setup packet TagAddr not zero",
280 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
281 auto I = PendingCallWrapperResults.find(0);
282 assert(PendingCallWrapperResults.size() == 1 &&
283 I != PendingCallWrapperResults.end() &&
284 "Setup message handler not connectly set up");
285 auto SetupMsgHandler = std::move(
I->second);
286 PendingCallWrapperResults.erase(
I);
289 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
290 SetupMsgHandler(std::move(WFR));
291 return Error::success();
294Error SimpleRemoteEPC::setup(Setup S) {
295 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
297 std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
298 auto EIF = EIP.get_future();
301 PendingCallWrapperResults[0] =
303 [&](shared::WrapperFunctionResult SetupMsgBytes) {
304 if (
const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
310 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
311 shared::SPSInputBuffer
IB(SetupMsgBytes.data(), SetupMsgBytes.size());
312 SimpleRemoteEPCExecutorInfo EI;
313 if (SPSSerialize::deserialize(IB, EI))
316 EIP.set_value(make_error<StringError>(
321 if (
auto Err =
T->start())
328 return EI.takeError();
332 dbgs() <<
"SimpleRemoteEPC received setup message:\n"
333 <<
" Triple: " << EI->TargetTriple <<
"\n"
334 <<
" Page size: " << EI->PageSize <<
"\n"
335 <<
" Bootstrap map" << (EI->BootstrapMap.empty() ?
" empty" :
":")
337 for (
const auto &KV : EI->BootstrapMap)
338 dbgs() <<
" " << KV.first() <<
": " << KV.second.size()
339 <<
"-byte SPS encoded buffer\n";
340 dbgs() <<
" Bootstrap symbols"
341 << (EI->BootstrapSymbols.empty() ?
" empty" :
":") <<
"\n";
342 for (
const auto &KV : EI->BootstrapSymbols)
343 dbgs() <<
" " << KV.first() <<
": " << KV.second <<
"\n";
345 TargetTriple = Triple(EI->TargetTriple);
347 BootstrapMap = std::move(EI->BootstrapMap);
348 BootstrapSymbols = std::move(EI->BootstrapSymbols);
350 if (
auto Err = getBootstrapSymbols(
353 {RunAsMainAddr, rt::RunAsMainWrapperName},
354 {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
355 {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
359 EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*
this))
360 DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*
DM));
362 return DM.takeError();
365 if (!S.CreateMemoryManager)
366 S.CreateMemoryManager = createDefaultMemoryManager;
368 if (
auto MemMgr = S.CreateMemoryManager(*
this)) {
369 OwnedMemMgr = std::move(*MemMgr);
370 this->MemMgr = OwnedMemMgr.get();
372 return MemMgr.takeError();
375 if (!S.CreateMemoryAccess)
376 S.CreateMemoryAccess = createDefaultMemoryAccess;
378 if (
auto MemAccess = S.CreateMemoryAccess(*
this)) {
379 OwnedMemAccess = std::move(*MemAccess);
380 this->MemAccess = OwnedMemAccess.get();
382 return MemAccess.takeError();
384 return Error::success();
387Error SimpleRemoteEPC::handleResult(
uint64_t SeqNo, ExecutorAddr TagAddr,
388 SimpleRemoteEPCArgBytesVector ArgBytes) {
389 IncomingWFRHandler SendResult;
392 return make_error<StringError>(
"Unexpected TagAddr in result message",
396 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
397 auto I = PendingCallWrapperResults.find(SeqNo);
398 if (
I == PendingCallWrapperResults.end())
399 return make_error<StringError>(
"No call for sequence number " +
402 SendResult = std::move(
I->second);
403 PendingCallWrapperResults.erase(
I);
408 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
409 SendResult(std::move(WFR));
410 return Error::success();
413void SimpleRemoteEPC::handleCallWrapper(
414 uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
415 SimpleRemoteEPCArgBytesVector ArgBytes) {
416 assert(ES &&
"No ExecutionSession attached");
418 [
this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
419 ES->runJITDispatchHandler(
420 [
this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
422 sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
423 ExecutorAddr(), {WFR.data(), WFR.size()}))
428 "callWrapper task"));
431Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
433 auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
434 if (
const char *ErrMsg = WFR.getOutOfBandError())
440 return make_error<StringError>(
"Could not deserialize hangup info",
static Error reportError(StringRef Message)
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Analysis containing CSE Info
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
static cl::opt< int > PageSize("imp-null-check-page-size", cl::desc("The page size of the target in bytes"), cl::init(4096), cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
const T & front() const
front - Get the first element.
bool empty() const
empty - Check if the array is empty.
Lightweight error class with error context and mandatory checking.
Tagged union holding either a T or a Error.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void lookupAsync(tpctypes::DylibHandle H, const SymbolLookupSet &Lookup, SymbolLookupCompleteFn Complete)
Looks up symbols within the given dylib.
Represents an address in the executor process.
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
Error getBootstrapSymbols(ArrayRef< std::pair< ExecutorAddr &, StringRef > > Pairs) const
For each (ExecutorAddr&, StringRef) pair, looks up the string in the bootstrap symbols map and writes...
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
A utility class for serializing to a blob from a variadic list.
unique_function is a type-erasing functor similar to std::function.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const char * DispatchFnName
const char * ExecutorSessionObjectName
Error fromSPSSerializable(SPSSerializableError BSE)
std::unique_ptr< GenericNamedTask > makeGenericNamedTask(FnT &&Fn, std::string Desc)
Create a generic named task from a std::string description.
static void lookupSymbolsAsyncHelper(EPCGenericDylibManager &DylibMgr, ArrayRef< SimpleRemoteEPC::LookupRequest > Request, std::vector< tpctypes::LookupResult > Result, SimpleRemoteEPC::SymbolLookupCompleteFn Complete)
Async helper to chain together calls to DylibMgr::lookupAsync to fulfill all all the requests.
This is an optimization pass for GlobalISel generic memory operations.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
auto formatv(const char *Fmt, Ts &&...Vals) -> formatv_object< decltype(std::make_tuple(support::detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Error joinErrors(Error E1, Error E2)
Concatenate errors.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Function addresses for memory access.
Helper type for serializing Errors.