LLVM  14.0.0git
EPCIndirectionUtils.cpp
Go to the documentation of this file.
1 //===------- EPCIndirectionUtils.cpp -- EPC based indirection APIs --------===//
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 
10 
13 
14 #include <future>
15 
16 using namespace llvm;
17 using namespace llvm::orc;
18 
19 namespace llvm {
20 namespace orc {
21 
23 public:
24  using IndirectStubInfo = EPCIndirectionUtils::IndirectStubInfo;
25  using IndirectStubInfoVector = EPCIndirectionUtils::IndirectStubInfoVector;
26 
28  getIndirectStubs(EPCIndirectionUtils &EPCIU, unsigned NumStubs) {
29  return EPCIU.getIndirectStubs(NumStubs);
30  };
31 };
32 
33 } // end namespace orc
34 } // end namespace llvm
35 
36 namespace {
37 
38 class EPCTrampolinePool : public TrampolinePool {
39 public:
40  EPCTrampolinePool(EPCIndirectionUtils &EPCIU);
41  Error deallocatePool();
42 
43 protected:
44  Error grow() override;
45 
46  using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc;
47 
48  EPCIndirectionUtils &EPCIU;
49  unsigned TrampolineSize = 0;
50  unsigned TrampolinesPerPage = 0;
51  std::vector<FinalizedAlloc> TrampolineBlocks;
52 };
53 
54 class EPCIndirectStubsManager : public IndirectStubsManager,
56 public:
57  EPCIndirectStubsManager(EPCIndirectionUtils &EPCIU) : EPCIU(EPCIU) {}
58 
59  Error deallocateStubs();
60 
61  Error createStub(StringRef StubName, JITTargetAddress StubAddr,
62  JITSymbolFlags StubFlags) override;
63 
64  Error createStubs(const StubInitsMap &StubInits) override;
65 
66  JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override;
67 
68  JITEvaluatedSymbol findPointer(StringRef Name) override;
69 
70  Error updatePointer(StringRef Name, JITTargetAddress NewAddr) override;
71 
72 private:
73  using StubInfo = std::pair<IndirectStubInfo, JITSymbolFlags>;
74 
75  std::mutex ISMMutex;
76  EPCIndirectionUtils &EPCIU;
77  StringMap<StubInfo> StubInfos;
78 };
79 
80 EPCTrampolinePool::EPCTrampolinePool(EPCIndirectionUtils &EPCIU)
81  : EPCIU(EPCIU) {
82  auto &EPC = EPCIU.getExecutorProcessControl();
83  auto &ABI = EPCIU.getABISupport();
84 
85  TrampolineSize = ABI.getTrampolineSize();
86  TrampolinesPerPage =
87  (EPC.getPageSize() - ABI.getPointerSize()) / TrampolineSize;
88 }
89 
90 Error EPCTrampolinePool::deallocatePool() {
91  Error Err = Error::success();
92  std::promise<MSVCPError> DeallocResultP;
93  auto DeallocResultF = DeallocResultP.get_future();
94 
96  std::move(TrampolineBlocks),
97  [&](Error Err) { DeallocResultP.set_value(std::move(Err)); });
98 
99  return DeallocResultF.get();
100 }
101 
102 Error EPCTrampolinePool::grow() {
103  using namespace jitlink;
104 
105  assert(AvailableTrampolines.empty() &&
106  "Grow called with trampolines still available");
107 
108  auto ResolverAddress = EPCIU.getResolverBlockAddress();
109  assert(ResolverAddress && "Resolver address can not be null");
110 
111  auto &EPC = EPCIU.getExecutorProcessControl();
112  auto PageSize = EPC.getPageSize();
113  auto Alloc = SimpleSegmentAlloc::Create(
114  EPC.getMemMgr(), nullptr,
115  {{MemProt::Read | MemProt::Exec, {PageSize, Align(PageSize)}}});
116  if (!Alloc)
117  return Alloc.takeError();
118 
119  unsigned NumTrampolines = TrampolinesPerPage;
120 
121  auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
123  SegInfo.WorkingMem.data(), SegInfo.Addr, ResolverAddress, NumTrampolines);
124  for (unsigned I = 0; I < NumTrampolines; ++I)
125  AvailableTrampolines.push_back(SegInfo.Addr + (I * TrampolineSize));
126 
127  auto FA = Alloc->finalize();
128  if (!FA)
129  return FA.takeError();
130 
131  TrampolineBlocks.push_back(std::move(*FA));
132 
133  return Error::success();
134 }
135 
136 Error EPCIndirectStubsManager::createStub(StringRef StubName,
137  JITTargetAddress StubAddr,
138  JITSymbolFlags StubFlags) {
139  StubInitsMap SIM;
140  SIM[StubName] = std::make_pair(StubAddr, StubFlags);
141  return createStubs(SIM);
142 }
143 
144 Error EPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
145  auto AvailableStubInfos = getIndirectStubs(EPCIU, StubInits.size());
146  if (!AvailableStubInfos)
147  return AvailableStubInfos.takeError();
148 
149  {
150  std::lock_guard<std::mutex> Lock(ISMMutex);
151  unsigned ASIdx = 0;
152  for (auto &SI : StubInits) {
153  auto &A = (*AvailableStubInfos)[ASIdx++];
154  StubInfos[SI.first()] = std::make_pair(A, SI.second.second);
155  }
156  }
157 
158  auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
159  switch (EPCIU.getABISupport().getPointerSize()) {
160  case 4: {
161  unsigned ASIdx = 0;
162  std::vector<tpctypes::UInt32Write> PtrUpdates;
163  for (auto &SI : StubInits)
164  PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
165  static_cast<uint32_t>(SI.second.first)});
166  return MemAccess.writeUInt32s(PtrUpdates);
167  }
168  case 8: {
169  unsigned ASIdx = 0;
170  std::vector<tpctypes::UInt64Write> PtrUpdates;
171  for (auto &SI : StubInits)
172  PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
173  static_cast<uint64_t>(SI.second.first)});
174  return MemAccess.writeUInt64s(PtrUpdates);
175  }
176  default:
177  return make_error<StringError>("Unsupported pointer size",
179  }
180 }
181 
182 JITEvaluatedSymbol EPCIndirectStubsManager::findStub(StringRef Name,
183  bool ExportedStubsOnly) {
184  std::lock_guard<std::mutex> Lock(ISMMutex);
185  auto I = StubInfos.find(Name);
186  if (I == StubInfos.end())
187  return nullptr;
188  return {I->second.first.StubAddress, I->second.second};
189 }
190 
191 JITEvaluatedSymbol EPCIndirectStubsManager::findPointer(StringRef Name) {
192  std::lock_guard<std::mutex> Lock(ISMMutex);
193  auto I = StubInfos.find(Name);
194  if (I == StubInfos.end())
195  return nullptr;
196  return {I->second.first.PointerAddress, I->second.second};
197 }
198 
199 Error EPCIndirectStubsManager::updatePointer(StringRef Name,
200  JITTargetAddress NewAddr) {
201 
202  JITTargetAddress PtrAddr = 0;
203  {
204  std::lock_guard<std::mutex> Lock(ISMMutex);
205  auto I = StubInfos.find(Name);
206  if (I == StubInfos.end())
207  return make_error<StringError>("Unknown stub name",
209  PtrAddr = I->second.first.PointerAddress;
210  }
211 
212  auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
213  switch (EPCIU.getABISupport().getPointerSize()) {
214  case 4: {
215  tpctypes::UInt32Write PUpdate(PtrAddr, NewAddr);
216  return MemAccess.writeUInt32s(PUpdate);
217  }
218  case 8: {
219  tpctypes::UInt64Write PUpdate(PtrAddr, NewAddr);
220  return MemAccess.writeUInt64s(PUpdate);
221  }
222  default:
223  return make_error<StringError>("Unsupported pointer size",
225  }
226 }
227 
228 } // end anonymous namespace.
229 
230 namespace llvm {
231 namespace orc {
232 
234 
237  const auto &TT = EPC.getTargetTriple();
238  switch (TT.getArch()) {
239  default:
240  return make_error<StringError>(
241  std::string("No EPCIndirectionUtils available for ") + TT.str(),
243  case Triple::aarch64:
244  case Triple::aarch64_32:
245  return CreateWithABI<OrcAArch64>(EPC);
246 
247  case Triple::x86:
248  return CreateWithABI<OrcI386>(EPC);
249 
250  case Triple::mips:
251  return CreateWithABI<OrcMips32Be>(EPC);
252 
253  case Triple::mipsel:
254  return CreateWithABI<OrcMips32Le>(EPC);
255 
256  case Triple::mips64:
257  case Triple::mips64el:
258  return CreateWithABI<OrcMips64>(EPC);
259 
260  case Triple::x86_64:
261  if (TT.getOS() == Triple::OSType::Win32)
262  return CreateWithABI<OrcX86_64_Win32>(EPC);
263  else
264  return CreateWithABI<OrcX86_64_SysV>(EPC);
265  }
266 }
267 
269 
270  auto &MemMgr = EPC.getMemMgr();
271  auto Err = MemMgr.deallocate(std::move(IndirectStubAllocs));
272 
273  if (TP)
274  Err = joinErrors(std::move(Err),
275  static_cast<EPCTrampolinePool &>(*TP).deallocatePool());
276 
277  if (ResolverBlock)
278  Err =
279  joinErrors(std::move(Err), MemMgr.deallocate(std::move(ResolverBlock)));
280 
281  return Err;
282 }
283 
286  JITTargetAddress ReentryCtxAddr) {
287  using namespace jitlink;
288 
289  assert(ABI && "ABI can not be null");
290  auto ResolverSize = ABI->getResolverCodeSize();
291 
292  auto Alloc =
293  SimpleSegmentAlloc::Create(EPC.getMemMgr(), nullptr,
294  {{MemProt::Read | MemProt::Exec,
295  {ResolverSize, Align(EPC.getPageSize())}}});
296 
297  if (!Alloc)
298  return Alloc.takeError();
299 
300  auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
301  ABI->writeResolverCode(SegInfo.WorkingMem.data(), SegInfo.Addr, ReentryFnAddr,
302  ReentryCtxAddr);
303 
304  auto FA = Alloc->finalize();
305  if (!FA)
306  return FA.takeError();
307 
308  ResolverBlock = std::move(*FA);
309  return SegInfo.Addr;
310 }
311 
312 std::unique_ptr<IndirectStubsManager>
314  return std::make_unique<EPCIndirectStubsManager>(*this);
315 }
316 
318  if (!TP)
319  TP = std::make_unique<EPCTrampolinePool>(*this);
320  return *TP;
321 }
322 
324  ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr) {
325  assert(!LCTM &&
326  "createLazyCallThroughManager can not have been called before");
327  LCTM = std::make_unique<LazyCallThroughManager>(ES, ErrorHandlerAddr,
328  &getTrampolinePool());
329  return *LCTM;
330 }
331 
332 EPCIndirectionUtils::EPCIndirectionUtils(ExecutorProcessControl &EPC,
333  std::unique_ptr<ABISupport> ABI)
334  : EPC(EPC), ABI(std::move(ABI)) {
335  assert(this->ABI && "ABI can not be null");
336 
337  assert(EPC.getPageSize() > getABISupport().getStubSize() &&
338  "Stubs larger than one page are not supported");
339 }
340 
342 EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
343  using namespace jitlink;
344 
345  std::lock_guard<std::mutex> Lock(EPCUIMutex);
346 
347  // If there aren't enough stubs available then allocate some more.
348  if (NumStubs > AvailableIndirectStubs.size()) {
349  auto NumStubsToAllocate = NumStubs;
350  auto PageSize = EPC.getPageSize();
351  auto StubBytes = alignTo(NumStubsToAllocate * ABI->getStubSize(), PageSize);
352  NumStubsToAllocate = StubBytes / ABI->getStubSize();
353  auto PtrBytes =
354  alignTo(NumStubsToAllocate * ABI->getPointerSize(), PageSize);
355 
356  auto StubProt = MemProt::Read | MemProt::Exec;
357  auto PtrProt = MemProt::Read | MemProt::Write;
358 
359  auto Alloc = SimpleSegmentAlloc::Create(
360  EPC.getMemMgr(), nullptr,
361  {{StubProt, {static_cast<size_t>(StubBytes), Align(PageSize)}},
362  {PtrProt, {static_cast<size_t>(PtrBytes), Align(PageSize)}}});
363 
364  if (!Alloc)
365  return Alloc.takeError();
366 
367  auto StubSeg = Alloc->getSegInfo(StubProt);
368  auto PtrSeg = Alloc->getSegInfo(PtrProt);
369 
370  ABI->writeIndirectStubsBlock(StubSeg.WorkingMem.data(), StubSeg.Addr,
371  PtrSeg.Addr, NumStubsToAllocate);
372 
373  auto FA = Alloc->finalize();
374  if (!FA)
375  return FA.takeError();
376 
377  IndirectStubAllocs.push_back(std::move(*FA));
378 
379  auto StubExecutorAddr = StubSeg.Addr;
380  auto PtrExecutorAddr = PtrSeg.Addr;
381  for (unsigned I = 0; I != NumStubsToAllocate; ++I) {
382  AvailableIndirectStubs.push_back(
383  IndirectStubInfo(StubExecutorAddr, PtrExecutorAddr));
384  StubExecutorAddr += ABI->getStubSize();
385  PtrExecutorAddr += ABI->getPointerSize();
386  }
387  }
388 
389  assert(NumStubs <= AvailableIndirectStubs.size() &&
390  "Sufficient stubs should have been allocated above");
391 
392  IndirectStubInfoVector Result;
393  while (NumStubs--) {
394  Result.push_back(AvailableIndirectStubs.back());
395  AvailableIndirectStubs.pop_back();
396  }
397 
398  return std::move(Result);
399 }
400 
402  JITTargetAddress TrampolineAddr) {
403  auto &LCTM = *jitTargetAddressToPointer<LazyCallThroughManager *>(LCTMAddr);
404  std::promise<JITTargetAddress> LandingAddrP;
405  auto LandingAddrF = LandingAddrP.get_future();
406  LCTM.resolveTrampolineLandingAddress(
407  TrampolineAddr,
408  [&](JITTargetAddress Addr) { LandingAddrP.set_value(Addr); });
409  return LandingAddrF.get();
410 }
411 
413  auto &LCTM = EPCIU.getLazyCallThroughManager();
414  return EPCIU
417  .takeError();
418 }
419 
420 } // end namespace orc
421 } // end namespace llvm
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:148
llvm::orc::EPCIndirectionUtils::cleanup
Error cleanup()
Release memory for resources held by this instance.
Definition: EPCIndirectionUtils.cpp:268
ABI
Generic address nodes are lowered to some combination of target independent and machine specific ABI
Definition: Relocation.txt:34
MathExtras.h
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::orc::ExecutorProcessControl::getMemoryAccess
MemoryAccess & getMemoryAccess() const
Return a MemoryAccess object for the target process.
Definition: ExecutorProcessControl.h:210
llvm::Triple::x86
@ x86
Definition: Triple.h:83
llvm::orc::EPCIndirectionUtils::createIndirectStubsManager
std::unique_ptr< IndirectStubsManager > createIndirectStubsManager()
Create an IndirectStubsManager for the executor process.
Definition: EPCIndirectionUtils.cpp:313
llvm::orc::setUpInProcessLCTMReentryViaEPCIU
Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU)
This will call writeResolver on the given EPCIndirectionUtils instance to set up re-entry via a funct...
Definition: EPCIndirectionUtils.cpp:412
llvm::orc::IndirectStubsManager
Base class for managing collections of named indirect stubs.
Definition: IndirectionUtils.h:275
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:331
llvm::orc::LazyCallThroughManager
Manages a set of 'lazy call-through' trampolines.
Definition: LazyReexports.h:38
llvm::Triple::x86_64
@ x86_64
Definition: Triple.h:84
llvm::orc::ExecutorProcessControl
ExecutorProcessControl supports interaction with a JIT target process.
Definition: ExecutorProcessControl.h:38
llvm::orc::EPCIndirectionUtilsAccess::IndirectStubInfoVector
EPCIndirectionUtils::IndirectStubInfoVector IndirectStubInfoVector
Definition: EPCIndirectionUtils.cpp:25
llvm::orc::EPCIndirectionUtils::getLazyCallThroughManager
LazyCallThroughManager & getLazyCallThroughManager()
Create a LazyCallThroughManager for the executor process.
Definition: EPCIndirectionUtils.h:123
llvm::orc::EPCIndirectionUtilsAccess
Definition: EPCIndirectionUtils.cpp:22
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::Triple::aarch64_32
@ aarch64_32
Definition: Triple.h:54
llvm::Triple::mips64
@ mips64
Definition: Triple.h:64
llvm::JITSymbolFlags
Flags for symbols in the JIT.
Definition: JITSymbol.h:74
llvm::JITEvaluatedSymbol
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
llvm::orc::EPCIndirectionUtils::getExecutorProcessControl
ExecutorProcessControl & getExecutorProcessControl() const
Return a reference to the ExecutorProcessControl object.
Definition: EPCIndirectionUtils.h:90
llvm::Lock
static sys::Mutex Lock
Definition: NVPTXUtilities.cpp:39
llvm::orc::EPCIndirectionUtils::ABISupport::~ABISupport
virtual ~ABISupport()
Definition: EPCIndirectionUtils.cpp:233
PageSize
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)
llvm::orc::ExecutorProcessControl::getMemMgr
jitlink::JITLinkMemoryManager & getMemMgr() const
Return a JITLinkMemoryManager for the target process.
Definition: ExecutorProcessControl.h:216
llvm::orc::reentry
static JITTargetAddress reentry(JITTargetAddress LCTMAddr, JITTargetAddress TrampolineAddr)
Definition: EPCIndirectionUtils.cpp:401
llvm::ARM_PROC::A
@ A
Definition: ARMBaseInfo.h:34
llvm::Triple::mips64el
@ mips64el
Definition: Triple.h:65
llvm::orc
Definition: CompileOnDemandLayer.h:57
llvm::ms_demangle::QualifierMangleMode::Result
@ Result
llvm::orc::TrampolinePool
Base class for pools of compiler re-entry trampolines.
Definition: IndirectionUtils.h:56
llvm::orc::EPCIndirectionUtils::ABISupport::writeTrampolines
virtual void writeTrampolines(char *TrampolineBlockWorkingMem, JITTargetAddress TrampolineBlockTragetAddr, JITTargetAddress ResolverAddr, unsigned NumTrampolines) const =0
llvm::StringMap
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition: StringMap.h:108
uint64_t
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:80
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::orc::EPCIndirectionUtilsAccess::IndirectStubInfo
EPCIndirectionUtils::IndirectStubInfo IndirectStubInfo
Definition: EPCIndirectionUtils.cpp:24
llvm::joinErrors
Error joinErrors(Error E1, Error E2)
Concatenate errors.
Definition: Error.h:428
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::move
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1609
SI
StandardInstrumentations SI(Debug, VerifyEach)
llvm::orc::EPCIndirectionUtils::getTrampolinePool
TrampolinePool & getTrampolinePool()
Create a TrampolinePool for the executor process.
Definition: EPCIndirectionUtils.cpp:317
llvm::orc::EPCIndirectionUtils::getABISupport
ABISupport & getABISupport() const
Return a reference to the ABISupport object for this instance.
Definition: EPCIndirectionUtils.h:93
llvm::orc::ExecutorProcessControl::MemoryAccess::writeUInt32s
Error writeUInt32s(ArrayRef< tpctypes::UInt32Write > Ws)
Definition: ExecutorProcessControl.h:139
EPCIndirectionUtils.h
llvm::orc::tpctypes::UIntWrite
Definition: TargetProcessControlTypes.h:109
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::orc::EPCIndirectionUtils::writeResolverBlock
Expected< JITTargetAddress > writeResolverBlock(JITTargetAddress ReentryFnAddr, JITTargetAddress ReentryCtxAddr)
Write resolver code to the executor process and return its address.
Definition: EPCIndirectionUtils.cpp:285
uint32_t
llvm::orc::EPCIndirectionUtils::getResolverBlockAddress
JITTargetAddress getResolverBlockAddress() const
Returns the address of the Resolver block.
Definition: EPCIndirectionUtils.h:108
llvm::pointerToJITTargetAddress
JITTargetAddress pointerToJITTargetAddress(T *Ptr)
Convert a pointer to a JITTargetAddress.
Definition: JITSymbol.h:69
llvm::orc::EPCIndirectionUtils::Create
static Expected< std::unique_ptr< EPCIndirectionUtils > > Create(ExecutorProcessControl &EPC)
Create based on the ExecutorProcessControl triple.
Definition: EPCIndirectionUtils.cpp:236
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
std
Definition: BitVector.h:838
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77
llvm::orc::ExecutorProcessControl::getTargetTriple
const Triple & getTargetTriple() const
Return the Triple for the target process.
Definition: ExecutorProcessControl.h:201
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
llvm::orc::ExecutionSession
An ExecutionSession represents a running JIT program.
Definition: Core.h:1275
llvm::Triple::mipsel
@ mipsel
Definition: Triple.h:63
llvm::orc::ExecutorProcessControl::getPageSize
unsigned getPageSize() const
Get the page size for the target process.
Definition: ExecutorProcessControl.h:204
llvm::orc::EPCIndirectionUtilsAccess::getIndirectStubs
static Expected< IndirectStubInfoVector > getIndirectStubs(EPCIndirectionUtils &EPCIU, unsigned NumStubs)
Definition: EPCIndirectionUtils.cpp:28
llvm::JITTargetAddress
uint64_t JITTargetAddress
Represents an address in the target process's address space.
Definition: JITSymbol.h:42
llvm::orc::EPCIndirectionUtils::createLazyCallThroughManager
LazyCallThroughManager & createLazyCallThroughManager(ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr)
Create a LazyCallThroughManager.
Definition: EPCIndirectionUtils.cpp:323
ExecutorProcessControl.h
llvm::orc::EPCIndirectionUtils
Provides ExecutorProcessControl based indirect stubs, trampoline pool and lazy call through manager.
Definition: EPCIndirectionUtils.h:30
llvm::orc::EPCIndirectionUtils::ABISupport::getPointerSize
unsigned getPointerSize() const
Definition: EPCIndirectionUtils.h:48
llvm::Triple::mips
@ mips
Definition: Triple.h:62
llvm::Triple::aarch64
@ aarch64
Definition: Triple.h:52
llvm::RISCVABI::ABI
ABI
Definition: RISCVBaseInfo.h:295