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