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