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 *[]);
140 if (C->EnterMessageScope(C)) {
141 auto CallId = registerPendingCallWrapperResult(std::move(OnComplete));
145 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: callWrapperAsync call id " << CallId
146 <<
" to " << WrapperFnAddr <<
"\n");
148 C->CallWrapper(C->IPCA, CallId, WrapperFnAddr.
toPtr<
void *>(),
150 C->LeaveMessageScope(C);
153 "connection closed"));
166 return DM.takeError();
167 return std::make_unique<EPCGenericDylibManager>(std::move(*
DM));
181uint64_t InProcessEPC::registerPendingCallWrapperResult(IncomingWFRHandler
H) {
182 std::scoped_lock<std::mutex> Lock(M);
183 assert(!PendingCallWrapperResults.
count(NextCallId) &&
184 "CallId already in use");
185 PendingCallWrapperResults[NextCallId] = std::move(
H);
189void InProcessEPC::doDisconnect() {
197 std::scoped_lock<std::mutex> Lock(M);
198 HandlersToDrain = std::move(PendingCallWrapperResults);
201 for (
auto &[
_,
H] : HandlersToDrain)
205void InProcessEPC::callJITDispatch(uint64_t CallId,
void *HandlerTag,
207 assert(C->ReturnJITDispatchResult &&
"ReturnJITDispatchResult not set");
209 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: JIT-dispatch call id " << CallId <<
" to "
210 << HandlerTag <<
"\n");
213 [
this, CallId](shared::WrapperFunctionBuffer ResultBytes) {
214 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: Returning JIT-dispatch result for "
217 if (C->EnterMessageScope(C)) {
218 C->ReturnJITDispatchResult(C->IPCA, CallId, ResultBytes.release());
219 C->LeaveMessageScope(C);
223 shared::WrapperFunctionBuffer(ArgBytes));
226void InProcessEPC::callJITDispatchEntry(
227 void *IPEPC, uint64_t CallId,
void *HandlerTag,
229 static_cast<InProcessEPC *
>(IPEPC)->callJITDispatch(CallId, HandlerTag,
233void InProcessEPC::returnWrapperResult(
236 LLVM_DEBUG(
dbgs() <<
"InProcessEPC: Wrapper result for call id " << CallId
241 std::scoped_lock<std::mutex> Lock(M);
242 auto I = PendingCallWrapperResults.find(CallId);
243 if (
I != PendingCallWrapperResults.end()) {
244 H = std::move(
I->second);
245 PendingCallWrapperResults.erase(
I);
251 "InProcessEPC received result for invalid call id " + Twine(CallId),
256 H(shared::WrapperFunctionBuffer(ResultBytes));
259void InProcessEPC::returnWrapperResultEntry(
261 static_cast<InProcessEPC *
>(IPEPC)->returnWrapperResult(CallId, ResultBytes);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
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.
static Expected< std::unique_ptr< MemoryAccess > > Create(ExecutionSession &ES)
Create an EPCGenericMemoryAccess instance that reaches the memory-access wrappers in ES's bootstrap J...
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
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< 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.
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.
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.