[LLJIT] Add convenience methods for loading dylibs and linking static libs.
authorLang Hames <lhames@gmail.com>
Mon, 27 Mar 2023 01:13:15 +0000 (18:13 -0700)
committerLang Hames <lhames@gmail.com>
Mon, 27 Mar 2023 01:20:47 +0000 (18:20 -0700)
LLJIT::loadPlatformDynamicLibrary loads a dynamic library at a given path
(interpreted in the executor process -- the process containing the JIT'd code),
and returns a JITDylib (whose name is the given path) that reflects the symbols
in that library. LLJIT clients wishing to make the given symbols visible to
their JIT'd code can add this JITDylib to the link order of their JITDylib(s)
using JITDylib::addToLinkOrder.

The LLJIT::linkStaticLibraryInto overloads load a static library (or universal
binary) at a given path (interpreted in the controller process -- the process
containing the LLJIT instance) and adds its symbols to the given JITDylib.

The lli tool is updated to use LLJIT::linkStaticLibraryInto to implement the
extra-archive option.

LLJIT::loadPlatformDynamicLibrary is not tested in this patch as we don't have
a good way to produce dylibs in LLVM's regression test suite.

llvm/include/llvm/ExecutionEngine/Orc/LLJIT.h
llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
llvm/tools/lli/lli.cpp

index 2982a7af09b0563bc891865586be8b60c563f81a..b61947efcc1dc454636a9f824b656a45bac87079 100644 (file)
@@ -76,6 +76,32 @@ public:
     return ES->getJITDylibByName(Name);
   }
 
+  /// Load a (real) dynamic library and make its symbols available through a
+  /// new JITDylib with the same name.
+  ///
+  /// If the given *executor* path contains a valid platform dynamic library
+  /// then that library will be loaded, and a new bare JITDylib whose name is
+  /// the given path will be created to make the library's symbols available to
+  /// JIT'd code.
+  Expected<JITDylib &> loadPlatformDynamicLibrary(const char *Path);
+
+  /// Link a static library into the given JITDylib.
+  ///
+  /// If the given MemoryBuffer contains a valid static archive (or a universal
+  /// binary with an archive slice that fits the LLJIT instance's platform /
+  /// architecture) then it will be added to the given JITDylib using a
+  /// StaticLibraryDefinitionGenerator.
+  Error linkStaticLibraryInto(JITDylib &JD,
+                              std::unique_ptr<MemoryBuffer> LibBuffer);
+
+  /// Link a static library into the given JITDylib.
+  ///
+  /// If the given *host* path contains a valid static archive (or a universal
+  /// binary with an archive slice that fits the LLJIT instance's platform /
+  /// architecture) then it will be added to the given JITDylib using a
+  /// StaticLibraryDefinitionGenerator.
+  Error linkStaticLibraryInto(JITDylib &JD, const char *Path);
+
   /// Create a new JITDylib with the given name and return a reference to it.
   ///
   /// JITDylib names must be unique. If the given name is derived from user
index a9cc6680c9eb42b97bf5b0f6608bf87f5af029ab..602c0d7a16ab8734cc3a7cbb3f30e58ac4d056d8 100644 (file)
@@ -9,6 +9,7 @@
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
 #include "llvm/ExecutionEngine/JITLink/EHFrameSupport.h"
 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
 #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
 #include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
@@ -758,6 +759,44 @@ LLJIT::~LLJIT() {
     ES->reportError(std::move(Err));
 }
 
+Expected<JITDylib &> LLJIT::loadPlatformDynamicLibrary(const char *Path) {
+  auto G = EPCDynamicLibrarySearchGenerator::Load(*ES, Path);
+  if (!G)
+    return G.takeError();
+
+  if (ES->getJITDylibByName(Path))
+    return make_error<StringError>(
+        Twine("LLJIT ExecutionSession already contains a JITDylib named \"") +
+            Path + "\"",
+        inconvertibleErrorCode());
+
+  auto &JD = ES->createBareJITDylib(Path);
+  JD.addGenerator(std::move(*G));
+  return JD;
+}
+
+Error LLJIT::linkStaticLibraryInto(JITDylib &JD,
+                                   std::unique_ptr<MemoryBuffer> LibBuffer) {
+  auto G = StaticLibraryDefinitionGenerator::Create(*ObjLinkingLayer,
+                                                    std::move(LibBuffer));
+  if (!G)
+    return G.takeError();
+
+  JD.addGenerator(std::move(*G));
+
+  return Error::success();
+}
+
+Error LLJIT::linkStaticLibraryInto(JITDylib &JD, const char *Path) {
+  auto G = StaticLibraryDefinitionGenerator::Load(*ObjLinkingLayer, Path);
+  if (!G)
+    return G.takeError();
+
+  JD.addGenerator(std::move(*G));
+
+  return Error::success();
+}
+
 Error LLJIT::addIRModule(ResourceTrackerSP RT, ThreadSafeModule TSM) {
   assert(TSM && "Can not add null module");
 
index ff73ac18f5eee01363213f284ac82aad865272f9..3a5135c8b6970b9c1c356e2a1ce6169e685ba85e 100644 (file)
@@ -1070,8 +1070,7 @@ int runOrcJIT(const char *ProgName) {
       assert(EAIdx != 0 && "ExtraArchive should have index > 0");
       auto JDItr = std::prev(IdxToDylib.lower_bound(EAIdx));
       auto &JD = *JDItr->second;
-      JD.addGenerator(ExitOnErr(orc::StaticLibraryDefinitionGenerator::Load(
-          J->getObjLinkingLayer(), EAItr->c_str())));
+      ExitOnErr(J->linkStaticLibraryInto(JD, EAItr->c_str()));
     }
   }