//===------ LinkGraphLinkingLayer.cpp - Link LinkGraphs with JITLink ------===//
//
// 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/LinkGraphLinkingLayer.h"

#include "llvm/ADT/SCCIterator.h"
#include "llvm/ExecutionEngine/JITLink/aarch32.h"
#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
#include "llvm/Support/MemoryBuffer.h"

#define DEBUG_TYPE "orc"

using namespace llvm;
using namespace llvm::jitlink;
using namespace llvm::orc;

namespace llvm {

struct BlockDepInfo;

using BlockDepInfoMap = DenseMap<jitlink::Block *, BlockDepInfo>;

struct BlockDepInfo {
  using SymbolDefList = SmallVector<jitlink::Symbol *>;
  using SymbolDepSet = DenseSet<jitlink::Symbol *>;
  using AnonBlockDepSet = DenseSet<jitlink::Block *>;

  BlockDepInfoMap *Graph = nullptr;
  SymbolDefList SymbolDefs;
  SymbolDepSet SymbolDeps;
  AnonBlockDepSet AnonBlockDeps;
  BlockDepInfo *SCCRoot = nullptr;
  std::optional<size_t> DepGroupIndex;
};

template <> struct GraphTraits<BlockDepInfo *> {
  using NodeRef = BlockDepInfo *;

  class ChildIteratorType {
    using impl_iterator = BlockDepInfo::AnonBlockDepSet::iterator;

  public:
    ChildIteratorType(NodeRef Parent, impl_iterator I)
        : Parent(Parent), I(std::move(I)) {}

    friend bool operator==(const ChildIteratorType &LHS,
                           const ChildIteratorType &RHS) {
      return LHS.I == RHS.I;
    }
    friend bool operator!=(const ChildIteratorType &LHS,
                           const ChildIteratorType &RHS) {
      return LHS.I != RHS.I;
    }

    ChildIteratorType &operator++() {
      ++I;
      return *this;
    }
    ChildIteratorType operator++(int) {
      auto Tmp = *this;
      ++I;
      return Tmp;
    }
    NodeRef operator*() {
      assert(Parent->Graph && "No pointer to BlockDepInfoMap");
      return &(*Parent->Graph)[*I];
    }

  private:
    NodeRef Parent;
    BlockDepInfo::AnonBlockDepSet::iterator I;
  };

  static NodeRef getEntryNode(NodeRef N) { return N; }

  static ChildIteratorType child_begin(NodeRef N) {
    return ChildIteratorType(N, N->AnonBlockDeps.begin());
  }
  static ChildIteratorType child_end(NodeRef N) {
    return ChildIteratorType(N, N->AnonBlockDeps.end());
  }
};

} // namespace llvm

namespace {

ExecutorAddr getJITSymbolPtrForSymbol(Symbol &Sym, const Triple &TT) {
  switch (TT.getArch()) {
  case Triple::arm:
  case Triple::armeb:
  case Triple::thumb:
  case Triple::thumbeb:
    if (hasTargetFlags(Sym, aarch32::ThumbSymbol)) {
      // Set LSB to indicate thumb target
      assert(Sym.isCallable() && "Only callable symbols can have thumb flag");
      assert((Sym.getAddress().getValue() & 0x01) == 0 && "LSB is clear");
      return Sym.getAddress() + 0x01;
    }
    return Sym.getAddress();
  default:
    return Sym.getAddress();
  }
}

} // end anonymous namespace

namespace llvm {
namespace orc {

class LinkGraphLinkingLayer::JITLinkCtx final : public JITLinkContext {
public:
  JITLinkCtx(LinkGraphLinkingLayer &Layer,
             std::unique_ptr<MaterializationResponsibility> MR,
             std::unique_ptr<MemoryBuffer> ObjBuffer)
      : JITLinkContext(&MR->getTargetJITDylib()), Layer(Layer),
        MR(std::move(MR)), ObjBuffer(std::move(ObjBuffer)) {
    std::lock_guard<std::mutex> Lock(Layer.LayerMutex);
    Plugins = Layer.Plugins;
  }

  ~JITLinkCtx() override {
    // If there is an object buffer return function then use it to
    // return ownership of the buffer.
    if (Layer.ReturnObjectBuffer && ObjBuffer)
      Layer.ReturnObjectBuffer(std::move(ObjBuffer));
  }

  JITLinkMemoryManager &getMemoryManager() override { return Layer.MemMgr; }

  void notifyMaterializing(LinkGraph &G) {
    for (auto &P : Plugins)
      P->notifyMaterializing(*MR, G, *this,
                             ObjBuffer ? ObjBuffer->getMemBufferRef()
                                       : MemoryBufferRef());
  }

  void notifyFailed(Error Err) override {
    for (auto &P : Plugins)
      Err = joinErrors(std::move(Err), P->notifyFailed(*MR));
    Layer.getExecutionSession().reportError(std::move(Err));
    MR->failMaterialization();
  }

  void lookup(const LookupMap &Symbols,
              std::unique_ptr<JITLinkAsyncLookupContinuation> LC) override {

    JITDylibSearchOrder LinkOrder;
    MR->getTargetJITDylib().withLinkOrderDo(
        [&](const JITDylibSearchOrder &LO) { LinkOrder = LO; });

    auto &ES = Layer.getExecutionSession();

    SymbolLookupSet LookupSet;
    for (auto &KV : Symbols) {
      orc::SymbolLookupFlags LookupFlags;
      switch (KV.second) {
      case jitlink::SymbolLookupFlags::RequiredSymbol:
        LookupFlags = orc::SymbolLookupFlags::RequiredSymbol;
        break;
      case jitlink::SymbolLookupFlags::WeaklyReferencedSymbol:
        LookupFlags = orc::SymbolLookupFlags::WeaklyReferencedSymbol;
        break;
      }
      LookupSet.add(KV.first, LookupFlags);
    }

    // OnResolve -- De-intern the symbols and pass the result to the linker.
    auto OnResolve = [LookupContinuation =
                          std::move(LC)](Expected<SymbolMap> Result) mutable {
      if (!Result)
        LookupContinuation->run(Result.takeError());
      else {
        AsyncLookupResult LR;
        LR.insert_range(*Result);
        LookupContinuation->run(std::move(LR));
      }
    };

    ES.lookup(LookupKind::Static, LinkOrder, std::move(LookupSet),
              SymbolState::Resolved, std::move(OnResolve),
              [this](const SymbolDependenceMap &Deps) {
                // Translate LookupDeps map to SymbolSourceJD.
                for (auto &[DepJD, Deps] : Deps)
                  for (auto &DepSym : Deps)
                    SymbolSourceJDs[NonOwningSymbolStringPtr(DepSym)] = DepJD;
              });
  }

  Error notifyResolved(LinkGraph &G) override {

    SymbolFlagsMap ExtraSymbolsToClaim;
    bool AutoClaim = Layer.AutoClaimObjectSymbols;

    SymbolMap InternedResult;
    for (auto *Sym : G.defined_symbols())
      if (Sym->getScope() < Scope::SideEffectsOnly) {
        auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
        auto Flags = getJITSymbolFlagsForSymbol(*Sym);
        InternedResult[Sym->getName()] = {Ptr, Flags};
        if (AutoClaim && !MR->getSymbols().count(Sym->getName())) {
          assert(!ExtraSymbolsToClaim.count(Sym->getName()) &&
                 "Duplicate symbol to claim?");
          ExtraSymbolsToClaim[Sym->getName()] = Flags;
        }
      }

    for (auto *Sym : G.absolute_symbols())
      if (Sym->getScope() < Scope::SideEffectsOnly) {
        auto Ptr = getJITSymbolPtrForSymbol(*Sym, G.getTargetTriple());
        auto Flags = getJITSymbolFlagsForSymbol(*Sym);
        InternedResult[Sym->getName()] = {Ptr, Flags};
        if (AutoClaim && !MR->getSymbols().count(Sym->getName())) {
          assert(!ExtraSymbolsToClaim.count(Sym->getName()) &&
                 "Duplicate symbol to claim?");
          ExtraSymbolsToClaim[Sym->getName()] = Flags;
        }
      }

    if (!ExtraSymbolsToClaim.empty())
      if (auto Err = MR->defineMaterializing(ExtraSymbolsToClaim))
        return Err;

    {

      // Check that InternedResult matches up with MR->getSymbols(), overriding
      // flags if requested.
      // This guards against faulty transformations / compilers / object caches.

      // First check that there aren't any missing symbols.
      size_t NumMaterializationSideEffectsOnlySymbols = 0;
      SymbolNameVector MissingSymbols;
      for (auto &[Sym, Flags] : MR->getSymbols()) {

        auto I = InternedResult.find(Sym);

        // If this is a materialization-side-effects only symbol then bump
        // the counter and remove in from the result, otherwise make sure that
        // it's defined.
        if (Flags.hasMaterializationSideEffectsOnly())
          ++NumMaterializationSideEffectsOnlySymbols;
        else if (I == InternedResult.end())
          MissingSymbols.push_back(Sym);
        else if (Layer.OverrideObjectFlags)
          I->second.setFlags(Flags);
      }

      // If there were missing symbols then report the error.
      if (!MissingSymbols.empty())
        return make_error<MissingSymbolDefinitions>(
            Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
            std::move(MissingSymbols));

      // If there are more definitions than expected, add them to the
      // ExtraSymbols vector.
      SymbolNameVector ExtraSymbols;
      if (InternedResult.size() >
          MR->getSymbols().size() - NumMaterializationSideEffectsOnlySymbols) {
        for (auto &KV : InternedResult)
          if (!MR->getSymbols().count(KV.first))
            ExtraSymbols.push_back(KV.first);
      }

      // If there were extra definitions then report the error.
      if (!ExtraSymbols.empty())
        return make_error<UnexpectedSymbolDefinitions>(
            Layer.getExecutionSession().getSymbolStringPool(), G.getName(),
            std::move(ExtraSymbols));
    }

    if (auto Err = MR->notifyResolved(InternedResult))
      return Err;

    return Error::success();
  }

  void notifyFinalized(JITLinkMemoryManager::FinalizedAlloc A) override {
    if (auto Err = notifyEmitted(std::move(A))) {
      Layer.getExecutionSession().reportError(std::move(Err));
      MR->failMaterialization();
      return;
    }

    if (auto Err = MR->notifyEmitted(SymbolDepGroups)) {
      Layer.getExecutionSession().reportError(std::move(Err));
      MR->failMaterialization();
    }
  }

  LinkGraphPassFunction getMarkLivePass(const Triple &TT) const override {
    return [this](LinkGraph &G) { return markResponsibilitySymbolsLive(G); };
  }

  Error modifyPassConfig(LinkGraph &LG, 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 claimOrExternalizeWeakAndCommonSymbols(G);
    });

    for (auto &P : Plugins)
      P->modifyPassConfig(*MR, LG, Config);

    Config.PreFixupPasses.push_back(
        [this](LinkGraph &G) { return registerDependencies(G); });

    return Error::success();
  }

  Error notifyEmitted(jitlink::JITLinkMemoryManager::FinalizedAlloc FA) {
    Error Err = Error::success();
    for (auto &P : Plugins)
      Err = joinErrors(std::move(Err), P->notifyEmitted(*MR));

    if (Err) {
      if (FA)
        Err =
            joinErrors(std::move(Err), Layer.MemMgr.deallocate(std::move(FA)));
      return Err;
    }

    if (FA)
      return Layer.recordFinalizedAlloc(*MR, std::move(FA));

    return Error::success();
  }

private:
  Error claimOrExternalizeWeakAndCommonSymbols(LinkGraph &G) {
    SymbolFlagsMap NewSymbolsToClaim;
    std::vector<std::pair<SymbolStringPtr, Symbol *>> NameToSym;

    auto ProcessSymbol = [&](Symbol *Sym) {
      if (Sym->hasName() && Sym->getLinkage() == Linkage::Weak &&
          Sym->getScope() != Scope::Local) {
        if (!MR->getSymbols().count(Sym->getName())) {
          NewSymbolsToClaim[Sym->getName()] =
              getJITSymbolFlagsForSymbol(*Sym) | JITSymbolFlags::Weak;
          NameToSym.push_back(std::make_pair(Sym->getName(), Sym));
        }
      }
    };

    for (auto *Sym : G.defined_symbols())
      ProcessSymbol(Sym);
    for (auto *Sym : G.absolute_symbols())
      ProcessSymbol(Sym);

    // Attempt to claim all weak defs that we're not already responsible for.
    // This may fail if the resource tracker has become defunct, but should
    // always succeed otherwise.
    if (auto Err = MR->defineMaterializing(std::move(NewSymbolsToClaim)))
      return Err;

    // Walk the list of symbols that we just tried to claim. Symbols that we're
    // responsible for are marked live. Symbols that we're not responsible for
    // are turned into external references.
    for (auto &KV : NameToSym) {
      if (MR->getSymbols().count(KV.first))
        KV.second->setLive(true);
      else
        G.makeExternal(*KV.second);
    }

    return Error::success();
  }

  Error markResponsibilitySymbolsLive(LinkGraph &G) const {
    for (auto *Sym : G.defined_symbols())
      if (Sym->hasName() && MR->getSymbols().count(Sym->getName()))
        Sym->setLive(true);
    return Error::success();
  }

  Error registerDependencies(LinkGraph &G) {
    auto &TargetJD = MR->getTargetJITDylib();
    for (auto &[Defs, Deps] : calculateDepGroups(G)) {
      SymbolDepGroups.push_back(SymbolDependenceGroup());
      auto &SDG = SymbolDepGroups.back();
      for (auto *Def : Defs)
        SDG.Symbols.insert(Def->getName());
      for (auto *Dep : Deps) {
        if (Dep->isDefined())
          SDG.Dependencies[&TargetJD].insert(Dep->getName());
        else {
          auto I =
              SymbolSourceJDs.find(NonOwningSymbolStringPtr(Dep->getName()));
          if (I != SymbolSourceJDs.end()) {
            auto &SymJD = *I->second;
            SDG.Dependencies[&SymJD].insert(Dep->getName());
          }
        }
      }
    }
    return Error::success();
  }

  LinkGraphLinkingLayer &Layer;
  std::vector<std::shared_ptr<LinkGraphLinkingLayer::Plugin>> Plugins;
  std::unique_ptr<MaterializationResponsibility> MR;
  std::unique_ptr<MemoryBuffer> ObjBuffer;
  DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
  std::vector<SymbolDependenceGroup> SymbolDepGroups;
};

LinkGraphLinkingLayer::Plugin::~Plugin() = default;

LinkGraphLinkingLayer::LinkGraphLinkingLayer(ExecutionSession &ES,
                                             JITLinkMemoryManager &MemMgr)
    : LinkGraphLayer(ES), MemMgr(MemMgr) {
  ES.registerResourceManager(*this);
}

LinkGraphLinkingLayer::LinkGraphLinkingLayer(
    ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
    : LinkGraphLayer(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
  ES.registerResourceManager(*this);
}

LinkGraphLinkingLayer::~LinkGraphLinkingLayer() {
  assert(Allocs.empty() &&
         "Layer destroyed with resources still attached "
         "(ExecutionSession::endSession() must be called prior to "
         "destruction)");
  getExecutionSession().deregisterResourceManager(*this);
}

void LinkGraphLinkingLayer::emit(
    std::unique_ptr<MaterializationResponsibility> R,
    std::unique_ptr<LinkGraph> G) {
  assert(R && "R must not be null");
  assert(G && "G must not be null");
  auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), nullptr);
  Ctx->notifyMaterializing(*G);
  link(std::move(G), std::move(Ctx));
}

void LinkGraphLinkingLayer::emit(
    std::unique_ptr<MaterializationResponsibility> R,
    std::unique_ptr<LinkGraph> G, std::unique_ptr<MemoryBuffer> ObjBuf) {
  assert(R && "R must not be null");
  assert(G && "G must not be null");
  assert(ObjBuf && "Object must not be null");
  auto Ctx =
      std::make_unique<JITLinkCtx>(*this, std::move(R), std::move(ObjBuf));
  Ctx->notifyMaterializing(*G);
  link(std::move(G), std::move(Ctx));
}

SmallVector<LinkGraphLinkingLayer::SymbolDepGroup>
LinkGraphLinkingLayer::calculateDepGroups(LinkGraph &G) {

  // Step 1.
  // Build initial map entries and symbol def lists.
  BlockDepInfoMap BlockDepInfos;
  for (auto *Sym : G.defined_symbols())
    if (Sym->getScope() != Scope::Local)
      BlockDepInfos[&Sym->getBlock()].SymbolDefs.push_back(Sym);

  // Step 2.
  // Complete the BlockDepInfos "graph" by adding symbol and block dependencies
  // for each block.
  {
    SmallVector<Block *> Worklist;
    Worklist.reserve(BlockDepInfos.size());

    // Build worklist, link each BlockDepInfo "node" back to the BlockInfos map
    // "graph" for our GraphTraits specialization above. This will allow us to
    // walk the SCCs of the anonymous-block-dependence graph.
    for (auto &[B, BDInfo] : BlockDepInfos) {
      BDInfo.Graph = &BlockDepInfos;
      Worklist.push_back(B);
    }

    // Calculate the relevant symbol and block dependencies for each block:
    // 1. Absolute symbols are ignored.
    // 2. External symbols are included in a block's symbol dep set.
    // 3. Blocks that do not define any symbols are included in the anonymous
    //    block dependence sets.
    // 4. For blocks that do define symbols we add only the first defined
    //    symbol to the symbol dep set (since all symbols for the block will
    //    have the same dependencies).
    while (!Worklist.empty()) {
      auto *B = Worklist.pop_back_val();
      BlockDepInfo *BDInfo = nullptr; // Populated lazily.

      for (auto &E : B->edges()) {
        if (E.getTarget().isAbsolute()) // skip: absolutes are assumed ready
          continue;

        if (!BDInfo) // Populate -- we'll need it below.
          BDInfo = &BlockDepInfos[B];

        if (E.getTarget().isExternal()) { // include and continue
          BDInfo->SymbolDeps.insert(&E.getTarget());
          continue;
        }

        // Target must be defined.
        auto *TgtB = &E.getTarget().getBlock();
        auto I = BlockDepInfos.find(TgtB);

        if (I != BlockDepInfos.end()) {
          // TgtB is in BlockInfos. Record a symbol dependence (if it defines
          // any symbols) or anonymous block dependence.
          auto &TgtBInfo = I->second;
          if (!TgtBInfo.SymbolDefs.empty())
            BDInfo->SymbolDeps.insert(TgtBInfo.SymbolDefs.front());
          else
            BDInfo->AnonBlockDeps.insert(TgtB);
        } else {
          // TgtB not in BlockInfos. It must be anonymous. We need to:
          // 1. Record the dependence.
          // 2. Add BlockInfos and Worklist entries for TgtB.
          // 3. Reset BInfo, since step (2) may have invalidated the pointer.
          BDInfo->AnonBlockDeps.insert(TgtB);
          Worklist.push_back(TgtB);
          BlockDepInfos[TgtB].Graph = &BlockDepInfos;
          BDInfo = nullptr;
          continue;
        }
      }
    }
  }

  // Step 3.
  // Convert block deps to SCC deps.
  SmallVector<SymbolDepGroup> DGs;
  for (auto &[B, BDInfo] : BlockDepInfos) {
    for (auto &SCC : make_range(scc_begin(&BDInfo), scc_end(&BDInfo))) {

      auto &SCCRootInfo = *SCC.front();

      // Continue if already visited. The loop over the SCC elements below
      // deletes the SCCs below as it goes, so this early continue just saves
      // us looking at a bunch of empty sets below that.
      if (SCCRootInfo.SCCRoot)
        continue;
      SCCRootInfo.SCCRoot = &SCCRootInfo;

      // Collect all symbol defs, deps, and anonymous block deps, and remove
      // the links to already visited SCCs.
      auto SCCSymbolDefs = std::move(SCCRootInfo.SymbolDefs);
      auto SCCSymbolDeps = std::move(SCCRootInfo.SymbolDeps);
      auto SCCAnonBlockDeps = std::move(SCCRootInfo.AnonBlockDeps);
      for (auto *SCCBInfo : make_range(std::next(SCC.begin()), SCC.end())) {
        SCCBInfo->SCCRoot = &SCCRootInfo;
        SCCSymbolDefs.append(SCCBInfo->SymbolDefs);
        SCCBInfo->SymbolDefs.clear();
        SCCSymbolDeps.insert(SCCBInfo->SymbolDeps.begin(),
                             SCCBInfo->SymbolDeps.end());
        SCCBInfo->SymbolDeps.clear();
        SCCAnonBlockDeps.insert(SCCBInfo->AnonBlockDeps.begin(),
                                SCCBInfo->AnonBlockDeps.end());
        SCCBInfo->AnonBlockDeps.clear();
      }

      // Identify DepGroups emitted for previously visited SCCs that this
      // SCC depends on.
      DenseSet<size_t> SrcDepGroups;
      for (auto *DepB : SCCAnonBlockDeps) {
        assert(BlockDepInfos.count(DepB) && "Unrecognized block");
        auto &DepBRootInfo = *BlockDepInfos[DepB].SCCRoot;
        if (DepBRootInfo.DepGroupIndex)
          SrcDepGroups.insert(*DepBRootInfo.DepGroupIndex);
      }

      // If this SCC doesn't depend on any existing dep groups then check
      // whether it has direct symbol deps of its own.
      if (SrcDepGroups.empty()) {

        // If this SCC has its own symbol deps then add a dep-group and
        // continue.
        if (!SCCSymbolDeps.empty()) {
          SCCRootInfo.DepGroupIndex = DGs.size();
          DGs.push_back({});
          DGs.back().Defs = std::move(SCCSymbolDefs);
          DGs.back().Deps = std::move(SCCSymbolDeps);
        }
        // Otherwise just continue.
        continue;
      }

      // Special case: If we only depend on one dep group and this SCC
      // doesn't have any symbol deps of its own then just merge this SCC's
      // defs into the existing dep group and continue.
      if (SrcDepGroups.size() == 1 && SCCSymbolDeps.empty()) {
        SCCRootInfo.DepGroupIndex = *SrcDepGroups.begin();
        DGs[*SCCRootInfo.DepGroupIndex].Defs.append(SCCSymbolDefs);
        continue;
      }

      // General case: This SCC depends on multiple dep groups, and/or has
      // its own symbol deps. Build a new dep group for it.
      SCCRootInfo.DepGroupIndex = DGs.size();
      DGs.push_back({});
      auto &DG = DGs.back();
      DG.Defs = std::move(SCCSymbolDefs);
      for (auto &DGIndex : SrcDepGroups)
        DG.Deps.insert(DGs[DGIndex].Deps.begin(), DGs[DGIndex].Deps.end());
      DG.Deps.insert(SCCSymbolDeps.begin(), SCCSymbolDeps.end());
    }
  }

  // Remove self-reference from each dep group, and filter out any dep groups
  // whose resulting deps or defs are empty.
  for (size_t I = 0; I != DGs.size();) {
    auto &DG = DGs[I];

    // Remove self-deps.
    for (auto &Def : DG.Defs)
      DG.Deps.erase(Def);

    // Remove groups with empty defs or deps.
    if (DG.Defs.empty() || DG.Deps.empty()) {
      std::swap(DG, DGs.back());
      DGs.pop_back();
    } else
      ++I;
  }

  return DGs;
}

Error LinkGraphLinkingLayer::recordFinalizedAlloc(
    MaterializationResponsibility &MR, FinalizedAlloc FA) {
  auto Err = MR.withResourceKeyDo(
      [&](ResourceKey K) { Allocs[K].push_back(std::move(FA)); });

  if (Err)
    Err = joinErrors(std::move(Err), MemMgr.deallocate(std::move(FA)));

  return Err;
}

Error LinkGraphLinkingLayer::handleRemoveResources(JITDylib &JD,
                                                   ResourceKey K) {

  {
    Error Err = Error::success();
    for (auto &P : Plugins)
      Err = joinErrors(std::move(Err), P->notifyRemovingResources(JD, K));
    if (Err)
      return Err;
  }

  std::vector<FinalizedAlloc> AllocsToRemove;
  getExecutionSession().runSessionLocked([&] {
    auto I = Allocs.find(K);
    if (I != Allocs.end()) {
      std::swap(AllocsToRemove, I->second);
      Allocs.erase(I);
    }
  });

  if (AllocsToRemove.empty())
    return Error::success();

  return MemMgr.deallocate(std::move(AllocsToRemove));
}

void LinkGraphLinkingLayer::handleTransferResources(JITDylib &JD,
                                                    ResourceKey DstKey,
                                                    ResourceKey SrcKey) {
  if (Allocs.contains(SrcKey)) {
    // DstKey may not be in the DenseMap yet, so the following line may resize
    // the container and invalidate iterators and value references.
    auto &DstAllocs = Allocs[DstKey];
    auto &SrcAllocs = Allocs[SrcKey];
    DstAllocs.reserve(DstAllocs.size() + SrcAllocs.size());
    for (auto &Alloc : SrcAllocs)
      DstAllocs.push_back(std::move(Alloc));

    Allocs.erase(SrcKey);
  }

  for (auto &P : Plugins)
    P->notifyTransferringResources(JD, DstKey, SrcKey);
}

} // End namespace orc.
} // End namespace llvm.
