Path: blob/main/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/JITLinkReentryTrampolines.cpp
213799 views
//===----- JITLinkReentryTrampolines.cpp -- JITLink-based trampoline- -----===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"910#include "llvm/ExecutionEngine/JITLink/aarch64.h"11#include "llvm/ExecutionEngine/JITLink/x86_64.h"12#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"1314#include <memory>1516#define DEBUG_TYPE "orc"1718using namespace llvm;19using namespace llvm::jitlink;2021namespace {22constexpr StringRef ReentryFnName = "__orc_rt_reenter";23constexpr StringRef ReentrySectionName = "__orc_stubs";24} // namespace2526namespace llvm::orc {2728class JITLinkReentryTrampolines::TrampolineAddrScraperPlugin29: public ObjectLinkingLayer::Plugin {30public:31void modifyPassConfig(MaterializationResponsibility &MR,32jitlink::LinkGraph &G,33jitlink::PassConfiguration &Config) override {34Config.PreFixupPasses.push_back(35[this](LinkGraph &G) { return recordTrampolineAddrs(G); });36}3738Error notifyFailed(MaterializationResponsibility &MR) override {39return Error::success();40}4142Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {43return Error::success();44}4546void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,47ResourceKey SrcKey) override {}4849void registerGraph(LinkGraph &G,50std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs) {51std::lock_guard<std::mutex> Lock(M);52assert(!PendingAddrs.count(&G) && "Duplicate registration");53PendingAddrs[&G] = std::move(Addrs);54}5556Error recordTrampolineAddrs(LinkGraph &G) {57std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs;58{59std::lock_guard<std::mutex> Lock(M);60auto I = PendingAddrs.find(&G);61if (I == PendingAddrs.end())62return Error::success();63Addrs = std::move(I->second);64PendingAddrs.erase(I);65}6667auto *Sec = G.findSectionByName(ReentrySectionName);68assert(Sec && "Reentry graph missing reentry section");69assert(!Sec->empty() && "Reentry graph is empty");7071for (auto *Sym : Sec->symbols())72if (!Sym->hasName())73Addrs->push_back({Sym->getAddress(), JITSymbolFlags()});7475return Error::success();76}7778private:79std::mutex M;80DenseMap<LinkGraph *, std::shared_ptr<std::vector<ExecutorSymbolDef>>>81PendingAddrs;82};8384Expected<std::unique_ptr<JITLinkReentryTrampolines>>85JITLinkReentryTrampolines::Create(ObjectLinkingLayer &ObjLinkingLayer) {8687EmitTrampolineFn EmitTrampoline;8889const auto &TT = ObjLinkingLayer.getExecutionSession().getTargetTriple();90switch (TT.getArch()) {91case Triple::aarch64:92EmitTrampoline = aarch64::createAnonymousReentryTrampoline;93break;94case Triple::x86_64:95EmitTrampoline = x86_64::createAnonymousReentryTrampoline;96break;97default:98return make_error<StringError>("JITLinkReentryTrampolines: architecture " +99TT.getArchName() + " not supported",100inconvertibleErrorCode());101}102103return std::make_unique<JITLinkReentryTrampolines>(ObjLinkingLayer,104std::move(EmitTrampoline));105}106107JITLinkReentryTrampolines::JITLinkReentryTrampolines(108ObjectLinkingLayer &ObjLinkingLayer, EmitTrampolineFn EmitTrampoline)109: ObjLinkingLayer(ObjLinkingLayer),110EmitTrampoline(std::move(EmitTrampoline)) {111auto TAS = std::make_shared<TrampolineAddrScraperPlugin>();112TrampolineAddrScraper = TAS.get();113ObjLinkingLayer.addPlugin(std::move(TAS));114}115116void JITLinkReentryTrampolines::emit(ResourceTrackerSP RT,117size_t NumTrampolines,118OnTrampolinesReadyFn OnTrampolinesReady) {119120if (NumTrampolines == 0)121return OnTrampolinesReady(std::vector<ExecutorSymbolDef>());122123JITDylibSP JD(&RT->getJITDylib());124auto &ES = ObjLinkingLayer.getExecutionSession();125126auto ReentryGraphSym =127ES.intern(("__orc_reentry_graph_#" + Twine(++ReentryGraphIdx)).str());128129auto G = std::make_unique<jitlink::LinkGraph>(130(*ReentryGraphSym).str(), ES.getSymbolStringPool(), ES.getTargetTriple(),131SubtargetFeatures(), jitlink::getGenericEdgeKindName);132133auto &ReentryFnSym = G->addExternalSymbol(ReentryFnName, 0, false);134135auto &ReentrySection =136G->createSection(ReentrySectionName, MemProt::Exec | MemProt::Read);137138for (size_t I = 0; I != NumTrampolines; ++I)139EmitTrampoline(*G, ReentrySection, ReentryFnSym).setLive(true);140141auto &FirstBlock = **ReentrySection.blocks().begin();142G->addDefinedSymbol(FirstBlock, 0, *ReentryGraphSym, FirstBlock.getSize(),143Linkage::Strong, Scope::SideEffectsOnly, true, true);144145auto TrampolineAddrs = std::make_shared<std::vector<ExecutorSymbolDef>>();146TrampolineAddrScraper->registerGraph(*G, TrampolineAddrs);147148// Add Graph via object linking layer.149if (auto Err = ObjLinkingLayer.add(std::move(RT), std::move(G)))150return OnTrampolinesReady(std::move(Err));151152// Trigger graph emission.153ES.lookup(154LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},155SymbolLookupSet(ReentryGraphSym,156SymbolLookupFlags::WeaklyReferencedSymbol),157SymbolState::Ready,158[OnTrampolinesReady = std::move(OnTrampolinesReady),159TrampolineAddrs =160std::move(TrampolineAddrs)](Expected<SymbolMap> Result) mutable {161if (Result)162OnTrampolinesReady(std::move(*TrampolineAddrs));163else164OnTrampolinesReady(Result.takeError());165},166NoDependenciesToRegister);167}168169Expected<std::unique_ptr<LazyReexportsManager>>170createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,171RedirectableSymbolManager &RSMgr,172JITDylib &PlatformJD,173LazyReexportsManager::Listener *L) {174auto JLT = JITLinkReentryTrampolines::Create(ObjLinkingLayer);175if (!JLT)176return JLT.takeError();177178return LazyReexportsManager::Create(179[JLT = std::move(*JLT)](ResourceTrackerSP RT, size_t NumTrampolines,180LazyReexportsManager::OnTrampolinesReadyFn181OnTrampolinesReady) mutable {182JLT->emit(std::move(RT), NumTrampolines, std::move(OnTrampolinesReady));183},184RSMgr, PlatformJD, L);185}186187} // namespace llvm::orc188189190