xref: /llvm-project/llvm/lib/ExecutionEngine/Orc/EPCIndirectionUtils.cpp (revision 4eaff6c58ae2f130ac8d63cf2c87bbb483114876)
1662c5544SLang Hames //===------- EPCIndirectionUtils.cpp -- EPC based indirection APIs --------===//
2662c5544SLang Hames //
3662c5544SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4662c5544SLang Hames // See https://llvm.org/LICENSE.txt for license information.
5662c5544SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6662c5544SLang Hames //
7662c5544SLang Hames //===----------------------------------------------------------------------===//
8662c5544SLang Hames 
9662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/EPCIndirectionUtils.h"
10662c5544SLang Hames 
11662c5544SLang Hames #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
12662c5544SLang Hames #include "llvm/Support/MathExtras.h"
13662c5544SLang Hames 
14662c5544SLang Hames #include <future>
15662c5544SLang Hames 
16662c5544SLang Hames using namespace llvm;
17662c5544SLang Hames using namespace llvm::orc;
18662c5544SLang Hames 
19662c5544SLang Hames namespace llvm {
20662c5544SLang Hames namespace orc {
21662c5544SLang Hames 
22662c5544SLang Hames class EPCIndirectionUtilsAccess {
23662c5544SLang Hames public:
24662c5544SLang Hames   using IndirectStubInfo = EPCIndirectionUtils::IndirectStubInfo;
25662c5544SLang Hames   using IndirectStubInfoVector = EPCIndirectionUtils::IndirectStubInfoVector;
26662c5544SLang Hames 
27662c5544SLang Hames   static Expected<IndirectStubInfoVector>
28662c5544SLang Hames   getIndirectStubs(EPCIndirectionUtils &EPCIU, unsigned NumStubs) {
29662c5544SLang Hames     return EPCIU.getIndirectStubs(NumStubs);
30662c5544SLang Hames   };
31662c5544SLang Hames };
32662c5544SLang Hames 
33662c5544SLang Hames } // end namespace orc
34662c5544SLang Hames } // end namespace llvm
35662c5544SLang Hames 
36662c5544SLang Hames namespace {
37662c5544SLang Hames 
38662c5544SLang Hames class EPCTrampolinePool : public TrampolinePool {
39662c5544SLang Hames public:
40662c5544SLang Hames   EPCTrampolinePool(EPCIndirectionUtils &EPCIU);
41662c5544SLang Hames   Error deallocatePool();
42662c5544SLang Hames 
43662c5544SLang Hames protected:
44662c5544SLang Hames   Error grow() override;
45662c5544SLang Hames 
46962a2479SLang Hames   using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc;
47662c5544SLang Hames 
48662c5544SLang Hames   EPCIndirectionUtils &EPCIU;
49662c5544SLang Hames   unsigned TrampolineSize = 0;
50662c5544SLang Hames   unsigned TrampolinesPerPage = 0;
51962a2479SLang Hames   std::vector<FinalizedAlloc> TrampolineBlocks;
52662c5544SLang Hames };
53662c5544SLang Hames 
54662c5544SLang Hames class EPCIndirectStubsManager : public IndirectStubsManager,
55662c5544SLang Hames                                 private EPCIndirectionUtilsAccess {
56662c5544SLang Hames public:
57662c5544SLang Hames   EPCIndirectStubsManager(EPCIndirectionUtils &EPCIU) : EPCIU(EPCIU) {}
58662c5544SLang Hames 
59662c5544SLang Hames   Error deallocateStubs();
60662c5544SLang Hames 
618b1771bdSLang Hames   Error createStub(StringRef StubName, ExecutorAddr StubAddr,
62662c5544SLang Hames                    JITSymbolFlags StubFlags) override;
63662c5544SLang Hames 
64662c5544SLang Hames   Error createStubs(const StubInitsMap &StubInits) override;
65662c5544SLang Hames 
668b1771bdSLang Hames   ExecutorSymbolDef findStub(StringRef Name, bool ExportedStubsOnly) override;
67662c5544SLang Hames 
688b1771bdSLang Hames   ExecutorSymbolDef findPointer(StringRef Name) override;
69662c5544SLang Hames 
708b1771bdSLang Hames   Error updatePointer(StringRef Name, ExecutorAddr NewAddr) override;
71662c5544SLang Hames 
72662c5544SLang Hames private:
73662c5544SLang Hames   using StubInfo = std::pair<IndirectStubInfo, JITSymbolFlags>;
74662c5544SLang Hames 
75662c5544SLang Hames   std::mutex ISMMutex;
76662c5544SLang Hames   EPCIndirectionUtils &EPCIU;
77662c5544SLang Hames   StringMap<StubInfo> StubInfos;
78662c5544SLang Hames };
79662c5544SLang Hames 
80662c5544SLang Hames EPCTrampolinePool::EPCTrampolinePool(EPCIndirectionUtils &EPCIU)
81662c5544SLang Hames     : EPCIU(EPCIU) {
82662c5544SLang Hames   auto &EPC = EPCIU.getExecutorProcessControl();
83662c5544SLang Hames   auto &ABI = EPCIU.getABISupport();
84662c5544SLang Hames 
85662c5544SLang Hames   TrampolineSize = ABI.getTrampolineSize();
86662c5544SLang Hames   TrampolinesPerPage =
87662c5544SLang Hames       (EPC.getPageSize() - ABI.getPointerSize()) / TrampolineSize;
88662c5544SLang Hames }
89662c5544SLang Hames 
90662c5544SLang Hames Error EPCTrampolinePool::deallocatePool() {
91962a2479SLang Hames   std::promise<MSVCPError> DeallocResultP;
92962a2479SLang Hames   auto DeallocResultF = DeallocResultP.get_future();
93962a2479SLang Hames 
94962a2479SLang Hames   EPCIU.getExecutorProcessControl().getMemMgr().deallocate(
95962a2479SLang Hames       std::move(TrampolineBlocks),
96962a2479SLang Hames       [&](Error Err) { DeallocResultP.set_value(std::move(Err)); });
97962a2479SLang Hames 
98962a2479SLang Hames   return DeallocResultF.get();
99662c5544SLang Hames }
100662c5544SLang Hames 
101662c5544SLang Hames Error EPCTrampolinePool::grow() {
102962a2479SLang Hames   using namespace jitlink;
103962a2479SLang Hames 
104662c5544SLang Hames   assert(AvailableTrampolines.empty() &&
105662c5544SLang Hames          "Grow called with trampolines still available");
106662c5544SLang Hames 
107662c5544SLang Hames   auto ResolverAddress = EPCIU.getResolverBlockAddress();
108662c5544SLang Hames   assert(ResolverAddress && "Resolver address can not be null");
109662c5544SLang Hames 
110662c5544SLang Hames   auto &EPC = EPCIU.getExecutorProcessControl();
111662c5544SLang Hames   auto PageSize = EPC.getPageSize();
112962a2479SLang Hames   auto Alloc = SimpleSegmentAlloc::Create(
113*4eaff6c5SLang Hames       EPC.getMemMgr(), EPC.getSymbolStringPool(), EPC.getTargetTriple(),
114*4eaff6c5SLang Hames       nullptr, {{MemProt::Read | MemProt::Exec, {PageSize, Align(PageSize)}}});
115662c5544SLang Hames   if (!Alloc)
116662c5544SLang Hames     return Alloc.takeError();
117662c5544SLang Hames 
118662c5544SLang Hames   unsigned NumTrampolines = TrampolinesPerPage;
119662c5544SLang Hames 
120962a2479SLang Hames   auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
1218b1771bdSLang Hames   EPCIU.getABISupport().writeTrampolines(
1228b1771bdSLang Hames       SegInfo.WorkingMem.data(), SegInfo.Addr, ResolverAddress, NumTrampolines);
123662c5544SLang Hames   for (unsigned I = 0; I < NumTrampolines; ++I)
1248b1771bdSLang Hames     AvailableTrampolines.push_back(SegInfo.Addr + (I * TrampolineSize));
125662c5544SLang Hames 
126962a2479SLang Hames   auto FA = Alloc->finalize();
127962a2479SLang Hames   if (!FA)
128962a2479SLang Hames     return FA.takeError();
129662c5544SLang Hames 
130962a2479SLang Hames   TrampolineBlocks.push_back(std::move(*FA));
131662c5544SLang Hames 
132662c5544SLang Hames   return Error::success();
133662c5544SLang Hames }
134662c5544SLang Hames 
135662c5544SLang Hames Error EPCIndirectStubsManager::createStub(StringRef StubName,
1368b1771bdSLang Hames                                           ExecutorAddr StubAddr,
137662c5544SLang Hames                                           JITSymbolFlags StubFlags) {
138662c5544SLang Hames   StubInitsMap SIM;
139662c5544SLang Hames   SIM[StubName] = std::make_pair(StubAddr, StubFlags);
140662c5544SLang Hames   return createStubs(SIM);
141662c5544SLang Hames }
142662c5544SLang Hames 
143662c5544SLang Hames Error EPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
144662c5544SLang Hames   auto AvailableStubInfos = getIndirectStubs(EPCIU, StubInits.size());
145662c5544SLang Hames   if (!AvailableStubInfos)
146662c5544SLang Hames     return AvailableStubInfos.takeError();
147662c5544SLang Hames 
148662c5544SLang Hames   {
149662c5544SLang Hames     std::lock_guard<std::mutex> Lock(ISMMutex);
150662c5544SLang Hames     unsigned ASIdx = 0;
151662c5544SLang Hames     for (auto &SI : StubInits) {
152662c5544SLang Hames       auto &A = (*AvailableStubInfos)[ASIdx++];
153662c5544SLang Hames       StubInfos[SI.first()] = std::make_pair(A, SI.second.second);
154662c5544SLang Hames     }
155662c5544SLang Hames   }
156662c5544SLang Hames 
157662c5544SLang Hames   auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
158662c5544SLang Hames   switch (EPCIU.getABISupport().getPointerSize()) {
159662c5544SLang Hames   case 4: {
160662c5544SLang Hames     unsigned ASIdx = 0;
161662c5544SLang Hames     std::vector<tpctypes::UInt32Write> PtrUpdates;
162662c5544SLang Hames     for (auto &SI : StubInits)
1635baaf0c2SLang Hames       PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
1648b1771bdSLang Hames                             static_cast<uint32_t>(SI.second.first.getValue())});
165662c5544SLang Hames     return MemAccess.writeUInt32s(PtrUpdates);
166662c5544SLang Hames   }
167662c5544SLang Hames   case 8: {
168662c5544SLang Hames     unsigned ASIdx = 0;
169662c5544SLang Hames     std::vector<tpctypes::UInt64Write> PtrUpdates;
170662c5544SLang Hames     for (auto &SI : StubInits)
1715baaf0c2SLang Hames       PtrUpdates.push_back({(*AvailableStubInfos)[ASIdx++].PointerAddress,
1728b1771bdSLang Hames                             static_cast<uint64_t>(SI.second.first.getValue())});
173662c5544SLang Hames     return MemAccess.writeUInt64s(PtrUpdates);
174662c5544SLang Hames   }
175662c5544SLang Hames   default:
176662c5544SLang Hames     return make_error<StringError>("Unsupported pointer size",
177662c5544SLang Hames                                    inconvertibleErrorCode());
178662c5544SLang Hames   }
179662c5544SLang Hames }
180662c5544SLang Hames 
1818b1771bdSLang Hames ExecutorSymbolDef EPCIndirectStubsManager::findStub(StringRef Name,
182662c5544SLang Hames                                                     bool ExportedStubsOnly) {
183662c5544SLang Hames   std::lock_guard<std::mutex> Lock(ISMMutex);
184662c5544SLang Hames   auto I = StubInfos.find(Name);
185662c5544SLang Hames   if (I == StubInfos.end())
1868b1771bdSLang Hames     return ExecutorSymbolDef();
187662c5544SLang Hames   return {I->second.first.StubAddress, I->second.second};
188662c5544SLang Hames }
189662c5544SLang Hames 
1908b1771bdSLang Hames ExecutorSymbolDef EPCIndirectStubsManager::findPointer(StringRef Name) {
191662c5544SLang Hames   std::lock_guard<std::mutex> Lock(ISMMutex);
192662c5544SLang Hames   auto I = StubInfos.find(Name);
193662c5544SLang Hames   if (I == StubInfos.end())
1948b1771bdSLang Hames     return ExecutorSymbolDef();
195662c5544SLang Hames   return {I->second.first.PointerAddress, I->second.second};
196662c5544SLang Hames }
197662c5544SLang Hames 
198662c5544SLang Hames Error EPCIndirectStubsManager::updatePointer(StringRef Name,
1998b1771bdSLang Hames                                              ExecutorAddr NewAddr) {
200662c5544SLang Hames 
2018b1771bdSLang Hames   ExecutorAddr PtrAddr;
202662c5544SLang Hames   {
203662c5544SLang Hames     std::lock_guard<std::mutex> Lock(ISMMutex);
204662c5544SLang Hames     auto I = StubInfos.find(Name);
205662c5544SLang Hames     if (I == StubInfos.end())
206662c5544SLang Hames       return make_error<StringError>("Unknown stub name",
207662c5544SLang Hames                                      inconvertibleErrorCode());
208662c5544SLang Hames     PtrAddr = I->second.first.PointerAddress;
209662c5544SLang Hames   }
210662c5544SLang Hames 
211662c5544SLang Hames   auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
212662c5544SLang Hames   switch (EPCIU.getABISupport().getPointerSize()) {
213662c5544SLang Hames   case 4: {
2148b1771bdSLang Hames     tpctypes::UInt32Write PUpdate(PtrAddr, NewAddr.getValue());
215662c5544SLang Hames     return MemAccess.writeUInt32s(PUpdate);
216662c5544SLang Hames   }
217662c5544SLang Hames   case 8: {
2188b1771bdSLang Hames     tpctypes::UInt64Write PUpdate(PtrAddr, NewAddr.getValue());
219662c5544SLang Hames     return MemAccess.writeUInt64s(PUpdate);
220662c5544SLang Hames   }
221662c5544SLang Hames   default:
222662c5544SLang Hames     return make_error<StringError>("Unsupported pointer size",
223662c5544SLang Hames                                    inconvertibleErrorCode());
224662c5544SLang Hames   }
225662c5544SLang Hames }
226662c5544SLang Hames 
227662c5544SLang Hames } // end anonymous namespace.
228662c5544SLang Hames 
229662c5544SLang Hames namespace llvm {
230662c5544SLang Hames namespace orc {
231662c5544SLang Hames 
2323a3cb929SKazu Hirata EPCIndirectionUtils::ABISupport::~ABISupport() = default;
233662c5544SLang Hames 
234662c5544SLang Hames Expected<std::unique_ptr<EPCIndirectionUtils>>
235662c5544SLang Hames EPCIndirectionUtils::Create(ExecutorProcessControl &EPC) {
236662c5544SLang Hames   const auto &TT = EPC.getTargetTriple();
237662c5544SLang Hames   switch (TT.getArch()) {
238662c5544SLang Hames   default:
239662c5544SLang Hames     return make_error<StringError>(
240662c5544SLang Hames         std::string("No EPCIndirectionUtils available for ") + TT.str(),
241662c5544SLang Hames         inconvertibleErrorCode());
242662c5544SLang Hames   case Triple::aarch64:
243662c5544SLang Hames   case Triple::aarch64_32:
244662c5544SLang Hames     return CreateWithABI<OrcAArch64>(EPC);
245662c5544SLang Hames 
246662c5544SLang Hames   case Triple::x86:
247662c5544SLang Hames     return CreateWithABI<OrcI386>(EPC);
248662c5544SLang Hames 
24915218a1aSwanglei   case Triple::loongarch64:
25015218a1aSwanglei     return CreateWithABI<OrcLoongArch64>(EPC);
25115218a1aSwanglei 
252662c5544SLang Hames   case Triple::mips:
253662c5544SLang Hames     return CreateWithABI<OrcMips32Be>(EPC);
254662c5544SLang Hames 
255662c5544SLang Hames   case Triple::mipsel:
256662c5544SLang Hames     return CreateWithABI<OrcMips32Le>(EPC);
257662c5544SLang Hames 
258662c5544SLang Hames   case Triple::mips64:
259662c5544SLang Hames   case Triple::mips64el:
260662c5544SLang Hames     return CreateWithABI<OrcMips64>(EPC);
261662c5544SLang Hames 
262acb408fbSAlex Fan   case Triple::riscv64:
263acb408fbSAlex Fan     return CreateWithABI<OrcRiscv64>(EPC);
264acb408fbSAlex Fan 
265662c5544SLang Hames   case Triple::x86_64:
266662c5544SLang Hames     if (TT.getOS() == Triple::OSType::Win32)
267662c5544SLang Hames       return CreateWithABI<OrcX86_64_Win32>(EPC);
268662c5544SLang Hames     else
269662c5544SLang Hames       return CreateWithABI<OrcX86_64_SysV>(EPC);
270662c5544SLang Hames   }
271662c5544SLang Hames }
272662c5544SLang Hames 
273662c5544SLang Hames Error EPCIndirectionUtils::cleanup() {
274662c5544SLang Hames 
275962a2479SLang Hames   auto &MemMgr = EPC.getMemMgr();
276962a2479SLang Hames   auto Err = MemMgr.deallocate(std::move(IndirectStubAllocs));
277662c5544SLang Hames 
278662c5544SLang Hames   if (TP)
279662c5544SLang Hames     Err = joinErrors(std::move(Err),
280662c5544SLang Hames                      static_cast<EPCTrampolinePool &>(*TP).deallocatePool());
281662c5544SLang Hames 
282662c5544SLang Hames   if (ResolverBlock)
283962a2479SLang Hames     Err =
284962a2479SLang Hames         joinErrors(std::move(Err), MemMgr.deallocate(std::move(ResolverBlock)));
285662c5544SLang Hames 
286662c5544SLang Hames   return Err;
287662c5544SLang Hames }
288662c5544SLang Hames 
2898b1771bdSLang Hames Expected<ExecutorAddr>
2908b1771bdSLang Hames EPCIndirectionUtils::writeResolverBlock(ExecutorAddr ReentryFnAddr,
2918b1771bdSLang Hames                                         ExecutorAddr ReentryCtxAddr) {
292962a2479SLang Hames   using namespace jitlink;
293962a2479SLang Hames 
294662c5544SLang Hames   assert(ABI && "ABI can not be null");
295662c5544SLang Hames   auto ResolverSize = ABI->getResolverCodeSize();
296662c5544SLang Hames 
297*4eaff6c5SLang Hames   auto Alloc =
298*4eaff6c5SLang Hames       SimpleSegmentAlloc::Create(EPC.getMemMgr(), EPC.getSymbolStringPool(),
299*4eaff6c5SLang Hames                                  EPC.getTargetTriple(), nullptr,
300962a2479SLang Hames                                  {{MemProt::Read | MemProt::Exec,
301962a2479SLang Hames                                    {ResolverSize, Align(EPC.getPageSize())}}});
302962a2479SLang Hames 
303662c5544SLang Hames   if (!Alloc)
304662c5544SLang Hames     return Alloc.takeError();
305662c5544SLang Hames 
306962a2479SLang Hames   auto SegInfo = Alloc->getSegInfo(MemProt::Read | MemProt::Exec);
3078b1771bdSLang Hames   ResolverBlockAddr = SegInfo.Addr;
30834e539dcSLang Hames   ABI->writeResolverCode(SegInfo.WorkingMem.data(), ResolverBlockAddr,
309118e953bSLang Hames                          ReentryFnAddr, ReentryCtxAddr);
310662c5544SLang Hames 
311962a2479SLang Hames   auto FA = Alloc->finalize();
312962a2479SLang Hames   if (!FA)
313962a2479SLang Hames     return FA.takeError();
314662c5544SLang Hames 
315962a2479SLang Hames   ResolverBlock = std::move(*FA);
31634e539dcSLang Hames   return ResolverBlockAddr;
317662c5544SLang Hames }
318662c5544SLang Hames 
319662c5544SLang Hames std::unique_ptr<IndirectStubsManager>
320662c5544SLang Hames EPCIndirectionUtils::createIndirectStubsManager() {
321662c5544SLang Hames   return std::make_unique<EPCIndirectStubsManager>(*this);
322662c5544SLang Hames }
323662c5544SLang Hames 
324662c5544SLang Hames TrampolinePool &EPCIndirectionUtils::getTrampolinePool() {
325662c5544SLang Hames   if (!TP)
326662c5544SLang Hames     TP = std::make_unique<EPCTrampolinePool>(*this);
327662c5544SLang Hames   return *TP;
328662c5544SLang Hames }
329662c5544SLang Hames 
330662c5544SLang Hames LazyCallThroughManager &EPCIndirectionUtils::createLazyCallThroughManager(
3318b1771bdSLang Hames     ExecutionSession &ES, ExecutorAddr ErrorHandlerAddr) {
332662c5544SLang Hames   assert(!LCTM &&
333662c5544SLang Hames          "createLazyCallThroughManager can not have been called before");
334662c5544SLang Hames   LCTM = std::make_unique<LazyCallThroughManager>(ES, ErrorHandlerAddr,
335662c5544SLang Hames                                                   &getTrampolinePool());
336662c5544SLang Hames   return *LCTM;
337662c5544SLang Hames }
338662c5544SLang Hames 
339662c5544SLang Hames EPCIndirectionUtils::EPCIndirectionUtils(ExecutorProcessControl &EPC,
340662c5544SLang Hames                                          std::unique_ptr<ABISupport> ABI)
341662c5544SLang Hames     : EPC(EPC), ABI(std::move(ABI)) {
342662c5544SLang Hames   assert(this->ABI && "ABI can not be null");
343662c5544SLang Hames 
344662c5544SLang Hames   assert(EPC.getPageSize() > getABISupport().getStubSize() &&
345662c5544SLang Hames          "Stubs larger than one page are not supported");
346662c5544SLang Hames }
347662c5544SLang Hames 
348662c5544SLang Hames Expected<EPCIndirectionUtils::IndirectStubInfoVector>
349662c5544SLang Hames EPCIndirectionUtils::getIndirectStubs(unsigned NumStubs) {
350962a2479SLang Hames   using namespace jitlink;
351662c5544SLang Hames 
352662c5544SLang Hames   std::lock_guard<std::mutex> Lock(EPCUIMutex);
353662c5544SLang Hames 
354662c5544SLang Hames   // If there aren't enough stubs available then allocate some more.
355662c5544SLang Hames   if (NumStubs > AvailableIndirectStubs.size()) {
356662c5544SLang Hames     auto NumStubsToAllocate = NumStubs;
357662c5544SLang Hames     auto PageSize = EPC.getPageSize();
358662c5544SLang Hames     auto StubBytes = alignTo(NumStubsToAllocate * ABI->getStubSize(), PageSize);
359662c5544SLang Hames     NumStubsToAllocate = StubBytes / ABI->getStubSize();
360962a2479SLang Hames     auto PtrBytes =
361662c5544SLang Hames         alignTo(NumStubsToAllocate * ABI->getPointerSize(), PageSize);
362662c5544SLang Hames 
363962a2479SLang Hames     auto StubProt = MemProt::Read | MemProt::Exec;
364962a2479SLang Hames     auto PtrProt = MemProt::Read | MemProt::Write;
365662c5544SLang Hames 
366962a2479SLang Hames     auto Alloc = SimpleSegmentAlloc::Create(
367*4eaff6c5SLang Hames         EPC.getMemMgr(), EPC.getSymbolStringPool(), EPC.getTargetTriple(),
368*4eaff6c5SLang Hames         nullptr,
369962a2479SLang Hames         {{StubProt, {static_cast<size_t>(StubBytes), Align(PageSize)}},
3703a52a639SLang Hames          {PtrProt, {static_cast<size_t>(PtrBytes), Align(PageSize)}}});
371962a2479SLang Hames 
372662c5544SLang Hames     if (!Alloc)
373662c5544SLang Hames       return Alloc.takeError();
374662c5544SLang Hames 
375962a2479SLang Hames     auto StubSeg = Alloc->getSegInfo(StubProt);
376962a2479SLang Hames     auto PtrSeg = Alloc->getSegInfo(PtrProt);
377662c5544SLang Hames 
3788b1771bdSLang Hames     ABI->writeIndirectStubsBlock(StubSeg.WorkingMem.data(), StubSeg.Addr,
3798b1771bdSLang Hames                                  PtrSeg.Addr, NumStubsToAllocate);
380662c5544SLang Hames 
381962a2479SLang Hames     auto FA = Alloc->finalize();
382962a2479SLang Hames     if (!FA)
383962a2479SLang Hames       return FA.takeError();
384662c5544SLang Hames 
385962a2479SLang Hames     IndirectStubAllocs.push_back(std::move(*FA));
386962a2479SLang Hames 
387962a2479SLang Hames     auto StubExecutorAddr = StubSeg.Addr;
388962a2479SLang Hames     auto PtrExecutorAddr = PtrSeg.Addr;
389662c5544SLang Hames     for (unsigned I = 0; I != NumStubsToAllocate; ++I) {
3908b1771bdSLang Hames       AvailableIndirectStubs.push_back(
3918b1771bdSLang Hames           IndirectStubInfo(StubExecutorAddr, PtrExecutorAddr));
392962a2479SLang Hames       StubExecutorAddr += ABI->getStubSize();
393962a2479SLang Hames       PtrExecutorAddr += ABI->getPointerSize();
394662c5544SLang Hames     }
395662c5544SLang Hames   }
396662c5544SLang Hames 
397662c5544SLang Hames   assert(NumStubs <= AvailableIndirectStubs.size() &&
398662c5544SLang Hames          "Sufficient stubs should have been allocated above");
399662c5544SLang Hames 
400662c5544SLang Hames   IndirectStubInfoVector Result;
401662c5544SLang Hames   while (NumStubs--) {
402662c5544SLang Hames     Result.push_back(AvailableIndirectStubs.back());
403662c5544SLang Hames     AvailableIndirectStubs.pop_back();
404662c5544SLang Hames   }
405662c5544SLang Hames 
406662c5544SLang Hames   return std::move(Result);
407662c5544SLang Hames }
408662c5544SLang Hames 
409662c5544SLang Hames static JITTargetAddress reentry(JITTargetAddress LCTMAddr,
410662c5544SLang Hames                                 JITTargetAddress TrampolineAddr) {
411662c5544SLang Hames   auto &LCTM = *jitTargetAddressToPointer<LazyCallThroughManager *>(LCTMAddr);
4128b1771bdSLang Hames   std::promise<ExecutorAddr> LandingAddrP;
413662c5544SLang Hames   auto LandingAddrF = LandingAddrP.get_future();
414662c5544SLang Hames   LCTM.resolveTrampolineLandingAddress(
4158b1771bdSLang Hames       ExecutorAddr(TrampolineAddr),
4168b1771bdSLang Hames       [&](ExecutorAddr Addr) { LandingAddrP.set_value(Addr); });
4178b1771bdSLang Hames   return LandingAddrF.get().getValue();
418662c5544SLang Hames }
419662c5544SLang Hames 
420662c5544SLang Hames Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU) {
421662c5544SLang Hames   auto &LCTM = EPCIU.getLazyCallThroughManager();
422662c5544SLang Hames   return EPCIU
4238b1771bdSLang Hames       .writeResolverBlock(ExecutorAddr::fromPtr(&reentry),
4248b1771bdSLang Hames                           ExecutorAddr::fromPtr(&LCTM))
425662c5544SLang Hames       .takeError();
426662c5544SLang Hames }
427662c5544SLang Hames 
428662c5544SLang Hames } // end namespace orc
429662c5544SLang Hames } // end namespace llvm
430