From c97ed210b4a3400e23639cc10e746b231729dd82 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 4 Oct 2017 15:37:27 -0700
Subject: [PATCH 6/6] [ORC] JIT event listener support.

---
 include/llvm-c/OrcBindings.h                       |  4 ++
 .../ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h | 22 +++++++++-
 lib/ExecutionEngine/Orc/OrcCBindings.cpp           | 25 ++++++++++++
 lib/ExecutionEngine/Orc/OrcCBindingsStack.h        | 47 +++++++++++++++++++++-
 4 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/include/llvm-c/OrcBindings.h b/include/llvm-c/OrcBindings.h
index 4ff1f47e87d..38fa44c231d 100644
--- a/include/llvm-c/OrcBindings.h
+++ b/include/llvm-c/OrcBindings.h
@@ -180,6 +180,10 @@ LLVMOrcErrorCode LLVMOrcGetSymbolAddressIn(LLVMOrcJITStackRef JITStack,
  */
 LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
 
+void LLVMOrcRegisterPerf(LLVMOrcJITStackRef JITStack);
+void LLVMOrcRegisterGDB(LLVMOrcJITStackRef JITStack);
+void LLVMOrcUnregisterPerf(LLVMOrcJITStackRef JITStack);
+
 #ifdef __cplusplus
 }
 #endif /* extern "C" */
diff --git a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
index 246c57341f3..d720f4053a3 100644
--- a/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h
@@ -75,6 +75,8 @@ protected:
       return JITSymbol(SymEntry->second);
     }
 
+    virtual ObjectPtr getObject() const = 0;
+
   protected:
     StringMap<JITEvaluatedSymbol> SymbolTable;
     bool Finalized = false;
@@ -106,6 +108,10 @@ public:
   /// @brief Functor for receiving finalization notifications.
   using NotifyFinalizedFtor = std::function<void(ObjHandleT)>;
 
+
+  /// @brief Functor for receiving freeing notifications.
+  using NotifyFreedFtor = std::function<void(ObjHandleT)>;
+
 private:
 
 
@@ -117,7 +123,8 @@ private:
                          SymbolResolverPtrT Resolver,
                          FinalizerFtor Finalizer,
                          bool ProcessAllSections)
-      : MemMgr(std::move(MemMgr)),
+        : MemMgr(std::move(MemMgr)),
+          Obj(Obj),
         PFC(llvm::make_unique<PreFinalizeContents>(std::move(Obj),
                                                    std::move(Resolver),
                                                    std::move(Finalizer),
@@ -168,6 +175,10 @@ private:
       PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     }
 
+    ObjectPtr getObject() const override {
+      return Obj;
+    };
+
   private:
 
     void buildInitialSymbolTable(const ObjectPtr &Obj) {
@@ -209,6 +220,7 @@ private:
     };
 
     MemoryManagerPtrT MemMgr;
+    ObjectPtr Obj;
     std::unique_ptr<PreFinalizeContents> PFC;
   };
 
@@ -238,10 +250,12 @@ public:
   RTDyldObjectLinkingLayer(
       MemoryManagerGetter GetMemMgr,
       NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
-      NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
+      NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor(),
+      NotifyFreedFtor NotifyFreed = NotifyFreedFtor())
       : GetMemMgr(GetMemMgr),
         NotifyLoaded(std::move(NotifyLoaded)),
         NotifyFinalized(std::move(NotifyFinalized)),
+        NotifyFreed(std::move(NotifyFreed)),
         ProcessAllSections(false) {}
 
   /// @brief Set the 'ProcessAllSections' flag.
@@ -300,6 +314,9 @@ public:
   /// required to detect or resolve such issues it should be added at a higher
   /// layer.
   Error removeObject(ObjHandleT H) {
+    if (this->NotifyFreed)
+      this->NotifyFreed(H);
+
     // How do we invalidate the symbols in H?
     LinkedObjList.erase(H);
     return Error::success();
@@ -350,6 +367,7 @@ private:
   MemoryManagerGetter GetMemMgr;
   NotifyLoadedFtor NotifyLoaded;
   NotifyFinalizedFtor NotifyFinalized;
+  NotifyFreedFtor NotifyFreed;
   bool ProcessAllSections = false;
 };
 
diff --git a/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/lib/ExecutionEngine/Orc/OrcCBindings.cpp
index 9b9c1512402..9c83ce2c340 100644
--- a/lib/ExecutionEngine/Orc/OrcCBindings.cpp
+++ b/lib/ExecutionEngine/Orc/OrcCBindings.cpp
@@ -10,6 +10,8 @@
 #include "OrcCBindingsStack.h"
 #include "llvm-c/OrcBindings.h"
 
+#include "llvm/ExecutionEngine/JITEventListener.h"
+
 using namespace llvm;
 
 LLVMSharedModuleRef LLVMOrcMakeSharedModule(LLVMModuleRef Mod) {
@@ -134,3 +136,26 @@ LLVMOrcErrorCode LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
   delete J;
   return Err;
 }
+
+
+static JITEventListener *perf_listener_orc = NULL;
+static JITEventListener *gdb_listener_orc = NULL;
+
+void LLVMOrcRegisterGDB(LLVMOrcJITStackRef JITStack) {
+  if (!gdb_listener_orc)
+    gdb_listener_orc = JITEventListener::createGDBRegistrationListener();
+  unwrap(JITStack)->RegisterJITEventListener(gdb_listener_orc);
+}
+
+void LLVMOrcRegisterPerf(LLVMOrcJITStackRef JITStack) {
+  if (!perf_listener_orc)
+    perf_listener_orc = JITEventListener::createPerfJITEventListener();
+  unwrap(JITStack)->RegisterJITEventListener(perf_listener_orc);
+}
+
+void LLVMOrcUnregisterPerf(LLVMOrcJITStackRef JITStack) {
+  if (perf_listener_orc) {
+    delete perf_listener_orc;
+    perf_listener_orc = NULL;
+  }
+}
diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
index 6eaac01d52f..b448a9c370c 100644
--- a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
+++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
@@ -15,6 +15,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/ExecutionEngine/JITEventListener.h"
 #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
 #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
@@ -24,8 +25,10 @@
 #include "llvm/ExecutionEngine/RuntimeDyld.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
 #include "llvm/IR/DataLayout.h"
+#include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
+#include "llvm/Object/ObjectFile.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/raw_ostream.h"
@@ -137,13 +140,18 @@ public:
         ObjectLayer(
           []() {
             return std::make_shared<SectionMemoryManager>();
-          }),
+          },
+          std::bind(&OrcCBindingsStack::notifyLoaded, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3),
+          std::bind(&OrcCBindingsStack::notifyFinalized, this, std::placeholders::_1),
+          std::bind(&OrcCBindingsStack::notifyFreed, this, std::placeholders::_1)),
         CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
         CODLayer(CompileLayer,
                  [](Function &F) { return std::set<Function *>({&F}); },
                  *this->CCMgr, std::move(IndirectStubsMgrBuilder), false),
         CXXRuntimeOverrides(
-            [this](const std::string &S) { return mangle(S); }) {}
+            [this](const std::string &S) { return mangle(S); }) {
+    ObjectLayer.setProcessAllSections(true);
+  }
 
   LLVMOrcErrorCode shutdown() {
     // Run any destructors registered with __cxa_atexit.
@@ -378,6 +386,10 @@ public:
 
   const std::string &getErrorMessage() const { return ErrMsg; }
 
+  void RegisterJITEventListener(JITEventListener *l) {
+    EventListeners.push_back(l);
+  }
+
 private:
   template <typename LayerT, typename HandleT>
   unsigned createHandle(LayerT &Layer, HandleT Handle) {
@@ -408,6 +420,33 @@ private:
     return Result;
   }
 
+  void notifyLoaded(orc::RTDyldObjectLinkingLayerBase::ObjHandleT H,
+                    const orc::RTDyldObjectLinkingLayerBase::ObjectPtr &Obj,
+                    const RuntimeDyld::LoadedObjectInfo &LoadedObjInfo) {
+    PendingLoadedObjectInfos.push_back(&LoadedObjInfo);
+    PendingLoadedObjects.push_back(Obj->getBinary());
+  }
+
+
+  void notifyFinalized(orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) {
+    for (auto &Listener : EventListeners) {
+      for (size_t I = 0, S = PendingLoadedObjects.size(); I < S; ++I) {
+        auto &Obj = PendingLoadedObjects[I];
+        auto &Info = PendingLoadedObjectInfos[I];
+        Listener->NotifyObjectEmitted(*Obj, *Info);
+      }
+    }
+
+    PendingLoadedObjects.clear();
+    PendingLoadedObjectInfos.clear();
+  }
+
+  void notifyFreed(orc::RTDyldObjectLinkingLayerBase::ObjHandleT H) {
+    for (auto &Listener : EventListeners) {
+      Listener->NotifyFreeingObject(*(*H)->getObject()->getBinary());
+    }
+  }
+
   DataLayout DL;
   SectionMemoryManager CCMgrMemMgr;
 
@@ -424,6 +463,10 @@ private:
   orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
   std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
   std::string ErrMsg;
+
+  std::vector<JITEventListener *> EventListeners;
+  std::vector<const RuntimeDyld::LoadedObjectInfo *> PendingLoadedObjectInfos;
+  std::vector<const object::ObjectFile*> PendingLoadedObjects;
 };
 
 } // end namespace llvm
-- 
2.14.1.536.g6867272d5b.dirty

