LLVM: include/llvm/ExecutionEngine/Orc/IndirectionUtils.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13#ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
14#define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
15
27#include
28#include
29#include
30#include
31#include
32#include
33#include
34#include <system_error>
35#include
36#include
37
38namespace llvm {
39
52
56}
57
58namespace orc {
59
60
61
62
63
64
66public:
69
73
75
76
77
79 std::lock_guardstd::mutex Lock(TPMutex);
81 if (auto Err = grow())
82 return std::move(Err);
83 }
87 return TrampolineAddr;
88 }
89
90
92 std::lock_guardstd::mutex Lock(TPMutex);
94 }
95
96protected:
98
101};
102
103
104template class LocalTrampolinePool : public TrampolinePool {
105public:
106
107
108
112
113 auto LTP = std::unique_ptr(
114 new LocalTrampolinePool(std::move(ResolveLanding), Err));
115
116 if (Err)
117 return std::move(Err);
118 return std::move(LTP);
119 }
120
121private:
122 static JITTargetAddress reenter(void *TrampolinePoolPtr, void *TrampolineId) {
125
126 std::promise LandingAddressP;
127 auto LandingAddressF = LandingAddressP.get_future();
128
131 LandingAddressP.set_value(LandingAddress);
132 });
133 return LandingAddressF.get().getValue();
134 }
135
136 LocalTrampolinePool(ResolveLandingFunction ResolveLanding, Error &Err)
137 : ResolveLanding(std::move(ResolveLanding)) {
138
139 ErrorAsOutParameter _(Err);
140
141
142 std::error_code EC;
144 ORCABI::ResolverCodeSize, nullptr,
146 if (EC) {
148 return;
149 }
150
151 ORCABI::writeResolverCode(static_cast<char *>(ResolverBlock.base()),
155
159 if (EC) {
161 return;
162 }
163 }
164
167
168 std::error_code EC;
169 auto TrampolineBlock =
173 if (EC)
175
176 unsigned NumTrampolines =
178 ORCABI::TrampolineSize;
179
180 char *TrampolineMem = static_cast<char *>(TrampolineBlock.base());
181 ORCABI::writeTrampolines(
184
185 for (unsigned I = 0; I < NumTrampolines; ++I)
188
190 TrampolineBlock.getMemoryBlock(),
193
194 TrampolineBlocks.push_back(std::move(TrampolineBlock));
196 }
197
199
200 sys::OwningMemoryBlock ResolverBlock;
201 std::vectorsys::OwningMemoryBlock TrampolineBlocks;
202};
203
204
206public:
208
210
211
213
214
215
217
218protected:
219
223 : TP(std::move(TP)), ES(ES),
224 CallbacksJD(ES.createBareJITDylib("")),
225 ErrorHandlerAddress(ErrorHandlerAddress) {}
226
228 this->TP = std::move(TP);
229 }
230
231private:
232 std::mutex CCMgrMutex;
233 std::unique_ptr TP;
237 std::map<ExecutorAddr, SymbolStringPtr> AddrToSymbol;
238 size_t NextCallbackId = 0;
239};
240
241
242template
244public:
245
249 auto CCMgr = std::unique_ptr(
250 new LocalJITCompileCallbackManager(ES, ErrorHandlerAddress, Err));
251 if (Err)
252 return std::move(Err);
253 return std::move(CCMgr);
254 }
255
256private:
257
258
259
263 using NotifyLandingResolvedFunction =
265
269 NotifyLandingResolvedFunction NotifyLandingResolved) {
271 });
272
273 if (!TP) {
274 Err = TP.takeError();
275 return;
276 }
277
279 }
280};
281
282
284public:
285
287
289
290
293
294
295
297
298
299
300
302 bool ExportedStubsOnly) = 0;
303
304
306
307
309
310
312
313 void
315 SymbolMap InitialDests) override;
316
317private:
318 void anchor() override;
319};
320
322public:
324 : NumStubs(NumStubs), StubsMem(std::move(StubsMem)) {}
325
329
331 "StubBytes is not a page size multiple");
333
334
335 std::error_code EC;
336 auto StubsAndPtrsMem =
338 ISAS.StubBytes + PointerAlloc, nullptr,
340 if (EC)
342
343 sys::MemoryBlock StubsBlock(StubsAndPtrsMem.base(), ISAS.StubBytes);
344 auto StubsBlockMem = static_cast<char *>(StubsAndPtrsMem.base());
345 auto PtrBlockAddress =
347
348 ORCABI::writeIndirectStubsBlock(StubsBlockMem,
350 PtrBlockAddress, ISAS.NumStubs);
351
355
357 }
358
360
362 return static_cast<char *>(StubsMem.base()) + Idx * ORCABI::StubSize;
363 }
364
365 void **getPtr(unsigned Idx) const {
366 char *PtrsBase =
367 static_cast<char *>(StubsMem.base()) + NumStubs * ORCABI::StubSize;
368 return reinterpret_cast<void **>(PtrsBase) + Idx;
369 }
370
371private:
372 unsigned NumStubs = 0;
374};
375
376
377
378template
380public:
383 std::lock_guardstd::mutex Lock(StubsMutex);
384 if (auto Err = reserveStubs(1))
385 return Err;
386
387 createStubInternal(StubName, StubAddr, StubFlags);
388
390 }
391
393 std::lock_guardstd::mutex Lock(StubsMutex);
394 if (auto Err = reserveStubs(StubInits.size()))
395 return Err;
396
397 for (const auto &Entry : StubInits)
398 createStubInternal(Entry.first(), Entry.second.first,
399 Entry.second.second);
400
402 }
403
405 std::lock_guardstd::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())
416 return StubSymbol;
417 }
418
420 std::lock_guardstd::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");
429 }
430
432 using AtomicIntPtr = std::atomic<uintptr_t>;
433
434 std::lock_guardstd::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());
442 }
443
444private:
445 Error reserveStubs(unsigned NumStubs) {
446 if (NumStubs <= FreeStubs.size())
448
449 unsigned NewStubsRequired = NumStubs - FreeStubs.size();
450 unsigned NewBlockId = IndirectStubsInfos.size();
451 auto ISI =
453 if (!ISI)
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));
459 }
460
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);
468 }
469
471 std::mutex StubsMutex;
472 std::vector<LocalIndirectStubsInfo> IndirectStubsInfos;
473 using StubKey = std::pair<uint16_t, uint16_t>;
474 std::vector FreeStubs;
475 StringMap<std::pair<StubKey, JITSymbolFlags>> StubIndexes;
476};
477
478
479
480
481
482
483LLVM_ABI Expected<std::unique_ptr>
486
487
488
489
490LLVM_ABI std::function<std::unique_ptr()>
492
493
494
495
496
497
499
500
501
503 const Twine &Name,
504 Constant *Initializer);
505
506
507
509
510
511
512
514public:
515
516
518
519private:
520 unsigned NextId = 0;
521};
522
523
524
525
526
527
528
529
530
531
532
533
534
537
538
542
543
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
573
574}
575
576}
577
578#endif
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
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 ...
This is an important base class in LLVM.
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.
Class to represent function types.
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.
Class to represent pointers.
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.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM Value Representation.
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.
Definition IndirectionUtils.h:283
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.
~IndirectStubsManager() override=default
StringMap< std::pair< ExecutorAddr, JITSymbolFlags > > StubInitsMap
Map type for initializing the manager. See init.
Definition IndirectionUtils.h:286
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 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.
Definition IndirectionUtils.h:205
JITCompileCallbackManager(std::unique_ptr< TrampolinePool > TP, ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Construct a JITCompileCallbackManager.
Definition IndirectionUtils.h:220
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)
Definition IndirectionUtils.h:227
std::function< ExecutorAddr()> CompileFunction
Definition IndirectionUtils.h:207
Represents a JIT'd dynamic library.
unsigned getNumStubs() const
Definition IndirectionUtils.h:359
void * getStub(unsigned Idx) const
Definition IndirectionUtils.h:361
LocalIndirectStubsInfo(unsigned NumStubs, sys::OwningMemoryBlock StubsMem)
Definition IndirectionUtils.h:323
static Expected< LocalIndirectStubsInfo > create(unsigned MinStubs, unsigned PageSize)
Definition IndirectionUtils.h:326
void ** getPtr(unsigned Idx) const
Definition IndirectionUtils.h:365
IndirectStubsManager implementation for the host architecture, e.g.
Definition IndirectionUtils.h:379
Error createStub(StringRef StubName, ExecutorAddr StubAddr, JITSymbolFlags StubFlags) override
Create a single stub with the given name, target address and flags.
Definition IndirectionUtils.h:381
ExecutorSymbolDef findPointer(StringRef Name) override
Find the implementation-pointer for the stub.
Definition IndirectionUtils.h:419
Error updatePointer(StringRef Name, ExecutorAddr NewAddr) override
Change the value of the implementation pointer for the stub.
Definition IndirectionUtils.h:431
ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly) override
Find the stub with the given name.
Definition IndirectionUtils.h:404
Error createStubs(const StubInitsMap &StubInits) override
Create StubInits.size() stubs with the given names, target addresses, and flags.
Definition IndirectionUtils.h:392
Manage compile callbacks for in-process JITs.
Definition IndirectionUtils.h:243
static Expected< std::unique_ptr< LocalJITCompileCallbackManager > > Create(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddress)
Create a new LocalJITCompileCallbackManager.
Definition IndirectionUtils.h:247
A trampoline pool for trampolines within the current process.
Definition IndirectionUtils.h:104
static Expected< std::unique_ptr< LocalTrampolinePool > > Create(ResolveLandingFunction ResolveLanding)
Creates a LocalTrampolinePool with the given RunCallback function.
Definition IndirectionUtils.h:110
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.
Definition IndirectionUtils.h:65
std::vector< ExecutorAddr > AvailableTrampolines
Definition IndirectionUtils.h:100
std::mutex TPMutex
Definition IndirectionUtils.h:99
virtual ~TrampolinePool()
unique_function< void( ExecutorAddr TrampolineAddr, NotifyLandingResolvedFunction OnLandingResolved) const > ResolveLandingFunction
Definition IndirectionUtils.h:70
unique_function< void(ExecutorAddr) const > NotifyLandingResolvedFunction
Definition IndirectionUtils.h:67
void releaseTrampoline(ExecutorAddr TrampolineAddr)
Returns the given trampoline to the pool for re-use.
Definition IndirectionUtils.h:91
Expected< ExecutorAddr > getTrampoline()
Get an available trampoline address.
Definition IndirectionUtils.h:78
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.
static unsigned getPageSizeEstimate()
Get the process's estimated page size.
unique_function is a type-erasing functor similar to std::function.
IndirectStubsAllocationSizes getIndirectStubsBlockSizes(unsigned MinStubs, unsigned RoundToMultipleOf=0)
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.
DenseMap< SymbolStringPtr, ExecutorSymbolDef > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
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.
FunctionAddr VTableAddr Value
uint64_t JITTargetAddress
Represents an address in the target process's address space.
LLVM_ATTRIBUTE_VISIBILITY_DEFAULT AnalysisKey InnerAnalysisManagerProxy< AnalysisManagerT, IRUnitT, ExtraArgTs... >::Key
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
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.