19#define DEBUG_TYPE "orc"
23Expected<std::unique_ptr<InProcessEPC>>
25 std::shared_ptr<SymbolStringPool>
SSP,
26 std::unique_ptr<TaskDispatcher>
D) {
27 assert(C &&
"C must not be null");
28 assert(BIA &&
"BIA must not be null");
32 assert(C->Retain &&
"C->Retain not set by controller");
33 assert(C->Release &&
"C->Release not set by controller");
34 assert(C->Disconnect &&
"C->Disconnect not set by controller");
35 assert(C->EnterMessageScope &&
"C->EnterMessageScope not set by controller");
36 assert(C->LeaveMessageScope &&
"C->LeaveMessageScope not set by controller");
37 assert(C->IPCA &&
"C->IPCA not set by controller");
38 assert(C->CallWrapper &&
"C->CallWrapper not set by controller");
39 assert(C->ReturnJITDispatchResult &&
40 "C->ReturnJITDispatchResult not set by controller");
43 SSP = std::make_shared<SymbolStringPool>();
46 D = std::make_unique<InPlaceTaskDispatcher>();
48 std::unique_ptr<InProcessEPC> IPEPC(
49 new InProcessEPC(C, std::move(
SSP), std::move(
D)));
52 C->IPEPC = IPEPC.get();
53 C->CallJITDispatch = callJITDispatchEntry;
54 C->ReturnWrapperResult = returnWrapperResultEntry;
61 "Cannot create InProcessEPC with page-size = 0",
68 "Cannot create InProcessEPC with target-triple = \"\"",
76 while ((RC = BIA->
GetNextValue(BIA, &Name, &ValBytes, &ValSize)) == 1) {
77 if (!IPEPC->BootstrapMap
79 std::vector<char>(ValBytes, ValBytes + ValSize))
82 (
"Cannot create InProcessEPC: bootstrap-value map contains "
89 "Cannot create InProcessEPC: bootstrap-value map corrupted",
97 while ((RC = BIA->
GetNextSymbol(BIA, &SymName, &SymAddr)) == 1) {
98 if (!IPEPC->BootstrapSymbols.try_emplace(SymName,
ExecutorAddr(SymAddr))
101 (
"Cannot create InProcessEPC: bootstrap-symbol map contains "
102 "duplicate symbol \"" +
108 "Cannot create InProcessEPC: bootstrap-symbol map corrupted",
112 return std::move(IPEPC);
133 using MainTy = int (*)(int,
char *[]);
138 using VoidTy = int (*)();
144 using IntTy = int (*)(int);
151 if (C->EnterMessageScope(C)) {
152 auto CallId = registerPendingCallWrapperResult(std::move(OnComplete));
156 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: callWrapperAsync call id " << CallId
157 <<
" to " << WrapperFnAddr <<
"\n");
159 C->CallWrapper(C->IPCA, CallId, WrapperFnAddr.
toPtr<
void *>(),
161 C->LeaveMessageScope(C);
164 "connection closed"));
177 return DM.takeError();
178 return std::make_unique<EPCGenericDylibManager>(std::move(*
DM));
198 return std::move(Err);
200 return std::make_unique<EPCGenericMemoryAccess>(*
this, FAs);
208uint64_t InProcessEPC::registerPendingCallWrapperResult(IncomingWFRHandler
H) {
209 std::scoped_lock<std::mutex> Lock(M);
210 assert(!PendingCallWrapperResults.
count(NextCallId) &&
211 "CallId already in use");
212 PendingCallWrapperResults[NextCallId] = std::move(
H);
216void InProcessEPC::doDisconnect() {
224 std::scoped_lock<std::mutex> Lock(M);
225 HandlersToDrain = std::move(PendingCallWrapperResults);
228 for (
auto &[
_,
H] : HandlersToDrain)
232void InProcessEPC::callJITDispatch(uint64_t CallId,
void *HandlerTag,
234 assert(C->ReturnJITDispatchResult &&
"ReturnJITDispatchResult not set");
236 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: JIT-dispatch call id " << CallId <<
" to "
237 << HandlerTag <<
"\n");
240 [
this, CallId](shared::WrapperFunctionBuffer ResultBytes) {
241 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: Returning JIT-dispatch result for "
244 if (C->EnterMessageScope(C)) {
245 C->ReturnJITDispatchResult(C->IPCA, CallId, ResultBytes.release());
246 C->LeaveMessageScope(C);
250 shared::WrapperFunctionBuffer(ArgBytes));
253void InProcessEPC::callJITDispatchEntry(
254 void *IPEPC, uint64_t CallId,
void *HandlerTag,
256 static_cast<InProcessEPC *
>(IPEPC)->callJITDispatch(CallId, HandlerTag,
260void InProcessEPC::returnWrapperResult(
263 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: Wrapper result for call id " << CallId
268 std::scoped_lock<std::mutex> Lock(M);
269 auto I = PendingCallWrapperResults.find(CallId);
270 if (
I != PendingCallWrapperResults.end()) {
271 H = std::move(
I->second);
272 PendingCallWrapperResults.erase(
I);
278 "InProcessEPC received result for invalid call id " + Twine(CallId),
283 H(shared::WrapperFunctionBuffer(ResultBytes));
286void InProcessEPC::returnWrapperResultEntry(
288 static_cast<InProcessEPC *
>(IPEPC)->returnWrapperResult(CallId, ResultBytes);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
Provides a library for accessing information about this process and other processes on the operating ...
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
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.
Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
static Expected< EPCGenericDylibManager > Create(JITDylib &JD, rt::SimpleExecutorDylibManagerSymbolNames SNs=rt::orc_rt_NativeDylibManagerSPSSymbols)
Create an EPCGenericDylibManager using the given implementation symbol names.
static Expected< std::unique_ptr< EPCGenericJITLinkMemoryManager > > Create(JITDylib &JD, rt::SimpleExecutorMemoryManagerSymbolNames SNs=rt::orc_rt_SimpleNativeMemoryMapSPSSymbols)
Create an EPCGenericJITLinkMemoryManager using the given implementation symbol names.
LLVM_ABI void runJITDispatchHandler(SendResultFunction SendResult, ExecutorAddr HandlerFnTagAddr, shared::WrapperFunctionBuffer ArgBytes)
Run a registered jit-side wrapper function.
void reportError(Error Err)
Report a error for this execution session.
Represents an address in the executor process.
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr(WrapFn &&Wrap=WrapFn()) const
Cast this ExecutorAddr to a pointer of the given type.
A handler or incoming WrapperFunctionBuffers – either return values from callWrapper* calls,...
std::unique_ptr< TaskDispatcher > D
std::shared_ptr< SymbolStringPool > SSP
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.
Expected< std::unique_ptr< jitlink::JITLinkMemoryManager > > createDefaultMemoryManager() override
Create a default JITLinkMemoryManager for the target process.
Expected< int32_t > runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override
Run function with a int (*)(int) signature.
Expected< int32_t > runAsVoidFunction(ExecutorAddr VoidFnAddr) override
Run function with a int (*)(void) signature.
Expected< std::unique_ptr< DylibManager > > createDefaultDylibMgr() override
Create a default DylibManager for the target process.
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
static Expected< std::unique_ptr< InProcessEPC > > Create(Connection *C, BootstrapInfoAccess *BIA, std::shared_ptr< SymbolStringPool > SSP=nullptr, std::unique_ptr< TaskDispatcher > D=nullptr)
Create a new InProcessEPC.
Error disconnect() override
Disconnect from the target process.
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.
static WrapperFunctionBuffer copyFrom(const char *Source, size_t Size)
Copy from the given char range.
static WrapperFunctionBuffer createOutOfBandError(const char *Msg)
Create an out-of-band error by copying the given string.
@ C
The default llvm calling convention, compatible with C.
LLVM_ABI const char * MemoryReadUInt64sWrapperName
LLVM_ABI const char * MemoryWriteUInt16sWrapperName
LLVM_ABI const char * MemoryReadStringsWrapperName
LLVM_ABI const char * MemoryReadUInt16sWrapperName
LLVM_ABI const char * MemoryReadUInt32sWrapperName
LLVM_ABI const char * MemoryWriteUInt64sWrapperName
LLVM_ABI const char * MemoryWriteUInt8sWrapperName
LLVM_ABI const char * MemoryWritePointersWrapperName
LLVM_ABI const char * MemoryWriteUInt32sWrapperName
LLVM_ABI const char * MemoryWriteBuffersWrapperName
LLVM_ABI const char * MemoryReadBuffersWrapperName
LLVM_ABI const char * MemoryReadUInt8sWrapperName
LLVM_ABI int runAsVoidFunction(int(*Func)(void))
LLVM_ABI int runAsIntFunction(int(*Func)(int), int Arg)
LLVM_ABI int runAsMain(int(*Main)(int, char *[]), ArrayRef< std::string > Args, std::optional< StringRef > ProgramName=std::nullopt)
Run a main function, returning the result.
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
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.
Function addresses for memory access.
ExecutorAddr WritePointers
ExecutorAddr WriteUInt64s
ExecutorAddr WriteUInt16s
ExecutorAddr WriteUInt32s
ExecutorAddr WriteBuffers
Provides access to bootstrap info.
uint64_t(* GetPageSize)(void *BIA)
const char *(* GetTargetTriple)(void *BIA)
int(* GetNextSymbol)(void *BIA, const char **Name, uint64_t *Addr)
int(* GetNextValue)(void *BIA, const char **Name, const char **ValueBytes, uint64_t *ValueSize)
Pseudo-connection C struct.