Go to the documentation of this file.
17 #define DEBUG_TYPE "orc"
27 std::shared_ptr<SymbolStringPool> SSP, std::unique_ptr<TaskDispatcher>
D,
29 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
34 OwnedMemMgr = std::make_unique<jitlink::InProcessMemoryManager>(
39 this->MemMgr = OwnedMemMgr.get();
44 GlobalManglingPrefix =
'_';
49 std::shared_ptr<SymbolStringPool> SSP,
50 std::unique_ptr<TaskDispatcher>
D,
51 std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr) {
54 SSP = std::make_shared<SymbolStringPool>();
57 #if LLVM_ENABLE_THREADS
58 D = std::make_unique<DynamicThreadPoolTaskDispatcher>();
60 D = std::make_unique<InPlaceTaskDispatcher>();
70 return std::make_unique<SelfExecutorProcessControl>(
78 auto Dylib = std::make_unique<sys::DynamicLibrary>(
80 if (!Dylib->isValid())
82 DynamicLibraries.push_back(
std::move(Dylib));
88 std::vector<tpctypes::LookupResult> R;
90 for (
auto &Elem : Request) {
91 auto *Dylib = jitTargetAddressToPointer<sys::DynamicLibrary *>(Elem.Handle);
93 [=](
const std::unique_ptr<sys::DynamicLibrary> &
DL) {
94 return DL.get() == Dylib;
98 R.push_back(std::vector<JITTargetAddress>());
99 for (
auto &KV : Elem.Symbols) {
100 auto &Sym = KV.first;
101 std::string Tmp((*Sym).data() + !!GlobalManglingPrefix,
102 (*Sym).size() - !!GlobalManglingPrefix);
103 void *
Addr = Dylib->getAddressOfSymbol(Tmp.c_str());
107 MissingSymbols.push_back(Sym);
108 return make_error<SymbolsNotFound>(
SSP,
std::move(MissingSymbols));
120 using MainTy =
int (*)(
int,
char *[]);
129 auto *WrapperFn = WrapperFnAddr.
toPtr<WrapperFnTy>();
130 SendResult(WrapperFn(ArgBuffer.
data(), ArgBuffer.
size()));
138 void SelfExecutorProcessControl::writeUInt8sAsync(
141 *
W.Addr.toPtr<uint8_t *>() =
W.Value;
145 void SelfExecutorProcessControl::writeUInt16sAsync(
152 void SelfExecutorProcessControl::writeUInt32sAsync(
153 ArrayRef<tpctypes::UInt32Write> Ws, WriteResultFn OnWriteComplete) {
159 void SelfExecutorProcessControl::writeUInt64sAsync(
160 ArrayRef<tpctypes::UInt64Write> Ws, WriteResultFn OnWriteComplete) {
166 void SelfExecutorProcessControl::writeBuffersAsync(
167 ArrayRef<tpctypes::BufferWrite> Ws, WriteResultFn OnWriteComplete) {
169 memcpy(
W.Addr.toPtr<
char *>(),
W.Buffer.data(),
W.Buffer.size());
173 shared::CWrapperFunctionResult
174 SelfExecutorProcessControl::jitDispatchViaWrapperFunctionManager(
175 void *Ctx,
const void *FnTag,
const char *Data,
size_t Size) {
178 dbgs() <<
"jit-dispatch call with tag " << FnTag <<
" and " <<
Size
179 <<
" byte payload.\n";
182 std::promise<shared::WrapperFunctionResult> ResultP;
183 auto ResultF = ResultP.get_future();
188 shared::WrapperFunctionResult
Result)
mutable {
193 return ResultF.get().release();
Represents an address in the executor process.
jitlink::JITLinkMemoryManager * MemMgr
This is an optimization pass for GlobalISel generic memory operations.
static ErrorSuccess success()
Create a success value.
Triple - Helper class for working with autoconf configuration names.
Error disconnect() override
Disconnect from the target process.
ExecutionSession & getExecutionSession()
Return the ExecutionSession associated with this instance.
std::enable_if_t< std::is_pointer< T >::value, T > toPtr() const
Cast this ExecutorAddr to a pointer of the given type.
ExecutorProcessControl supports interaction with a JIT target process.
std::shared_ptr< SymbolStringPool > SSP
Tagged union holding either a T or a Error.
void runJITDispatchHandler(SendResultFunction SendResult, JITTargetAddress HandlerFnTagAddr, ArrayRef< char > ArgBuffer)
Run a registered jit-side wrapper function.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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)
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path.
Clang compiles this i1 i64 store i64 i64 store i64 i64 store i64 i64 store i64 align Which gets codegen d xmm0 movaps rbp movaps rbp movaps rbp movaps rbp rbp rbp rbp rbp It would be better to have movq s of instead of the movaps s LLVM produces ret int
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
int runAsMain(int(*Main)(int, char *[]), ArrayRef< std::string > Args, Optional< StringRef > ProgramName=None)
Run a main function, returning the result.
static ExecutorAddr fromPtr(T *Value)
Create an ExecutorAddr from the given pointer.
A handler or incoming WrapperFunctionResults – either return values from callWrapper* calls,...
Expected< tpctypes::DylibHandle > loadDylib(const char *DylibPath) override
Load the dynamic library at the given path and return a handle to it.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
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
static Expected< unsigned > getPageSize()
Get the process's page size.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef< char > ArgBuffer) override
Run a wrapper function in the executor.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
SelfExecutorProcessControl(std::shared_ptr< SymbolStringPool > SSP, std::unique_ptr< TaskDispatcher > D, Triple TargetTriple, unsigned PageSize, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr)
Expected< std::vector< tpctypes::LookupResult > > lookupSymbols(ArrayRef< LookupRequest > Request) override
Search for symbols in the target process.
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
static Expected< std::unique_ptr< SelfExecutorProcessControl > > Create(std::shared_ptr< SymbolStringPool > SSP=nullptr, std::unique_ptr< TaskDispatcher > D=nullptr, std::unique_ptr< jitlink::JITLinkMemoryManager > MemMgr=nullptr)
Create a SelfExecutorProcessControl with the given symbol string pool and memory manager.
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
std::string getProcessTriple()
getProcessTriple() - Return an appropriate target triple for generating code to be loaded into the cu...
Lightweight error class with error context and mandatory checking.
std::unique_ptr< TaskDispatcher > D
virtual ~ExecutorProcessControl()
size_t size() const
size - Get the array size.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
std::vector< SymbolStringPtr > SymbolNameVector
A vector of symbol names.
Expected< int32_t > runAsMain(ExecutorAddr MainFnAddr, ArrayRef< std::string > Args) override
Run function with a main-like signature.