llvm-project/llvm/lib/ExecutionEngine/Orc/JITLinkReentryTrampolines.cpp
Lang Hames 4eaff6c58a [JITLink] Use target triple for LinkGraph pointer size and endianness.
Removes LinkGraph's PointerSize and Endianness members and uses the triple to
find these values instead.

Also removes some redundant Triple copies.
2025-01-14 18:11:19 +11:00

189 lines
6.6 KiB
C++

//===----- JITLinkReentryTrampolines.cpp -- JITLink-based trampoline- -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"
#include "llvm/ExecutionEngine/JITLink/aarch64.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include <memory>
#define DEBUG_TYPE "orc"
using namespace llvm;
using namespace llvm::jitlink;
namespace {
constexpr StringRef ReentryFnName = "__orc_rt_reenter";
constexpr StringRef ReentrySectionName = "__orc_stubs";
} // namespace
namespace llvm::orc {
class JITLinkReentryTrampolines::TrampolineAddrScraperPlugin
: public ObjectLinkingLayer::Plugin {
public:
void modifyPassConfig(MaterializationResponsibility &MR,
jitlink::LinkGraph &G,
jitlink::PassConfiguration &Config) override {
Config.PreFixupPasses.push_back(
[this](LinkGraph &G) { return recordTrampolineAddrs(G); });
}
Error notifyFailed(MaterializationResponsibility &MR) override {
return Error::success();
}
Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {
return Error::success();
}
void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
ResourceKey SrcKey) override {}
void registerGraph(LinkGraph &G,
std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs) {
std::lock_guard<std::mutex> Lock(M);
assert(!PendingAddrs.count(&G) && "Duplicate registration");
PendingAddrs[&G] = std::move(Addrs);
}
Error recordTrampolineAddrs(LinkGraph &G) {
std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs;
{
std::lock_guard<std::mutex> Lock(M);
auto I = PendingAddrs.find(&G);
if (I == PendingAddrs.end())
return Error::success();
Addrs = std::move(I->second);
PendingAddrs.erase(I);
}
auto *Sec = G.findSectionByName(ReentrySectionName);
assert(Sec && "Reentry graph missing reentry section");
assert(!Sec->empty() && "Reentry graph is empty");
for (auto *Sym : Sec->symbols())
if (!Sym->hasName())
Addrs->push_back({Sym->getAddress(), JITSymbolFlags()});
return Error::success();
}
private:
std::mutex M;
DenseMap<LinkGraph *, std::shared_ptr<std::vector<ExecutorSymbolDef>>>
PendingAddrs;
};
Expected<std::unique_ptr<JITLinkReentryTrampolines>>
JITLinkReentryTrampolines::Create(ObjectLinkingLayer &ObjLinkingLayer) {
EmitTrampolineFn EmitTrampoline;
const auto &TT = ObjLinkingLayer.getExecutionSession().getTargetTriple();
switch (TT.getArch()) {
case Triple::aarch64:
EmitTrampoline = aarch64::createAnonymousReentryTrampoline;
break;
case Triple::x86_64:
EmitTrampoline = x86_64::createAnonymousReentryTrampoline;
break;
default:
return make_error<StringError>("JITLinkReentryTrampolines: architecture " +
TT.getArchName() + " not supported",
inconvertibleErrorCode());
}
return std::make_unique<JITLinkReentryTrampolines>(ObjLinkingLayer,
std::move(EmitTrampoline));
}
JITLinkReentryTrampolines::JITLinkReentryTrampolines(
ObjectLinkingLayer &ObjLinkingLayer, EmitTrampolineFn EmitTrampoline)
: ObjLinkingLayer(ObjLinkingLayer),
EmitTrampoline(std::move(EmitTrampoline)) {
auto TAS = std::make_shared<TrampolineAddrScraperPlugin>();
TrampolineAddrScraper = TAS.get();
ObjLinkingLayer.addPlugin(std::move(TAS));
}
void JITLinkReentryTrampolines::emit(ResourceTrackerSP RT,
size_t NumTrampolines,
OnTrampolinesReadyFn OnTrampolinesReady) {
if (NumTrampolines == 0)
return OnTrampolinesReady(std::vector<ExecutorSymbolDef>());
JITDylibSP JD(&RT->getJITDylib());
auto &ES = ObjLinkingLayer.getExecutionSession();
auto ReentryGraphSym =
ES.intern(("__orc_reentry_graph_#" + Twine(++ReentryGraphIdx)).str());
auto G = std::make_unique<jitlink::LinkGraph>(
(*ReentryGraphSym).str(), ES.getSymbolStringPool(), ES.getTargetTriple(),
SubtargetFeatures(), jitlink::getGenericEdgeKindName);
auto &ReentryFnSym = G->addExternalSymbol(ReentryFnName, 0, false);
auto &ReentrySection =
G->createSection(ReentrySectionName, MemProt::Exec | MemProt::Read);
for (size_t I = 0; I != NumTrampolines; ++I)
EmitTrampoline(*G, ReentrySection, ReentryFnSym).setLive(true);
auto &FirstBlock = **ReentrySection.blocks().begin();
G->addDefinedSymbol(FirstBlock, 0, *ReentryGraphSym, FirstBlock.getSize(),
Linkage::Strong, Scope::SideEffectsOnly, true, true);
auto TrampolineAddrs = std::make_shared<std::vector<ExecutorSymbolDef>>();
TrampolineAddrScraper->registerGraph(*G, TrampolineAddrs);
// Add Graph via object linking layer.
if (auto Err = ObjLinkingLayer.add(std::move(RT), std::move(G)))
return OnTrampolinesReady(std::move(Err));
// Trigger graph emission.
ES.lookup(
LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},
SymbolLookupSet(ReentryGraphSym,
SymbolLookupFlags::WeaklyReferencedSymbol),
SymbolState::Ready,
[OnTrampolinesReady = std::move(OnTrampolinesReady),
TrampolineAddrs =
std::move(TrampolineAddrs)](Expected<SymbolMap> Result) mutable {
if (Result)
OnTrampolinesReady(std::move(*TrampolineAddrs));
else
OnTrampolinesReady(Result.takeError());
},
NoDependenciesToRegister);
}
Expected<std::unique_ptr<LazyReexportsManager>>
createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,
RedirectableSymbolManager &RSMgr,
JITDylib &PlatformJD,
LazyReexportsManager::Listener *L) {
auto JLT = JITLinkReentryTrampolines::Create(ObjLinkingLayer);
if (!JLT)
return JLT.takeError();
return LazyReexportsManager::Create(
[JLT = std::move(*JLT)](ResourceTrackerSP RT, size_t NumTrampolines,
LazyReexportsManager::OnTrampolinesReadyFn
OnTrampolinesReady) mutable {
JLT->emit(std::move(RT), NumTrampolines, std::move(OnTrampolinesReady));
},
RSMgr, PlatformJD, L);
}
} // namespace llvm::orc