123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- //===------- ObjectLinkingLayer.cpp - JITLink backed ORC ObjectLayer ------===//
- //
- // 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/ObjectLinkingLayer.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
- #include <vector>
- #define DEBUG_TYPE "orc"
- using namespace llvm;
- using namespace llvm::jitlink;
- using namespace llvm::orc;
- namespace llvm {
- namespace orc {
- class ObjectLinkingLayerJITLinkContext final : public JITLinkContext {
- public:
- ObjectLinkingLayerJITLinkContext(ObjectLinkingLayer &Layer,
- MaterializationResponsibility MR,
- std::unique_ptr<MemoryBuffer> ObjBuffer)
- : Layer(Layer), MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {}
- JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }
- MemoryBufferRef getObjectBuffer() const override {
- return ObjBuffer->getMemBufferRef();
- }
- void notifyFailed(Error Err) override {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- }
- void lookup(const DenseSet<StringRef> &Symbols,
- std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {
- JITDylibSearchList SearchOrder;
- MR.getTargetJITDylib().withSearchOrderDo(
- [&](const JITDylibSearchList &JDs) { SearchOrder = JDs; });
- auto &ES = Layer.getExecutionSession();
- SymbolNameSet InternedSymbols;
- for (auto &S : Symbols)
- InternedSymbols.insert(ES.intern(S));
- // OnResolve -- De-intern the symbols and pass the result to the linker.
- auto OnResolve = [this, LookupContinuation = std::move(LC)](
- Expected<SymbolMap> Result) mutable {
- auto Main = Layer.getExecutionSession().intern("_main");
- if (!Result)
- LookupContinuation->run(Result.takeError());
- else {
- AsyncLookupResult LR;
- for (auto &KV : *Result)
- LR[*KV.first] = KV.second;
- LookupContinuation->run(std::move(LR));
- }
- };
- ES.lookup(SearchOrder, std::move(InternedSymbols), SymbolState::Resolved,
- std::move(OnResolve), [this](const SymbolDependenceMap &Deps) {
- registerDependencies(Deps);
- });
- }
- void notifyResolved(LinkGraph &G) override {
- auto &ES = Layer.getExecutionSession();
- SymbolFlagsMap ExtraSymbolsToClaim;
- bool AutoClaim = Layer.AutoClaimObjectSymbols;
- SymbolMap InternedResult;
- for (auto *Sym : G.defined_symbols())
- if (Sym->hasName() && Sym->getScope() != Scope::Local) {
- auto InternedName = ES.intern(Sym->getName());
- JITSymbolFlags Flags;
- if (Sym->isCallable())
- Flags |= JITSymbolFlags::Callable;
- if (Sym->getScope() == Scope::Default)
- Flags |= JITSymbolFlags::Exported;
- InternedResult[InternedName] =
- JITEvaluatedSymbol(Sym->getAddress(), Flags);
- if (AutoClaim && !MR.getSymbols().count(InternedName)) {
- assert(!ExtraSymbolsToClaim.count(InternedName) &&
- "Duplicate symbol to claim?");
- ExtraSymbolsToClaim[InternedName] = Flags;
- }
- }
- for (auto *Sym : G.absolute_symbols())
- if (Sym->hasName()) {
- auto InternedName = ES.intern(Sym->getName());
- JITSymbolFlags Flags;
- Flags |= JITSymbolFlags::Absolute;
- if (Sym->isCallable())
- Flags |= JITSymbolFlags::Callable;
- if (Sym->getLinkage() == Linkage::Weak)
- Flags |= JITSymbolFlags::Weak;
- InternedResult[InternedName] =
- JITEvaluatedSymbol(Sym->getAddress(), Flags);
- if (AutoClaim && !MR.getSymbols().count(InternedName)) {
- assert(!ExtraSymbolsToClaim.count(InternedName) &&
- "Duplicate symbol to claim?");
- ExtraSymbolsToClaim[InternedName] = Flags;
- }
- }
- if (!ExtraSymbolsToClaim.empty())
- if (auto Err = MR.defineMaterializing(ExtraSymbolsToClaim))
- return notifyFailed(std::move(Err));
- if (auto Err = MR.notifyResolved(InternedResult)) {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- return;
- }
- Layer.notifyLoaded(MR);
- }
- void notifyFinalized(
- std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
- if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- return;
- }
- if (auto Err = MR.notifyEmitted()) {
- Layer.getExecutionSession().reportError(std::move(Err));
- MR.failMaterialization();
- }
- }
- LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
- return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
- }
- Error modifyPassConfig(const Triple &TT, PassConfiguration &Config) override {
- // Add passes to mark duplicate defs as should-discard, and to walk the
- // link graph to build the symbol dependence graph.
- Config.PrePrunePasses.push_back(
- [this](LinkGraph &G) { return externalizeWeakAndCommonSymbols(G); });
- Config.PostPrunePasses.push_back(
- [this](LinkGraph &G) { return computeNamedSymbolDependencies(G); });
- Layer.modifyPassConfig(MR, TT, Config);
- return Error::success();
- }
- private:
- using AnonToNamedDependenciesMap = DenseMap<const Symbol *, SymbolNameSet>;
- Error externalizeWeakAndCommonSymbols(LinkGraph &G) {
- auto &ES = Layer.getExecutionSession();
- for (auto *Sym : G.defined_symbols())
- if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
- if (!MR.getSymbols().count(ES.intern(Sym->getName())))
- G.makeExternal(*Sym);
- }
- for (auto *Sym : G.absolute_symbols())
- if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak) {
- if (!MR.getSymbols().count(ES.intern(Sym->getName())))
- G.makeExternal(*Sym);
- }
- return Error::success();
- }
- Error markResponsibilitySymbolsLive(LinkGraph &G) const {
- auto &ES = Layer.getExecutionSession();
- for (auto *Sym : G.defined_symbols())
- if (Sym->hasName() && MR.getSymbols().count(ES.intern(Sym->getName())))
- Sym->setLive(true);
- return Error::success();
- }
- Error computeNamedSymbolDependencies(LinkGraph &G) {
- auto &ES = MR.getTargetJITDylib().getExecutionSession();
- auto AnonDeps = computeAnonDeps(G);
- for (auto *Sym : G.defined_symbols()) {
- // Skip anonymous and non-global atoms: we do not need dependencies for
- // these.
- if (Sym->getScope() == Scope::Local)
- continue;
- auto SymName = ES.intern(Sym->getName());
- SymbolNameSet &SymDeps = NamedSymbolDeps[SymName];
- for (auto &E : Sym->getBlock().edges()) {
- auto &TargetSym = E.getTarget();
- if (TargetSym.getScope() != Scope::Local)
- SymDeps.insert(ES.intern(TargetSym.getName()));
- else {
- assert(TargetSym.isDefined() &&
- "Anonymous/local symbols must be defined");
- auto I = AnonDeps.find(&TargetSym);
- if (I != AnonDeps.end())
- for (auto &S : I->second)
- SymDeps.insert(S);
- }
- }
- }
- return Error::success();
- }
- AnonToNamedDependenciesMap computeAnonDeps(LinkGraph &G) {
- auto &ES = MR.getTargetJITDylib().getExecutionSession();
- AnonToNamedDependenciesMap DepMap;
- // For all anonymous symbols:
- // (1) Add their named dependencies.
- // (2) Add them to the worklist for further iteration if they have any
- // depend on any other anonymous symbols.
- struct WorklistEntry {
- WorklistEntry(Symbol *Sym, DenseSet<Symbol *> SymAnonDeps)
- : Sym(Sym), SymAnonDeps(std::move(SymAnonDeps)) {}
- Symbol *Sym = nullptr;
- DenseSet<Symbol *> SymAnonDeps;
- };
- std::vector<WorklistEntry> Worklist;
- for (auto *Sym : G.defined_symbols())
- if (!Sym->hasName()) {
- auto &SymNamedDeps = DepMap[Sym];
- DenseSet<Symbol *> SymAnonDeps;
- for (auto &E : Sym->getBlock().edges()) {
- auto &TargetSym = E.getTarget();
- if (TargetSym.hasName())
- SymNamedDeps.insert(ES.intern(TargetSym.getName()));
- else {
- assert(TargetSym.isDefined() &&
- "Anonymous symbols must be defined");
- SymAnonDeps.insert(&TargetSym);
- }
- }
- if (!SymAnonDeps.empty())
- Worklist.push_back(WorklistEntry(Sym, std::move(SymAnonDeps)));
- }
- // Loop over all anonymous symbols with anonymous dependencies, propagating
- // their respective *named* dependencies. Iterate until we hit a stable
- // state.
- bool Changed;
- do {
- Changed = false;
- for (auto &WLEntry : Worklist) {
- auto *Sym = WLEntry.Sym;
- auto &SymNamedDeps = DepMap[Sym];
- auto &SymAnonDeps = WLEntry.SymAnonDeps;
- for (auto *TargetSym : SymAnonDeps) {
- auto I = DepMap.find(TargetSym);
- if (I != DepMap.end())
- for (const auto &S : I->second)
- Changed |= SymNamedDeps.insert(S).second;
- }
- }
- } while (Changed);
- return DepMap;
- }
- void registerDependencies(const SymbolDependenceMap &QueryDeps) {
- for (auto &NamedDepsEntry : NamedSymbolDeps) {
- auto &Name = NamedDepsEntry.first;
- auto &NameDeps = NamedDepsEntry.second;
- SymbolDependenceMap SymbolDeps;
- for (const auto &QueryDepsEntry : QueryDeps) {
- JITDylib &SourceJD = *QueryDepsEntry.first;
- const SymbolNameSet &Symbols = QueryDepsEntry.second;
- auto &DepsForJD = SymbolDeps[&SourceJD];
- for (const auto &S : Symbols)
- if (NameDeps.count(S))
- DepsForJD.insert(S);
- if (DepsForJD.empty())
- SymbolDeps.erase(&SourceJD);
- }
- MR.addDependencies(Name, SymbolDeps);
- }
- }
- ObjectLinkingLayer &Layer;
- MaterializationResponsibility MR;
- std::unique_ptr<MemoryBuffer> ObjBuffer;
- DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
- };
- ObjectLinkingLayer::Plugin::~Plugin() {}
- ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
- JITLinkMemoryManager &MemMgr)
- : ObjectLayer(ES), MemMgr(MemMgr) {}
- ObjectLinkingLayer::~ObjectLinkingLayer() {
- if (auto Err = removeAllModules())
- getExecutionSession().reportError(std::move(Err));
- }
- void ObjectLinkingLayer::emit(MaterializationResponsibility R,
- std::unique_ptr<MemoryBuffer> O) {
- assert(O && "Object must not be null");
- jitLink(std::make_unique<ObjectLinkingLayerJITLinkContext>(
- *this, std::move(R), std::move(O)));
- }
- void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
- const Triple &TT,
- PassConfiguration &PassConfig) {
- for (auto &P : Plugins)
- P->modifyPassConfig(MR, TT, PassConfig);
- }
- void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
- for (auto &P : Plugins)
- P->notifyLoaded(MR);
- }
- Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
- AllocPtr Alloc) {
- Error Err = Error::success();
- for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
- if (Err)
- return Err;
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- UntrackedAllocs.push_back(std::move(Alloc));
- }
- return Error::success();
- }
- Error ObjectLinkingLayer::removeModule(VModuleKey K) {
- Error Err = Error::success();
- for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
- AllocPtr Alloc;
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- auto AllocItr = TrackedAllocs.find(K);
- Alloc = std::move(AllocItr->second);
- TrackedAllocs.erase(AllocItr);
- }
- assert(Alloc && "No allocation for key K");
- return joinErrors(std::move(Err), Alloc->deallocate());
- }
- Error ObjectLinkingLayer::removeAllModules() {
- Error Err = Error::success();
- for (auto &P : Plugins)
- Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
- std::vector<AllocPtr> Allocs;
- {
- std::lock_guard<std::mutex> Lock(LayerMutex);
- Allocs = std::move(UntrackedAllocs);
- for (auto &KV : TrackedAllocs)
- Allocs.push_back(std::move(KV.second));
- TrackedAllocs.clear();
- }
- while (!Allocs.empty()) {
- Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
- Allocs.pop_back();
- }
- return Err;
- }
- EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
- EHFrameRegistrar &Registrar)
- : Registrar(Registrar) {}
- void EHFrameRegistrationPlugin::modifyPassConfig(
- MaterializationResponsibility &MR, const Triple &TT,
- PassConfiguration &PassConfig) {
- assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
- PassConfig.PostFixupPasses.push_back(
- createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr,
- size_t Size) {
- if (Addr)
- InProcessLinks[&MR] = { Addr, Size };
- }));
- }
- Error EHFrameRegistrationPlugin::notifyEmitted(
- MaterializationResponsibility &MR) {
- auto EHFrameRangeItr = InProcessLinks.find(&MR);
- if (EHFrameRangeItr == InProcessLinks.end())
- return Error::success();
- auto EHFrameRange = EHFrameRangeItr->second;
- assert(EHFrameRange.Addr &&
- "eh-frame addr to register can not be null");
- InProcessLinks.erase(EHFrameRangeItr);
- if (auto Key = MR.getVModuleKey())
- TrackedEHFrameRanges[Key] = EHFrameRange;
- else
- UntrackedEHFrameRanges.push_back(EHFrameRange);
- return Registrar.registerEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
- }
- Error EHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
- auto EHFrameRangeItr = TrackedEHFrameRanges.find(K);
- if (EHFrameRangeItr == TrackedEHFrameRanges.end())
- return Error::success();
- auto EHFrameRange = EHFrameRangeItr->second;
- assert(EHFrameRange.Addr && "Tracked eh-frame range must not be null");
- TrackedEHFrameRanges.erase(EHFrameRangeItr);
- return Registrar.deregisterEHFrames(EHFrameRange.Addr, EHFrameRange.Size);
- }
- Error EHFrameRegistrationPlugin::notifyRemovingAllModules() {
- std::vector<EHFrameRange> EHFrameRanges =
- std::move(UntrackedEHFrameRanges);
- EHFrameRanges.reserve(EHFrameRanges.size() + TrackedEHFrameRanges.size());
- for (auto &KV : TrackedEHFrameRanges)
- EHFrameRanges.push_back(KV.second);
- TrackedEHFrameRanges.clear();
- Error Err = Error::success();
- while (!EHFrameRanges.empty()) {
- auto EHFrameRange = EHFrameRanges.back();
- assert(EHFrameRange.Addr && "Untracked eh-frame range must not be null");
- EHFrameRanges.pop_back();
- Err = joinErrors(std::move(Err),
- Registrar.deregisterEHFrames(EHFrameRange.Addr,
- EHFrameRange.Size));
- }
- return Err;
- }
- } // End namespace orc.
- } // End namespace llvm.
|