13#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
32#include <system_error>
77 std::lock_guard<std::mutex> Lock(
TPMutex);
79 if (
auto Err =
grow())
80 return std::move(Err);
85 return TrampolineAddr;
90 std::lock_guard<std::mutex> Lock(
TPMutex);
111 auto LTP = std::unique_ptr<LocalTrampolinePool>(
115 return std::move(Err);
116 return std::move(LTP);
120 static JITTargetAddress reenter(
void *TrampolinePoolPtr,
void *TrampolineId) {
124 std::promise<ExecutorAddr> LandingAddressP;
125 auto LandingAddressF = LandingAddressP.get_future();
129 LandingAddressP.set_value(LandingAddress);
131 return LandingAddressF.get().getValue();
135 : ResolveLanding(
std::
move(ResolveLanding)) {
137 ErrorAsOutParameter
_(&Err);
142 ORCABI::ResolverCodeSize,
nullptr,
149 ORCABI::writeResolverCode(
static_cast<char *
>(ResolverBlock.
base()),
163 Error grow()
override {
167 auto TrampolineBlock =
174 unsigned NumTrampolines =
176 ORCABI::TrampolineSize;
178 char *TrampolineMem =
static_cast<char *
>(TrampolineBlock.base());
179 ORCABI::writeTrampolines(
183 for (
unsigned I = 0;
I < NumTrampolines; ++
I)
188 TrampolineBlock.getMemoryBlock(),
192 TrampolineBlocks.push_back(std::move(TrampolineBlock));
198 sys::OwningMemoryBlock ResolverBlock;
199 std::vector<sys::OwningMemoryBlock> TrampolineBlocks;
222 CallbacksJD(ES.createBareJITDylib(
"<Callbacks>")),
223 ErrorHandlerAddress(ErrorHandlerAddress) {}
226 this->TP = std::move(TP);
230 std::mutex CCMgrMutex;
231 std::unique_ptr<TrampolinePool> TP;
235 std::map<ExecutorAddr, SymbolStringPtr> AddrToSymbol;
236 size_t NextCallbackId = 0;
240template <
typename ORCABI>
247 auto CCMgr = std::unique_ptr<LocalJITCompileCallbackManager>(
250 return std::move(Err);
251 return std::move(CCMgr);
261 using NotifyLandingResolvedFunction =
267 NotifyLandingResolvedFunction NotifyLandingResolved) {
272 Err = TP.takeError();
300 bool ExportedStubsOnly) = 0;
309 virtual void anchor();
315 : NumStubs(NumStubs), StubsMem(
std::
move(StubsMem)) {}
319 auto ISAS = getIndirectStubsBlockSizes<ORCABI>(MinStubs,
PageSize);
322 "StubBytes is not a page size multiple");
327 auto StubsAndPtrsMem =
329 ISAS.StubBytes + PointerAlloc,
nullptr,
335 auto StubsBlockMem =
static_cast<char *
>(StubsAndPtrsMem.base());
336 auto PtrBlockAddress =
339 ORCABI::writeIndirectStubsBlock(StubsBlockMem,
341 PtrBlockAddress, ISAS.NumStubs);
353 return static_cast<char *
>(StubsMem.
base()) +
Idx * ORCABI::StubSize;
358 static_cast<char *
>(StubsMem.
base()) + NumStubs * ORCABI::StubSize;
359 return reinterpret_cast<void **
>(PtrsBase) +
Idx;
363 unsigned NumStubs = 0;
369template <
typename TargetT>
374 std::lock_guard<std::mutex> Lock(StubsMutex);
375 if (
auto Err = reserveStubs(1))
378 createStubInternal(StubName, StubAddr, StubFlags);
384 std::lock_guard<std::mutex> Lock(StubsMutex);
385 if (
auto Err = reserveStubs(StubInits.
size()))
388 for (
const auto &Entry : StubInits)
389 createStubInternal(Entry.first(), Entry.second.first,
390 Entry.second.second);
396 std::lock_guard<std::mutex> Lock(StubsMutex);
397 auto I = StubIndexes.find(
Name);
398 if (
I == StubIndexes.end())
400 auto Key =
I->second.first;
401 void *StubPtr = IndirectStubsInfos[Key.first].getStub(Key.second);
402 assert(StubPtr &&
"Missing stub address");
405 if (ExportedStubsOnly && !StubSymbol.getFlags().isExported())
411 std::lock_guard<std::mutex> Lock(StubsMutex);
412 auto I = StubIndexes.find(
Name);
413 if (
I == StubIndexes.end())
415 auto Key =
I->second.first;
416 void *PtrPtr = IndirectStubsInfos[Key.first].getPtr(Key.second);
417 assert(PtrPtr &&
"Missing pointer address");
423 using AtomicIntPtr = std::atomic<uintptr_t>;
425 std::lock_guard<std::mutex> Lock(StubsMutex);
426 auto I = StubIndexes.find(
Name);
427 assert(
I != StubIndexes.end() &&
"No stub pointer for symbol");
428 auto Key =
I->second.first;
429 AtomicIntPtr *AtomicStubPtr =
reinterpret_cast<AtomicIntPtr *
>(
430 IndirectStubsInfos[Key.first].getPtr(Key.second));
431 *AtomicStubPtr =
static_cast<uintptr_t
>(NewAddr.
getValue());
436 Error reserveStubs(
unsigned NumStubs) {
437 if (NumStubs <= FreeStubs.size())
440 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
441 unsigned NewBlockId = IndirectStubsInfos.size();
445 return ISI.takeError();
446 for (
unsigned I = 0;
I < ISI->getNumStubs(); ++
I)
447 FreeStubs.push_back(std::make_pair(NewBlockId,
I));
448 IndirectStubsInfos.push_back(std::move(*ISI));
452 void createStubInternal(
StringRef StubName, ExecutorAddr InitAddr,
454 auto Key = FreeStubs.back();
455 FreeStubs.pop_back();
456 *IndirectStubsInfos[Key.first].getPtr(Key.second) =
457 InitAddr.toPtr<
void *>();
458 StubIndexes[StubName] = std::make_pair(Key, StubFlags);
462 std::mutex StubsMutex;
463 std::vector<LocalIndirectStubsInfo<TargetT>> IndirectStubsInfos;
464 using StubKey = std::pair<uint16_t, uint16_t>;
465 std::vector<StubKey> FreeStubs;
466 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
474Expected<std::unique_ptr<JITCompileCallbackManager>>
476 ExecutorAddr ErrorHandlerAddress);
481std::function<std::unique_ptr<IndirectStubsManager>()>
494 Constant *Initializer);
498void 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.
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 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.