16 #ifndef LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H 17 #define LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H 43 #define DEBUG_TYPE "orc-remote" 65 Client.destroyRemoteAllocator(
Id);
78 Unmapped.back().CodeAllocs.emplace_back(Size, Alignment);
79 uint8_t *Alloc =
reinterpret_cast<uint8_t *
>(
80 Unmapped.back().CodeAllocs.back().getLocalAddress());
82 << SectionName <<
": " << Alloc <<
" (" << Size
83 <<
" bytes, alignment " << Alignment <<
")\n");
89 bool IsReadOnly)
override {
91 Unmapped.back().RODataAllocs.emplace_back(Size, Alignment);
92 uint8_t *Alloc =
reinterpret_cast<uint8_t *
>(
93 Unmapped.back().RODataAllocs.back().getLocalAddress());
95 << SectionName <<
": " << Alloc <<
" (" << Size
96 <<
" bytes, alignment " << Alignment <<
")\n");
100 Unmapped.back().RWDataAllocs.emplace_back(Size, Alignment);
101 uint8_t *Alloc =
reinterpret_cast<uint8_t *
>(
102 Unmapped.back().RWDataAllocs.back().getLocalAddress());
104 << SectionName <<
": " << Alloc <<
" (" << Size
105 <<
" bytes, alignment " << Alignment <<
")\n");
110 uintptr_t RODataSize,
uint32_t RODataAlign,
111 uintptr_t RWDataSize,
113 Unmapped.push_back(ObjectAllocs());
118 Unmapped.back().RemoteCodeAddr =
119 Client.reserveMem(
Id, CodeSize, CodeAlign);
123 <<
format(
"0x%016" PRIx64, Unmapped.back().RemoteCodeAddr)
124 <<
" (" << CodeSize <<
" bytes, alignment " << CodeAlign
128 if (RODataSize != 0) {
129 Unmapped.back().RemoteRODataAddr =
130 Client.reserveMem(
Id, RODataSize, RODataAlign);
133 dbgs() <<
" ro-data: " 134 <<
format(
"0x%016" PRIx64, Unmapped.back().RemoteRODataAddr)
135 <<
" (" << RODataSize <<
" bytes, alignment " << RODataAlign
139 if (RWDataSize != 0) {
140 Unmapped.back().RemoteRWDataAddr =
141 Client.reserveMem(
Id, RWDataSize, RWDataAlign);
144 dbgs() <<
" rw-data: " 145 <<
format(
"0x%016" PRIx64, Unmapped.back().RemoteRWDataAddr)
146 <<
" (" << RWDataSize <<
" bytes, alignment " << RWDataAlign
154 size_t Size)
override {
155 UnfinalizedEHFrames.push_back({LoadAddr, Size});
159 for (
auto &Frame : RegisteredEHFrames) {
161 Client.deregisterEHFrames(Frame.Addr, Frame.Size);
168 for (
auto &ObjAllocs : Unmapped) {
169 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.CodeAllocs,
170 ObjAllocs.RemoteCodeAddr);
171 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RODataAllocs,
172 ObjAllocs.RemoteRODataAddr);
173 mapAllocsToRemoteAddrs(Dyld, ObjAllocs.RWDataAllocs,
174 ObjAllocs.RemoteRWDataAddr);
175 Unfinalized.push_back(std::move(ObjAllocs));
183 for (
auto &ObjAllocs : Unfinalized) {
184 if (copyAndProtect(ObjAllocs.CodeAllocs, ObjAllocs.RemoteCodeAddr,
188 if (copyAndProtect(ObjAllocs.RODataAllocs, ObjAllocs.RemoteRODataAddr,
192 if (copyAndProtect(ObjAllocs.RWDataAllocs, ObjAllocs.RemoteRWDataAddr,
198 for (
auto &EHFrame : UnfinalizedEHFrames) {
199 if (
auto Err = Client.registerEHFrames(EHFrame.Addr, EHFrame.Size)) {
210 RegisteredEHFrames = std::move(UnfinalizedEHFrames);
211 UnfinalizedEHFrames = {};
220 :
Size(Size),
Align(Align), Contents(
new char[Size + Align - 1]) {}
222 Alloc(
const Alloc &) =
delete;
223 Alloc &
operator=(
const Alloc &) =
delete;
224 Alloc(Alloc &&) =
default;
227 uint64_t getSize()
const {
return Size; }
231 char *getLocalAddress()
const {
232 uintptr_t LocalAddr =
reinterpret_cast<uintptr_t
>(Contents.get());
233 LocalAddr =
alignTo(LocalAddr, Align);
234 return reinterpret_cast<char *
>(LocalAddr);
238 this->RemoteAddr = RemoteAddr;
246 std::unique_ptr<char[]> Contents;
250 struct ObjectAllocs {
251 ObjectAllocs() =
default;
252 ObjectAllocs(
const ObjectAllocs &) =
delete;
253 ObjectAllocs &
operator=(
const ObjectAllocs &) =
delete;
254 ObjectAllocs(ObjectAllocs &&) =
default;
255 ObjectAllocs &
operator=(ObjectAllocs &&) =
default;
260 std::vector<Alloc> CodeAllocs, RODataAllocs, RWDataAllocs;
265 : Client(Client), Id(Id) {
270 void mapAllocsToRemoteAddrs(
RuntimeDyld &Dyld, std::vector<Alloc> &Allocs,
272 for (
auto &Alloc : Allocs) {
273 NextAddr =
alignTo(NextAddr, Alloc.getAlign());
276 dbgs() <<
" " << static_cast<void *>(Alloc.getLocalAddress())
277 <<
" -> " <<
format(
"0x%016" PRIx64, NextAddr) <<
"\n");
278 Alloc.setRemoteAddress(NextAddr);
283 NextAddr += Alloc.getSize();
289 bool copyAndProtect(
const std::vector<Alloc> &Allocs,
291 unsigned Permissions) {
292 if (RemoteSegmentAddr) {
293 assert(!Allocs.empty() &&
"No sections in allocated segment");
295 for (
auto &Alloc : Allocs) {
297 << static_cast<void *>(Alloc.getLocalAddress())
299 <<
format(
"0x%016" PRIx64, Alloc.getRemoteAddress())
300 <<
" (" << Alloc.getSize() <<
" bytes)\n";);
302 if (Client.writeMem(Alloc.getRemoteAddress(), Alloc.getLocalAddress(),
311 <<
" permissions on block: " 312 <<
format(
"0x%016" PRIx64, RemoteSegmentAddr)
314 if (Client.setProtections(Id, RemoteSegmentAddr, Permissions))
322 std::vector<ObjectAllocs> Unmapped;
323 std::vector<ObjectAllocs> Unfinalized;
329 std::vector<EHFrame> UnfinalizedEHFrames;
330 std::vector<EHFrame> RegisteredEHFrames;
338 : Client(Client), Id(Id) {}
341 Client.destroyIndirectStubsManager(Id);
346 if (
auto Err = reserveStubs(1))
349 return createStubInternal(StubName, StubAddr, StubFlags);
353 if (
auto Err = reserveStubs(StubInits.
size()))
356 for (
auto &Entry : StubInits)
357 if (
auto Err = createStubInternal(Entry.first(), Entry.second.first,
358 Entry.second.second))
365 auto I = StubIndexes.find(Name);
366 if (
I == StubIndexes.end())
368 auto Key =
I->second.first;
369 auto Flags =
I->second.second;
371 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
377 auto I = StubIndexes.find(Name);
378 if (
I == StubIndexes.end())
380 auto Key =
I->second.first;
381 auto Flags =
I->second.second;
386 auto I = StubIndexes.find(Name);
387 assert(
I != StubIndexes.end() &&
"No stub pointer for symbol");
388 auto Key =
I->second.first;
389 return Client.writePointer(getPtrAddr(Key), NewAddr);
393 struct RemoteIndirectStubsInfo {
399 using StubKey = std::pair<uint16_t, uint16_t>;
401 Error reserveStubs(
unsigned NumStubs) {
402 if (NumStubs <= FreeStubs.size())
405 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
408 unsigned NumStubsEmitted;
410 if (
auto StubInfoOrErr = Client.emitIndirectStubs(Id, NewStubsRequired))
411 std::tie(StubBase, PtrBase, NumStubsEmitted) = *StubInfoOrErr;
413 return StubInfoOrErr.takeError();
415 unsigned NewBlockId = RemoteIndirectStubsInfos.size();
416 RemoteIndirectStubsInfos.push_back({StubBase, PtrBase, NumStubsEmitted});
418 for (
unsigned I = 0;
I < NumStubsEmitted; ++
I)
419 FreeStubs.push_back(std::make_pair(NewBlockId,
I));
426 auto Key = FreeStubs.back();
427 FreeStubs.pop_back();
428 StubIndexes[StubName] = std::make_pair(
Key, StubFlags);
429 return Client.writePointer(getPtrAddr(
Key), InitAddr);
433 assert(RemoteIndirectStubsInfos[K.first].StubBase != 0 &&
434 "Missing stub address");
435 return RemoteIndirectStubsInfos[K.first].StubBase +
436 K.second * Client.getIndirectStubSize();
440 assert(RemoteIndirectStubsInfos[K.first].PtrBase != 0 &&
441 "Missing pointer address");
442 return RemoteIndirectStubsInfos[K.first].PtrBase +
443 K.second * Client.getPointerSize();
448 std::vector<RemoteIndirectStubsInfo> RemoteIndirectStubsInfos;
449 std::vector<StubKey> FreeStubs;
458 std::lock_guard<std::mutex>
Lock(RTPMutex);
459 if (AvailableTrampolines.empty()) {
460 if (
auto Err = grow())
461 return std::move(Err);
463 assert(!AvailableTrampolines.empty() &&
"Failed to grow trampoline pool");
464 auto TrampolineAddr = AvailableTrampolines.back();
465 AvailableTrampolines.pop_back();
466 return TrampolineAddr;
473 if (
auto TrampolineInfoOrErr = Client.emitTrampolineBlock())
474 std::tie(BlockAddr, NumTrampolines) = *TrampolineInfoOrErr;
476 return TrampolineInfoOrErr.takeError();
478 uint32_t TrampolineSize = Client.getTrampolineSize();
479 for (
unsigned I = 0;
I < NumTrampolines; ++
I)
480 this->AvailableTrampolines.push_back(BlockAddr + (
I * TrampolineSize));
487 std::vector<JITTargetAddress> AvailableTrampolines;
498 ErrorHandlerAddress) {}
507 auto Client = std::unique_ptr<OrcRemoteTargetClient>(
510 return std::move(Err);
511 return std::move(Client);
518 <<
format(
"0x%016" PRIx64, Addr) <<
"\n");
519 return callB<exec::CallIntVoid>(Addr);
525 const std::vector<std::string> &
Args) {
527 <<
format(
"0x%016" PRIx64, Addr) <<
"\n");
528 return callB<exec::CallMain>(Addr,
Args);
535 <<
format(
"0x%016" PRIx64, Addr) <<
"\n");
536 return callB<exec::CallVoidVoid>(Addr);
543 auto Id = AllocatorIds.getNext();
544 if (
auto Err = callB<mem::CreateRemoteAllocator>(Id))
545 return std::move(Err);
546 return std::unique_ptr<RemoteRTDyldMemoryManager>(
554 auto Id = IndirectStubOwnerIds.getNext();
555 if (
auto Err = callB<stubs::CreateIndirectStubsOwner>(Id))
556 return std::move(Err);
557 return llvm::make_unique<RemoteIndirectStubsManager>(*
this, Id);
562 assert(!CallbackManager &&
"CallbackManager already obtained");
565 if (
auto Err = callB<stubs::EmitResolverBlock>())
566 return std::move(Err);
569 CallbackManager.emplace(*
this, ES, ErrorHandlerAddress);
578 return callB<utils::GetSymbolAddress>(
Name);
593 addHandler<utils::RequestCompile>(
596 return CallbackManager->executeCompileCallback(Addr);
600 if (
auto RIOrErr = callB<utils::GetRemoteInfo>()) {
601 std::tie(RemoteTargetTriple, RemotePointerSize, RemotePageSize,
602 RemoteTrampolineSize, RemoteIndirectStubSize) = *RIOrErr;
605 Err = RIOrErr.takeError();
609 if (
auto Err = callB<eh::RegisterEHFrames>(Addr, Size))
614 if (
auto Err = callB<mem::DestroyRemoteAllocator>(Id)) {
618 AllocatorIds.release(Id);
623 IndirectStubOwnerIds.release(Id);
624 if (
auto Err = callB<stubs::DestroyIndirectStubsOwner>(Id))
630 return callB<stubs::EmitIndirectStubs>(Id, NumStubsRequired);
634 return callB<stubs::EmitTrampolineBlock>();
637 uint32_t getIndirectStubSize()
const {
return RemoteIndirectStubSize; }
638 uint32_t getPageSize()
const {
return RemotePageSize; }
639 uint32_t getPointerSize()
const {
return RemotePointerSize; }
641 uint32_t getTrampolineSize()
const {
return RemoteTrampolineSize; }
645 return callB<mem::ReadMem>(Src,
Size);
650 return callB<eh::RegisterEHFrames>(RAddr,
Size);
655 if (
auto AddrOrErr = callB<mem::ReserveMem>(Id, Size, Align))
665 if (
auto Err = callB<mem::SetProtections>(Id, RemoteSegAddr, ProtFlags)) {
681 return callB<mem::WritePtr>(Addr, PtrVal);
687 std::function<void(Error)> ReportError;
688 std::string RemoteTargetTriple;
692 uint32_t RemoteIndirectStubSize = 0;
703 #endif // LLVM_EXECUTIONENGINE_ORC_ORCREMOTETARGETCLIENT_H bool needsToReserveAllocationSpace() override
Override to return true to enable the reserveAllocationSpace callback.
Error createStubs(const StubInitsMap &StubInits) override
Create StubInits.size() stubs with the given names, target addresses, and flags.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
Base class for managing collections of named indirect stubs.
bool getAlign(const Function &F, unsigned index, unsigned &align)
This class represents lattice values for constants.
Remote indirect stubs manager.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Interface for byte-streams to be used with RPC.
Expected< std::unique_ptr< RemoteRTDyldMemoryManager > > createRemoteMemoryManager()
Create an RCMemoryManager which will allocate its memory on the remote target.
This class is the base class for all object file types.
uint64_t alignTo(uint64_t Value, uint64_t Align, uint64_t Skew=0)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&... args)
Constructs a new T() with the given args and returns a unique_ptr<T> which owns the object...
RemoteRTDyldMemoryManager(const RemoteRTDyldMemoryManager &)=delete
void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign, uintptr_t RODataSize, uint32_t RODataAlign, uintptr_t RWDataSize, uint32_t RWDataAlign) override
Inform the memory manager about the total amount of memory required to allocate all sections to be lo...
Base class for error info classes.
uint8_t * allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName, bool IsReadOnly) override
Allocate a memory block of (at least) the given size suitable for data.
JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override
Find the stub with the given name.
Target-independent base class for compile callback management.
void notifyObjectLoaded(RuntimeDyld &Dyld, const object::ObjectFile &Obj) override
This method is called after an object has been loaded into memory but before relocations are applied ...
Expected< int > callMain(JITTargetAddress Addr, const std::vector< std::string > &Args)
Call the int(int, char*[]) function at the given address in the target and return its result...
Error createStub(StringRef StubName, JITTargetAddress StubAddr, JITSymbolFlags StubFlags) override
Create a single stub with the given name, target address and flags.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
RemoteCompileCallbackManager(OrcRemoteTargetClient &Client, ExecutionSession &ES, JITTargetAddress ErrorHandlerAddress)
virtual void log(raw_ostream &OS) const =0
Print an error message to an output stream.
Base class for pools of compiler re-entry trampolines.
Tagged union holding either a T or a Error.
Error callVoidVoid(JITTargetAddress Addr)
Call the void() function at the given address in the target and wait for it to finish.
Expected< JITTargetAddress > getSymbolAddress(StringRef Name)
Search for symbols in the remote process.
uint64_t JITTargetAddress
Represents an address in the target process's address space.
friend class OrcRemoteTargetClient
Remote compile callback manager.
const std::string & getTargetTriple() const
Get the triple for the remote target.
This class provides utilities (including memory manager, indirect stubs manager, and compile callback...
Flags for symbols in the JIT.
void deregisterEHFrames() override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
static ErrorSuccess success()
Create a success value.
Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override
Change the value of the implementation pointer for the stub.
bool finalizeMemory(std::string *ErrMsg=nullptr) override
This method is called when object loading is complete and section page permissions can be applied...
An ExecutionSession represents a running JIT program.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings"...
Expected< RemoteCompileCallbackManager & > enableCompileCallbacks(JITTargetAddress ErrorHandlerAddress)
Represents a symbol that has been evaluated to an address already.
Expected< JITTargetAddress > getTrampoline() override
Get an available trampoline address.
Helper for Errors used as out-parameters.
void reportError(Error Err)
Report a error for this execution session.
RemoteRTDyldMemoryManager & operator=(const RemoteRTDyldMemoryManager &)=delete
RemoteTrampolinePool(OrcRemoteTargetClient &Client)
~RemoteIndirectStubsManager() override
uint8_t * allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, StringRef SectionName) override
Allocate a memory block of (at least) the given size suitable for executable code.
Expected< int > callIntVoid(JITTargetAddress Addr)
Call the int(void) function at the given address in the target and return its result.
~RemoteRTDyldMemoryManager()
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
JITEvaluatedSymbol findPointer(StringRef Name) override
Find the implementation-pointer for the stub.
A raw_ostream that writes to an std::string.
Lightweight error class with error context and mandatory checking.
Remote-mapped RuntimeDyld-compatible memory manager.
static Expected< std::unique_ptr< OrcRemoteTargetClient > > Create(rpc::RawByteChannel &Channel, ExecutionSession &ES)
Create an OrcRemoteTargetClient.
StringRef - Represent a constant reference to a string, i.e.
void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress)
Map a section to its target address space value.
void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override
Register the EH frames with the runtime so that c++ exceptions work.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
Expected< std::unique_ptr< RemoteIndirectStubsManager > > createIndirectStubsManager()
Create an RCIndirectStubsManager that will allocate stubs on the remote target.
RemoteIndirectStubsManager(OrcRemoteTargetClient &Client, ResourceIdMgr::ResourceId Id)