LLVM  14.0.0git
SimpleRemoteEPC.cpp
Go to the documentation of this file.
1 //===------- SimpleRemoteEPC.cpp -- Simple remote executor control --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
14 
15 #define DEBUG_TYPE "orc"
16 
17 namespace llvm {
18 namespace orc {
19 
21 #ifndef NDEBUG
22  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
23  assert(Disconnected && "Destroyed without disconnection");
24 #endif // NDEBUG
25 }
26 
28 SimpleRemoteEPC::loadDylib(const char *DylibPath) {
29  return DylibMgr->open(DylibPath, 0);
30 }
31 
34  std::vector<tpctypes::LookupResult> Result;
35 
36  for (auto &Element : Request) {
37  if (auto R = DylibMgr->lookup(Element.Handle, Element.Symbols)) {
38  Result.push_back({});
39  Result.back().reserve(R->size());
40  for (auto Addr : *R)
41  Result.back().push_back(Addr.getValue());
42  } else
43  return R.takeError();
44  }
45  return std::move(Result);
46 }
47 
50  int64_t Result = 0;
51  if (auto Err = callSPSWrapper<rt::SPSRunAsMainSignature>(
52  RunAsMainAddr, Result, ExecutorAddr(MainFnAddr), Args))
53  return std::move(Err);
54  return Result;
55 }
56 
58  IncomingWFRHandler OnComplete,
59  ArrayRef<char> ArgBuffer) {
60  uint64_t SeqNo;
61  {
62  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
63  SeqNo = getNextSeqNo();
64  assert(!PendingCallWrapperResults.count(SeqNo) && "SeqNo already in use");
65  PendingCallWrapperResults[SeqNo] = std::move(OnComplete);
66  }
67 
68  if (auto Err = sendMessage(SimpleRemoteEPCOpcode::CallWrapper, SeqNo,
69  WrapperFnAddr, ArgBuffer)) {
71 
72  // We just registered OnComplete, but there may be a race between this
73  // thread returning from sendMessage and handleDisconnect being called from
74  // the transport's listener thread. If handleDisconnect gets there first
75  // then it will have failed 'H' for us. If we get there first (or if
76  // handleDisconnect already ran) then we need to take care of it.
77  {
78  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
79  auto I = PendingCallWrapperResults.find(SeqNo);
80  if (I != PendingCallWrapperResults.end()) {
81  H = std::move(I->second);
82  PendingCallWrapperResults.erase(I);
83  }
84  }
85 
86  if (H)
88 
90  }
91 }
92 
94  T->disconnect();
95  D->shutdown();
96  std::unique_lock<std::mutex> Lock(SimpleRemoteEPCMutex);
97  DisconnectCV.wait(Lock, [this] { return Disconnected; });
98  return std::move(DisconnectErr);
99 }
100 
103  ExecutorAddr TagAddr,
105 
106  LLVM_DEBUG({
107  dbgs() << "SimpleRemoteEPC::handleMessage: opc = ";
108  switch (OpC) {
110  dbgs() << "Setup";
111  assert(SeqNo == 0 && "Non-zero SeqNo for Setup?");
112  assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Setup?");
113  break;
115  dbgs() << "Hangup";
116  assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
117  assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
118  break;
120  dbgs() << "Result";
121  assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
122  break;
124  dbgs() << "CallWrapper";
125  break;
126  }
127  dbgs() << ", seqno = " << SeqNo
128  << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
129  << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
130  << " bytes\n";
131  });
132 
133  using UT = std::underlying_type_t<SimpleRemoteEPCOpcode>;
134  if (static_cast<UT>(OpC) > static_cast<UT>(SimpleRemoteEPCOpcode::LastOpC))
135  return make_error<StringError>("Unexpected opcode",
137 
138  switch (OpC) {
140  if (auto Err = handleSetup(SeqNo, TagAddr, std::move(ArgBytes)))
141  return std::move(Err);
142  break;
144  T->disconnect();
145  if (auto Err = handleHangup(std::move(ArgBytes)))
146  return std::move(Err);
147  return EndSession;
149  if (auto Err = handleResult(SeqNo, TagAddr, std::move(ArgBytes)))
150  return std::move(Err);
151  break;
153  handleCallWrapper(SeqNo, TagAddr, std::move(ArgBytes));
154  break;
155  }
156  return ContinueSession;
157 }
158 
160  LLVM_DEBUG({
161  dbgs() << "SimpleRemoteEPC::handleDisconnect: "
162  << (Err ? "failure" : "success") << "\n";
163  });
164 
165  PendingCallWrapperResultsMap TmpPending;
166 
167  {
168  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
169  std::swap(TmpPending, PendingCallWrapperResults);
170  }
171 
172  for (auto &KV : TmpPending)
173  KV.second(
175 
176  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
177  DisconnectErr = joinErrors(std::move(DisconnectErr), std::move(Err));
178  Disconnected = true;
179  DisconnectCV.notify_all();
180 }
181 
183 SimpleRemoteEPC::createDefaultMemoryManager(SimpleRemoteEPC &SREPC) {
185  if (auto Err = SREPC.getBootstrapSymbols(
186  {{SAs.Allocator, rt::SimpleExecutorMemoryManagerInstanceName},
187  {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},
188  {SAs.Finalize, rt::SimpleExecutorMemoryManagerFinalizeWrapperName},
189  {SAs.Deallocate,
190  rt::SimpleExecutorMemoryManagerDeallocateWrapperName}}))
191  return std::move(Err);
192 
193  return std::make_unique<EPCGenericJITLinkMemoryManager>(SREPC, SAs);
194 }
195 
196 Expected<std::unique_ptr<ExecutorProcessControl::MemoryAccess>>
197 SimpleRemoteEPC::createDefaultMemoryAccess(SimpleRemoteEPC &SREPC) {
198  return nullptr;
199 }
200 
201 Error SimpleRemoteEPC::sendMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo,
202  ExecutorAddr TagAddr,
203  ArrayRef<char> ArgBytes) {
204  assert(OpC != SimpleRemoteEPCOpcode::Setup &&
205  "SimpleRemoteEPC sending Setup message? That's the wrong direction.");
206 
207  LLVM_DEBUG({
208  dbgs() << "SimpleRemoteEPC::sendMessage: opc = ";
209  switch (OpC) {
210  case SimpleRemoteEPCOpcode::Hangup:
211  dbgs() << "Hangup";
212  assert(SeqNo == 0 && "Non-zero SeqNo for Hangup?");
213  assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Hangup?");
214  break;
215  case SimpleRemoteEPCOpcode::Result:
216  dbgs() << "Result";
217  assert(TagAddr.getValue() == 0 && "Non-zero TagAddr for Result?");
218  break;
219  case SimpleRemoteEPCOpcode::CallWrapper:
220  dbgs() << "CallWrapper";
221  break;
222  default:
223  llvm_unreachable("Invalid opcode");
224  }
225  dbgs() << ", seqno = " << SeqNo
226  << ", tag-addr = " << formatv("{0:x}", TagAddr.getValue())
227  << ", arg-buffer = " << formatv("{0:x}", ArgBytes.size())
228  << " bytes\n";
229  });
230  auto Err = T->sendMessage(OpC, SeqNo, TagAddr, ArgBytes);
231  LLVM_DEBUG({
232  if (Err)
233  dbgs() << " \\--> SimpleRemoteEPC::sendMessage failed\n";
234  });
235  return Err;
236 }
237 
238 Error SimpleRemoteEPC::handleSetup(uint64_t SeqNo, ExecutorAddr TagAddr,
240  if (SeqNo != 0)
241  return make_error<StringError>("Setup packet SeqNo not zero",
243 
244  if (TagAddr)
245  return make_error<StringError>("Setup packet TagAddr not zero",
247 
248  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
249  auto I = PendingCallWrapperResults.find(0);
250  assert(PendingCallWrapperResults.size() == 1 &&
251  I != PendingCallWrapperResults.end() &&
252  "Setup message handler not connectly set up");
253  auto SetupMsgHandler = std::move(I->second);
254  PendingCallWrapperResults.erase(I);
255 
256  auto WFR =
257  shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
258  SetupMsgHandler(std::move(WFR));
259  return Error::success();
260 }
261 
262 Error SimpleRemoteEPC::setup(Setup S) {
263  using namespace SimpleRemoteEPCDefaultBootstrapSymbolNames;
264 
265  std::promise<MSVCPExpected<SimpleRemoteEPCExecutorInfo>> EIP;
266  auto EIF = EIP.get_future();
267 
268  // Prepare a handler for the setup packet.
269  PendingCallWrapperResults[0] =
270  RunInPlace()(
271  [&](shared::WrapperFunctionResult SetupMsgBytes) {
272  if (const char *ErrMsg = SetupMsgBytes.getOutOfBandError()) {
273  EIP.set_value(
274  make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
275  return;
276  }
277  using SPSSerialize =
278  shared::SPSArgList<shared::SPSSimpleRemoteEPCExecutorInfo>;
279  shared::SPSInputBuffer IB(SetupMsgBytes.data(), SetupMsgBytes.size());
280  SimpleRemoteEPCExecutorInfo EI;
281  if (SPSSerialize::deserialize(IB, EI))
282  EIP.set_value(EI);
283  else
284  EIP.set_value(make_error<StringError>(
285  "Could not deserialize setup message", inconvertibleErrorCode()));
286  });
287 
288  // Start the transport.
289  if (auto Err = T->start())
290  return Err;
291 
292  // Wait for setup packet to arrive.
293  auto EI = EIF.get();
294  if (!EI) {
295  T->disconnect();
296  return EI.takeError();
297  }
298 
299  LLVM_DEBUG({
300  dbgs() << "SimpleRemoteEPC received setup message:\n"
301  << " Triple: " << EI->TargetTriple << "\n"
302  << " Page size: " << EI->PageSize << "\n"
303  << " Bootstrap symbols:\n";
304  for (const auto &KV : EI->BootstrapSymbols)
305  dbgs() << " " << KV.first() << ": "
306  << formatv("{0:x16}", KV.second.getValue()) << "\n";
307  });
308  TargetTriple = Triple(EI->TargetTriple);
309  PageSize = EI->PageSize;
310  BootstrapSymbols = std::move(EI->BootstrapSymbols);
311 
312  if (auto Err = getBootstrapSymbols(
313  {{JDI.JITDispatchContext, ExecutorSessionObjectName},
314  {JDI.JITDispatchFunction, DispatchFnName},
315  {RunAsMainAddr, rt::RunAsMainWrapperName}}))
316  return Err;
317 
318  if (auto DM =
319  EPCGenericDylibManager::CreateWithDefaultBootstrapSymbols(*this))
320  DylibMgr = std::make_unique<EPCGenericDylibManager>(std::move(*DM));
321  else
322  return DM.takeError();
323 
324  // Set a default CreateMemoryManager if none is specified.
325  if (!S.CreateMemoryManager)
326  S.CreateMemoryManager = createDefaultMemoryManager;
327 
328  if (auto MemMgr = S.CreateMemoryManager(*this)) {
329  OwnedMemMgr = std::move(*MemMgr);
330  this->MemMgr = OwnedMemMgr.get();
331  } else
332  return MemMgr.takeError();
333 
334  // Set a default CreateMemoryAccess if none is specified.
335  if (!S.CreateMemoryAccess)
336  S.CreateMemoryAccess = createDefaultMemoryAccess;
337 
338  if (auto MemAccess = S.CreateMemoryAccess(*this)) {
339  OwnedMemAccess = std::move(*MemAccess);
340  this->MemAccess = OwnedMemAccess.get();
341  } else
342  return MemAccess.takeError();
343 
344  return Error::success();
345 }
346 
347 Error SimpleRemoteEPC::handleResult(uint64_t SeqNo, ExecutorAddr TagAddr,
349  IncomingWFRHandler SendResult;
350 
351  if (TagAddr)
352  return make_error<StringError>("Unexpected TagAddr in result message",
354 
355  {
356  std::lock_guard<std::mutex> Lock(SimpleRemoteEPCMutex);
357  auto I = PendingCallWrapperResults.find(SeqNo);
358  if (I == PendingCallWrapperResults.end())
359  return make_error<StringError>("No call for sequence number " +
360  Twine(SeqNo),
362  SendResult = std::move(I->second);
363  PendingCallWrapperResults.erase(I);
364  releaseSeqNo(SeqNo);
365  }
366 
367  auto WFR =
368  shared::WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
369  SendResult(std::move(WFR));
370  return Error::success();
371 }
372 
373 void SimpleRemoteEPC::handleCallWrapper(
374  uint64_t RemoteSeqNo, ExecutorAddr TagAddr,
376  assert(ES && "No ExecutionSession attached");
377  ES->runJITDispatchHandler(
378  [this, RemoteSeqNo](shared::WrapperFunctionResult WFR) {
379  if (auto Err = sendMessage(SimpleRemoteEPCOpcode::Result, RemoteSeqNo,
380  ExecutorAddr(), {WFR.data(), WFR.size()}))
381  getExecutionSession().reportError(std::move(Err));
382  },
383  TagAddr.getValue(), ArgBytes);
384 }
385 
386 Error SimpleRemoteEPC::handleHangup(SimpleRemoteEPCArgBytesVector ArgBytes) {
387  using namespace llvm::orc::shared;
388  auto WFR = WrapperFunctionResult::copyFrom(ArgBytes.data(), ArgBytes.size());
389  if (const char *ErrMsg = WFR.getOutOfBandError())
390  return make_error<StringError>(ErrMsg, inconvertibleErrorCode());
391 
393  SPSInputBuffer IB(WFR.data(), WFR.size());
395  return make_error<StringError>("Could not deserialize hangup info",
398 }
399 
400 } // end namespace orc
401 } // end namespace llvm
llvm::orc::ExecutorAddr
Represents an address in the executor process.
Definition: ExecutorAddress.h:37
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::orc::SimpleRemoteEPCOpcode
SimpleRemoteEPCOpcode
Definition: SimpleRemoteEPCUtils.h:37
llvm::orc::SimpleRemoteEPC::handleMessage
Expected< HandleMessageAction > handleMessage(SimpleRemoteEPCOpcode OpC, uint64_t SeqNo, ExecutorAddr TagAddr, SimpleRemoteEPCArgBytesVector ArgBytes) override
Handle receipt of a message.
Definition: SimpleRemoteEPC.cpp:102
llvm::lltok::Error
@ Error
Definition: LLToken.h:21
llvm::orc::ExecutionSession::reportError
void reportError(Error Err)
Report a error for this execution session.
Definition: Core.h:1379
llvm::orc::ExecutorProcessControl::getBootstrapSymbols
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...
Definition: ExecutorProcessControl.h:229
DM
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
llvm::orc::SimpleRemoteEPC::~SimpleRemoteEPC
~SimpleRemoteEPC()
Definition: SimpleRemoteEPC.cpp:20
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::orc::EPCGenericJITLinkMemoryManager::SymbolAddrs
Function addresses for memory access.
Definition: EPCGenericJITLinkMemoryManager.h:30
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::orc::ExecutorAddr::getValue
uint64_t getValue() const
Definition: ExecutorAddress.h:60
llvm::DenseMapBase::erase
bool erase(const KeyT &Val)
Definition: DenseMap.h:302
llvm::orc::ExecutorProcessControl::getExecutionSession
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
Definition: ExecutorProcessControl.h:187
llvm::orc::shared
Definition: ELFNixPlatform.h:243
llvm::DenseMapBase::count
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition: DenseMap.h:145
T
#define T
Definition: Mips16ISelLowering.cpp:341
llvm::orc::shared::SPSInputBuffer
Input char buffer with underflow check.
Definition: SimplePackedSerialization.h:72
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
EPCGenericJITLinkMemoryManager.h
LLVM_DEBUG
#define LLVM_DEBUG(X)
Definition: Debug.h:101
llvm::orc::shared::WrapperFunctionResult::copyFrom
static WrapperFunctionResult copyFrom(const char *Source, size_t Size)
Copy from the given char range.
Definition: WrapperFunctionUtils.h:129
llvm::dbgs
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:163
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
llvm::formatv
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
Definition: FormatVariadic.h:250
PageSize
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)
llvm::orc::shared::detail::fromSPSSerializable
Error fromSPSSerializable(SPSSerializableError BSE)
Definition: SimplePackedSerialization.h:540
reportError
static Error reportError(StringRef Message)
Definition: BitcodeAnalyzer.cpp:19
llvm::orc::shared::detail::SPSSerializableError
Helper type for serializing Errors.
Definition: SimplePackedSerialization.h:518
SimpleRemoteEPC.h
llvm::orc::SimpleRemoteEPCOpcode::Result
@ Result
EPCGenericMemoryAccess.h
llvm::orc::SimpleRemoteEPCDefaultBootstrapSymbolNames::ExecutorSessionObjectName
const char * ExecutorSessionObjectName
Definition: SimpleRemoteEPCUtils.cpp:40
llvm::orc::SimpleRemoteEPC::handleDisconnect
void handleDisconnect(Error Err) override
Handle a disconnection from the underlying transport.
Definition: SimpleRemoteEPC.cpp:159
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::orc::SimpleRemoteEPC::callWrapperAsync
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
Definition: SimpleRemoteEPC.cpp:57
FormatVariadic.h
llvm::orc::SimpleRemoteEPC::disconnect
Error disconnect() override
Disconnect from the target process.
Definition: SimpleRemoteEPC.cpp:93
llvm::orc::ExecutorProcessControl::IncomingWFRHandler
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
Definition: ExecutorProcessControl.h:48
llvm::orc::SimpleRemoteEPCOpcode::Hangup
@ Hangup
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::orc::SimpleRemoteEPC
Definition: SimpleRemoteEPC.h:31
llvm::DenseMap< uint64_t, IncomingWFRHandler >
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:428
llvm::orc::SimpleRemoteEPC::loadDylib
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
Definition: SimpleRemoteEPC.cpp:28
llvm::DenseMapBase::find
iterator find(const_arg_type_t< KeyT > Val)
Definition: DenseMap.h:150
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
std::swap
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:840
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
llvm::orc::SimpleRemoteEPCArgBytesVector
SmallVector< char, 128 > SimpleRemoteEPCArgBytesVector
Definition: SimpleRemoteEPCUtils.h:51
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
H
#define H(x, y, z)
Definition: MD5.cpp:58
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
llvm::DenseMapBase::end
iterator end()
Definition: DenseMap.h:83
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::orc::SimpleRemoteEPCTransportClient::ContinueSession
@ ContinueSession
Definition: SimpleRemoteEPCUtils.h:55
llvm::orc::SimpleRemoteEPCOpcode::CallWrapper
@ CallWrapper
llvm::orc::ExecutorProcessControl::D
std::unique_ptr< TaskDispatcher > D
Definition: ExecutorProcessControl.h:359
llvm::orc::shared::WrapperFunctionResult::createOutOfBandError
static WrapperFunctionResult createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
Definition: WrapperFunctionUtils.h:146
llvm::orc::SimpleRemoteEPCDefaultBootstrapSymbolNames::DispatchFnName
const char * DispatchFnName
Definition: SimpleRemoteEPCUtils.cpp:42
llvm::orc::SimpleRemoteEPCOpcode::Setup
@ Setup
llvm::orc::rt::RunAsMainWrapperName
const char * RunAsMainWrapperName
Definition: OrcRTBridge.cpp:43
llvm::orc::SimpleRemoteEPCOpcode::LastOpC
@ LastOpC
llvm::AMDGPU::HSAMD::Kernel::Key::Args
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Definition: AMDGPUMetadata.h:389
OrcRTBridge.h
llvm::orc::SimpleRemoteEPCTransportClient::EndSession
@ EndSession
Definition: SimpleRemoteEPCUtils.h:55
llvm::orc::shared::SPSArgList
A utility class for serializing to a blob from a variadic list.
Definition: SimplePackedSerialization.h:106
llvm::orc::SimpleRemoteEPC::runAsMain
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.
Definition: SimpleRemoteEPC.cpp:48
llvm::orc::SimpleRemoteEPC::lookupSymbols
Expected< std::vector< tpctypes::LookupResult > > lookupSymbols(ArrayRef< LookupRequest > Request) override
Search for symbols in the target process.
Definition: SimpleRemoteEPC.cpp:33