[llvm] b3d2548 - [ORC] Introduce LinkGraphLayer interface and LinkGraphLinkingLayer. (#120182)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 16 22:19:02 PST 2024


Author: Lang Hames
Date: 2024-12-17T17:18:58+11:00
New Revision: b3d2548d5b04ed3b7aaedfd22e62da40875c0f31

URL: https://github.com/llvm/llvm-project/commit/b3d2548d5b04ed3b7aaedfd22e62da40875c0f31
DIFF: https://github.com/llvm/llvm-project/commit/b3d2548d5b04ed3b7aaedfd22e62da40875c0f31.diff

LOG: [ORC] Introduce LinkGraphLayer interface and LinkGraphLinkingLayer. (#120182)

Introduces a new layer interface, LinkGraphLayer, that can be used to
add LinkGraphs to an ExecutionSession.

This patch moves most of ObjectLinkingLayer's functionality into a new
LinkGraphLinkingLayer which should (in the future) be able to be used
without linking libObject. ObjectLinkingLayer now inherits from
LinkGraphLinkingLayer and just handles conversion of object files to
LinkGraphs, which are then handed down to LinkGraphLinkingLayer to be
linked.

Added: 
    llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLayer.h
    llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
    llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
    llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp

Modified: 
    llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
    llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
    llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
    llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
index f44b6b3860fc31..cebab0f2b30a3f 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/COFFPlatform.h
@@ -22,6 +22,7 @@
 #include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
 
 #include <future>
+#include <list>
 #include <memory>
 #include <thread>
 #include <vector>

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLayer.h
new file mode 100644
index 00000000000000..771a118efae2d1
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLayer.h
@@ -0,0 +1,110 @@
+//===- LinkGraphLayer.h - Add LinkGraphs to an ExecutionSession -*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// LinkGraphLayer and associated utilities.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLAYER_H
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#include <atomic>
+#include <memory>
+
+namespace llvm::orc {
+
+class LinkGraphLayer {
+public:
+  LinkGraphLayer(ExecutionSession &ES) : ES(ES) {}
+
+  virtual ~LinkGraphLayer();
+
+  ExecutionSession &getExecutionSession() { return ES; }
+
+  /// Adds a LinkGraph to the JITDylib for the given ResourceTracker.
+  virtual Error add(ResourceTrackerSP RT, std::unique_ptr<jitlink::LinkGraph> G,
+                    MaterializationUnit::Interface I);
+
+  /// Adds a LinkGraph to the JITDylib for the given ResourceTracker. The
+  /// interface for the graph will be built using getLinkGraphInterface.
+  Error add(ResourceTrackerSP RT, std::unique_ptr<jitlink::LinkGraph> G) {
+    auto LGI = getInterface(*G);
+    return add(std::move(RT), std::move(G), std::move(LGI));
+  }
+
+  /// Adds a LinkGraph to the given JITDylib.
+  Error add(JITDylib &JD, std::unique_ptr<jitlink::LinkGraph> G,
+            MaterializationUnit::Interface I) {
+    return add(JD.getDefaultResourceTracker(), std::move(G), std::move(I));
+  }
+
+  /// Adds a LinkGraph to the given JITDylib. The interface for the object will
+  /// be built using getLinkGraphInterface.
+  Error add(JITDylib &JD, std::unique_ptr<jitlink::LinkGraph> G) {
+    return add(JD.getDefaultResourceTracker(), std::move(G));
+  }
+
+  /// Emit should materialize the given IR.
+  virtual void emit(std::unique_ptr<MaterializationResponsibility> R,
+                    std::unique_ptr<jitlink::LinkGraph> G) = 0;
+
+  /// Get the interface for the given LinkGraph.
+  MaterializationUnit::Interface getInterface(jitlink::LinkGraph &G);
+
+  /// Get the JITSymbolFlags for the given symbol.
+  static JITSymbolFlags getJITSymbolFlagsForSymbol(jitlink::Symbol &Sym);
+
+private:
+  ExecutionSession &ES;
+  std::atomic<uint64_t> Counter{0};
+};
+
+/// MaterializationUnit for wrapping LinkGraphs.
+class LinkGraphMaterializationUnit : public MaterializationUnit {
+public:
+  LinkGraphMaterializationUnit(LinkGraphLayer &LGLayer,
+                               std::unique_ptr<jitlink::LinkGraph> G,
+                               Interface I)
+      : MaterializationUnit(I), LGLayer(LGLayer), G(std::move(G)) {}
+
+  LinkGraphMaterializationUnit(LinkGraphLayer &LGLayer,
+                               std::unique_ptr<jitlink::LinkGraph> G)
+      : MaterializationUnit(LGLayer.getInterface(*G)), LGLayer(LGLayer),
+        G(std::move(G)) {}
+
+  StringRef getName() const override;
+
+  void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
+    LGLayer.emit(std::move(MR), std::move(G));
+  }
+
+private:
+  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override;
+
+  LinkGraphLayer &LGLayer;
+  std::unique_ptr<jitlink::LinkGraph> G;
+};
+
+inline Error LinkGraphLayer::add(ResourceTrackerSP RT,
+                                 std::unique_ptr<jitlink::LinkGraph> G,
+                                 MaterializationUnit::Interface I) {
+  auto &JD = RT->getJITDylib();
+
+  return JD.define(std::make_unique<LinkGraphMaterializationUnit>(
+                       *this, std::move(G), std::move(I)),
+                   std::move(RT));
+}
+
+} // end namespace llvm::orc
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLAYER_H

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
new file mode 100644
index 00000000000000..3375bd9e4e2e89
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h
@@ -0,0 +1,201 @@
+//===-- LinkGraphLinkingLayer.h - Link LinkGraphs with JITLink --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// LinkGraphLinkingLayer and associated utilities.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLINKINGLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLINKINGLAYER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/LinkGraphLayer.h"
+#include "llvm/Support/Error.h"
+#include <algorithm>
+#include <cassert>
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <utility>
+#include <vector>
+
+namespace llvm {
+
+namespace jitlink {
+class EHFrameRegistrar;
+} // namespace jitlink
+
+namespace orc {
+
+/// LinkGraphLinkingLayer links LinkGraphs into the Executor using JITLink.
+///
+/// Clients can use this class to add LinkGraphs to an ExecutionSession, and it
+/// serves as a base for the ObjectLinkingLayer that can link object files.
+class LinkGraphLinkingLayer : public LinkGraphLayer, private ResourceManager {
+  class JITLinkCtx;
+
+public:
+  /// Plugin instances can be added to the ObjectLinkingLayer to receive
+  /// callbacks when code is loaded or emitted, and when JITLink is being
+  /// configured.
+  class Plugin {
+  public:
+    virtual ~Plugin();
+    virtual void modifyPassConfig(MaterializationResponsibility &MR,
+                                  jitlink::LinkGraph &G,
+                                  jitlink::PassConfiguration &Config) {}
+
+    // Deprecated. Don't use this in new code. There will be a proper mechanism
+    // for capturing object buffers.
+    virtual void notifyMaterializing(MaterializationResponsibility &MR,
+                                     jitlink::LinkGraph &G,
+                                     jitlink::JITLinkContext &Ctx,
+                                     MemoryBufferRef InputObject) {}
+
+    virtual void notifyLoaded(MaterializationResponsibility &MR) {}
+    virtual Error notifyEmitted(MaterializationResponsibility &MR) {
+      return Error::success();
+    }
+    virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
+    virtual Error notifyRemovingResources(JITDylib &JD, ResourceKey K) = 0;
+    virtual void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+                                             ResourceKey SrcKey) = 0;
+  };
+
+  /// Construct a LinkGraphLinkingLayer using the ExecutorProcessControl
+  /// instance's memory manager.
+  LinkGraphLinkingLayer(ExecutionSession &ES);
+
+  /// Construct a LinkGraphLinkingLayer using a custom memory manager.
+  LinkGraphLinkingLayer(ExecutionSession &ES,
+                        jitlink::JITLinkMemoryManager &MemMgr);
+
+  /// Construct an LinkGraphLinkingLayer. Takes ownership of the given
+  /// JITLinkMemoryManager. This method is a temporary hack to simplify
+  /// co-existence with RTDyldObjectLinkingLayer (which also owns its
+  /// allocators).
+  LinkGraphLinkingLayer(ExecutionSession &ES,
+                        std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
+
+  /// Destroy the LinkGraphLinkingLayer.
+  ~LinkGraphLinkingLayer();
+
+  /// Add a plugin.
+  LinkGraphLinkingLayer &addPlugin(std::shared_ptr<Plugin> P) {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    Plugins.push_back(std::move(P));
+    return *this;
+  }
+
+  /// Remove a plugin. This remove applies only to subsequent links (links
+  /// already underway will continue to use the plugin), and does not of itself
+  /// destroy the plugin -- destruction will happen once all shared pointers
+  /// (including those held by in-progress links) are destroyed.
+  void removePlugin(Plugin &P) {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    auto I = llvm::find_if(Plugins, [&](const std::shared_ptr<Plugin> &Elem) {
+      return Elem.get() == &P;
+    });
+    assert(I != Plugins.end() && "Plugin not present");
+    Plugins.erase(I);
+  }
+
+  /// Emit a LinkGraph.
+  void emit(std::unique_ptr<MaterializationResponsibility> R,
+            std::unique_ptr<jitlink::LinkGraph> G) override;
+
+  /// Instructs this LinkgraphLinkingLayer instance to override the symbol flags
+  /// found in the LinkGraph with the flags supplied by the
+  /// MaterializationResponsibility instance. This is a workaround to support
+  /// symbol visibility in COFF, which does not use the libObject's
+  /// SF_Exported flag. Use only when generating / adding COFF object files.
+  ///
+  /// FIXME: We should be able to remove this if/when COFF properly tracks
+  /// exported symbols.
+  LinkGraphLinkingLayer &
+  setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
+    this->OverrideObjectFlags = OverrideObjectFlags;
+    return *this;
+  }
+
+  /// If set, this LinkGraphLinkingLayer instance will claim responsibility
+  /// for any symbols provided by a given object file that were not already in
+  /// the MaterializationResponsibility instance. Setting this flag allows
+  /// higher-level program representations (e.g. LLVM IR) to be added based on
+  /// only a subset of the symbols they provide, without having to write
+  /// intervening layers to scan and add the additional symbols. This trades
+  /// diagnostic quality for convenience however: If all symbols are enumerated
+  /// up-front then clashes can be detected and reported early (and usually
+  /// deterministically). If this option is set, clashes for the additional
+  /// symbols may not be detected until late, and detection may depend on
+  /// the flow of control through JIT'd code. Use with care.
+  LinkGraphLinkingLayer &
+  setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
+    this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
+    return *this;
+  }
+
+protected:
+  /// Emit a LinkGraph with the given backing buffer.
+  ///
+  /// This overload is intended for use by ObjectLinkingLayer.
+  void emit(std::unique_ptr<MaterializationResponsibility> R,
+            std::unique_ptr<jitlink::LinkGraph> G,
+            std::unique_ptr<MemoryBuffer> ObjBuf);
+
+  std::function<void(std::unique_ptr<MemoryBuffer>)> ReturnObjectBuffer;
+
+private:
+  using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc;
+
+  Error recordFinalizedAlloc(MaterializationResponsibility &MR,
+                             FinalizedAlloc FA);
+
+  Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
+  void handleTransferResources(JITDylib &JD, ResourceKey DstKey,
+                               ResourceKey SrcKey) override;
+
+  mutable std::mutex LayerMutex;
+  jitlink::JITLinkMemoryManager &MemMgr;
+  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership;
+  bool OverrideObjectFlags = false;
+  bool AutoClaimObjectSymbols = false;
+  DenseMap<ResourceKey, std::vector<FinalizedAlloc>> Allocs;
+  std::vector<std::shared_ptr<Plugin>> Plugins;
+};
+
+class EHFrameRegistrationPlugin : public LinkGraphLinkingLayer::Plugin {
+public:
+  EHFrameRegistrationPlugin(
+      ExecutionSession &ES,
+      std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
+  void modifyPassConfig(MaterializationResponsibility &MR,
+                        jitlink::LinkGraph &G,
+                        jitlink::PassConfiguration &PassConfig) override;
+  Error notifyEmitted(MaterializationResponsibility &MR) override;
+  Error notifyFailed(MaterializationResponsibility &MR) override;
+  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override;
+  void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
+                                   ResourceKey SrcKey) override;
+
+private:
+  std::mutex EHFramePluginMutex;
+  ExecutionSession &ES;
+  std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
+  DenseMap<MaterializationResponsibility *, ExecutorAddrRange> InProcessLinks;
+  DenseMap<ResourceKey, std::vector<ExecutorAddrRange>> EHFrameRanges;
+};
+
+} // end namespace orc
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LINKGRAPHLINKINGLAYER_H

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index 340298f8c52856..b392c5bf671481 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -16,18 +16,12 @@
 
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/JITLink/JITLink.h"
-#include "llvm/ExecutionEngine/JITSymbol.h"
 #include "llvm/ExecutionEngine/Orc/Core.h"
 #include "llvm/ExecutionEngine/Orc/Layer.h"
+#include "llvm/ExecutionEngine/Orc/LinkGraphLinkingLayer.h"
 #include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cassert>
-#include <functional>
-#include <list>
+
 #include <memory>
-#include <utility>
-#include <vector>
 
 namespace llvm {
 
@@ -44,60 +38,36 @@ namespace orc {
 /// Clients can use this class to add relocatable object files to an
 /// ExecutionSession, and it typically serves as the base layer (underneath
 /// a compiling layer like IRCompileLayer) for the rest of the JIT.
-class ObjectLinkingLayer : public RTTIExtends<ObjectLinkingLayer, ObjectLayer>,
-                           private ResourceManager {
-  class JITLinkCtx;
+class ObjectLinkingLayer : public LinkGraphLinkingLayer,
+                           public RTTIExtends<ObjectLinkingLayer, ObjectLayer> {
+private:
+  using BaseObjectLayer = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
 
 public:
   static char ID;
 
-  /// Plugin instances can be added to the ObjectLinkingLayer to receive
-  /// callbacks when code is loaded or emitted, and when JITLink is being
-  /// configured.
-  class Plugin {
-  public:
-    virtual ~Plugin();
-    virtual void modifyPassConfig(MaterializationResponsibility &MR,
-                                  jitlink::LinkGraph &G,
-                                  jitlink::PassConfiguration &Config) {}
-
-    // Deprecated. Don't use this in new code. There will be a proper mechanism
-    // for capturing object buffers.
-    virtual void notifyMaterializing(MaterializationResponsibility &MR,
-                                     jitlink::LinkGraph &G,
-                                     jitlink::JITLinkContext &Ctx,
-                                     MemoryBufferRef InputObject) {}
-
-    virtual void notifyLoaded(MaterializationResponsibility &MR) {}
-    virtual Error notifyEmitted(MaterializationResponsibility &MR) {
-      return Error::success();
-    }
-    virtual Error notifyFailed(MaterializationResponsibility &MR) = 0;
-    virtual Error notifyRemovingResources(JITDylib &JD, ResourceKey K) = 0;
-    virtual void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
-                                             ResourceKey SrcKey) = 0;
-  };
-
   using ReturnObjectBufferFunction =
       std::function<void(std::unique_ptr<MemoryBuffer>)>;
 
   /// Construct an ObjectLinkingLayer using the ExecutorProcessControl
   /// instance's memory manager.
-  ObjectLinkingLayer(ExecutionSession &ES);
+  ObjectLinkingLayer(ExecutionSession &ES)
+      : LinkGraphLinkingLayer(ES), BaseObjectLayer(ES) {}
 
   /// Construct an ObjectLinkingLayer using a custom memory manager.
   ObjectLinkingLayer(ExecutionSession &ES,
-                     jitlink::JITLinkMemoryManager &MemMgr);
+                     jitlink::JITLinkMemoryManager &MemMgr)
+      : LinkGraphLinkingLayer(ES, MemMgr), BaseObjectLayer(ES) {}
 
   /// Construct an ObjectLinkingLayer. Takes ownership of the given
   /// JITLinkMemoryManager. This method is a temporary hack to simplify
   /// co-existence with RTDyldObjectLinkingLayer (which also owns its
   /// allocators).
   ObjectLinkingLayer(ExecutionSession &ES,
-                     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr);
+                     std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgr)
+      : LinkGraphLinkingLayer(ES, std::move(MemMgr)), BaseObjectLayer(ES) {}
 
-  /// Destruct an ObjectLinkingLayer.
-  ~ObjectLinkingLayer();
+  using LinkGraphLinkingLayer::getExecutionSession;
 
   /// Set an object buffer return function. By default object buffers are
   /// deleted once the JIT has linked them. If a return function is set then
@@ -106,116 +76,14 @@ class ObjectLinkingLayer : public RTTIExtends<ObjectLinkingLayer, ObjectLayer>,
     this->ReturnObjectBuffer = std::move(ReturnObjectBuffer);
   }
 
-  /// Add a plugin.
-  ObjectLinkingLayer &addPlugin(std::shared_ptr<Plugin> P) {
-    std::lock_guard<std::mutex> Lock(LayerMutex);
-    Plugins.push_back(std::move(P));
-    return *this;
-  }
-
-  /// Remove a plugin. This remove applies only to subsequent links (links
-  /// already underway will continue to use the plugin), and does not of itself
-  /// destroy the plugin -- destruction will happen once all shared pointers
-  /// (including those held by in-progress links) are destroyed.
-  void removePlugin(Plugin &P) {
-    std::lock_guard<std::mutex> Lock(LayerMutex);
-    auto I = llvm::find_if(Plugins, [&](const std::shared_ptr<Plugin> &Elem) {
-      return Elem.get() == &P;
-    });
-    assert(I != Plugins.end() && "Plugin not present");
-    Plugins.erase(I);
-  }
+  using LinkGraphLinkingLayer::add;
+  using LinkGraphLinkingLayer::emit;
 
-  /// Add a LinkGraph to the JITDylib targeted by the given tracker.
-  Error add(ResourceTrackerSP, std::unique_ptr<jitlink::LinkGraph> G);
-
-  /// Add a LinkGraph to the given JITDylib.
-  Error add(JITDylib &JD, std::unique_ptr<jitlink::LinkGraph> G) {
-    return add(JD.getDefaultResourceTracker(), std::move(G));
-  }
-
-  // Un-hide ObjectLayer add methods.
   using ObjectLayer::add;
 
   /// Emit an object file.
   void emit(std::unique_ptr<MaterializationResponsibility> R,
             std::unique_ptr<MemoryBuffer> O) override;
-
-  /// Emit a LinkGraph.
-  void emit(std::unique_ptr<MaterializationResponsibility> R,
-            std::unique_ptr<jitlink::LinkGraph> G);
-
-  /// Instructs this ObjectLinkingLayer instance to override the symbol flags
-  /// found in the AtomGraph with the flags supplied by the
-  /// MaterializationResponsibility instance. This is a workaround to support
-  /// symbol visibility in COFF, which does not use the libObject's
-  /// SF_Exported flag. Use only when generating / adding COFF object files.
-  ///
-  /// FIXME: We should be able to remove this if/when COFF properly tracks
-  /// exported symbols.
-  ObjectLinkingLayer &
-  setOverrideObjectFlagsWithResponsibilityFlags(bool OverrideObjectFlags) {
-    this->OverrideObjectFlags = OverrideObjectFlags;
-    return *this;
-  }
-
-  /// If set, this ObjectLinkingLayer instance will claim responsibility
-  /// for any symbols provided by a given object file that were not already in
-  /// the MaterializationResponsibility instance. Setting this flag allows
-  /// higher-level program representations (e.g. LLVM IR) to be added based on
-  /// only a subset of the symbols they provide, without having to write
-  /// intervening layers to scan and add the additional symbols. This trades
-  /// diagnostic quality for convenience however: If all symbols are enumerated
-  /// up-front then clashes can be detected and reported early (and usually
-  /// deterministically). If this option is set, clashes for the additional
-  /// symbols may not be detected until late, and detection may depend on
-  /// the flow of control through JIT'd code. Use with care.
-  ObjectLinkingLayer &
-  setAutoClaimResponsibilityForObjectSymbols(bool AutoClaimObjectSymbols) {
-    this->AutoClaimObjectSymbols = AutoClaimObjectSymbols;
-    return *this;
-  }
-
-private:
-  using FinalizedAlloc = jitlink::JITLinkMemoryManager::FinalizedAlloc;
-
-  Error recordFinalizedAlloc(MaterializationResponsibility &MR,
-                             FinalizedAlloc FA);
-
-  Error handleRemoveResources(JITDylib &JD, ResourceKey K) override;
-  void handleTransferResources(JITDylib &JD, ResourceKey DstKey,
-                               ResourceKey SrcKey) override;
-
-  mutable std::mutex LayerMutex;
-  jitlink::JITLinkMemoryManager &MemMgr;
-  std::unique_ptr<jitlink::JITLinkMemoryManager> MemMgrOwnership;
-  bool OverrideObjectFlags = false;
-  bool AutoClaimObjectSymbols = false;
-  ReturnObjectBufferFunction ReturnObjectBuffer;
-  DenseMap<ResourceKey, std::vector<FinalizedAlloc>> Allocs;
-  std::vector<std::shared_ptr<Plugin>> Plugins;
-};
-
-class EHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
-public:
-  EHFrameRegistrationPlugin(
-      ExecutionSession &ES,
-      std::unique_ptr<jitlink::EHFrameRegistrar> Registrar);
-  void modifyPassConfig(MaterializationResponsibility &MR,
-                        jitlink::LinkGraph &G,
-                        jitlink::PassConfiguration &PassConfig) override;
-  Error notifyEmitted(MaterializationResponsibility &MR) override;
-  Error notifyFailed(MaterializationResponsibility &MR) override;
-  Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override;
-  void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,
-                                   ResourceKey SrcKey) override;
-
-private:
-  std::mutex EHFramePluginMutex;
-  ExecutionSession &ES;
-  std::unique_ptr<jitlink::EHFrameRegistrar> Registrar;
-  DenseMap<MaterializationResponsibility *, ExecutorAddrRange> InProcessLinks;
-  DenseMap<ResourceKey, std::vector<ExecutorAddrRange>> EHFrameRanges;
 };
 
 } // end namespace orc

diff  --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 5615ad94006d3b..93d253ee49aa6c 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -33,6 +33,8 @@ add_llvm_component_library(LLVMOrcJIT
   LazyObjectLinkingLayer.cpp
   LazyReexports.cpp
   Layer.cpp
+  LinkGraphLayer.cpp
+  LinkGraphLinkingLayer.cpp
   LoadLinkableFile.cpp
   LookupAndRecordAddrs.cpp
   LLJIT.cpp

diff  --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
new file mode 100644
index 00000000000000..5789079c2bf6ca
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLayer.cpp
@@ -0,0 +1,105 @@
+//===----- LinkGraphLayer.cpp - Add LinkGraphs to an ExecutionSession -----===//
+//
+// 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/LinkGraphLayer.h"
+
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/Orc/Shared/MachOObjectFormat.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::orc;
+
+namespace {
+
+bool hasInitializerSection(LinkGraph &G) {
+  bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
+  bool IsElf = G.getTargetTriple().isOSBinFormatELF();
+  if (!IsMachO && !IsElf)
+    return false;
+
+  for (auto &Sec : G.sections()) {
+    if (IsMachO && isMachOInitializerSection(Sec.getName()))
+      return true;
+    if (IsElf && isELFInitializerSection(Sec.getName()))
+      return true;
+  }
+
+  return false;
+}
+
+} // end anonymous namespace
+
+namespace llvm::orc {
+
+LinkGraphLayer::~LinkGraphLayer() = default;
+
+MaterializationUnit::Interface LinkGraphLayer::getInterface(LinkGraph &G) {
+
+  MaterializationUnit::Interface LGI;
+
+  auto AddSymbol = [&](Symbol *Sym) {
+    // Skip local symbols.
+    if (Sym->getScope() == Scope::Local)
+      return;
+    assert(Sym->hasName() && "Anonymous non-local symbol?");
+
+    LGI.SymbolFlags[Sym->getName()] = getJITSymbolFlagsForSymbol(*Sym);
+  };
+
+  for (auto *Sym : G.defined_symbols())
+    AddSymbol(Sym);
+  for (auto *Sym : G.absolute_symbols())
+    AddSymbol(Sym);
+
+  if (hasInitializerSection(G)) {
+    std::string InitSymString;
+    {
+      raw_string_ostream(InitSymString)
+          << "$." << G.getName() << ".__inits" << Counter++;
+    }
+    LGI.InitSymbol = ES.intern(InitSymString);
+  }
+
+  return LGI;
+}
+
+JITSymbolFlags LinkGraphLayer::getJITSymbolFlagsForSymbol(Symbol &Sym) {
+  JITSymbolFlags Flags;
+
+  if (Sym.getLinkage() == Linkage::Weak)
+    Flags |= JITSymbolFlags::Weak;
+
+  if (Sym.getScope() == Scope::Default)
+    Flags |= JITSymbolFlags::Exported;
+  else if (Sym.getScope() == Scope::SideEffectsOnly)
+    Flags |= JITSymbolFlags::MaterializationSideEffectsOnly;
+
+  if (Sym.isCallable())
+    Flags |= JITSymbolFlags::Callable;
+
+  return Flags;
+}
+
+StringRef LinkGraphMaterializationUnit::getName() const { return G->getName(); }
+
+void LinkGraphMaterializationUnit::discard(const JITDylib &JD,
+                                           const SymbolStringPtr &Name) {
+  for (auto *Sym : G->defined_symbols())
+    if (Sym->getName() == Name) {
+      assert(Sym->getLinkage() == Linkage::Weak &&
+             "Discarding non-weak definition");
+      G->makeExternal(*Sym);
+      break;
+    }
+}
+
+} // namespace llvm::orc

diff  --git a/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
new file mode 100644
index 00000000000000..fc5a11b338af16
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/LinkGraphLinkingLayer.cpp
@@ -0,0 +1,681 @@
+//===----- LinkGraphLinkingLayer.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/LinkGraphLinkingLayer.h"
+#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
+#include "llvm/ExecutionEngine/JITLink/aarch32.h"
+#include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
+#include "llvm/Support/MemoryBuffer.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+using namespace llvm::orc;
+
+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() {
+    // 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;
+        for (auto &KV : *Result)
+          LR[KV.first] = KV.second;
+        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;
+
+    notifyLoaded();
+    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();
+  }
+
+  void notifyLoaded() {
+    for (auto &P : Plugins)
+      P->notifyLoaded(*MR);
+  }
+
+  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) {
+
+    struct BlockInfo {
+      bool InWorklist = false;
+      DenseSet<Symbol *> Defs;
+      DenseSet<Symbol *> SymbolDeps;
+      DenseSet<Block *> AnonEdges, AnonBackEdges;
+    };
+
+    DenseMap<Block *, BlockInfo> BlockInfos;
+
+    // Reserve space so that BlockInfos doesn't need to resize. This is
+    // essential to avoid invalidating pointers to entries below.
+    {
+      size_t NumBlocks = 0;
+      for (auto &Sec : G.sections())
+        NumBlocks += Sec.blocks_size();
+      BlockInfos.reserve(NumBlocks);
+    }
+
+    // Identify non-locally-scoped symbols defined by each block.
+    for (auto *Sym : G.defined_symbols()) {
+      if (Sym->getScope() != Scope::Local)
+        BlockInfos[&Sym->getBlock()].Defs.insert(Sym);
+    }
+
+    // Identify the symbolic and anonymous-block dependencies for each block.
+    for (auto *B : G.blocks()) {
+      auto &BI = BlockInfos[B];
+
+      for (auto &E : B->edges()) {
+
+        // External symbols are trivially depended on.
+        if (E.getTarget().isExternal()) {
+          BI.SymbolDeps.insert(&E.getTarget());
+          continue;
+        }
+
+        // Anonymous symbols aren't depended on at all (they're assumed to be
+        // already available).
+        if (E.getTarget().isAbsolute())
+          continue;
+
+        // If we get here then we depend on a symbol defined by some other
+        // block.
+        auto &TgtBI = BlockInfos[&E.getTarget().getBlock()];
+
+        // If that block has any definitions then use the first one as the
+        // "effective" dependence here (all symbols in TgtBI will become
+        // ready at the same time, and chosing a single symbol to represent
+        // the block keeps the SymbolDepGroup size small).
+        if (!TgtBI.Defs.empty()) {
+          BI.SymbolDeps.insert(*TgtBI.Defs.begin());
+          continue;
+        }
+
+        // Otherwise we've got a dependence on an anonymous block. Record it
+        // here for back-propagating symbol dependencies below.
+        BI.AnonEdges.insert(&E.getTarget().getBlock());
+        TgtBI.AnonBackEdges.insert(B);
+      }
+    }
+
+    // Prune anonymous blocks.
+    {
+      std::vector<Block *> BlocksToRemove;
+      for (auto &[B, BI] : BlockInfos) {
+        // Skip blocks with defs. We only care about anonyous blocks.
+        if (!BI.Defs.empty())
+          continue;
+
+        BlocksToRemove.push_back(B);
+
+        for (auto *FB : BI.AnonEdges)
+          BlockInfos[FB].AnonBackEdges.erase(B);
+
+        for (auto *BB : BI.AnonBackEdges)
+          BlockInfos[BB].AnonEdges.erase(B);
+
+        for (auto *FB : BI.AnonEdges) {
+          auto &FBI = BlockInfos[FB];
+          for (auto *BB : BI.AnonBackEdges)
+            FBI.AnonBackEdges.insert(BB);
+        }
+
+        for (auto *BB : BI.AnonBackEdges) {
+          auto &BBI = BlockInfos[BB];
+          for (auto *SD : BI.SymbolDeps)
+            BBI.SymbolDeps.insert(SD);
+          for (auto *FB : BI.AnonEdges)
+            BBI.AnonEdges.insert(FB);
+        }
+      }
+
+      for (auto *B : BlocksToRemove)
+        BlockInfos.erase(B);
+    }
+
+    // Build the initial dependence propagation worklist.
+    std::deque<Block *> Worklist;
+    for (auto &[B, BI] : BlockInfos) {
+      if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) {
+        Worklist.push_back(B);
+        BI.InWorklist = true;
+      }
+    }
+
+    // Propagate symbol deps through the graph.
+    while (!Worklist.empty()) {
+      auto *B = Worklist.front();
+      Worklist.pop_front();
+
+      auto &BI = BlockInfos[B];
+      BI.InWorklist = false;
+
+      for (auto *DB : BI.AnonBackEdges) {
+        auto &DBI = BlockInfos[DB];
+        for (auto *Sym : BI.SymbolDeps) {
+          if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) {
+            Worklist.push_back(DB);
+            DBI.InWorklist = true;
+          }
+        }
+      }
+    }
+
+    // Transform our local dependence information into a list of
+    // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in
+    // the upcoming notifyFinalized call.
+    auto &TargetJD = MR->getTargetJITDylib();
+
+    for (auto &[B, BI] : BlockInfos) {
+      if (!BI.Defs.empty()) {
+        SymbolDepGroups.push_back(SymbolDependenceGroup());
+        auto &SDG = SymbolDepGroups.back();
+
+        for (auto *Def : BI.Defs)
+          SDG.Symbols.insert(Def->getName());
+
+        for (auto *Dep : BI.SymbolDeps) {
+          auto DepName = Dep->getName();
+          if (Dep->isDefined())
+            SDG.Dependencies[&TargetJD].insert(std::move(DepName));
+          else {
+            auto SourceJDItr =
+                SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName));
+            if (SourceJDItr != SymbolSourceJDs.end())
+              SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName));
+          }
+        }
+      }
+    }
+
+    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)
+    : LinkGraphLayer(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
+  ES.registerResourceManager(*this);
+}
+
+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");
+  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));
+}
+
+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);
+}
+
+EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
+    ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
+    : ES(ES), Registrar(std::move(Registrar)) {}
+
+void EHFrameRegistrationPlugin::modifyPassConfig(
+    MaterializationResponsibility &MR, LinkGraph &G,
+    PassConfiguration &PassConfig) {
+
+  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
+      G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
+        if (Addr) {
+          std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+          assert(!InProcessLinks.count(&MR) &&
+                 "Link for MR already being tracked?");
+          InProcessLinks[&MR] = {Addr, Size};
+        }
+      }));
+}
+
+Error EHFrameRegistrationPlugin::notifyEmitted(
+    MaterializationResponsibility &MR) {
+
+  ExecutorAddrRange EmittedRange;
+  {
+    std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+
+    auto EHFrameRangeItr = InProcessLinks.find(&MR);
+    if (EHFrameRangeItr == InProcessLinks.end())
+      return Error::success();
+
+    EmittedRange = EHFrameRangeItr->second;
+    assert(EmittedRange.Start && "eh-frame addr to register can not be null");
+    InProcessLinks.erase(EHFrameRangeItr);
+  }
+
+  if (auto Err = MR.withResourceKeyDo(
+          [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
+    return Err;
+
+  return Registrar->registerEHFrames(EmittedRange);
+}
+
+Error EHFrameRegistrationPlugin::notifyFailed(
+    MaterializationResponsibility &MR) {
+  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
+  InProcessLinks.erase(&MR);
+  return Error::success();
+}
+
+Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
+                                                         ResourceKey K) {
+  std::vector<ExecutorAddrRange> RangesToRemove;
+
+  ES.runSessionLocked([&] {
+    auto I = EHFrameRanges.find(K);
+    if (I != EHFrameRanges.end()) {
+      RangesToRemove = std::move(I->second);
+      EHFrameRanges.erase(I);
+    }
+  });
+
+  Error Err = Error::success();
+  while (!RangesToRemove.empty()) {
+    auto RangeToRemove = RangesToRemove.back();
+    RangesToRemove.pop_back();
+    assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
+    Err = joinErrors(std::move(Err),
+                     Registrar->deregisterEHFrames(RangeToRemove));
+  }
+
+  return Err;
+}
+
+void EHFrameRegistrationPlugin::notifyTransferringResources(
+    JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
+  auto SI = EHFrameRanges.find(SrcKey);
+  if (SI == EHFrameRanges.end())
+    return;
+
+  auto DI = EHFrameRanges.find(DstKey);
+  if (DI != EHFrameRanges.end()) {
+    auto &SrcRanges = SI->second;
+    auto &DstRanges = DI->second;
+    DstRanges.reserve(DstRanges.size() + SrcRanges.size());
+    for (auto &SrcRange : SrcRanges)
+      DstRanges.push_back(std::move(SrcRange));
+    EHFrameRanges.erase(SI);
+  } else {
+    // We need to move SrcKey's ranges over without invalidating the SI
+    // iterator.
+    auto Tmp = std::move(SI->second);
+    EHFrameRanges.erase(SI);
+    EHFrameRanges[DstKey] = std::move(Tmp);
+  }
+}
+
+} // End namespace orc.
+} // End namespace llvm.

diff  --git a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
index 4630e62bef74f6..6688b0935a2de5 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
@@ -7,789 +7,30 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
-#include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
-#include "llvm/ExecutionEngine/JITLink/aarch32.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
-#include "llvm/ExecutionEngine/Orc/Shared/ObjectFormats.h"
 #include "llvm/Support/MemoryBuffer.h"
 
-#include <string>
-
 #define DEBUG_TYPE "orc"
 
-using namespace llvm;
-using namespace llvm::jitlink;
-using namespace llvm::orc;
-
-namespace {
-
-bool hasInitializerSection(jitlink::LinkGraph &G) {
-  bool IsMachO = G.getTargetTriple().isOSBinFormatMachO();
-  bool IsElf = G.getTargetTriple().isOSBinFormatELF();
-  if (!IsMachO && !IsElf)
-    return false;
-
-  for (auto &Sec : G.sections()) {
-    if (IsMachO && isMachOInitializerSection(Sec.getName()))
-      return true;
-    if (IsElf && isELFInitializerSection(Sec.getName()))
-      return true;
-  }
-
-  return false;
-}
-
-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();
-  }
-}
-
-JITSymbolFlags getJITSymbolFlagsForSymbol(Symbol &Sym) {
-  JITSymbolFlags Flags;
-
-  if (Sym.getLinkage() == Linkage::Weak)
-    Flags |= JITSymbolFlags::Weak;
-
-  if (Sym.getScope() == Scope::Default)
-    Flags |= JITSymbolFlags::Exported;
-  else if (Sym.getScope() == Scope::SideEffectsOnly)
-    Flags |= JITSymbolFlags::MaterializationSideEffectsOnly;
-
-  if (Sym.isCallable())
-    Flags |= JITSymbolFlags::Callable;
-
-  return Flags;
-}
-
-class LinkGraphMaterializationUnit : public MaterializationUnit {
-public:
-  static std::unique_ptr<LinkGraphMaterializationUnit>
-  Create(ObjectLinkingLayer &ObjLinkingLayer, std::unique_ptr<LinkGraph> G) {
-    auto LGI = scanLinkGraph(ObjLinkingLayer.getExecutionSession(), *G);
-    return std::unique_ptr<LinkGraphMaterializationUnit>(
-        new LinkGraphMaterializationUnit(ObjLinkingLayer, std::move(G),
-                                         std::move(LGI)));
-  }
-
-  StringRef getName() const override { return G->getName(); }
-  void materialize(std::unique_ptr<MaterializationResponsibility> MR) override {
-    ObjLinkingLayer.emit(std::move(MR), std::move(G));
-  }
-
-private:
-  static Interface scanLinkGraph(ExecutionSession &ES, LinkGraph &G) {
-
-    Interface LGI;
-
-    auto AddSymbol = [&](Symbol *Sym) {
-      // Skip local symbols.
-      if (Sym->getScope() == Scope::Local)
-        return;
-      assert(Sym->hasName() && "Anonymous non-local symbol?");
-
-      LGI.SymbolFlags[Sym->getName()] = getJITSymbolFlagsForSymbol(*Sym);
-    };
-
-    for (auto *Sym : G.defined_symbols())
-      AddSymbol(Sym);
-    for (auto *Sym : G.absolute_symbols())
-      AddSymbol(Sym);
-
-    if (hasInitializerSection(G))
-      LGI.InitSymbol = makeInitSymbol(ES, G);
-
-    return LGI;
-  }
-
-  static SymbolStringPtr makeInitSymbol(ExecutionSession &ES, LinkGraph &G) {
-    std::string InitSymString;
-    raw_string_ostream(InitSymString)
-        << "$." << G.getName() << ".__inits" << Counter++;
-    return ES.intern(InitSymString);
-  }
-
-  LinkGraphMaterializationUnit(ObjectLinkingLayer &ObjLinkingLayer,
-                               std::unique_ptr<LinkGraph> G, Interface LGI)
-      : MaterializationUnit(std::move(LGI)), ObjLinkingLayer(ObjLinkingLayer),
-        G(std::move(G)) {}
-
-  void discard(const JITDylib &JD, const SymbolStringPtr &Name) override {
-    for (auto *Sym : G->defined_symbols())
-      if (Sym->getName() == Name) {
-        assert(Sym->getLinkage() == Linkage::Weak &&
-               "Discarding non-weak definition");
-        G->makeExternal(*Sym);
-        break;
-      }
-  }
-
-  ObjectLinkingLayer &ObjLinkingLayer;
-  std::unique_ptr<LinkGraph> G;
-  static std::atomic<uint64_t> Counter;
-};
-
-std::atomic<uint64_t> LinkGraphMaterializationUnit::Counter{0};
-
-} // end anonymous namespace
-
-namespace llvm {
-namespace orc {
-
-class ObjectLinkingLayer::JITLinkCtx final : public JITLinkContext {
-public:
-  JITLinkCtx(ObjectLinkingLayer &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() {
-    // 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;
-        for (auto &KV : *Result)
-          LR[KV.first] = KV.second;
-        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;
-
-    notifyLoaded();
-    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();
-  }
-
-  void notifyLoaded() {
-    for (auto &P : Plugins)
-      P->notifyLoaded(*MR);
-  }
-
-  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) {
-
-    struct BlockInfo {
-      bool InWorklist = false;
-      DenseSet<Symbol *> Defs;
-      DenseSet<Symbol *> SymbolDeps;
-      DenseSet<Block *> AnonEdges, AnonBackEdges;
-    };
-
-    DenseMap<Block *, BlockInfo> BlockInfos;
-
-    // Reserve space so that BlockInfos doesn't need to resize. This is
-    // essential to avoid invalidating pointers to entries below.
-    {
-      size_t NumBlocks = 0;
-      for (auto &Sec : G.sections())
-        NumBlocks += Sec.blocks_size();
-      BlockInfos.reserve(NumBlocks);
-    }
-
-    // Identify non-locally-scoped symbols defined by each block.
-    for (auto *Sym : G.defined_symbols()) {
-      if (Sym->getScope() != Scope::Local)
-        BlockInfos[&Sym->getBlock()].Defs.insert(Sym);
-    }
-
-    // Identify the symbolic and anonymous-block dependencies for each block.
-    for (auto *B : G.blocks()) {
-      auto &BI = BlockInfos[B];
-
-      for (auto &E : B->edges()) {
-
-        // External symbols are trivially depended on.
-        if (E.getTarget().isExternal()) {
-          BI.SymbolDeps.insert(&E.getTarget());
-          continue;
-        }
-
-        // Anonymous symbols aren't depended on at all (they're assumed to be
-        // already available).
-        if (E.getTarget().isAbsolute())
-          continue;
-
-        // If we get here then we depend on a symbol defined by some other
-        // block.
-        auto &TgtBI = BlockInfos[&E.getTarget().getBlock()];
-
-        // If that block has any definitions then use the first one as the
-        // "effective" dependence here (all symbols in TgtBI will become
-        // ready at the same time, and chosing a single symbol to represent
-        // the block keeps the SymbolDepGroup size small).
-        if (!TgtBI.Defs.empty()) {
-          BI.SymbolDeps.insert(*TgtBI.Defs.begin());
-          continue;
-        }
-
-        // Otherwise we've got a dependence on an anonymous block. Record it
-        // here for back-propagating symbol dependencies below.
-        BI.AnonEdges.insert(&E.getTarget().getBlock());
-        TgtBI.AnonBackEdges.insert(B);
-      }
-    }
-
-    // Prune anonymous blocks.
-    {
-      std::vector<Block *> BlocksToRemove;
-      for (auto &[B, BI] : BlockInfos) {
-        // Skip blocks with defs. We only care about anonyous blocks.
-        if (!BI.Defs.empty())
-          continue;
-
-        BlocksToRemove.push_back(B);
-
-        for (auto *FB : BI.AnonEdges)
-          BlockInfos[FB].AnonBackEdges.erase(B);
-
-        for (auto *BB : BI.AnonBackEdges)
-          BlockInfos[BB].AnonEdges.erase(B);
-
-        for (auto *FB : BI.AnonEdges) {
-          auto &FBI = BlockInfos[FB];
-          for (auto *BB : BI.AnonBackEdges)
-            FBI.AnonBackEdges.insert(BB);
-        }
-
-        for (auto *BB : BI.AnonBackEdges) {
-          auto &BBI = BlockInfos[BB];
-          for (auto *SD : BI.SymbolDeps)
-            BBI.SymbolDeps.insert(SD);
-          for (auto *FB : BI.AnonEdges)
-            BBI.AnonEdges.insert(FB);
-        }
-      }
-
-      for (auto *B : BlocksToRemove)
-        BlockInfos.erase(B);
-    }
-
-    // Build the initial dependence propagation worklist.
-    std::deque<Block *> Worklist;
-    for (auto &[B, BI] : BlockInfos) {
-      if (!BI.SymbolDeps.empty() && !BI.AnonBackEdges.empty()) {
-        Worklist.push_back(B);
-        BI.InWorklist = true;
-      }
-    }
-
-    // Propagate symbol deps through the graph.
-    while (!Worklist.empty()) {
-      auto *B = Worklist.front();
-      Worklist.pop_front();
-
-      auto &BI = BlockInfos[B];
-      BI.InWorklist = false;
-
-      for (auto *DB : BI.AnonBackEdges) {
-        auto &DBI = BlockInfos[DB];
-        for (auto *Sym : BI.SymbolDeps) {
-          if (DBI.SymbolDeps.insert(Sym).second && !DBI.InWorklist) {
-            Worklist.push_back(DB);
-            DBI.InWorklist = true;
-          }
-        }
-      }
-    }
-
-    // Transform our local dependence information into a list of
-    // SymbolDependenceGroups (in the SymbolDepGroups member), ready for use in
-    // the upcoming notifyFinalized call.
-    auto &TargetJD = MR->getTargetJITDylib();
-
-    for (auto &[B, BI] : BlockInfos) {
-      if (!BI.Defs.empty()) {
-        SymbolDepGroups.push_back(SymbolDependenceGroup());
-        auto &SDG = SymbolDepGroups.back();
-
-        for (auto *Def : BI.Defs)
-          SDG.Symbols.insert(Def->getName());
-
-        for (auto *Dep : BI.SymbolDeps) {
-          auto DepName = Dep->getName();
-          if (Dep->isDefined())
-            SDG.Dependencies[&TargetJD].insert(std::move(DepName));
-          else {
-            auto SourceJDItr =
-                SymbolSourceJDs.find(NonOwningSymbolStringPtr(DepName));
-            if (SourceJDItr != SymbolSourceJDs.end())
-              SDG.Dependencies[SourceJDItr->second].insert(std::move(DepName));
-          }
-        }
-      }
-    }
-
-    return Error::success();
-  }
-
-  ObjectLinkingLayer &Layer;
-  std::vector<std::shared_ptr<ObjectLinkingLayer::Plugin>> Plugins;
-  std::unique_ptr<MaterializationResponsibility> MR;
-  std::unique_ptr<MemoryBuffer> ObjBuffer;
-  DenseMap<NonOwningSymbolStringPtr, JITDylib *> SymbolSourceJDs;
-  std::vector<SymbolDependenceGroup> SymbolDepGroups;
-};
-
-ObjectLinkingLayer::Plugin::~Plugin() = default;
+namespace llvm::orc {
 
 char ObjectLinkingLayer::ID;
 
-using BaseT = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
-
-ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES)
-    : BaseT(ES), MemMgr(ES.getExecutorProcessControl().getMemMgr()) {
-  ES.registerResourceManager(*this);
-}
-
-ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
-                                       JITLinkMemoryManager &MemMgr)
-    : BaseT(ES), MemMgr(MemMgr) {
-  ES.registerResourceManager(*this);
-}
-
-ObjectLinkingLayer::ObjectLinkingLayer(
-    ExecutionSession &ES, std::unique_ptr<JITLinkMemoryManager> MemMgr)
-    : BaseT(ES), MemMgr(*MemMgr), MemMgrOwnership(std::move(MemMgr)) {
-  ES.registerResourceManager(*this);
-}
-
-ObjectLinkingLayer::~ObjectLinkingLayer() {
-  assert(Allocs.empty() && "Layer destroyed with resources still attached");
-  getExecutionSession().deregisterResourceManager(*this);
-}
-
-Error ObjectLinkingLayer::add(ResourceTrackerSP RT,
-                              std::unique_ptr<LinkGraph> G) {
-  auto &JD = RT->getJITDylib();
-  return JD.define(LinkGraphMaterializationUnit::Create(*this, std::move(G)),
-                   std::move(RT));
-}
+using BaseObjectLayer = RTTIExtends<ObjectLinkingLayer, ObjectLayer>;
 
 void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
                               std::unique_ptr<MemoryBuffer> O) {
   assert(O && "Object must not be null");
   MemoryBufferRef ObjBuffer = O->getMemBufferRef();
 
-  auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), std::move(O));
-  if (auto G = createLinkGraphFromObject(
+  if (auto G = jitlink::createLinkGraphFromObject(
           ObjBuffer, getExecutionSession().getSymbolStringPool())) {
-    Ctx->notifyMaterializing(**G);
-    link(std::move(*G), std::move(Ctx));
+    emit(std::move(R), std::move(*G), std::move(O));
   } else {
-    Ctx->notifyFailed(G.takeError());
-  }
-}
-
-void ObjectLinkingLayer::emit(std::unique_ptr<MaterializationResponsibility> R,
-                              std::unique_ptr<LinkGraph> G) {
-  auto Ctx = std::make_unique<JITLinkCtx>(*this, std::move(R), nullptr);
-  Ctx->notifyMaterializing(*G);
-  link(std::move(G), std::move(Ctx));
-}
-
-Error ObjectLinkingLayer::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 ObjectLinkingLayer::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 ObjectLinkingLayer::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);
-}
-
-EHFrameRegistrationPlugin::EHFrameRegistrationPlugin(
-    ExecutionSession &ES, std::unique_ptr<EHFrameRegistrar> Registrar)
-    : ES(ES), Registrar(std::move(Registrar)) {}
-
-void EHFrameRegistrationPlugin::modifyPassConfig(
-    MaterializationResponsibility &MR, LinkGraph &G,
-    PassConfiguration &PassConfig) {
-
-  PassConfig.PostFixupPasses.push_back(createEHFrameRecorderPass(
-      G.getTargetTriple(), [this, &MR](ExecutorAddr Addr, size_t Size) {
-        if (Addr) {
-          std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
-          assert(!InProcessLinks.count(&MR) &&
-                 "Link for MR already being tracked?");
-          InProcessLinks[&MR] = {Addr, Size};
-        }
-      }));
-}
-
-Error EHFrameRegistrationPlugin::notifyEmitted(
-    MaterializationResponsibility &MR) {
-
-  ExecutorAddrRange EmittedRange;
-  {
-    std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
-
-    auto EHFrameRangeItr = InProcessLinks.find(&MR);
-    if (EHFrameRangeItr == InProcessLinks.end())
-      return Error::success();
-
-    EmittedRange = EHFrameRangeItr->second;
-    assert(EmittedRange.Start && "eh-frame addr to register can not be null");
-    InProcessLinks.erase(EHFrameRangeItr);
-  }
-
-  if (auto Err = MR.withResourceKeyDo(
-          [&](ResourceKey K) { EHFrameRanges[K].push_back(EmittedRange); }))
-    return Err;
-
-  return Registrar->registerEHFrames(EmittedRange);
-}
-
-Error EHFrameRegistrationPlugin::notifyFailed(
-    MaterializationResponsibility &MR) {
-  std::lock_guard<std::mutex> Lock(EHFramePluginMutex);
-  InProcessLinks.erase(&MR);
-  return Error::success();
-}
-
-Error EHFrameRegistrationPlugin::notifyRemovingResources(JITDylib &JD,
-                                                         ResourceKey K) {
-  std::vector<ExecutorAddrRange> RangesToRemove;
-
-  ES.runSessionLocked([&] {
-    auto I = EHFrameRanges.find(K);
-    if (I != EHFrameRanges.end()) {
-      RangesToRemove = std::move(I->second);
-      EHFrameRanges.erase(I);
-    }
-  });
-
-  Error Err = Error::success();
-  while (!RangesToRemove.empty()) {
-    auto RangeToRemove = RangesToRemove.back();
-    RangesToRemove.pop_back();
-    assert(RangeToRemove.Start && "Untracked eh-frame range must not be null");
-    Err = joinErrors(std::move(Err),
-                     Registrar->deregisterEHFrames(RangeToRemove));
-  }
-
-  return Err;
-}
-
-void EHFrameRegistrationPlugin::notifyTransferringResources(
-    JITDylib &JD, ResourceKey DstKey, ResourceKey SrcKey) {
-  auto SI = EHFrameRanges.find(SrcKey);
-  if (SI == EHFrameRanges.end())
+    R->getExecutionSession().reportError(G.takeError());
+    R->failMaterialization();
     return;
-
-  auto DI = EHFrameRanges.find(DstKey);
-  if (DI != EHFrameRanges.end()) {
-    auto &SrcRanges = SI->second;
-    auto &DstRanges = DI->second;
-    DstRanges.reserve(DstRanges.size() + SrcRanges.size());
-    for (auto &SrcRange : SrcRanges)
-      DstRanges.push_back(std::move(SrcRange));
-    EHFrameRanges.erase(SI);
-  } else {
-    // We need to move SrcKey's ranges over without invalidating the SI
-    // iterator.
-    auto Tmp = std::move(SI->second);
-    EHFrameRanges.erase(SI);
-    EHFrameRanges[DstKey] = std::move(Tmp);
   }
 }
 
-} // End namespace orc.
-} // End namespace llvm.
+} // namespace llvm::orc


        


More information about the llvm-commits mailing list