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);
34 std::vector<tpctypes::LookupResult>
Result;
36 for (
auto &Element : Request) {
37 if (
auto R = DylibMgr->lookup(Element.Handle, Element.Symbols)) {
39 Result.back().reserve(R->size());
51 if (
auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
52 RunAsMainAddr,
Result, MainFnAddr, Args))
53 return std::move(Err);
59 if (
auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
60 RunAsVoidFunctionAddr,
Result, VoidFnAddr))
61 return std::move(Err);
68 if (
auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
69 RunAsIntFunctionAddr,
Result, IntFnAddr,
Arg))
70 return std::move(Err);
79 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
80 SeqNo = getNextSeqNo();
81 assert(!PendingCallWrapperResults.
count(SeqNo) &&
"SeqNo already in use");
82 PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
86 WrapperFnAddr, ArgBuffer)) {
95 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
96 auto I = PendingCallWrapperResults.
find(SeqNo);
97 if (
I != PendingCallWrapperResults.
end()) {
98 H = std::move(
I->second);
99 PendingCallWrapperResults.
erase(
I);
113 std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
114 DisconnectCV.wait(Lock, [
this] {
return Disconnected; });
115 return std::move(DisconnectErr);
124 dbgs() <<
"SimpleRemoteEPC::handleMessage: opc = ";
128 assert(SeqNo == 0 &&
"Non-zero SeqNo for Setup?");
129 assert(!TagAddr &&
"Non-zero TagAddr for Setup?");
133 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
134 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
138 assert(!TagAddr &&
"Non-zero TagAddr for Result?");
141 dbgs() <<
"CallWrapper";
144 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
145 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.
size())
149 using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
151 return make_error<StringError>(
"Unexpected opcode",
156 if (
auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
157 return std::move(Err);
161 if (
auto Err = handleHangup(std::move(ArgBytes)))
162 return std::move(Err);
165 if (
auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
166 return std::move(Err);
169 handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
177 dbgs() <<
"SimpleRemoteEPC::handleDisconnect: "
178 << (Err ?
"failure" :
"success") <<
"\n";
184 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
185 std::swap(TmpPending, PendingCallWrapperResults);
188 for (
auto &KV : TmpPending)
192 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
193 DisconnectErr =
joinErrors(std::move(DisconnectErr), std::move(Err));
195 DisconnectCV.notify_all();
202 {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
203 {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
204 {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
206 rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
207 return std::move(Err);
209 return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
212Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
213SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
217Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC,
uint64_t SeqNo,
218 ExecutorAddr TagAddr,
219 ArrayRef<char> ArgBytes) {
220 assert(OpC != SimpleRemoteEPCOpcode::Setup &&
221 "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
224 dbgs() <<
"SimpleRemoteEPC::sendMessage: opc = ";
226 case SimpleRemoteEPCOpcode::Hangup:
228 assert(SeqNo == 0 &&
"Non-zero SeqNo for Hangup?");
229 assert(!TagAddr &&
"Non-zero TagAddr for Hangup?");
231 case SimpleRemoteEPCOpcode::Result:
233 assert(!TagAddr &&
"Non-zero TagAddr for Result?");
235 case SimpleRemoteEPCOpcode::CallWrapper:
236 dbgs() <<
"CallWrapper";
241 dbgs() <<
", seqno = " << SeqNo <<
", tag-addr = " << TagAddr
242 <<
", arg-buffer = " <<
formatv(
"{0:x}", ArgBytes.size())
245 auto Err =
T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
248 dbgs() <<
" \\--> SimpleRemoteEPC::sendMessage failed\n";
253Error SimpleRemoteEPC::handleSetup(
uint64_t SeqNo, ExecutorAddr TagAddr,
254 SimpleRemoteEPCArgBytesVector ArgBytes) {
256 return make_error<StringError>(
"Setup packet SeqNo not zero",
260 return make_error<StringError>(
"Setup packet TagAddr not zero",
263 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
264 auto I = PendingCallWrapperResults.find(0);
265 assert(PendingCallWrapperResults.size() == 1 &&
266 I != PendingCallWrapperResults.end() &&
267 "Setup message handler not connectly set up");
268 auto SetupMsgHandler = std::move(
I->second);
269 PendingCallWrapperResults.erase(
I);
272 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
273 SetupMsgHandler(std::move(WFR));
277Error SimpleRemoteEPC::setup(Setup S) {
278 using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
280 std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
281 auto EIF = EIP.get_future();
284 PendingCallWrapperResults[0] =
286 [&](shared::WrapperFunctionResult SetupMsgBytes) {
287 if (
const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
293 shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
294 shared::SPSInputBuffer
IB(SetupMsgBytes.data(), SetupMsgBytes.size());
295 SimpleRemoteEPCExecutorInfo EI;
296 if (SPSSerialize::deserialize(IB, EI))
299 EIP.set_value(make_error<StringError>(
304 if (
auto Err =
T->start())
311 return EI.takeError();
315 dbgs() <<
"SimpleRemoteEPC received setup message:\n"
316 <<
" Triple: " << EI->TargetTriple <<
"\n"
317 <<
" Page size: " << EI->PageSize <<
"\n"
318 <<
" Bootstrap map" << (EI->BootstrapMap.empty() ?
" empty" :
":")
320 for (
const auto &KV : EI->BootstrapMap)
321 dbgs() <<
" " << KV.first() <<
": " << KV.second.size()
322 <<
"-byte SPS encoded buffer\n";
323 dbgs() <<
" Bootstrap symbols"
324 << (EI->BootstrapSymbols.empty() ?
" empty" :
":") <<
"\n";
325 for (
const auto &KV : EI->BootstrapSymbols)
326 dbgs() <<
" " << KV.first() <<
": " << KV.second <<
"\n";
328 TargetTriple = Triple(EI->TargetTriple);
330 BootstrapMap = std::move(EI->BootstrapMap);
331 BootstrapSymbols = std::move(EI->BootstrapSymbols);
333 if (
auto Err = getBootstrapSymbols(
336 {RunAsMainAddr, rt::RunAsMainWrapperName},
337 {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
338 {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
342 EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*
this))
343 DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*
DM));
345 return DM.takeError();
348 if (!S.CreateMemoryManager)
349 S.CreateMemoryManager = createDefaultMemoryManager;
351 if (
auto MemMgr = S.CreateMemoryManager(*
this)) {
352 OwnedMemMgr = std::move(*MemMgr);
353 this->MemMgr = OwnedMemMgr.get();
355 return MemMgr.takeError();
358 if (!S.CreateMemoryAccess)
359 S.CreateMemoryAccess = createDefaultMemoryAccess;
361 if (
auto MemAccess = S.CreateMemoryAccess(*
this)) {
362 OwnedMemAccess = std::move(*MemAccess);
363 this->MemAccess = OwnedMemAccess.get();
365 return MemAccess.takeError();
370Error SimpleRemoteEPC::handleResult(
uint64_t SeqNo, ExecutorAddr TagAddr,
371 SimpleRemoteEPCArgBytesVector ArgBytes) {
372 IncomingWFRHandler SendResult;
375 return make_error<StringError>(
"Unexpected TagAddr in result message",
379 std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
380 auto I = PendingCallWrapperResults.find(SeqNo);
381 if (
I == PendingCallWrapperResults.end())
382 return make_error<StringError>(
"No call for sequence number " +
385 SendResult = std::move(
I->second);
386 PendingCallWrapperResults.erase(
I);
391 shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
392 SendResult(std::move(WFR));
396void SimpleRemoteEPC::handleCallWrapper(
397 uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
398 SimpleRemoteEPCArgBytesVector ArgBytes) {
399 assert(ES &&
"No ExecutionSession attached");
401 [
this, RemoteSeqNo, TagAddr, ArgBytes = std::move(ArgBytes)]() {
402 ES->runJITDispatchHandler(
403 [
this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
405 sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
406 ExecutorAddr(), {WFR.data(), WFR.size()}))
411 "callWrapper task"));
414Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
416 auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
417 if (
const char *ErrMsg = WFR.getOutOfBandError())
423 return make_error<StringError>(
"Could not deserialize hangup info",
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
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),...
iterator find(const_arg_type_t< KeyT > Val)
bool erase(const KeyT &Val)
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
void reportError(Error Err)
Report a error for this execution session.
Represents an address in the executor process.
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
std::unique_ptr< TaskDispatcher > D
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...
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
void handleDisconnect(Error Err) override
Handle a disconnection from the underlying transport.
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.
Expected< HandleMessageAction > handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, SimpleRemoteEPCArgBytesVector ArgBytes) override
Handle receipt of a message.
Error disconnect() override
Disconnect from the target process.
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
Expected< std::vector< tpctypes::LookupResult > > lookupSymbols(ArrayRef< LookupRequest > Request) override
Search for symbols in the target process.
Expected< int32_t > runAsVoidFunction(ExecutorAddr VoidFnAddr) override
Run function with a int (*)(void) signature.
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
Expected< int32_t > runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override
Run function with a int (*)(int) signature.
A utility class for serializing to a blob from a variadic list.
static WrapperFunctionResult 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.
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.
This is an optimization pass for GlobalISel generic memory operations.
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
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.