13#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
33#include <system_error>
78 std::lock_guard<std::mutex> Lock(
TPMutex);
80 if (
auto Err =
grow())
81 return std::move(Err);
86 return TrampolineAddr;
91 std::lock_guard<std::mutex> Lock(
TPMutex);
112 auto LTP = std::unique_ptr<LocalTrampolinePool>(
116 return std::move(Err);
117 return std::move(LTP);
121 static JITTargetAddress reenter(
void *TrampolinePoolPtr,
void *TrampolineId) {
125 std::promise<ExecutorAddr> LandingAddressP;
126 auto LandingAddressF = LandingAddressP.get_future();
130 LandingAddressP.set_value(LandingAddress);
132 return LandingAddressF.get().getValue();
136 : ResolveLanding(
std::
move(ResolveLanding)) {
138 ErrorAsOutParameter
_(Err);
143 ORCABI::ResolverCodeSize,
nullptr,
150 ORCABI::writeResolverCode(
static_cast<char *
>(ResolverBlock.
base()),
164 Error grow()
override {
168 auto TrampolineBlock =
175 unsigned NumTrampolines =
177 ORCABI::TrampolineSize;
179 char *TrampolineMem =
static_cast<char *
>(TrampolineBlock.base());
180 ORCABI::writeTrampolines(
184 for (
unsigned I = 0;
I < NumTrampolines; ++
I)
189 TrampolineBlock.getMemoryBlock(),
193 TrampolineBlocks.push_back(std::move(TrampolineBlock));
199 sys::OwningMemoryBlock ResolverBlock;
200 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
223 CallbacksJD(ES.createBareJITDylib(
"<Callbacks>")),
224 ErrorHandlerAddress(ErrorHandlerAddress) {}
227 this->TP = std::move(TP);
231 std::mutex CCMgrMutex;
232 std::unique_ptr<TrampolinePool> TP;
236 std::map<ExecutorAddr, SymbolStringPtr> AddrToSymbol;
237 size_t NextCallbackId = 0;
241template <
typename ORCABI>
248 auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
251 return std::move(Err);
252 return std::move(CCMgr);
262 using NotifyLandingResolvedFunction =
268 NotifyLandingResolvedFunction NotifyLandingResolved) {
273 Err = TP.takeError();
301 bool ExportedStubsOnly) = 0;
317 void anchor()
override;
323 : NumStubs(NumStubs), StubsMem(
std::
move(StubsMem)) {}
327 auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs,
PageSize);
330 "StubBytes is not a page size multiple");
335 auto StubsAndPtrsMem =
337 ISAS.StubBytes + PointerAlloc,
nullptr,
343 auto StubsBlockMem =
static_cast<char *
>(StubsAndPtrsMem.base());
344 auto PtrBlockAddress =
347 ORCABI::writeIndirectStubsBlock(StubsBlockMem,
349 PtrBlockAddress, ISAS.NumStubs);
361 return static_cast<char *
>(StubsMem.
base()) +
Idx * ORCABI::StubSize;
366 static_cast<char *
>(StubsMem.
base()) + NumStubs * ORCABI::StubSize;
367 return reinterpret_cast<void **
>(PtrsBase) +
Idx;
371 unsigned NumStubs = 0;
377template <
typename TargetT>
382 std::lock_guard<std::mutex> Lock(StubsMutex);
383 if (
auto Err = reserveStubs(1))
386 createStubInternal(StubName, StubAddr, StubFlags);
392 std::lock_guard<std::mutex> Lock(StubsMutex);
393 if (
auto Err = reserveStubs(StubInits.
size()))
396 for (
const auto &Entry : StubInits)
397 createStubInternal(Entry.first(), Entry.second.first,
398 Entry.second.second);
404 std::lock_guard<std::mutex> Lock(StubsMutex);
405 auto I = StubIndexes.find(
Name);
406 if (
I == StubIndexes.end())
408 auto Key =
I->second.first;
409 void *StubPtr = IndirectStubsInfos[Key.first].getStub(Key.second);
410 assert(StubPtr &&
"Missing stub address");
413 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
419 std::lock_guard<std::mutex> Lock(StubsMutex);
420 auto I = StubIndexes.find(
Name);
421 if (
I == StubIndexes.end())
423 auto Key =
I->second.first;
424 void *PtrPtr = IndirectStubsInfos[Key.first].getPtr(Key.second);
425 assert(PtrPtr &&
"Missing pointer address");
431 using AtomicIntPtr = std::atomic<uintptr_t>;
433 std::lock_guard<std::mutex> Lock(StubsMutex);
434 auto I = StubIndexes.find(
Name);
435 assert(
I != StubIndexes.end() &&
"No stub pointer for symbol");
436 auto Key =
I->second.first;
437 AtomicIntPtr *AtomicStubPtr =
reinterpret_cast<AtomicIntPtr *
>(
438 IndirectStubsInfos[Key.first].getPtr(Key.second));
439 *AtomicStubPtr =
static_cast<uintptr_t
>(NewAddr.
getValue());
444 Error reserveStubs(
unsigned NumStubs) {
445 if (NumStubs <= FreeStubs.size())
448 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
449 unsigned NewBlockId = IndirectStubsInfos.size();
453 return ISI.takeError();
454 for (
unsigned I = 0;
I < ISI->getNumStubs(); ++
I)
455 FreeStubs.push_back(std::make_pair(NewBlockId,
I));
456 IndirectStubsInfos.push_back(std::move(*ISI));
460 void createStubInternal(
StringRef StubName, ExecutorAddr InitAddr,
462 auto Key = FreeStubs.back();
463 FreeStubs.pop_back();
464 *IndirectStubsInfos[Key.first].getPtr(Key.second) =
465 InitAddr.toPtr<
void *>();
466 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
470 std::mutex StubsMutex;
471 std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
472 using StubKey = std::pair<uint16_t, uint16_t>;
473 std::vector<StubKey> FreeStubs;
474 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
482Expected<std::unique_ptr<JITCompileCallbackManager>>
484 ExecutorAddr ErrorHandlerAddress);
489std::function<std::unique_ptr<IndirectStubsManager>()>
502 Constant *Initializer);
506void makeStub(Function &
F, Value &ImplPointer);
This file defines the StringMap class.
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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)
Machine Check Debug Module
Provides a library for accessing information about this process and other processes on the operating ...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Helper for Errors used as out-parameters.
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.
Flags for symbols in the JIT.
Superclass for all disassemblers.
A Module instance is used to store all the information related to an LLVM module.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
StringRef - Represent a constant reference to a string, i.e.
An ExecutionSession represents a running JIT program.
Represents an address in the executor process.
uint64_t getValue() const
static ExecutorAddr fromPtr(T *Ptr, UnwrapFn &&Unwrap=UnwrapFn())
Create an ExecutorAddr from the given pointer.
Represents a defining location for a JIT symbol.
Base class for managing collections of named indirect stubs.
virtual Error createStub(StringRef StubName, ExecutorAddr StubAddr, JITSymbolFlags StubFlags)=0
Create a single stub with the given name, target address and flags.
virtual ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly)=0
Find the stub with the given name.
virtual ExecutorSymbolDef findPointer(StringRef Name)=0
Find the implementation-pointer for the stub.
virtual Error updatePointer(StringRef Name, ExecutorAddr NewAddr)=0
Change the value of the implementation pointer for the stub.
virtual ~IndirectStubsManager()=default
virtual Error createStubs(const StubInitsMap &StubInits)=0
Create StubInits.size() stubs with the given names, target addresses, and flags.
void emitRedirectableSymbols(std::unique_ptr< MaterializationResponsibility > MR, SymbolMap InitialDests) override
Emit redirectable symbol.
Error redirect(JITDylib &JD, const SymbolMap &NewDests) override
— RedirectableSymbolManager implementation —
Target-independent base class for compile callback management.
JITCompileCallbackManager(std::unique_ptr< TrampolinePool > TP, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Construct a JITCompileCallbackManager.
ExecutorAddr executeCompileCallback(ExecutorAddr TrampolineAddr)
Execute the callback for the given trampoline id.
virtual ~JITCompileCallbackManager()=default
Expected< ExecutorAddr > getCompileCallback(CompileFunction Compile)
Reserve a compile callback.
void setTrampolinePool(std::unique_ptr< TrampolinePool > TP)
std::function< ExecutorAddr()> CompileFunction
Represents a JIT'd dynamic library.
unsigned getNumStubs() const
void * getStub(unsigned Idx) const
LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
static Expected< LocalIndirectStubsInfo > create(unsigned MinStubs, unsigned PageSize)
void ** getPtr(unsigned Idx) const
IndirectStubsManager implementation for the host architecture, e.g.
Error createStub(StringRef StubName, ExecutorAddr StubAddr, JITSymbolFlags StubFlags) override
Create a single stub with the given name, target address and flags.
ExecutorSymbolDef findPointer(StringRef Name) override
Find the implementation-pointer for the stub.
Error updatePointer(StringRef Name, ExecutorAddr NewAddr) override
Change the value of the implementation pointer for the stub.
ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly) override
Find the stub with the given name.
Error createStubs(const StubInitsMap &StubInits) override
Create StubInits.size() stubs with the given names, target addresses, and flags.
Manage compile callbacks for in-process JITs.
static Expected< std::unique_ptr< LocalJITCompileCallbackManager > > Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Create a new LocalJITCompileCallbackManager.
A trampoline pool for trampolines within the current process.
static Expected< std::unique_ptr< LocalTrampolinePool > > Create(ResolveLandingFunction ResolveLanding)
Creates a LocalTrampolinePool with the given RunCallback function.
Base class for managing redirectable symbols in which a call gets redirected to another symbol in run...
Base class for pools of compiler re-entry trampolines.
std::vector< ExecutorAddr > AvailableTrampolines
virtual ~TrampolinePool()
unique_function< void(ExecutorAddr) const > NotifyLandingResolvedFunction
unique_function< void(ExecutorAddr TrampolineAddr, NotifyLandingResolvedFunction OnLandingResolved) const > ResolveLandingFunction
void releaseTrampoline(ExecutorAddr TrampolineAddr)
Returns the given trampoline to the pool for re-use.
Expected< ExecutorAddr > getTrampoline()
Get an available trampoline address.
This class encapsulates the notion of a memory block which has an address and a size.
static MemoryBlock allocateMappedMemory(size_t NumBytes, const MemoryBlock *const NearBlock, unsigned Flags, std::error_code &EC)
This method allocates a block of memory that is suitable for loading dynamically generated code (e....
static std::error_code protectMappedMemory(const MemoryBlock &Block, unsigned Flags)
This method sets the protection flags for a block of memory to the state specified by /p Flags.
Owning version of MemoryBlock.
MemoryBlock getMemoryBlock() const
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
unique_function is a type-erasing functor similar to std::function.
Constant * createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr)
Build a function pointer of FunctionType with the given constant address.
Expected< std::unique_ptr< JITCompileCallbackManager > > createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Create a local compile callback manager.
void makeStub(Function &F, Value &ImplPointer)
Turn a function declaration into a stub function that makes an indirect call using the given function...
Error addFunctionPointerRelocationsToCurrentSymbol(jitlink::Symbol &Sym, jitlink::LinkGraph &G, MCDisassembler &Disassembler, MCInstrAnalysis &MIA)
Introduce relocations to Sym in its own definition if there are any pointers formed via PC-relative a...
GlobalVariable * cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap=nullptr)
Clone a global variable declaration into a new module.
Function * cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap=nullptr)
Clone a function declaration into a new module.
std::function< std::unique_ptr< IndirectStubsManager >()> createLocalIndirectStubsManagerBuilder(const Triple &T)
Create a local indirect stubs manager builder.
GlobalAlias * cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, ValueToValueMapTy &VMap)
Clone a global alias declaration into a new module.
GlobalVariable * createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer)
Create a function pointer with the given type, name, and initializer in the given Module.
This is an optimization pass for GlobalISel generic memory operations.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Error errorCodeToError(std::error_code EC)
Helper for converting an std::error_code to a Error.
Implement std::hash so that hash_code can be used in STL containers.