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>
getIndirectStubs(EPCIndirectionUtils & EPCIU,unsigned NumStubs)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:
EPCIndirectStubsManager(EPCIndirectionUtils & EPCIU)57662c5544SLang Hames   EPCIndirectStubsManager(EPCIndirectionUtils &EPCIU) : EPCIU(EPCIU) {}
58662c5544SLang Hames 
59662c5544SLang Hames   Error deallocateStubs();
60662c5544SLang Hames 
61662c5544SLang Hames   Error createStub(StringRef StubName, JITTargetAddress StubAddr,
62662c5544SLang Hames                    JITSymbolFlags StubFlags) override;
63662c5544SLang Hames 
64662c5544SLang Hames   Error createStubs(const StubInitsMap &StubInits) override;
65662c5544SLang Hames 
66662c5544SLang Hames   JITEvaluatedSymbol findStub(StringRef Name, bool ExportedStubsOnly) override;
67662c5544SLang Hames 
68662c5544SLang Hames   JITEvaluatedSymbol findPointer(StringRef Name) override;
69662c5544SLang Hames 
70662c5544SLang Hames   Error updatePointer(StringRef Name, JITTargetAddress 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 
EPCTrampolinePool(EPCIndirectionUtils & EPCIU)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 
deallocatePool()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 
grow()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(
113962a2479SLang Hames       EPC.getMemMgr(), nullptr,
114962a2479SLang Hames       {{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);
121118e953bSLang Hames   EPCIU.getABISupport().writeTrampolines(SegInfo.WorkingMem.data(),
122118e953bSLang Hames                                          SegInfo.Addr.getValue(),
123118e953bSLang Hames                                          ResolverAddress, NumTrampolines);
124662c5544SLang Hames   for (unsigned I = 0; I < NumTrampolines; ++I)
125118e953bSLang Hames     AvailableTrampolines.push_back(SegInfo.Addr.getValue() +
126118e953bSLang Hames                                    (I * TrampolineSize));
127662c5544SLang Hames 
128962a2479SLang Hames   auto FA = Alloc->finalize();
129962a2479SLang Hames   if (!FA)
130962a2479SLang Hames     return FA.takeError();
131662c5544SLang Hames 
132962a2479SLang Hames   TrampolineBlocks.push_back(std::move(*FA));
133662c5544SLang Hames 
134662c5544SLang Hames   return Error::success();
135662c5544SLang Hames }
136662c5544SLang Hames 
createStub(StringRef StubName,JITTargetAddress StubAddr,JITSymbolFlags StubFlags)137662c5544SLang Hames Error EPCIndirectStubsManager::createStub(StringRef StubName,
138662c5544SLang Hames                                           JITTargetAddress StubAddr,
139662c5544SLang Hames                                           JITSymbolFlags StubFlags) {
140662c5544SLang Hames   StubInitsMap SIM;
141662c5544SLang Hames   SIM[StubName] = std::make_pair(StubAddr, StubFlags);
142662c5544SLang Hames   return createStubs(SIM);
143662c5544SLang Hames }
144662c5544SLang Hames 
createStubs(const StubInitsMap & StubInits)145662c5544SLang Hames Error EPCIndirectStubsManager::createStubs(const StubInitsMap &StubInits) {
146662c5544SLang Hames   auto AvailableStubInfos = getIndirectStubs(EPCIU, StubInits.size());
147662c5544SLang Hames   if (!AvailableStubInfos)
148662c5544SLang Hames     return AvailableStubInfos.takeError();
149662c5544SLang Hames 
150662c5544SLang Hames   {
151662c5544SLang Hames     std::lock_guard<std::mutex> Lock(ISMMutex);
152662c5544SLang Hames     unsigned ASIdx = 0;
153662c5544SLang Hames     for (auto &SI : StubInits) {
154662c5544SLang Hames       auto &A = (*AvailableStubInfos)[ASIdx++];
155662c5544SLang Hames       StubInfos[SI.first()] = std::make_pair(A, SI.second.second);
156662c5544SLang Hames     }
157662c5544SLang Hames   }
158662c5544SLang Hames 
159662c5544SLang Hames   auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
160662c5544SLang Hames   switch (EPCIU.getABISupport().getPointerSize()) {
161662c5544SLang Hames   case 4: {
162662c5544SLang Hames     unsigned ASIdx = 0;
163662c5544SLang Hames     std::vector<tpctypes::UInt32Write> PtrUpdates;
164662c5544SLang Hames     for (auto &SI : StubInits)
165999c6a23SLang Hames       PtrUpdates.push_back(
166999c6a23SLang Hames           {ExecutorAddr((*AvailableStubInfos)[ASIdx++].PointerAddress),
167662c5544SLang Hames            static_cast<uint32_t>(SI.second.first)});
168662c5544SLang Hames     return MemAccess.writeUInt32s(PtrUpdates);
169662c5544SLang Hames   }
170662c5544SLang Hames   case 8: {
171662c5544SLang Hames     unsigned ASIdx = 0;
172662c5544SLang Hames     std::vector<tpctypes::UInt64Write> PtrUpdates;
173662c5544SLang Hames     for (auto &SI : StubInits)
174999c6a23SLang Hames       PtrUpdates.push_back(
175999c6a23SLang Hames           {ExecutorAddr((*AvailableStubInfos)[ASIdx++].PointerAddress),
176662c5544SLang Hames            static_cast<uint64_t>(SI.second.first)});
177662c5544SLang Hames     return MemAccess.writeUInt64s(PtrUpdates);
178662c5544SLang Hames   }
179662c5544SLang Hames   default:
180662c5544SLang Hames     return make_error<StringError>("Unsupported pointer size",
181662c5544SLang Hames                                    inconvertibleErrorCode());
182662c5544SLang Hames   }
183662c5544SLang Hames }
184662c5544SLang Hames 
findStub(StringRef Name,bool ExportedStubsOnly)185662c5544SLang Hames JITEvaluatedSymbol EPCIndirectStubsManager::findStub(StringRef Name,
186662c5544SLang Hames                                                      bool ExportedStubsOnly) {
187662c5544SLang Hames   std::lock_guard<std::mutex> Lock(ISMMutex);
188662c5544SLang Hames   auto I = StubInfos.find(Name);
189662c5544SLang Hames   if (I == StubInfos.end())
190662c5544SLang Hames     return nullptr;
191662c5544SLang Hames   return {I->second.first.StubAddress, I->second.second};
192662c5544SLang Hames }
193662c5544SLang Hames 
findPointer(StringRef Name)194662c5544SLang Hames JITEvaluatedSymbol EPCIndirectStubsManager::findPointer(StringRef Name) {
195662c5544SLang Hames   std::lock_guard<std::mutex> Lock(ISMMutex);
196662c5544SLang Hames   auto I = StubInfos.find(Name);
197662c5544SLang Hames   if (I == StubInfos.end())
198662c5544SLang Hames     return nullptr;
199662c5544SLang Hames   return {I->second.first.PointerAddress, I->second.second};
200662c5544SLang Hames }
201662c5544SLang Hames 
updatePointer(StringRef Name,JITTargetAddress NewAddr)202662c5544SLang Hames Error EPCIndirectStubsManager::updatePointer(StringRef Name,
203662c5544SLang Hames                                              JITTargetAddress NewAddr) {
204662c5544SLang Hames 
205662c5544SLang Hames   JITTargetAddress PtrAddr = 0;
206662c5544SLang Hames   {
207662c5544SLang Hames     std::lock_guard<std::mutex> Lock(ISMMutex);
208662c5544SLang Hames     auto I = StubInfos.find(Name);
209662c5544SLang Hames     if (I == StubInfos.end())
210662c5544SLang Hames       return make_error<StringError>("Unknown stub name",
211662c5544SLang Hames                                      inconvertibleErrorCode());
212662c5544SLang Hames     PtrAddr = I->second.first.PointerAddress;
213662c5544SLang Hames   }
214662c5544SLang Hames 
215662c5544SLang Hames   auto &MemAccess = EPCIU.getExecutorProcessControl().getMemoryAccess();
216662c5544SLang Hames   switch (EPCIU.getABISupport().getPointerSize()) {
217662c5544SLang Hames   case 4: {
218999c6a23SLang Hames     tpctypes::UInt32Write PUpdate(ExecutorAddr(PtrAddr), NewAddr);
219662c5544SLang Hames     return MemAccess.writeUInt32s(PUpdate);
220662c5544SLang Hames   }
221662c5544SLang Hames   case 8: {
222999c6a23SLang Hames     tpctypes::UInt64Write PUpdate(ExecutorAddr(PtrAddr), NewAddr);
223662c5544SLang Hames     return MemAccess.writeUInt64s(PUpdate);
224662c5544SLang Hames   }
225662c5544SLang Hames   default:
226662c5544SLang Hames     return make_error<StringError>("Unsupported pointer size",
227662c5544SLang Hames                                    inconvertibleErrorCode());
228662c5544SLang Hames   }
229662c5544SLang Hames }
230662c5544SLang Hames 
231662c5544SLang Hames } // end anonymous namespace.
232662c5544SLang Hames 
233662c5544SLang Hames namespace llvm {
234662c5544SLang Hames namespace orc {
235662c5544SLang Hames 
2363a3cb929SKazu Hirata EPCIndirectionUtils::ABISupport::~ABISupport() = default;
237662c5544SLang Hames 
238662c5544SLang Hames Expected<std::unique_ptr<EPCIndirectionUtils>>
Create(ExecutorProcessControl & EPC)239662c5544SLang Hames EPCIndirectionUtils::Create(ExecutorProcessControl &EPC) {
240662c5544SLang Hames   const auto &TT = EPC.getTargetTriple();
241662c5544SLang Hames   switch (TT.getArch()) {
242662c5544SLang Hames   default:
243662c5544SLang Hames     return make_error<StringError>(
244662c5544SLang Hames         std::string("No EPCIndirectionUtils available for ") + TT.str(),
245662c5544SLang Hames         inconvertibleErrorCode());
246662c5544SLang Hames   case Triple::aarch64:
247662c5544SLang Hames   case Triple::aarch64_32:
248662c5544SLang Hames     return CreateWithABI<OrcAArch64>(EPC);
249662c5544SLang Hames 
250662c5544SLang Hames   case Triple::x86:
251662c5544SLang Hames     return CreateWithABI<OrcI386>(EPC);
252662c5544SLang Hames 
253662c5544SLang Hames   case Triple::mips:
254662c5544SLang Hames     return CreateWithABI<OrcMips32Be>(EPC);
255662c5544SLang Hames 
256662c5544SLang Hames   case Triple::mipsel:
257662c5544SLang Hames     return CreateWithABI<OrcMips32Le>(EPC);
258662c5544SLang Hames 
259662c5544SLang Hames   case Triple::mips64:
260662c5544SLang Hames   case Triple::mips64el:
261662c5544SLang Hames     return CreateWithABI<OrcMips64>(EPC);
262662c5544SLang Hames 
263*acb408fbSAlex Fan   case Triple::riscv64:
264*acb408fbSAlex Fan     return CreateWithABI<OrcRiscv64>(EPC);
265*acb408fbSAlex Fan 
266662c5544SLang Hames   case Triple::x86_64:
267662c5544SLang Hames     if (TT.getOS() == Triple::OSType::Win32)
268662c5544SLang Hames       return CreateWithABI<OrcX86_64_Win32>(EPC);
269662c5544SLang Hames     else
270662c5544SLang Hames       return CreateWithABI<OrcX86_64_SysV>(EPC);
271662c5544SLang Hames   }
272662c5544SLang Hames }
273662c5544SLang Hames 
cleanup()274662c5544SLang Hames Error EPCIndirectionUtils::cleanup() {
275662c5544SLang Hames 
276962a2479SLang Hames   auto &MemMgr = EPC.getMemMgr();
277962a2479SLang Hames   auto Err = MemMgr.deallocate(std::move(IndirectStubAllocs));
278662c5544SLang Hames 
279662c5544SLang Hames   if (TP)
280662c5544SLang Hames     Err = joinErrors(std::move(Err),
281662c5544SLang Hames                      static_cast<EPCTrampolinePool &>(*TP).deallocatePool());
282662c5544SLang Hames 
283662c5544SLang Hames   if (ResolverBlock)
284962a2479SLang Hames     Err =
285962a2479SLang Hames         joinErrors(std::move(Err), MemMgr.deallocate(std::move(ResolverBlock)));
286662c5544SLang Hames 
287662c5544SLang Hames   return Err;
288662c5544SLang Hames }
289662c5544SLang Hames 
290662c5544SLang Hames Expected<JITTargetAddress>
writeResolverBlock(JITTargetAddress ReentryFnAddr,JITTargetAddress ReentryCtxAddr)291662c5544SLang Hames EPCIndirectionUtils::writeResolverBlock(JITTargetAddress ReentryFnAddr,
292662c5544SLang Hames                                         JITTargetAddress ReentryCtxAddr) {
293962a2479SLang Hames   using namespace jitlink;
294962a2479SLang Hames 
295662c5544SLang Hames   assert(ABI && "ABI can not be null");
296662c5544SLang Hames   auto ResolverSize = ABI->getResolverCodeSize();
297662c5544SLang Hames 
298962a2479SLang Hames   auto Alloc =
299962a2479SLang Hames       SimpleSegmentAlloc::Create(EPC.getMemMgr(), 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);
30734e539dcSLang Hames   ResolverBlockAddr = SegInfo.Addr.getValue();
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>
createIndirectStubsManager()320662c5544SLang Hames EPCIndirectionUtils::createIndirectStubsManager() {
321662c5544SLang Hames   return std::make_unique<EPCIndirectStubsManager>(*this);
322662c5544SLang Hames }
323662c5544SLang Hames 
getTrampolinePool()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 
createLazyCallThroughManager(ExecutionSession & ES,JITTargetAddress ErrorHandlerAddr)330662c5544SLang Hames LazyCallThroughManager &EPCIndirectionUtils::createLazyCallThroughManager(
331662c5544SLang Hames     ExecutionSession &ES, JITTargetAddress 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 
EPCIndirectionUtils(ExecutorProcessControl & EPC,std::unique_ptr<ABISupport> ABI)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>
getIndirectStubs(unsigned NumStubs)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(
367962a2479SLang Hames         EPC.getMemMgr(), nullptr,
368962a2479SLang Hames         {{StubProt, {static_cast<size_t>(StubBytes), Align(PageSize)}},
3693a52a639SLang Hames          {PtrProt, {static_cast<size_t>(PtrBytes), Align(PageSize)}}});
370962a2479SLang Hames 
371662c5544SLang Hames     if (!Alloc)
372662c5544SLang Hames       return Alloc.takeError();
373662c5544SLang Hames 
374962a2479SLang Hames     auto StubSeg = Alloc->getSegInfo(StubProt);
375962a2479SLang Hames     auto PtrSeg = Alloc->getSegInfo(PtrProt);
376662c5544SLang Hames 
377118e953bSLang Hames     ABI->writeIndirectStubsBlock(StubSeg.WorkingMem.data(),
378118e953bSLang Hames                                  StubSeg.Addr.getValue(),
379118e953bSLang Hames                                  PtrSeg.Addr.getValue(), 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) {
390118e953bSLang Hames       AvailableIndirectStubs.push_back(IndirectStubInfo(
391118e953bSLang Hames           StubExecutorAddr.getValue(), PtrExecutorAddr.getValue()));
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 
reentry(JITTargetAddress LCTMAddr,JITTargetAddress TrampolineAddr)409662c5544SLang Hames static JITTargetAddress reentry(JITTargetAddress LCTMAddr,
410662c5544SLang Hames                                 JITTargetAddress TrampolineAddr) {
411662c5544SLang Hames   auto &LCTM = *jitTargetAddressToPointer<LazyCallThroughManager *>(LCTMAddr);
412662c5544SLang Hames   std::promise<JITTargetAddress> LandingAddrP;
413662c5544SLang Hames   auto LandingAddrF = LandingAddrP.get_future();
414662c5544SLang Hames   LCTM.resolveTrampolineLandingAddress(
415662c5544SLang Hames       TrampolineAddr,
416662c5544SLang Hames       [&](JITTargetAddress Addr) { LandingAddrP.set_value(Addr); });
417662c5544SLang Hames   return LandingAddrF.get();
418662c5544SLang Hames }
419662c5544SLang Hames 
setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils & EPCIU)420662c5544SLang Hames Error setUpInProcessLCTMReentryViaEPCIU(EPCIndirectionUtils &EPCIU) {
421662c5544SLang Hames   auto &LCTM = EPCIU.getLazyCallThroughManager();
422662c5544SLang Hames   return EPCIU
423662c5544SLang Hames       .writeResolverBlock(pointerToJITTargetAddress(&reentry),
424662c5544SLang Hames                           pointerToJITTargetAddress(&LCTM))
425662c5544SLang Hames       .takeError();
426662c5544SLang Hames }
427662c5544SLang Hames 
428662c5544SLang Hames } // end namespace orc
429662c5544SLang Hames } // end namespace llvm
430