[llvm] r359357 - [ORC] Add a 'plugin' interface to ObjectLinkingLayer for events/configuration.

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 26 15:58:40 PDT 2019


Author: lhames
Date: Fri Apr 26 15:58:39 2019
New Revision: 359357

URL: http://llvm.org/viewvc/llvm-project?rev=359357&view=rev
Log:
[ORC] Add a 'plugin' interface to ObjectLinkingLayer for events/configuration.

ObjectLinkingLayer::Plugin provides event notifications when objects are loaded,
emitted, and removed. It also provides a modifyPassConfig callback that allows
plugins to modify the JITLink pass configuration.

This patch moves eh-frame registration into its own plugin, and teaches
llvm-jitlink to only add that plugin when performing execution runs on
non-Windows platforms. This should allow us to re-enable the test case that was
removed in r359198.

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
    llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
    llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
    llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
    llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
    llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/JITLink/EHFrameSupport.h Fri Apr 26 15:58:39 2019
@@ -27,14 +27,17 @@ Error registerEHFrameSection(const void
 /// Deregisters all FDEs in the given eh-frame section with the current process.
 Error deregisterEHFrameSection(const void *EHFrameSectionAddr);
 
+using StoreFrameAddressFunction = std::function<void(JITTargetAddress)>;
+
 /// Creates a pass that records the address of the EH frame section. If no
 /// eh-frame section is found, it will set EHFrameAddr to zero.
 ///
 /// Authors of JITLinkContexts can use this function to register a post-fixup
 /// pass that records the address of the eh-frame section. This address can
 /// be used after finalization to register and deregister the frame.
-AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
-                                                JITTargetAddress &EHFrameAddr);
+AtomGraphPassFunction
+createEHFrameRecorderPass(const Triple &TT,
+                          StoreFrameAddressFunction StoreFrameAddress);
 
 } // end namespace jitlink
 } // end namespace llvm

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h Fri Apr 26 15:58:39 2019
@@ -41,27 +41,48 @@ namespace orc {
 
 class ObjectLinkingLayerJITLinkContext;
 
+/// An ObjectLayer implementation built on JITLink.
+///
+/// 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 ObjectLayer {
   friend class ObjectLinkingLayerJITLinkContext;
 
 public:
-  /// Function object for receiving object-loaded notifications.
-  using NotifyLoadedFunction = std::function<void(VModuleKey)>;
-
-  /// Function object for receiving finalization notifications.
-  using NotifyEmittedFunction = std::function<void(VModuleKey)>;
-
-  /// Function object for modifying PassConfiguration objects.
-  using ModifyPassConfigFunction =
-      std::function<void(const Triple &TT, jitlink::PassConfiguration &Config)>;
+  /// 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,
+                                  const Triple &TT,
+                                  jitlink::PassConfiguration &Config) {}
+    virtual void notifyLoaded(MaterializationResponsibility &MR) {}
+    virtual Error notifyEmitted(MaterializationResponsibility &MR) {
+      return Error::success();
+    }
+    virtual Error notifyRemovingModule(VModuleKey K) {
+      return Error::success();
+    }
+    virtual Error notifyRemovingAllModules() { return Error::success(); }
+  };
 
   /// Construct an ObjectLinkingLayer with the given NotifyLoaded,
-  ///        and NotifyEmitted functors.
-  ObjectLinkingLayer(
-      ExecutionSession &ES, jitlink::JITLinkMemoryManager &MemMgr,
-      NotifyLoadedFunction NotifyLoaded = NotifyLoadedFunction(),
-      NotifyEmittedFunction NotifyEmitted = NotifyEmittedFunction(),
-      ModifyPassConfigFunction ModifyPassConfig = ModifyPassConfigFunction());
+  /// and NotifyEmitted functors.
+  ObjectLinkingLayer(ExecutionSession &ES,
+                     jitlink::JITLinkMemoryManager &MemMgr);
+
+  /// Destruct an ObjectLinkingLayer.
+  ~ObjectLinkingLayer();
+
+  /// Add a pass-config modifier.
+  ObjectLinkingLayer &addPlugin(std::unique_ptr<Plugin> P) {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    Plugins.push_back(std::move(P));
+    return *this;
+  }
 
   /// Emit the object.
   void emit(MaterializationResponsibility R,
@@ -101,31 +122,35 @@ public:
 private:
   using AllocPtr = std::unique_ptr<jitlink::JITLinkMemoryManager::Allocation>;
 
-  class ObjectResources {
-  public:
-    ObjectResources() = default;
-    ObjectResources(AllocPtr Alloc, JITTargetAddress EHFrameAddr);
-    ObjectResources(ObjectResources &&Other);
-    ObjectResources &operator=(ObjectResources &&Other);
-    ~ObjectResources();
-
-  private:
-    AllocPtr Alloc;
-    JITTargetAddress EHFrameAddr = 0;
-  };
+  void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+                        jitlink::PassConfiguration &PassConfig);
+  void notifyLoaded(MaterializationResponsibility &MR);
+  Error notifyEmitted(MaterializationResponsibility &MR, AllocPtr Alloc);
 
-  void notifyFinalized(ObjectResources OR) {
-    ObjResources.push_back(std::move(OR));
-  }
+  Error removeModule(VModuleKey K);
+  Error removeAllModules();
 
   mutable std::mutex LayerMutex;
   jitlink::JITLinkMemoryManager &MemMgr;
-  NotifyLoadedFunction NotifyLoaded;
-  NotifyEmittedFunction NotifyEmitted;
-  ModifyPassConfigFunction ModifyPassConfig;
   bool OverrideObjectFlags = false;
   bool AutoClaimObjectSymbols = false;
-  std::vector<ObjectResources> ObjResources;
+  DenseMap<VModuleKey, AllocPtr> TrackedAllocs;
+  std::vector<AllocPtr> UntrackedAllocs;
+  std::vector<std::unique_ptr<Plugin>> Plugins;
+};
+
+class LocalEHFrameRegistrationPlugin : public ObjectLinkingLayer::Plugin {
+public:
+  Error notifyEmitted(MaterializationResponsibility &MR) override;
+  void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+                        jitlink::PassConfiguration &PassConfig) override;
+  Error notifyRemovingModule(VModuleKey K) override;
+  Error notifyRemovingAllModules() override;
+
+private:
+  DenseMap<MaterializationResponsibility *, const void *> InProcessLinks;
+  DenseMap<VModuleKey, const void *> TrackedEHFrameAddrs;
+  std::vector<const void *> UntrackedEHFrameAddrs;
 };
 
 } // end namespace orc

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp Fri Apr 26 15:58:39 2019
@@ -507,8 +507,9 @@ Error deregisterEHFrameSection(const voi
 #endif
 }
 
-AtomGraphPassFunction createEHFrameRecorderPass(const Triple &TT,
-                                                JITTargetAddress &EHFrameAddr) {
+AtomGraphPassFunction
+createEHFrameRecorderPass(const Triple &TT,
+                          StoreFrameAddressFunction StoreFrameAddress) {
   const char *EHFrameSectionName = nullptr;
   if (TT.getObjectFormat() == Triple::MachO)
     EHFrameSectionName = "__eh_frame";
@@ -516,7 +517,7 @@ AtomGraphPassFunction createEHFrameRecor
     EHFrameSectionName = ".eh_frame";
 
   auto RecordEHFrame = [EHFrameSectionName,
-                        &EHFrameAddr](AtomGraph &G) -> Error {
+                        StoreFrameAddress](AtomGraph &G) -> Error {
     // Search for a non-empty eh-frame and record the address of the first atom
     // in it.
     JITTargetAddress Addr = 0;
@@ -529,7 +530,7 @@ AtomGraphPassFunction createEHFrameRecor
         break;
       }
 
-    EHFrameAddr = Addr;
+    StoreFrameAddress(Addr);
     return Error::success();
   };
 

Modified: llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/ObjectLinkingLayer.cpp Fri Apr 26 15:58:39 2019
@@ -133,25 +133,19 @@ public:
 
     MR.resolve(InternedResult);
 
-    if (Layer.NotifyLoaded)
-      Layer.NotifyLoaded(MR.getVModuleKey());
+    Layer.notifyLoaded(MR);
   }
 
   void notifyFinalized(
       std::unique_ptr<JITLinkMemoryManager::Allocation> A) override {
 
-    if (EHFrameAddr) {
-      // If there is an eh-frame then try to register it.
-      if (auto Err = registerEHFrameSection((void *)EHFrameAddr)) {
-        Layer.getExecutionSession().reportError(std::move(Err));
-        MR.failMaterialization();
-        return;
-      }
-    }
+    if (auto Err = Layer.notifyEmitted(MR, std::move(A))) {
+      Layer.getExecutionSession().reportError(std::move(Err));
+      MR.failMaterialization();
 
+      return;
+    }
     MR.emit();
-    Layer.notifyFinalized(
-        ObjectLinkingLayer::ObjectResources(std::move(A), EHFrameAddr));
   }
 
   AtomGraphPassFunction getMarkLivePass(const Triple &TT) const override {
@@ -166,11 +160,7 @@ public:
     Config.PostPrunePasses.push_back(
         [this](AtomGraph &G) { return computeNamedSymbolDependencies(G); });
 
-    Config.PostFixupPasses.push_back(
-        createEHFrameRecorderPass(TT, EHFrameAddr));
-
-    if (Layer.ModifyPassConfig)
-      Layer.ModifyPassConfig(TT, Config);
+    Layer.modifyPassConfig(MR, TT, Config);
 
     return Error::success();
   }
@@ -328,16 +318,18 @@ private:
   MaterializationResponsibility MR;
   std::unique_ptr<MemoryBuffer> ObjBuffer;
   DenseMap<SymbolStringPtr, SymbolNameSet> NamedSymbolDeps;
-  JITTargetAddress EHFrameAddr = 0;
 };
 
-ObjectLinkingLayer::ObjectLinkingLayer(
-    ExecutionSession &ES, JITLinkMemoryManager &MemMgr,
-    NotifyLoadedFunction NotifyLoaded, NotifyEmittedFunction NotifyEmitted,
-    ModifyPassConfigFunction ModifyPassConfig)
-    : ObjectLayer(ES), MemMgr(MemMgr), NotifyLoaded(std::move(NotifyLoaded)),
-      NotifyEmitted(std::move(NotifyEmitted)),
-      ModifyPassConfig(std::move(ModifyPassConfig)) {}
+ObjectLinkingLayer::Plugin::~Plugin() {}
+
+ObjectLinkingLayer::ObjectLinkingLayer(ExecutionSession &ES,
+                                       JITLinkMemoryManager &MemMgr)
+    : ObjectLayer(ES), MemMgr(MemMgr) {}
+
+ObjectLinkingLayer::~ObjectLinkingLayer() {
+  if (auto Err = removeAllModules())
+    getExecutionSession().reportError(std::move(Err));
+}
 
 void ObjectLinkingLayer::emit(MaterializationResponsibility R,
                               std::unique_ptr<MemoryBuffer> O) {
@@ -346,36 +338,145 @@ void ObjectLinkingLayer::emit(Materializ
       *this, std::move(R), std::move(O)));
 }
 
-ObjectLinkingLayer::ObjectResources::ObjectResources(
-    AllocPtr Alloc, JITTargetAddress EHFrameAddr)
-    : Alloc(std::move(Alloc)), EHFrameAddr(EHFrameAddr) {}
+void ObjectLinkingLayer::modifyPassConfig(MaterializationResponsibility &MR,
+                                          const Triple &TT,
+                                          PassConfiguration &PassConfig) {
+  for (auto &P : Plugins)
+    P->modifyPassConfig(MR, TT, PassConfig);
+}
+
+void ObjectLinkingLayer::notifyLoaded(MaterializationResponsibility &MR) {
+  for (auto &P : Plugins)
+    P->notifyLoaded(MR);
+}
 
-ObjectLinkingLayer::ObjectResources::ObjectResources(ObjectResources &&Other)
-    : Alloc(std::move(Other.Alloc)), EHFrameAddr(Other.EHFrameAddr) {
-  Other.EHFrameAddr = 0;
+Error ObjectLinkingLayer::notifyEmitted(MaterializationResponsibility &MR,
+                                        AllocPtr Alloc) {
+  Error Err = Error::success();
+  for (auto &P : Plugins)
+    Err = joinErrors(std::move(Err), P->notifyEmitted(MR));
+
+  if (Err)
+    return Err;
+
+  {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    UntrackedAllocs.push_back(std::move(Alloc));
+  }
+
+  return Error::success();
 }
 
-ObjectLinkingLayer::ObjectResources &
-ObjectLinkingLayer::ObjectResources::operator=(ObjectResources &&Other) {
-  std::swap(Alloc, Other.Alloc);
-  std::swap(EHFrameAddr, Other.EHFrameAddr);
-  return *this;
+Error ObjectLinkingLayer::removeModule(VModuleKey K) {
+  Error Err = Error::success();
+
+  for (auto &P : Plugins)
+    Err = joinErrors(std::move(Err), P->notifyRemovingModule(K));
+
+  AllocPtr Alloc;
+
+  {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    auto AllocItr = TrackedAllocs.find(K);
+    Alloc = std::move(AllocItr->second);
+    TrackedAllocs.erase(AllocItr);
+  }
+
+  assert(Alloc && "No allocation for key K");
+
+  return joinErrors(std::move(Err), Alloc->deallocate());
 }
 
-ObjectLinkingLayer::ObjectResources::~ObjectResources() {
-  const char *ErrBanner =
-      "ObjectLinkingLayer received error deallocating object resources:";
+Error ObjectLinkingLayer::removeAllModules() {
+
+  Error Err = Error::success();
 
-  assert((EHFrameAddr == 0 || Alloc) &&
-         "Non-null EHFrameAddr must have an associated allocation");
+  for (auto &P : Plugins)
+    Err = joinErrors(std::move(Err), P->notifyRemovingAllModules());
+
+  std::vector<AllocPtr> Allocs;
+  {
+    std::lock_guard<std::mutex> Lock(LayerMutex);
+    Allocs = std::move(UntrackedAllocs);
+
+    for (auto &KV : TrackedAllocs)
+      Allocs.push_back(std::move(KV.second));
+
+    TrackedAllocs.clear();
+  }
+
+  while (!Allocs.empty()) {
+    Err = joinErrors(std::move(Err), Allocs.back()->deallocate());
+    Allocs.pop_back();
+  }
 
-  if (EHFrameAddr)
-    if (auto Err = deregisterEHFrameSection((void *)EHFrameAddr))
-      logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
+  return Err;
+}
+
+void LocalEHFrameRegistrationPlugin::modifyPassConfig(
+    MaterializationResponsibility &MR, const Triple &TT,
+    PassConfiguration &PassConfig) {
+  assert(!InProcessLinks.count(&MR) && "Link for MR already being tracked?");
+
+  PassConfig.PostFixupPasses.push_back(
+      createEHFrameRecorderPass(TT, [this, &MR](JITTargetAddress Addr) {
+        if (Addr)
+          InProcessLinks[&MR] = jitTargetAddressToPointer<void *>(Addr);
+      }));
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyEmitted(
+    MaterializationResponsibility &MR) {
+
+  auto EHFrameAddrItr = InProcessLinks.find(&MR);
+  if (EHFrameAddrItr == InProcessLinks.end())
+    return Error::success();
+
+  const void *EHFrameAddr = EHFrameAddrItr->second;
+  assert(EHFrameAddr && "eh-frame addr to register can not be null");
+
+  InProcessLinks.erase(EHFrameAddrItr);
+  if (auto Key = MR.getVModuleKey())
+    TrackedEHFrameAddrs[Key] = EHFrameAddr;
+  else
+    UntrackedEHFrameAddrs.push_back(EHFrameAddr);
+
+  return registerEHFrameSection(EHFrameAddr);
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyRemovingModule(VModuleKey K) {
+  auto EHFrameAddrItr = TrackedEHFrameAddrs.find(K);
+  if (EHFrameAddrItr == TrackedEHFrameAddrs.end())
+    return Error::success();
+
+  const void *EHFrameAddr = EHFrameAddrItr->second;
+  assert(EHFrameAddr && "Tracked eh-frame addr must not be null");
+
+  TrackedEHFrameAddrs.erase(EHFrameAddrItr);
+
+  return deregisterEHFrameSection(EHFrameAddr);
+}
+
+Error LocalEHFrameRegistrationPlugin::notifyRemovingAllModules() {
+
+  std::vector<const void *> EHFrameAddrs = std::move(UntrackedEHFrameAddrs);
+  EHFrameAddrs.reserve(EHFrameAddrs.size() + TrackedEHFrameAddrs.size());
+
+  for (auto &KV : TrackedEHFrameAddrs)
+    EHFrameAddrs.push_back(KV.second);
+
+  TrackedEHFrameAddrs.clear();
+
+  Error Err = Error::success();
+
+  while (!EHFrameAddrs.empty()) {
+    const void *EHFrameAddr = EHFrameAddrs.back();
+    assert(EHFrameAddr && "Untracked eh-frame addr must not be null");
+    EHFrameAddrs.pop_back();
+    Err = joinErrors(std::move(Err), deregisterEHFrameSection(EHFrameAddr));
+  }
 
-  if (Alloc)
-    if (auto Err = Alloc->deallocate())
-      logAllUnhandledErrors(std::move(Err), llvm::errs(), ErrBanner);
+  return Err;
 }
 
 } // End namespace orc.

Modified: llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test (original)
+++ llvm/trunk/test/ExecutionEngine/JITLink/X86/MachO_x86-64_ehframe.test Fri Apr 26 15:58:39 2019
@@ -1,9 +1,4 @@
-# RUN: llvm-jitlink -noexec  %S/Inputs/MachO_x86-64_ehframe.o
-#
-# FIXME: Produces these errors:
-#   JIT session error: Symbols not found: { __ZTIi, ___gxx_personality_v0 }
-#   llvm-jitlink.exe: Failed to materialize symbols: { biz, _main, baz }
-# XFAIL: windows-msvc
+# RUN: llvm-jitlink -noexec -define-abs __ZTIi=0x1 -define-abs ___gxx_personality_v0=0x2 %S/Inputs/MachO_x86-64_ehframe.o
 #
 # Perform a no-exec link of MachO_x86-64_ehframe and verify that it does not
 # generate any errors despite the last FDE referring to the first CIE (rather

Modified: llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp?rev=359357&r1=359356&r2=359357&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp (original)
+++ llvm/trunk/tools/llvm-jitlink/llvm-jitlink.cpp Fri Apr 26 15:58:39 2019
@@ -214,13 +214,27 @@ static void dumpSectionContents(raw_ostr
   }
 }
 
-Session::Session(Triple TT)
-    : ObjLayer(ES, MemMgr, ObjectLinkingLayer::NotifyLoadedFunction(),
-               ObjectLinkingLayer::NotifyEmittedFunction(),
-               [this](const Triple &TT, PassConfiguration &PassConfig) {
-                 modifyPassConfig(TT, PassConfig);
-               }),
-      TT(std::move(TT)) {}
+Session::Session(Triple TT) : ObjLayer(ES, MemMgr), TT(std::move(TT)) {
+
+  /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the
+  /// Session.
+  class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {
+  public:
+    JITLinkSessionPlugin(Session &S) : S(S) {}
+    void modifyPassConfig(MaterializationResponsibility &MR, const Triple &TT,
+                          PassConfiguration &PassConfig) {
+      S.modifyPassConfig(TT, PassConfig);
+    }
+
+  private:
+    Session &S;
+  };
+
+  if (!NoExec && !TT.isOSWindows())
+    ObjLayer.addPlugin(llvm::make_unique<LocalEHFrameRegistrationPlugin>());
+
+  ObjLayer.addPlugin(llvm::make_unique<JITLinkSessionPlugin>(*this));
+}
 
 void Session::dumpSessionInfo(raw_ostream &OS) {
   OS << "Registered addresses:\n" << SymbolInfos << FileInfos;




More information about the llvm-commits mailing list