LLVM 23.0.0git
EPCIndirectionUtils.h
Go to the documentation of this file.
1//===--- EPCIndirectionUtils.h - EPC based indirection utils ----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Indirection utilities (stubs, trampolines, lazy call-throughs) that use the
10// ExecutorProcessControl API to interact with the executor process.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H
15#define LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H
16
21
22#include <mutex>
23
24namespace llvm {
25namespace orc {
26
28class MemoryAccess;
29
30/// Provides ExecutorProcessControl based indirect stubs, trampoline pool and
31/// lazy call through manager.
32class EPCIndirectionUtils {
34
35public:
36 /// ABI support base class. Used to write resolver, stub, and trampoline
37 /// blocks.
39 protected:
40 ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize,
41 unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
42 : PointerSize(PointerSize), TrampolineSize(TrampolineSize),
43 StubSize(StubSize),
44 StubToPointerMaxDisplacement(StubToPointerMaxDisplacement),
45 ResolverCodeSize(ResolverCodeSize) {}
46
47 public:
48 virtual ~ABISupport();
49
50 unsigned getPointerSize() const { return PointerSize; }
51 unsigned getTrampolineSize() const { return TrampolineSize; }
52 unsigned getStubSize() const { return StubSize; }
54 return StubToPointerMaxDisplacement;
55 }
56 unsigned getResolverCodeSize() const { return ResolverCodeSize; }
57
58 virtual void writeResolverCode(char *ResolverWorkingMem,
59 ExecutorAddr ResolverTargetAddr,
60 ExecutorAddr ReentryFnAddr,
61 ExecutorAddr ReentryCtxAddr) const = 0;
62
63 virtual void writeTrampolines(char *TrampolineBlockWorkingMem,
64 ExecutorAddr TrampolineBlockTragetAddr,
65 ExecutorAddr ResolverAddr,
66 unsigned NumTrampolines) const = 0;
67
69 char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress,
70 ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) const = 0;
71
72 private:
73 unsigned PointerSize = 0;
74 unsigned TrampolineSize = 0;
75 unsigned StubSize = 0;
76 unsigned StubToPointerMaxDisplacement = 0;
77 unsigned ResolverCodeSize = 0;
78 };
79
80 /// Create using the given ABI class.
81 template <typename ORCABI>
82 static std::unique_ptr<EPCIndirectionUtils>
85
86 /// Create based on the ExecutorProcessControl triple.
89 MemoryAccess &MemAccess);
90
91 /// Return a reference to the ExecutorProcessControl object.
93
94 /// Return a reference to the MemoryAccess object for this instance.
95 MemoryAccess &getMemoryAccess() const { return MemAccess; }
96
97 /// Return a reference to the JITLinkMemoryManager object for this instance.
98 jitlink::JITLinkMemoryManager &getMemManager() const { return MemMgr; }
99
100 /// Return a reference to the ABISupport object for this instance.
101 ABISupport &getABISupport() const { return *ABI; }
102
103 /// Release memory for resources held by this instance. This *must* be called
104 /// prior to destruction of the class.
106
107 /// Write resolver code to the executor process and return its address.
108 /// This must be called before any call to createTrampolinePool or
109 /// createLazyCallThroughManager.
111 writeResolverBlock(ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr);
112
113 /// Returns the address of the Resolver block. Returns zero if the
114 /// writeResolverBlock method has not previously been called.
115 ExecutorAddr getResolverBlockAddress() const { return ResolverBlockAddr; }
116
117 /// Create an IndirectStubsManager for the executor process.
118 LLVM_ABI std::unique_ptr<IndirectStubsManager> createIndirectStubsManager();
119
120 /// Create a TrampolinePool for the executor process.
122
123 /// Create a LazyCallThroughManager.
124 /// This function should only be called once.
127 ExecutorAddr ErrorHandlerAddr);
128
129 /// Create a LazyCallThroughManager for the executor process.
131 assert(LCTM && "createLazyCallThroughManager must be called first");
132 return *LCTM;
133 }
134
135private:
137
138 struct IndirectStubInfo {
139 IndirectStubInfo() = default;
140 IndirectStubInfo(ExecutorAddr StubAddress, ExecutorAddr PointerAddress)
141 : StubAddress(StubAddress), PointerAddress(PointerAddress) {}
142 ExecutorAddr StubAddress;
143 ExecutorAddr PointerAddress;
144 };
145
146 using IndirectStubInfoVector = std::vector<IndirectStubInfo>;
147
148 /// Create an EPCIndirectionUtils instance.
149 EPCIndirectionUtils(ExecutorProcessControl &EPC,
150 jitlink::JITLinkMemoryManager &MemMgr,
151 MemoryAccess &MemAccess, std::unique_ptr<ABISupport> ABI);
152
153 Expected<IndirectStubInfoVector> getIndirectStubs(unsigned NumStubs);
154
155 std::mutex EPCUIMutex;
156 ExecutorProcessControl &EPC;
157 jitlink::JITLinkMemoryManager &MemMgr;
158 MemoryAccess &MemAccess;
159 std::unique_ptr<ABISupport> ABI;
160 ExecutorAddr ResolverBlockAddr;
161 FinalizedAlloc ResolverBlock;
162 std::unique_ptr<TrampolinePool> TP;
163 std::unique_ptr<LazyCallThroughManager> LCTM;
164
165 std::vector<IndirectStubInfo> AvailableIndirectStubs;
166 std::vector<FinalizedAlloc> IndirectStubAllocs;
167};
168
169/// This will call writeResolver on the given EPCIndirectionUtils instance
170/// to set up re-entry via a function that will directly return the trampoline
171/// landing address.
172///
173/// The EPCIndirectionUtils' LazyCallThroughManager must have been previously
174/// created via EPCIndirectionUtils::createLazyCallThroughManager.
175///
176/// The EPCIndirectionUtils' writeResolver method must not have been previously
177/// called.
178///
179/// This function is experimental and likely subject to revision.
181
182namespace detail {
183
184template <typename ORCABI>
186public:
188 : ABISupport(ORCABI::PointerSize, ORCABI::TrampolineSize,
189 ORCABI::StubSize, ORCABI::StubToPointerMaxDisplacement,
190 ORCABI::ResolverCodeSize) {}
191
192 void writeResolverCode(char *ResolverWorkingMem,
193 ExecutorAddr ResolverTargetAddr,
194 ExecutorAddr ReentryFnAddr,
195 ExecutorAddr ReentryCtxAddr) const override {
196 ORCABI::writeResolverCode(ResolverWorkingMem, ResolverTargetAddr,
197 ReentryFnAddr, ReentryCtxAddr);
198 }
199
200 void writeTrampolines(char *TrampolineBlockWorkingMem,
201 ExecutorAddr TrampolineBlockTargetAddr,
202 ExecutorAddr ResolverAddr,
203 unsigned NumTrampolines) const override {
204 ORCABI::writeTrampolines(TrampolineBlockWorkingMem,
205 TrampolineBlockTargetAddr, ResolverAddr,
206 NumTrampolines);
207 }
208
209 void writeIndirectStubsBlock(char *StubsBlockWorkingMem,
210 ExecutorAddr StubsBlockTargetAddress,
211 ExecutorAddr PointersBlockTargetAddress,
212 unsigned NumStubs) const override {
213 ORCABI::writeIndirectStubsBlock(StubsBlockWorkingMem,
214 StubsBlockTargetAddress,
215 PointersBlockTargetAddress, NumStubs);
216 }
217};
218
219} // end namespace detail
220
221template <typename ORCABI>
222std::unique_ptr<EPCIndirectionUtils>
225 MemoryAccess &MemAccess) {
226 return std::unique_ptr<EPCIndirectionUtils>(new EPCIndirectionUtils(
227 EPC, MemMgr, MemAccess,
228 std::make_unique<detail::ABISupportImpl<ORCABI>>()));
229}
230
231} // end namespace orc
232} // end namespace llvm
233
234#endif // LLVM_EXECUTIONENGINE_ORC_EPCINDIRECTIONUTILS_H
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
#define LLVM_ABI
Definition Compiler.h:213
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
Tagged union holding either a T or a Error.
Definition Error.h:485
virtual void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) const =0
ABISupport(unsigned PointerSize, unsigned TrampolineSize, unsigned StubSize, unsigned StubToPointerMaxDisplacement, unsigned ResolverCodeSize)
virtual void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddr, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr) const =0
virtual void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTragetAddr, ExecutorAddr ResolverAddr, unsigned NumTrampolines) const =0
Provides ExecutorProcessControl based indirect stubs, trampoline pool and lazy call through manager.
LLVM_ABI std::unique_ptr< IndirectStubsManager > createIndirectStubsManager()
Create an IndirectStubsManager for the executor process.
LLVM_ABI Expected< ExecutorAddr > writeResolverBlock(ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr)
Write resolver code to the executor process and return its address.
LazyCallThroughManager & getLazyCallThroughManager()
Create a LazyCallThroughManager for the executor process.
MemoryAccess & getMemoryAccess() const
Return a reference to the MemoryAccess object for this instance.
ExecutorProcessControl & getExecutorProcessControl() const
Return a reference to the ExecutorProcessControl object.
jitlink::JITLinkMemoryManager & getMemManager() const
Return a reference to the JITLinkMemoryManager object for this instance.
static LLVM_ABI Expected< std::unique_ptr< EPCIndirectionUtils > > Create(ExecutorProcessControl &EPC, jitlink::JITLinkMemoryManager &MemMgr, MemoryAccess &MemAccess)
Create based on the ExecutorProcessControl triple.
LLVM_ABI LazyCallThroughManager & createLazyCallThroughManager(ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr)
Create a LazyCallThroughManager.
LLVM_ABI Error cleanup()
Release memory for resources held by this instance.
LLVM_ABI TrampolinePool & getTrampolinePool()
Create a TrampolinePool for the executor process.
static std::unique_ptr< EPCIndirectionUtils > CreateWithABI(ExecutorProcessControl &EPC, jitlink::JITLinkMemoryManager &MemMgr, MemoryAccess &MemAccess)
Create using the given ABI class.
ABISupport & getABISupport() const
Return a reference to the ABISupport object for this instance.
ExecutorAddr getResolverBlockAddress() const
Returns the address of the Resolver block.
An ExecutionSession represents a running JIT program.
Definition Core.h:1355
Represents an address in the executor process.
ExecutorProcessControl supports interaction with a JIT target process.
Manages a set of 'lazy call-through' trampolines.
APIs for manipulating memory in the target process.
Base class for pools of compiler re-entry trampolines.
void writeTrampolines(char *TrampolineBlockWorkingMem, ExecutorAddr TrampolineBlockTargetAddr, ExecutorAddr ResolverAddr, unsigned NumTrampolines) const override
void writeIndirectStubsBlock(char *StubsBlockWorkingMem, ExecutorAddr StubsBlockTargetAddress, ExecutorAddr PointersBlockTargetAddress, unsigned NumStubs) const override
void writeResolverCode(char *ResolverWorkingMem, ExecutorAddr ResolverTargetAddr, ExecutorAddr ReentryFnAddr, ExecutorAddr ReentryCtxAddr) const override
LLVM_ABI Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU)
This will call writeResolver on the given EPCIndirectionUtils instance to set up re-entry via a funct...
This is an optimization pass for GlobalISel generic memory operations.