[Orc] Add a JITSymbol class to the Orc APIs, refactor APIs, update clients.
authorLang Hames <lhames@gmail.com>
Mon, 9 Feb 2015 01:20:51 +0000 (01:20 +0000)
committerLang Hames <lhames@gmail.com>
Mon, 9 Feb 2015 01:20:51 +0000 (01:20 +0000)
This patch refactors a key piece of the Orc APIs: It removes the
*::getSymbolAddress and *::lookupSymbolAddressIn methods, which returned target
addresses (uint64_ts), and replaces them with *::findSymbol and *::findSymbolIn
respectively, which return instances of the new JITSymbol type. Unlike the old
methods, calling findSymbol or findSymbolIn does not cause the symbol to be
immediately materialized when found. Instead, the symbol will be materialized
if/when the getAddress method is called on the returned JITSymbol. This allows
us to query for the existence of symbols without actually materializing them. In
the future I expect more information to be attached to the JITSymbol class, for
example whether the returned symbol is a weak or strong definition. This will
allow us to properly handle weak symbols and multiple definitions.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@228557 91177308-0d34-0410-b5e6-96231b3b80d8

examples/Kaleidoscope/Orc/initial/toy.cpp
examples/Kaleidoscope/Orc/lazy_codegen/toy.cpp
examples/Kaleidoscope/Orc/lazy_irgen/toy.cpp
include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
include/llvm/ExecutionEngine/Orc/JITSymbol.h [new file with mode: 0644]
include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
lib/ExecutionEngine/Orc/OrcMCJITReplacement.h

index f075af1..0940578 100644 (file)
@@ -1149,8 +1149,8 @@ public:
     // new module. Create one that resolves symbols by looking back into the JIT.
     auto MM = createLookasideRTDyldMM<SectionMemoryManager>(
                 [&](const std::string &S) {
-                  return getMangledSymbolAddress(S);
-                }, 
+                  return findMangledSymbol(S).getAddress();
+                },
                 [](const std::string &S) { return 0; } );
 
     return CompileLayer.addModuleSet(std::move(S), std::move(MM));
@@ -1158,17 +1158,17 @@ public:
 
   void removeModule(ModuleHandleT H) { CompileLayer.removeModuleSet(H); }
 
-  uint64_t getMangledSymbolAddress(const std::string &Name) {
-    return CompileLayer.getSymbolAddress(Name, false);
+  JITSymbol findMangledSymbol(const std::string &Name) {
+    return CompileLayer.findSymbol(Name, false);
   }
 
-  uint64_t getSymbolAddress(const std::string Name) {
+  JITSymbol findSymbol(const std::string Name) {
     std::string MangledName;
     {
       raw_string_ostream MangledNameStream(MangledName);
       Mang.getNameWithPrefix(MangledNameStream, Name);
     }
-    return getMangledSymbolAddress(MangledName);
+    return findMangledSymbol(MangledName);
   }
 
 private:
@@ -1228,11 +1228,11 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) {
       auto H = J.addModule(C.takeM());
 
       // Get the address of the JIT'd function in memory.
-      uint64_t ExprFuncAddr = J.getSymbolAddress("__anon_expr");
+      auto ExprSymbol = J.findSymbol("__anon_expr");
       
       // Cast it to the right type (takes no arguments, returns a double) so we
       // can call it as a native function.
-      double (*FP)() = (double (*)())(intptr_t)ExprFuncAddr;
+      double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
 #ifdef MINIMAL_STDERR_OUTPUT
       FP();
 #else
index 1a2043f..7125cba 100644 (file)
@@ -1150,8 +1150,8 @@ public:
     // new module. Create one that resolves symbols by looking back into the JIT.
     auto MM = createLookasideRTDyldMM<SectionMemoryManager>(
                 [&](const std::string &S) {
-                  return getMangledSymbolAddress(S);
-                }, 
+                  return findMangledSymbol(S).getAddress();
+                },
                 [](const std::string &S) { return 0; } );
 
     return LazyEmitLayer.addModuleSet(std::move(S), std::move(MM));
@@ -1159,17 +1159,17 @@ public:
 
   void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); }
 
-  uint64_t getMangledSymbolAddress(const std::string &Name) {
-    return LazyEmitLayer.getSymbolAddress(Name, false);
+  JITSymbol findMangledSymbol(const std::string &Name) {
+    return LazyEmitLayer.findSymbol(Name, false);
   }
 
-  uint64_t getSymbolAddress(const std::string Name) {
+  JITSymbol findSymbol(const std::string Name) {
     std::string MangledName;
     {
       raw_string_ostream MangledNameStream(MangledName);
       Mang.getNameWithPrefix(MangledNameStream, Name);
     }
-    return getMangledSymbolAddress(MangledName);
+    return findMangledSymbol(MangledName);
   }
 
 private:
@@ -1230,11 +1230,11 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) {
       auto H = J.addModule(C.takeM());
 
       // Get the address of the JIT'd function in memory.
-      uint64_t ExprFuncAddr = J.getSymbolAddress("__anon_expr");
+      auto ExprSymbol = J.findSymbol("__anon_expr");
       
       // Cast it to the right type (takes no arguments, returns a double) so we
       // can call it as a native function.
-      double (*FP)() = (double (*)())(intptr_t)ExprFuncAddr;
+      double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
 #ifdef MINIMAL_STDERR_OUTPUT
       FP();
 #else
index 2963f30..11a17dd 100644 (file)
@@ -1174,8 +1174,8 @@ public:
     auto MM = createLookasideRTDyldMM<SectionMemoryManager>(
                 [&](const std::string &Name) -> uint64_t {
                   // First try to find 'Name' within the JIT.
-                  if (uint64_t Addr = getMangledSymbolAddress(Name))
-                    return Addr;
+                  if (auto Symbol = findMangledSymbol(Name))
+                    return Symbol.getAddress();
 
                   // If we don't find 'Name' in the JIT, see if we have some AST
                   // for it.
@@ -1192,8 +1192,8 @@ public:
                   // finished with it.
                   Session.FunctionDefs.erase(DefI);
 
-                  return getMangledSymbolAddress(Name);
-                }, 
+                  return findMangledSymbol(Name).getAddress();
+                },
                 [](const std::string &S) { return 0; } );
 
     return LazyEmitLayer.addModuleSet(std::move(S), std::move(MM));
@@ -1201,12 +1201,12 @@ public:
 
   void removeModule(ModuleHandleT H) { LazyEmitLayer.removeModuleSet(H); }
 
-  uint64_t getMangledSymbolAddress(const std::string &Name) {
-    return LazyEmitLayer.getSymbolAddress(Name, false);
+  JITSymbol findMangledSymbol(const std::string &Name) {
+    return LazyEmitLayer.findSymbol(Name, false);
   }
 
-  uint64_t getSymbolAddress(const std::string &Name) {
-    return getMangledSymbolAddress(Mangle(Name));
+  JITSymbol findSymbol(const std::string &Name) {
+    return findMangledSymbol(Mangle(Name));
   }
 
 private:
@@ -1253,11 +1253,11 @@ static void HandleTopLevelExpression(SessionContext &S, KaleidoscopeJIT &J) {
       auto H = J.addModule(C.takeM());
 
       // Get the address of the JIT'd function in memory.
-      uint64_t ExprFuncAddr = J.getSymbolAddress("__anon_expr");
+      auto ExprSymbol = J.findSymbol("__anon_expr");
       
       // Cast it to the right type (takes no arguments, returns a double) so we
       // can call it as a native function.
-      double (*FP)() = (double (*)())(intptr_t)ExprFuncAddr;
+      double (*FP)() = (double (*)())(intptr_t)ExprSymbol.getAddress();
 #ifdef MINIMAL_STDERR_OUTPUT
       FP();
 #else
index 31eb143..25381f1 100644 (file)
@@ -78,24 +78,25 @@ public:
     void removeLogicalModule(LMHandle LMH) { Handles.erase(LMH); }
 
     /// @brief Look up a symbol in this context.
-    uint64_t lookup(LMHandle LMH, const std::string &Name) {
-      if (uint64_t Addr = lookupOnlyIn(LMH, Name))
-        return Addr;
+    JITSymbol findSymbol(LMHandle LMH, const std::string &Name) {
+      if (auto Symbol = findSymbolIn(LMH, Name))
+        return Symbol;
 
       for (auto I = Handles.begin(), E = Handles.end(); I != E; ++I)
         if (I != LMH)
-          if (uint64_t Addr = lookupOnlyIn(I, Name))
-            return Addr;
+          if (auto Symbol = findSymbolIn(I, Name))
+            return Symbol;
 
-      return 0;
+      return nullptr;
     }
 
   private:
-    uint64_t lookupOnlyIn(LMHandle LMH, const std::string &Name) {
+
+    JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) {
       for (auto H : *LMH)
-        if (uint64_t Addr = BaseLayer.lookupSymbolAddressIn(H, Name, false))
-          return Addr;
-      return 0;
+        if (auto Symbol = BaseLayer.findSymbolIn(H, Name, false))
+          return Symbol;
+      return nullptr;
     }
 
     BaseLayerT &BaseLayer;
@@ -190,7 +191,9 @@ public:
       MSI.JITResolveCallbackHandlers.push_back(
           createCallbackHandlerFromJITIndirections(
               Indirections, MSI.PersistentManglers.back(),
-              [=](StringRef S) { return DylibLookup->lookup(LMH, S); }));
+              [=](StringRef S) {
+                return DylibLookup->findSymbol(LMH, S).getAddress();
+              }));
 
       // Insert callback asm code into the first module.
       InsertCallbackAsm(*ExplodedModules[0],
@@ -209,12 +212,12 @@ public:
             std::move(MSet),
             createLookasideRTDyldMM<SectionMemoryManager>(
                 [=](const std::string &Name) {
-                  if (uint64_t Addr = DylibLookup->lookup(LMH, Name))
-                    return Addr;
-                  return getSymbolAddress(Name, true);
+                  if (auto Symbol = DylibLookup->findSymbol(LMH, Name))
+                    return Symbol.getAddress();
+                  return findSymbol(Name, true).getAddress();
                 },
                 [=](const std::string &Name) {
-                  return DylibLookup->lookup(LMH, Name);
+                  return DylibLookup->findSymbol(LMH, Name).getAddress();
                 }));
         DylibLookup->addToLogicalModule(LMH, H);
         MSI.BaseLayerModuleSetHandles.push_back(H);
@@ -222,7 +225,7 @@ public:
 
       initializeFuncAddrs(*MSI.JITResolveCallbackHandlers.back(), Indirections,
                           MSI.PersistentManglers.back(), [=](StringRef S) {
-                            return DylibLookup->lookup(LMH, S);
+                            return DylibLookup->findSymbol(LMH, S).getAddress();
                           });
     }
 
@@ -238,23 +241,24 @@ public:
     ModuleSetInfos.erase(H);
   }
 
-  /// @brief Get the address of a symbol provided by this layer, or some layer
-  ///        below this one.
-  uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
-    return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
+  /// @brief Search for the given named symbol.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it exists.
+  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
+    return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
   /// @brief Get the address of a symbol provided by this layer, or some layer
   ///        below this one.
-  uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
-                                 bool ExportedSymbolsOnly) {
+  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+                         bool ExportedSymbolsOnly) {
     BaseLayerModuleSetHandleListT &BaseLayerHandles = H->second;
     for (auto &BH : BaseLayerHandles) {
-      if (uint64_t Addr =
-            BaseLayer.lookupSymbolAddressIn(BH, Name, ExportedSymbolsOnly))
-        return Addr;
+      if (auto Symbol = BaseLayer.findSymbolIn(BH, Name, ExportedSymbolsOnly))
+        return Symbol;
     }
-    return 0;
+    return nullptr;
   }
 
 private:
index 3076c12..873deb6 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_IRCOMPILELAYER_H
 
+#include "JITSymbol.h"
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
 #include "llvm/Object/ObjectFile.h"
@@ -89,18 +90,25 @@ public:
   /// @brief Remove the module set associated with the handle H.
   void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeObjectSet(H); }
 
-  /// @brief Get the address of a loaded symbol. This call is forwarded to the
-  ///        base layer's getSymbolAddress implementation.
-  uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
-    return BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly);
+  /// @brief Search for the given named symbol.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it exists.
+  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+    return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
   }
 
   /// @brief Get the address of the given symbol in the context of the set of
   ///        compiled modules represented by the handle H. This call is
   ///        forwarded to the base layer's implementation.
-  uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
-                                 bool ExportedSymbolsOnly) {
-    return BaseLayer.lookupSymbolAddressIn(H, Name, ExportedSymbolsOnly);
+  /// @param H The handle for the module set to search in.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it is found in the
+  ///         given module set.
+  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+                         bool ExportedSymbolsOnly) {
+    return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
   }
 
 private:
index 151b040..0bc71bf 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
 #define LLVM_EXECUTIONENGINE_ORC_INDIRECTIONUTILS_H
 
+#include "JITSymbol.h"
 #include "llvm/IR/Mangler.h"
 #include "llvm/IR/Module.h"
 #include <sstream>
@@ -84,7 +85,7 @@ public:
   ///
   ///   This is expected to be called by code in the JIT process itself, in
   /// order to resolve a function.
-  virtual uint64_t resolve(StubIndex StubIdx) = 0;
+  virtual TargetAddress resolve(StubIndex StubIdx) = 0;
 
 private:
   FuncNameList FuncNames;
@@ -97,9 +98,9 @@ public:
   JITResolveCallbackHandlerImpl(LookupFtor Lookup, UpdateFtor Update)
       : Lookup(std::move(Lookup)), Update(std::move(Update)) {}
 
-  uint64_t resolve(StubIndex StubIdx) override {
+  TargetAddress resolve(StubIndex StubIdx) override {
     const std::string &FuncName = getFuncName(StubIdx);
-    uint64_t Addr = Lookup(FuncName);
+    TargetAddress Addr = Lookup(FuncName);
     Update(FuncName, Addr);
     return Addr;
   }
@@ -211,10 +212,10 @@ createCallbackHandlerFromJITIndirections(const JITIndirections &Indirs,
           [=](const std::string &S) {
             return Lookup(NM.getMangledName(GetImplName(S)));
           },
-          [=](const std::string &S, uint64_t Addr) {
+          [=](const std::string &S, TargetAddress Addr) {
             void *ImplPtr = reinterpret_cast<void *>(
                 Lookup(NM.getMangledName(GetAddrName(S))));
-            memcpy(ImplPtr, &Addr, sizeof(uint64_t));
+            memcpy(ImplPtr, &Addr, sizeof(TargetAddress));
           });
 
   for (const auto &FuncName : Indirs.IndirectedNames)
@@ -248,12 +249,12 @@ void initializeFuncAddrs(JITResolveCallbackHandler &J,
 
   // Now update indirects to point to the JIT resolve callback asm.
   for (JITResolveCallbackHandler::StubIndex I = 0; I < J.getNumFuncs(); ++I) {
-    uint64_t ResolveCallbackIdxAddr =
+    TargetAddress ResolveCallbackIdxAddr =
         Lookup(getJITResolveCallbackIndexLabel(I));
     void *AddrPtr = reinterpret_cast<void *>(
         Lookup(NM.getMangledName(Indirs.GetAddrName(J.getFuncName(I)))));
     assert(AddrPtr && "Can't find stub addr global to initialize.");
-    memcpy(AddrPtr, &ResolveCallbackIdxAddr, sizeof(uint64_t));
+    memcpy(AddrPtr, &ResolveCallbackIdxAddr, sizeof(TargetAddress));
   }
 }
 
diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
new file mode 100644 (file)
index 0000000..c55e43c
--- /dev/null
@@ -0,0 +1,55 @@
+//===----------- JITSymbol.h - JIT symbol abstraction -----------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Abstraction for target process addresses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
+#define LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
+
+#include <functional>
+
+namespace llvm {
+
+/// @brief Represents an address in the target process's address space.
+typedef uint64_t TargetAddress;
+
+/// @brief Represents a symbol in the JIT.
+class JITSymbol {
+public:
+  typedef std::function<TargetAddress()> GetAddressFtor;
+
+  JITSymbol(std::nullptr_t) : CachedAddr(0) {}
+
+  JITSymbol(GetAddressFtor GetAddress)
+      : CachedAddr(0), GetAddress(std::move(GetAddress)) {}
+
+  /// @brief Returns true if the symbol exists, false otherwise.
+  explicit operator bool() const { return CachedAddr || GetAddress; }
+
+  /// @brief Get the address of the symbol in the target address space. Returns
+  ///        '0' if the symbol does not exist.
+  TargetAddress getAddress() {
+    if (GetAddress) {
+      CachedAddr = GetAddress();
+      assert(CachedAddr && "Symbol could not be materialized.");
+      GetAddress = nullptr;
+    }
+    return CachedAddr;
+  }
+
+private:
+  TargetAddress CachedAddr;
+  GetAddressFtor GetAddress;
+};
+
+}
+
+#endif // LLVM_EXECUTIONENGINE_ORC_JITSYMBOL_H
index 428a263..a56f8b6 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
 
+#include "JITSymbol.h"
 #include "LookasideRTDyldMM.h"
 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
 #include "llvm/IR/GlobalValue.h"
@@ -26,8 +27,8 @@ namespace llvm {
 ///
 ///   This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
 /// not immediately emit them the layer below. Instead, emissing to the base
-/// layer is deferred until some symbol in the module set is requested via
-/// getSymbolAddress.
+/// layer is deferred until the first time the client requests the address
+/// (via JITSymbol::getAddress) for a symbol contained in this layer.
 template <typename BaseLayerT> class LazyEmittingLayer {
 public:
   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
@@ -38,32 +39,37 @@ private:
     EmissionDeferredSet() : EmitState(NotEmitted) {}
     virtual ~EmissionDeferredSet() {}
 
-    uint64_t Search(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
+    JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
       switch (EmitState) {
-        case NotEmitted:
-          if (Provides(Name, ExportedSymbolsOnly)) {
-            EmitState = Emitting;
-            Handle = Emit(B);
-            EmitState = Emitted;
-          } else
-            return 0;
-          break;
-        case Emitting: 
-          // The module has been added to the base layer but we haven't gotten a
-          // handle back yet so we can't use lookupSymbolAddressIn. Just return
-          // '0' here - LazyEmittingLayer::getSymbolAddress will do a global
-          // search in the base layer when it doesn't find the symbol here, so
-          // we'll find it in the end.
-          return 0;
-        case Emitted:
-          // Nothing to do. Go ahead and search the base layer.
-          break;
+      case NotEmitted:
+        if (provides(Name, ExportedSymbolsOnly))
+          return JITSymbol(
+              [this,ExportedSymbolsOnly,Name,&B]() -> TargetAddress {
+                if (EmitState == Emitting)
+                  return 0;
+                else if (EmitState != Emitted) {
+                  EmitState = Emitting;
+                  Handle = emit(B);
+                  EmitState = Emitted;
+                }
+                return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly)
+                          .getAddress();
+              });
+        else
+          return nullptr;
+      case Emitting:
+        // Calling "emit" can trigger external symbol lookup (e.g. to check for
+        // pre-existing definitions of common-symbol), but it will never find in
+        // this module that it would not have found already, so return null from
+        // here.
+        return nullptr;
+      case Emitted:
+        return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
       }
-
-      return B.lookupSymbolAddressIn(Handle, Name, ExportedSymbolsOnly);
+      llvm_unreachable("Invalid emit-state.");
     }
 
-    void RemoveModulesFromBaseLayer(BaseLayerT &BaseLayer) {
+    void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
       if (EmitState != NotEmitted)
         BaseLayer.removeModuleSet(Handle);
     }
@@ -74,8 +80,8 @@ private:
            std::unique_ptr<RTDyldMemoryManager> MM);
 
   protected:
-    virtual bool Provides(StringRef Name, bool ExportedSymbolsOnly) const = 0;
-    virtual BaseLayerHandleT Emit(BaseLayerT &BaseLayer) = 0;
+    virtual bool provides(StringRef Name, bool ExportedSymbolsOnly) const = 0;
+    virtual BaseLayerHandleT emit(BaseLayerT &BaseLayer) = 0;
 
   private:
     enum { NotEmitted, Emitting, Emitted } EmitState;
@@ -90,14 +96,14 @@ private:
         : Ms(std::move(Ms)), MM(std::move(MM)) {}
 
   protected:
-    BaseLayerHandleT Emit(BaseLayerT &BaseLayer) override {
+    BaseLayerHandleT emit(BaseLayerT &BaseLayer) override {
       // We don't need the mangled names set any more: Once we've emitted this
       // to the base layer we'll just look for symbols there.
       MangledNames.reset();
       return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
     }
 
-    bool Provides(StringRef Name, bool ExportedSymbolsOnly) const override {
+    bool provides(StringRef Name, bool ExportedSymbolsOnly) const override {
       // FIXME: We could clean all this up if we had a way to reliably demangle
       //        names: We could just demangle name and search, rather than
       //        mangling everything else.
@@ -190,12 +196,6 @@ public:
   LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
 
   /// @brief Add the given set of modules to the lazy emitting layer.
-  ///
-  ///   This method stores the set of modules in a side table, rather than
-  /// immediately emitting them to the next layer of the JIT. When the address
-  /// of a symbol provided by this set is requested (via getSymbolAddress) it
-  /// triggers the emission of this set to the layer below (along with the given
-  /// memory manager instance), and returns the address of the requested symbol.
   template <typename ModuleSetT>
   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
                                 std::unique_ptr<RTDyldMemoryManager> MM) {
@@ -209,39 +209,35 @@ public:
   ///   This method will free the memory associated with the given module set,
   /// both in this layer, and the base layer.
   void removeModuleSet(ModuleSetHandleT H) {
-    (*H)->RemoveModulesFromBaseLayer(BaseLayer);
+    (*H)->removeModulesFromBaseLayer(BaseLayer);
     ModuleSetList.erase(H);
   }
 
-  /// @brief Get the address of a symbol provided by this layer, or some layer
-  ///        below this one.
-  ///
-  ///   When called for a symbol that has been added to this layer (via
-  /// addModuleSet) but not yet emitted, this will trigger the emission of the
-  /// module set containing the definiton of the symbol.
-  uint64_t getSymbolAddress(const std::string &Name, bool ExportedSymbolsOnly) {
-    // Look up symbol among existing definitions.
-    if (uint64_t Addr = BaseLayer.getSymbolAddress(Name, ExportedSymbolsOnly))
-      return Addr;
-
-    // If not found then search the deferred sets. The call to 'Search' will
-    // cause the set to be emitted to the next layer if it provides a definition
-    // of 'Name'.
+  /// @brief Search for the given named symbol.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it exists.
+  JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+    // Look for the symbol among existing definitions.
+    if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
+      return Symbol;
+
+    // If not found then search the deferred sets. If any of these contain a
+    // definition of 'Name' then they will return a JITSymbol that will emit
+    // the corresponding module when the symbol address is requested.
     for (auto &DeferredSet : ModuleSetList)
-      if (uint64_t Addr =
-              DeferredSet->Search(Name, ExportedSymbolsOnly, BaseLayer))
-        return Addr;
+      if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
+        return Symbol;
 
-    // If no definition found anywhere return 0.
-    return 0;
+    // If no definition found anywhere return a null symbol.
+    return nullptr;
   }
 
   /// @brief Get the address of the given symbol in the context of the set of
-  ///        compiled modules represented by the handle H. This call is
-  ///        forwarded to the base layer's implementation.
-  uint64_t lookupSymbolAddressIn(ModuleSetHandleT H, const std::string &Name,
-                                 bool ExportedSymbolsOnly) {
-    return (*H)->Search(Name, ExportedSymbolsOnly, BaseLayer);
+  ///        compiled modules represented by the handle H.
+  JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+                         bool ExportedSymbolsOnly) {
+    return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
   }
 };
 
index 957fec4..ce306e6 100644 (file)
@@ -14,6 +14,7 @@
 #ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
 #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
 
+#include "JITSymbol.h"
 #include "LookasideRTDyldMM.h"
 #include "llvm/ExecutionEngine/ExecutionEngine.h"
 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
@@ -24,6 +25,7 @@ namespace llvm {
 
 class ObjectLinkingLayerBase {
 protected:
+
   /// @brief Holds a set of objects to be allocated/linked as a unit in the JIT.
   ///
   /// An instance of this class will be created for each set of objects added
@@ -48,7 +50,7 @@ protected:
       return RTDyld->loadObject(Obj);
     }
 
-    uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
+    TargetAddress getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
       if (ExportedSymbolsOnly)
         return RTDyld->getExportedSymbolLoadAddress(Name);
       return RTDyld->getSymbolLoadAddress(Name);
@@ -65,10 +67,10 @@ protected:
       State = Finalized;
     }
 
-    void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
+    void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
       assert((State != Finalized) &&
              "Attempting to remap sections for finalized objects.");
-      RTDyld->mapSectionAddress(LocalAddress, TargetAddress);
+      RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
     }
 
     void takeOwnershipOfBuffer(std::unique_ptr<MemoryBuffer> B) {
@@ -178,8 +180,8 @@ public:
 
   /// @brief Map section addresses for the objects associated with the handle H.
   void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
-                         uint64_t TargetAddress) {
-    H->mapSectionAddress(LocalAddress, TargetAddress);
+                         TargetAddress TargetAddr) {
+    H->mapSectionAddress(LocalAddress, TargetAddr);
   }
 
   /// @brief Remove the set of objects associated with handle H.
@@ -195,42 +197,40 @@ public:
     LinkedObjSetList.erase(H);
   }
 
-  /// @brief Get the address of a loaded symbol.
-  ///
-  /// @return The address in the target process's address space of the named
-  ///         symbol. Null if no such symbol is known.
-  ///
-  ///   This method will trigger the finalization of the linked object set
-  /// containing the definition of the given symbol, if it is found.
-  uint64_t getSymbolAddress(StringRef Name, bool ExportedSymbolsOnly) {
+  /// @brief Search for the given named symbol.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it exists.
+  JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
     for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
          ++I)
-      if (uint64_t Addr = lookupSymbolAddressIn(I, Name, ExportedSymbolsOnly))
-        return Addr;
+      if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
+        return Symbol;
 
-    return 0;
+    return nullptr;
   }
 
-  /// @brief Search for a given symbol in the context of the set of loaded
-  ///        objects represented by the handle H.
-  ///
-  /// @return The address in the target process's address space of the named
-  ///         symbol. Null if the given object set does not contain a definition
-  ///         of this symbol.
-  ///
-  ///   This method will trigger the finalization of the linked object set
-  /// represented by the handle H if that set contains the requested symbol.
-  uint64_t lookupSymbolAddressIn(ObjSetHandleT H, StringRef Name,
-                                 bool ExportedSymbolsOnly) {
-    if (uint64_t Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly)) {
-      if (H->NeedsFinalization()) {
-        H->Finalize();
-        if (NotifyFinalized)
-          NotifyFinalized(H);
-      }
-      return Addr;
-    }
-    return 0;
+  /// @brief Search for the given named symbol in the context of the set of
+  ///        loaded objects represented by the handle H.
+  /// @param H The handle for the object set to search in.
+  /// @param Name The name of the symbol to search for.
+  /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+  /// @return A handle for the given named symbol, if it is found in the
+  ///         given object set.
+  JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
+                         bool ExportedSymbolsOnly) {
+    if (auto Addr = H->getSymbolAddress(Name, ExportedSymbolsOnly))
+      return JITSymbol(
+        [this, Addr, H](){
+          if (H->NeedsFinalization()) {
+            H->Finalize();
+            if (NotifyFinalized)
+              NotifyFinalized(H);
+          }
+          return Addr;
+        });
+
+    return nullptr;
   }
 
 private:
index ddbc732..f09d13e 100644 (file)
@@ -213,7 +213,7 @@ public:
 
 private:
   uint64_t getSymbolAddressWithoutMangling(StringRef Name) {
-    if (uint64_t Addr = LazyEmitLayer.getSymbolAddress(Name, false))
+    if (uint64_t Addr = LazyEmitLayer.findSymbol(Name, false).getAddress())
       return Addr;
     if (uint64_t Addr = MM->getSymbolAddress(Name))
       return Addr;
@@ -241,7 +241,7 @@ private:
               static_cast<object::ObjectFile *>(ChildBin.release())));
           ObjectLayer.addObjectSet(
               std::move(ObjSet), llvm::make_unique<ForwardingRTDyldMM>(*this));
-          if (uint64_t Addr = ObjectLayer.getSymbolAddress(Name, true))
+          if (uint64_t Addr = ObjectLayer.findSymbol(Name, true).getAddress())
             return Addr;
         }
       }