13#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
34#include <system_error>
79 std::lock_guard<std::mutex> Lock(TPMutex);
80 if (AvailableTrampolines.empty()) {
81 if (
auto Err = grow())
82 return std::move(Err);
84 assert(!AvailableTrampolines.empty() &&
"Failed to grow trampoline pool");
85 auto TrampolineAddr = AvailableTrampolines.back();
86 AvailableTrampolines.pop_back();
87 return TrampolineAddr;
92 std::lock_guard<std::mutex> Lock(TPMutex);
93 AvailableTrampolines.push_back(TrampolineAddr);
113 auto LTP = std::unique_ptr<LocalTrampolinePool>(
117 return std::move(Err);
118 return std::move(LTP);
122 static JITTargetAddress reenter(
void *TrampolinePoolPtr,
void *TrampolineId) {
126 std::promise<ExecutorAddr> LandingAddressP;
127 auto LandingAddressF = LandingAddressP.get_future();
131 LandingAddressP.set_value(LandingAddress);
133 return LandingAddressF.get().getValue();
137 : ResolveLanding(
std::
move(ResolveLanding)) {
139 ErrorAsOutParameter
_(Err);
144 ORCABI::ResolverCodeSize,
nullptr,
151 ORCABI::writeResolverCode(
static_cast<char *
>(ResolverBlock.
base()),
165 Error grow()
override {
169 auto TrampolineBlock =
176 unsigned NumTrampolines =
178 ORCABI::TrampolineSize;
180 char *TrampolineMem =
static_cast<char *
>(TrampolineBlock.base());
181 ORCABI::writeTrampolines(
185 for (
unsigned I = 0;
I < NumTrampolines; ++
I)
190 TrampolineBlock.getMemoryBlock(),
194 TrampolineBlocks.push_back(std::move(TrampolineBlock));
200 sys::OwningMemoryBlock ResolverBlock;
201 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
224 CallbacksJD(ES.createBareJITDylib(
"<Callbacks>")),
225 ErrorHandlerAddress(ErrorHandlerAddress) {}
228 this->TP = std::move(TP);
232 std::mutex CCMgrMutex;
233 std::unique_ptr<TrampolinePool> TP;
237 std::map<ExecutorAddr, SymbolStringPtr> AddrToSymbol;
238 size_t NextCallbackId = 0;
242template <
typename ORCABI>
249 auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
252 return std::move(Err);
253 return std::move(CCMgr);
263 using NotifyLandingResolvedFunction =
269 NotifyLandingResolvedFunction NotifyLandingResolved) {
274 Err = TP.takeError();
302 bool ExportedStubsOnly) = 0;
314 emitRedirectableSymbols(std::unique_ptr<MaterializationResponsibility> MR,
318 void anchor()
override;
324 : NumStubs(NumStubs), StubsMem(
std::
move(StubsMem)) {}
328 auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs,
PageSize);
331 "StubBytes is not a page size multiple");
336 auto StubsAndPtrsMem =
338 ISAS.StubBytes + PointerAlloc,
nullptr,
344 auto StubsBlockMem =
static_cast<char *
>(StubsAndPtrsMem.base());
345 auto PtrBlockAddress =
348 ORCABI::writeIndirectStubsBlock(StubsBlockMem,
350 PtrBlockAddress, ISAS.NumStubs);
362 return static_cast<char *
>(StubsMem.
base()) +
Idx * ORCABI::StubSize;
367 static_cast<char *
>(StubsMem.
base()) + NumStubs * ORCABI::StubSize;
368 return reinterpret_cast<void **
>(PtrsBase) +
Idx;
372 unsigned NumStubs = 0;
378template <
typename TargetT>
383 std::lock_guard<std::mutex> Lock(StubsMutex);
384 if (
auto Err = reserveStubs(1))
387 createStubInternal(StubName, StubAddr, StubFlags);
393 std::lock_guard<std::mutex> Lock(StubsMutex);
394 if (
auto Err = reserveStubs(StubInits.
size()))
397 for (
const auto &Entry : StubInits)
398 createStubInternal(Entry.first(), Entry.second.first,
399 Entry.second.second);
405 std::lock_guard<std::mutex> Lock(StubsMutex);
406 auto I = StubIndexes.find(
Name);
407 if (
I == StubIndexes.end())
409 auto Key =
I->second.first;
410 void *StubPtr = IndirectStubsInfos[Key.first].getStub(Key.second);
411 assert(StubPtr &&
"Missing stub address");
414 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
420 std::lock_guard<std::mutex> Lock(StubsMutex);
421 auto I = StubIndexes.find(
Name);
422 if (
I == StubIndexes.end())
424 auto Key =
I->second.first;
425 void *PtrPtr = IndirectStubsInfos[Key.first].getPtr(Key.second);
426 assert(PtrPtr &&
"Missing pointer address");
432 using AtomicIntPtr = std::atomic<uintptr_t>;
434 std::lock_guard<std::mutex> Lock(StubsMutex);
435 auto I = StubIndexes.find(
Name);
436 assert(
I != StubIndexes.end() &&
"No stub pointer for symbol");
437 auto Key =
I->second.first;
438 AtomicIntPtr *AtomicStubPtr =
reinterpret_cast<AtomicIntPtr *
>(
439 IndirectStubsInfos[Key.first].getPtr(Key.second));
440 *AtomicStubPtr =
static_cast<uintptr_t
>(NewAddr.
getValue());
445 Error reserveStubs(
unsigned NumStubs) {
446 if (NumStubs <= FreeStubs.size())
449 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
450 unsigned NewBlockId = IndirectStubsInfos.size();
454 return ISI.takeError();
455 for (
unsigned I = 0;
I < ISI->getNumStubs(); ++
I)
456 FreeStubs.push_back(std::make_pair(NewBlockId,
I));
457 IndirectStubsInfos.push_back(std::move(*ISI));
461 void createStubInternal(
StringRef StubName, ExecutorAddr InitAddr,
463 auto Key = FreeStubs.back();
464 FreeStubs.pop_back();
465 *IndirectStubsInfos[Key.first].getPtr(Key.second) =
466 InitAddr.toPtr<
void *>();
467 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
471 std::mutex StubsMutex;
472 std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
473 using StubKey = std::pair<uint16_t, uint16_t>;
474 std::vector<StubKey> FreeStubs;
475 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
483LLVM_ABI Expected<std::unique_ptr<JITCompileCallbackManager>>
485 ExecutorAddr ErrorHandlerAddress);
490LLVM_ABI std::function<std::unique_ptr<IndirectStubsManager>()>
504 Constant *Initializer);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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 ...
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.
Target-independent base class for compile callback management.
JITCompileCallbackManager(std::unique_ptr< TrampolinePool > TP, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Construct a JITCompileCallbackManager.
LLVM_ABI ExecutorAddr executeCompileCallback(ExecutorAddr TrampolineAddr)
Execute the callback for the given trampoline id.
virtual ~JITCompileCallbackManager()=default
LLVM_ABI 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 LLVM_ABI 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.
static LLVM_ABI 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....
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.
LLVM_ABI Constant * createIRTypedAddress(FunctionType &FT, ExecutorAddr Addr)
Build a function pointer of FunctionType with the given constant address.
LLVM_ABI Expected< std::unique_ptr< JITCompileCallbackManager > > createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Create a local compile callback manager.
LLVM_ABI void makeStub(Function &F, Value &ImplPointer)
Turn a function declaration into a stub function that makes an indirect call using the given function...
LLVM_ABI 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...
LLVM_ABI GlobalVariable * cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, ValueToValueMapTy *VMap=nullptr)
Clone a global variable declaration into a new module.
LLVM_ABI Function * cloneFunctionDecl(Module &Dst, const Function &F, ValueToValueMapTy *VMap=nullptr)
Clone a function declaration into a new module.
LLVM_ABI std::function< std::unique_ptr< IndirectStubsManager >()> createLocalIndirectStubsManagerBuilder(const Triple &T)
Create a local indirect stubs manager builder.
LLVM_ABI GlobalAlias * cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA, ValueToValueMapTy &VMap)
Clone a global alias declaration into a new module.
LLVM_ABI 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.
LLVM_ABI 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.