brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.6 KiB · d305342 Raw
189 lines · cpp
1//===----- JITLinkReentryTrampolines.cpp -- JITLink-based trampoline- -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"10 11#include "llvm/ExecutionEngine/JITLink/aarch64.h"12#include "llvm/ExecutionEngine/JITLink/x86_64.h"13#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"14 15#include <memory>16 17#define DEBUG_TYPE "orc"18 19using namespace llvm;20using namespace llvm::jitlink;21 22namespace {23constexpr StringRef ReentryFnName = "__orc_rt_reenter";24constexpr StringRef ReentrySectionName = "__orc_stubs";25} // namespace26 27namespace llvm::orc {28 29class JITLinkReentryTrampolines::TrampolineAddrScraperPlugin30    : public ObjectLinkingLayer::Plugin {31public:32  void modifyPassConfig(MaterializationResponsibility &MR,33                        jitlink::LinkGraph &G,34                        jitlink::PassConfiguration &Config) override {35    Config.PreFixupPasses.push_back(36        [this](LinkGraph &G) { return recordTrampolineAddrs(G); });37  }38 39  Error notifyFailed(MaterializationResponsibility &MR) override {40    return Error::success();41  }42 43  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {44    return Error::success();45  }46 47  void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,48                                   ResourceKey SrcKey) override {}49 50  void registerGraph(LinkGraph &G,51                     std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs) {52    std::lock_guard<std::mutex> Lock(M);53    assert(!PendingAddrs.count(&G) && "Duplicate registration");54    PendingAddrs[&G] = std::move(Addrs);55  }56 57  Error recordTrampolineAddrs(LinkGraph &G) {58    std::shared_ptr<std::vector<ExecutorSymbolDef>> Addrs;59    {60      std::lock_guard<std::mutex> Lock(M);61      auto I = PendingAddrs.find(&G);62      if (I == PendingAddrs.end())63        return Error::success();64      Addrs = std::move(I->second);65      PendingAddrs.erase(I);66    }67 68    auto *Sec = G.findSectionByName(ReentrySectionName);69    assert(Sec && "Reentry graph missing reentry section");70    assert(!Sec->empty() && "Reentry graph is empty");71 72    for (auto *Sym : Sec->symbols())73      if (!Sym->hasName())74        Addrs->push_back({Sym->getAddress(), JITSymbolFlags()});75 76    return Error::success();77  }78 79private:80  std::mutex M;81  DenseMap<LinkGraph *, std::shared_ptr<std::vector<ExecutorSymbolDef>>>82      PendingAddrs;83};84 85Expected<std::unique_ptr<JITLinkReentryTrampolines>>86JITLinkReentryTrampolines::Create(ObjectLinkingLayer &ObjLinkingLayer) {87 88  EmitTrampolineFn EmitTrampoline;89 90  const auto &TT = ObjLinkingLayer.getExecutionSession().getTargetTriple();91  switch (TT.getArch()) {92  case Triple::aarch64:93    EmitTrampoline = aarch64::createAnonymousReentryTrampoline;94    break;95  case Triple::x86_64:96    EmitTrampoline = x86_64::createAnonymousReentryTrampoline;97    break;98  default:99    return make_error<StringError>("JITLinkReentryTrampolines: architecture " +100				   TT.getArchName() + " not supported",101                                   inconvertibleErrorCode());102  }103 104  return std::make_unique<JITLinkReentryTrampolines>(ObjLinkingLayer,105                                                     std::move(EmitTrampoline));106}107 108JITLinkReentryTrampolines::JITLinkReentryTrampolines(109    ObjectLinkingLayer &ObjLinkingLayer, EmitTrampolineFn EmitTrampoline)110    : ObjLinkingLayer(ObjLinkingLayer),111      EmitTrampoline(std::move(EmitTrampoline)) {112  auto TAS = std::make_shared<TrampolineAddrScraperPlugin>();113  TrampolineAddrScraper = TAS.get();114  ObjLinkingLayer.addPlugin(std::move(TAS));115}116 117void JITLinkReentryTrampolines::emit(ResourceTrackerSP RT,118                                     size_t NumTrampolines,119                                     OnTrampolinesReadyFn OnTrampolinesReady) {120 121  if (NumTrampolines == 0)122    return OnTrampolinesReady(std::vector<ExecutorSymbolDef>());123 124  JITDylibSP JD(&RT->getJITDylib());125  auto &ES = ObjLinkingLayer.getExecutionSession();126 127  auto ReentryGraphSym =128      ES.intern(("__orc_reentry_graph_#" + Twine(++ReentryGraphIdx)).str());129 130  auto G = std::make_unique<jitlink::LinkGraph>(131      (*ReentryGraphSym).str(), ES.getSymbolStringPool(), ES.getTargetTriple(),132      SubtargetFeatures(), jitlink::getGenericEdgeKindName);133 134  auto &ReentryFnSym = G->addExternalSymbol(ReentryFnName, 0, false);135 136  auto &ReentrySection =137      G->createSection(ReentrySectionName, MemProt::Exec | MemProt::Read);138 139  for (size_t I = 0; I != NumTrampolines; ++I)140    EmitTrampoline(*G, ReentrySection, ReentryFnSym).setLive(true);141 142  auto &FirstBlock = **ReentrySection.blocks().begin();143  G->addDefinedSymbol(FirstBlock, 0, *ReentryGraphSym, FirstBlock.getSize(),144                      Linkage::Strong, Scope::SideEffectsOnly, true, true);145 146  auto TrampolineAddrs = std::make_shared<std::vector<ExecutorSymbolDef>>();147  TrampolineAddrScraper->registerGraph(*G, TrampolineAddrs);148 149  // Add Graph via object linking layer.150  if (auto Err = ObjLinkingLayer.add(std::move(RT), std::move(G)))151    return OnTrampolinesReady(std::move(Err));152 153  // Trigger graph emission.154  ES.lookup(155      LookupKind::Static, {{JD.get(), JITDylibLookupFlags::MatchAllSymbols}},156      SymbolLookupSet(ReentryGraphSym,157                      SymbolLookupFlags::WeaklyReferencedSymbol),158      SymbolState::Ready,159      [OnTrampolinesReady = std::move(OnTrampolinesReady),160       TrampolineAddrs =161           std::move(TrampolineAddrs)](Expected<SymbolMap> Result) mutable {162        if (Result)163          OnTrampolinesReady(std::move(*TrampolineAddrs));164        else165          OnTrampolinesReady(Result.takeError());166      },167      NoDependenciesToRegister);168}169 170Expected<std::unique_ptr<LazyReexportsManager>>171createJITLinkLazyReexportsManager(ObjectLinkingLayer &ObjLinkingLayer,172                                  RedirectableSymbolManager &RSMgr,173                                  JITDylib &PlatformJD,174                                  LazyReexportsManager::Listener *L) {175  auto JLT = JITLinkReentryTrampolines::Create(ObjLinkingLayer);176  if (!JLT)177    return JLT.takeError();178 179  return LazyReexportsManager::Create(180      [JLT = std::move(*JLT)](ResourceTrackerSP RT, size_t NumTrampolines,181                              LazyReexportsManager::OnTrampolinesReadyFn182                                  OnTrampolinesReady) mutable {183        JLT->emit(std::move(RT), NumTrampolines, std::move(OnTrampolinesReady));184      },185      RSMgr, PlatformJD, L);186}187 188} // namespace llvm::orc189