[compiler-rt] 1aa71f8 - [ORC][ORC_RT] Integrate ORC platforms with LLJIT and lli

Peter S. Housel via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 9 22:48:51 PDT 2022


Author: Peter S. Housel
Date: 2022-06-09T22:47:58-07:00
New Revision: 1aa71f8679e439db651c06e8e68ef21e6deffa93

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

LOG: [ORC][ORC_RT] Integrate ORC platforms with LLJIT and lli

This change enables integrating orc::LLJIT with the ORCv2
platforms (MachOPlatform and ELFNixPlatform) and the compiler-rt orc
runtime. Changes include:

- Adding SPS wrapper functions for the orc runtime's dlfcn emulation
  functions, allowing initialization and deinitialization to be invoked
  by LLJIT.

- Changing the LLJIT code generation default to add UseInitArray so
  that .init_array constructors are generated for ELF platforms.

- Integrating the ORCv2 Platforms into lli, and adding a
  PlatformSupport implementation to the LLJIT instance used by lli which
  implements initialization and deinitialization by calling the new
  wrapper functions in the runtime.

Reviewed By: lhames

Differential Revision: https://reviews.llvm.org/D126492

Added: 
    compiler-rt/lib/orc/dlfcn_wrapper.cpp
    compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp
    compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll
    compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp
    compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll
    compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp
    compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll

Modified: 
    compiler-rt/lib/orc/CMakeLists.txt
    compiler-rt/test/orc/lit.cfg.py
    llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
    llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
    llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
    llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
    llvm/tools/lli/lli.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/orc/CMakeLists.txt b/compiler-rt/lib/orc/CMakeLists.txt
index 7375934c47ec..d2786acf3cfe 100644
--- a/compiler-rt/lib/orc/CMakeLists.txt
+++ b/compiler-rt/lib/orc/CMakeLists.txt
@@ -9,6 +9,7 @@ set(ORC_SOURCES
   macho_platform.cpp
   elfnix_platform.cpp
   run_program_wrapper.cpp
+  dlfcn_wrapper.cpp
   )
 
 # Implementation files for all ORC architectures.

diff  --git a/compiler-rt/lib/orc/dlfcn_wrapper.cpp b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
new file mode 100644
index 000000000000..c513aae97bb3
--- /dev/null
+++ b/compiler-rt/lib/orc/dlfcn_wrapper.cpp
@@ -0,0 +1,52 @@
+//===- dlfcn_wrapper.cpp --------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of the ORC runtime support library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "adt.h"
+#include "common.h"
+#include "wrapper_function_utils.h"
+
+#include <vector>
+
+using namespace __orc_rt;
+
+extern "C" const char *__orc_rt_jit_dlerror();
+extern "C" void *__orc_rt_jit_dlopen(const char *path, int mode);
+extern "C" int __orc_rt_jit_dlclose(void *dso_handle);
+
+ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
+__orc_rt_jit_dlerror_wrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<SPSString()>::handle(
+             ArgData, ArgSize,
+             []() { return std::string(__orc_rt_jit_dlerror()); })
+      .release();
+}
+
+ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
+__orc_rt_jit_dlopen_wrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<SPSExecutorAddr(SPSString, int32_t)>::handle(
+             ArgData, ArgSize,
+             [](const std::string &Path, int32_t mode) {
+               return ExecutorAddr::fromPtr(
+                   __orc_rt_jit_dlopen(Path.c_str(), mode));
+             })
+      .release();
+}
+
+ORC_RT_INTERFACE __orc_rt_CWrapperFunctionResult
+__orc_rt_jit_dlclose_wrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<int32_t(SPSExecutorAddr)>::handle(
+             ArgData, ArgSize,
+             [](ExecutorAddr &DSOHandle) {
+               return __orc_rt_jit_dlclose(DSOHandle.toPtr<void *>());
+             })
+      .release();
+}

diff  --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp
new file mode 100644
index 000000000000..b73ec2387028
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-ehframe.cpp
@@ -0,0 +1,15 @@
+// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s
+// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s
+
+// CHECK: catch
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  try {
+    throw 0;
+  } catch (int X) {
+    puts("catch");
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll
new file mode 100644
index 000000000000..e5b976423238
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Darwin/x86-64/lljit-initialize-deinitialize.ll
@@ -0,0 +1,32 @@
+; RUN: %lli_orc_jitlink -relocation-model=pic %s | FileCheck %s
+
+; CHECK: constructor
+; CHECK-NEXT: main
+; CHECK-NEXT: destructor
+
+ at __dso_handle = external hidden global i8
+ at .str = private unnamed_addr constant [5 x i8] c"main\00", align 1
+ at .str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
+ at .str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+
+define dso_local void @destructor(i8* %0) {
+  %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
+  ret void
+}
+
+declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+
+; Function Attrs: nofree norecurse nounwind uwtable
+define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 {
+  %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
+  ret i32 0
+}
+
+declare i32 @puts(i8* nocapture readonly)
+
+define internal void @constructor() {
+  %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5
+  %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5
+  ret void
+}

diff  --git a/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp
new file mode 100644
index 000000000000..b73ec2387028
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-ehframe.cpp
@@ -0,0 +1,15 @@
+// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s
+// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s
+
+// CHECK: catch
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  try {
+    throw 0;
+  } catch (int X) {
+    puts("catch");
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll
new file mode 100644
index 000000000000..34bfc10b9d89
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/FreeBSD/x86-64/lljit-initialize-deinitialize.ll
@@ -0,0 +1,32 @@
+; RUN: %lli_orc_jitlink %s | FileCheck %s
+
+; CHECK: constructor
+; CHECK-NEXT: main
+; CHECK-NEXT: destructor
+
+ at __dso_handle = external hidden global i8
+ at .str = private unnamed_addr constant [5 x i8] c"main\00", align 1
+ at .str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
+ at .str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+
+define dso_local void @destructor(i8* %0) {
+  %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
+  ret void
+}
+
+declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+
+; Function Attrs: nofree norecurse nounwind uwtable
+define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 {
+  %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
+  ret i32 0
+}
+
+declare i32 @puts(i8* nocapture readonly)
+
+define internal void @constructor() {
+  %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5
+  %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5
+  ret void
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp
new file mode 100644
index 000000000000..b73ec2387028
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-ehframe.cpp
@@ -0,0 +1,15 @@
+// RUN: %clangxx -fPIC -emit-llvm -c -o %t %s
+// RUN: %lli_orc_jitlink -relocation-model=pic %t | FileCheck %s
+
+// CHECK: catch
+
+#include <stdio.h>
+
+int main(int argc, char *argv[]) {
+  try {
+    throw 0;
+  } catch (int X) {
+    puts("catch");
+  }
+  return 0;
+}

diff  --git a/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll
new file mode 100644
index 000000000000..34bfc10b9d89
--- /dev/null
+++ b/compiler-rt/test/orc/TestCases/Linux/x86-64/lljit-initialize-deinitialize.ll
@@ -0,0 +1,32 @@
+; RUN: %lli_orc_jitlink %s | FileCheck %s
+
+; CHECK: constructor
+; CHECK-NEXT: main
+; CHECK-NEXT: destructor
+
+ at __dso_handle = external hidden global i8
+ at .str = private unnamed_addr constant [5 x i8] c"main\00", align 1
+ at .str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
+ at .str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
+ at llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @constructor, i8* null }]
+
+define dso_local void @destructor(i8* %0) {
+  %2 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([11 x i8], [11 x i8]* @.str.2, i64 0, i64 0))
+  ret void
+}
+
+declare i32 @__cxa_atexit(void (i8*)*, i8*, i8*)
+
+; Function Attrs: nofree norecurse nounwind uwtable
+define dso_local i32 @main(i32 %0, i8** nocapture readnone %1) local_unnamed_addr #2 {
+  %3 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([5 x i8], [5 x i8]* @.str, i64 0, i64 0))
+  ret i32 0
+}
+
+declare i32 @puts(i8* nocapture readonly)
+
+define internal void @constructor() {
+  %1 = tail call i32 @puts(i8* nonnull dereferenceable(1) getelementptr inbounds ([12 x i8], [12 x i8]* @.str.1, i64 0, i64 0)) #5
+  %2 = tail call i32 @__cxa_atexit(void (i8*)* @destructor, i8* null, i8* nonnull @__dso_handle) #5
+  ret void
+}

diff  --git a/compiler-rt/test/orc/lit.cfg.py b/compiler-rt/test/orc/lit.cfg.py
index b2e97cefbf0e..78c653373be2 100644
--- a/compiler-rt/test/orc/lit.cfg.py
+++ b/compiler-rt/test/orc/lit.cfg.py
@@ -13,6 +13,7 @@ def build_invocation(compile_flags):
 
 # Assume that llvm-jitlink is in the config.llvm_tools_dir.
 llvm_jitlink = os.path.join(config.llvm_tools_dir, 'llvm-jitlink')
+lli = os.path.join(config.llvm_tools_dir, 'lli')
 if config.host_os == 'Darwin':
   orc_rt_path = '%s/libclang_rt.orc_osx.a' % config.compiler_rt_libdir
 else:
@@ -30,9 +31,11 @@ def build_invocation(compile_flags):
      build_invocation(config.cxx_mode_flags + [config.target_cflags])))
 config.substitutions.append(
     ('%llvm_jitlink', (llvm_jitlink + ' -orc-runtime=' + orc_rt_path)))
+config.substitutions.append(
+    ('%lli_orc_jitlink', (lli + ' -jit-kind=orc -jit-linker=jitlink -orc-runtime=' + orc_rt_path)))
 
 # Default test suffixes.
-config.suffixes = ['.c', '.cpp', '.S']
+config.suffixes = ['.c', '.cpp', '.S', '.ll']
 
 # Exclude Inputs directories.
 config.excludes = ['Inputs']

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h b/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
index 2cc8c29b2813..e6a63707653a 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h
@@ -125,7 +125,7 @@ class JITTargetMachineBuilder {
   /// Set TargetOptions.
   ///
   /// Note: This operation will overwrite any previously configured options,
-  /// including EmulatedTLS and ExplicitEmulatedTLS which
+  /// including EmulatedTLS, ExplicitEmulatedTLS, and UseInitArray which
   /// the JITTargetMachineBuilder sets by default. Clients are responsible
   /// for re-enabling these overwritten options.
   JITTargetMachineBuilder &setOptions(TargetOptions Options) {

diff  --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index 0185a9d15de2..730e193ec41b 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -263,6 +263,10 @@ ELFNixPlatform::standardRuntimeUtilityAliases() {
   static const std::pair<const char *, const char *>
       StandardRuntimeUtilityAliases[] = {
           {"__orc_rt_run_program", "__orc_rt_elfnix_run_program"},
+          {"__orc_rt_jit_dlerror", "__orc_rt_elfnix_jit_dlerror"},
+          {"__orc_rt_jit_dlopen", "__orc_rt_elfnix_jit_dlopen"},
+          {"__orc_rt_jit_dlclose", "__orc_rt_elfnix_jit_dlclose"},
+          {"__orc_rt_jit_dlsym", "__orc_rt_elfnix_jit_dlsym"},
           {"__orc_rt_log_error", "__orc_rt_log_error_to_stderr"}};
 
   return ArrayRef<std::pair<const char *, const char *>>(

diff  --git a/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
index 0fbf79b8a56d..c60f4b3b263c 100644
--- a/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/JITTargetMachineBuilder.cpp
@@ -19,6 +19,7 @@ JITTargetMachineBuilder::JITTargetMachineBuilder(Triple TT)
     : TT(std::move(TT)) {
   Options.EmulatedTLS = true;
   Options.ExplicitEmulatedTLS = true;
+  Options.UseInitArray = true;
 }
 
 Expected<JITTargetMachineBuilder> JITTargetMachineBuilder::detectHost() {

diff  --git a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
index b2de83acc2e9..d5274b06a76f 100644
--- a/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/MachOPlatform.cpp
@@ -302,6 +302,10 @@ MachOPlatform::standardRuntimeUtilityAliases() {
   static const std::pair<const char *, const char *>
       StandardRuntimeUtilityAliases[] = {
           {"___orc_rt_run_program", "___orc_rt_macho_run_program"},
+          {"___orc_rt_jit_dlerror", "___orc_rt_macho_jit_dlerror"},
+          {"___orc_rt_jit_dlopen", "___orc_rt_macho_jit_dlopen"},
+          {"___orc_rt_jit_dlclose", "___orc_rt_macho_jit_dlclose"},
+          {"___orc_rt_jit_dlsym", "___orc_rt_macho_jit_dlsym"},
           {"___orc_rt_log_error", "___orc_rt_log_error_to_stderr"}};
 
   return ArrayRef<std::pair<const char *, const char *>>(

diff  --git a/llvm/tools/lli/lli.cpp b/llvm/tools/lli/lli.cpp
index e45088865bea..f2e3886bdf07 100644
--- a/llvm/tools/lli/lli.cpp
+++ b/llvm/tools/lli/lli.cpp
@@ -28,12 +28,15 @@
 #include "llvm/ExecutionEngine/ObjectCache.h"
 #include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
 #include "llvm/ExecutionEngine/Orc/DebugUtils.h"
+#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
 #include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
+#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
 #include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
 #include "llvm/ExecutionEngine/Orc/EPCGenericRTDyldMemoryManager.h"
 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
 #include "llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h"
 #include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
@@ -120,6 +123,9 @@ namespace {
                                       "RuntimeDyld"),
                            clEnumValN(JITLinkerKind::JITLink, "jitlink",
                                       "Orc-specific linker")));
+  cl::opt<std::string> OrcRuntime("orc-runtime",
+                                  cl::desc("Use ORC runtime from given path"),
+                                  cl::init(""));
 
   cl::opt<unsigned>
   LazyJITCompileThreads("compile-threads",
@@ -230,13 +236,15 @@ namespace {
       cl::desc("Do not resolve lli process symbols in JIT'd code"),
       cl::init(false));
 
-  enum class LLJITPlatform { Inactive, DetectHost, GenericIR };
+  enum class LLJITPlatform { Inactive, DetectHost, ORC, GenericIR };
 
   cl::opt<LLJITPlatform>
       Platform("lljit-platform", cl::desc("Platform to use with LLJIT"),
                cl::init(LLJITPlatform::DetectHost),
                cl::values(clEnumValN(LLJITPlatform::DetectHost, "DetectHost",
                                      "Select based on JIT target triple"),
+                          clEnumValN(LLJITPlatform::ORC, "ORC",
+                                     "Use ORCPlatform with the ORC runtime"),
                           clEnumValN(LLJITPlatform::GenericIR, "GenericIR",
                                      "Use LLJITGenericIRPlatform"),
                           clEnumValN(LLJITPlatform::Inactive, "Inactive",
@@ -365,6 +373,53 @@ class LLIObjectCache : public ObjectCache {
   }
 };
 
+class ORCPlatformSupport : public orc::LLJIT::PlatformSupport {
+public:
+  ORCPlatformSupport(orc::LLJIT &J) : J(J) {}
+
+  Error initialize(orc::JITDylib &JD) override {
+    using llvm::orc::shared::SPSExecutorAddr;
+    using llvm::orc::shared::SPSString;
+    using SPSDLOpenSig = SPSExecutorAddr(SPSString, int32_t);
+    enum dlopen_mode : int32_t {
+      ORC_RT_RTLD_LAZY = 0x1,
+      ORC_RT_RTLD_NOW = 0x2,
+      ORC_RT_RTLD_LOCAL = 0x4,
+      ORC_RT_RTLD_GLOBAL = 0x8
+    };
+
+    if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlopen_wrapper")) {
+      return J.getExecutionSession().callSPSWrapper<SPSDLOpenSig>(
+          *WrapperAddr, DSOHandles[&JD], JD.getName(),
+          int32_t(ORC_RT_RTLD_LAZY));
+    } else
+      return WrapperAddr.takeError();
+  }
+
+  Error deinitialize(orc::JITDylib &JD) override {
+    using llvm::orc::shared::SPSExecutorAddr;
+    using SPSDLCloseSig = int32_t(SPSExecutorAddr);
+
+    if (auto WrapperAddr = J.lookup("__orc_rt_jit_dlclose_wrapper")) {
+      int32_t result;
+      auto E = J.getExecutionSession().callSPSWrapper<SPSDLCloseSig>(
+          *WrapperAddr, result, DSOHandles[&JD]);
+      if (E)
+        return E;
+      else if (result)
+        return make_error<StringError>("dlclose failed",
+                                       inconvertibleErrorCode());
+      DSOHandles.erase(&JD);
+    } else
+      return WrapperAddr.takeError();
+    return Error::success();
+  }
+
+private:
+  orc::LLJIT &J;
+  DenseMap<orc::JITDylib *, orc::ExecutorAddr> DSOHandles;
+};
+
 // On Mingw and Cygwin, an external symbol named '__main' is called from the
 // generated 'main' function to allow static initialization.  To avoid linking
 // problems with remote targets (because lli's remote target support does not
@@ -904,21 +959,29 @@ int runOrcJIT(const char *ProgName) {
   }
 
   // Set up LLJIT platform.
-  {
-    LLJITPlatform P = Platform;
-    if (P == LLJITPlatform::DetectHost)
+  LLJITPlatform P = Platform;
+  if (P == LLJITPlatform::DetectHost) {
+    if (JITLinker == JITLinkerKind::JITLink && !OrcRuntime.empty() &&
+        (TT->isOSBinFormatMachO() || TT->isOSBinFormatELF()))
+      P = LLJITPlatform::ORC;
+    else
       P = LLJITPlatform::GenericIR;
-
-    switch (P) {
-    case LLJITPlatform::GenericIR:
-      // Nothing to do: LLJITBuilder will use this by default.
-      break;
-    case LLJITPlatform::Inactive:
-      Builder.setPlatformSetUp(orc::setUpInactivePlatform);
-      break;
-    default:
-      llvm_unreachable("Unrecognized platform value");
-    }
+  }
+  switch (P) {
+  case LLJITPlatform::ORC:
+    Builder.setPlatformSetUp([](llvm::orc::LLJIT &J) -> llvm::Error {
+      J.setPlatformSupport(std::make_unique<ORCPlatformSupport>(J));
+      return Error::success();
+    });
+    break;
+  case LLJITPlatform::GenericIR:
+    // Nothing to do: LLJITBuilder will use this by default.
+    break;
+  case LLJITPlatform::Inactive:
+    Builder.setPlatformSetUp(orc::setUpInactivePlatform);
+    break;
+  default:
+    llvm_unreachable("Unrecognized platform value");
   }
 
   std::unique_ptr<orc::ExecutorProcessControl> EPC = nullptr;
@@ -926,13 +989,15 @@ int runOrcJIT(const char *ProgName) {
     EPC = ExitOnErr(orc::SelfExecutorProcessControl::Create(
         std::make_shared<orc::SymbolStringPool>()));
 
-    Builder.setObjectLinkingLayerCreator([&EPC](orc::ExecutionSession &ES,
-                                                const Triple &) {
+    Builder.setObjectLinkingLayerCreator([&EPC, &P](orc::ExecutionSession &ES,
+                                                    const Triple &TT) {
       auto L = std::make_unique<orc::ObjectLinkingLayer>(ES, EPC->getMemMgr());
-      L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
-          ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
-      L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
-          ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
+      if (P != LLJITPlatform::ORC) {
+        L->addPlugin(std::make_unique<orc::EHFrameRegistrationPlugin>(
+            ES, ExitOnErr(orc::EPCEHFrameRegistrar::Create(ES))));
+        L->addPlugin(std::make_unique<orc::DebugObjectManagerPlugin>(
+            ES, ExitOnErr(orc::createJITLoaderGDBRegistrar(ES))));
+      }
       return L;
     });
   }
@@ -979,6 +1044,31 @@ int runOrcJIT(const char *ProgName) {
         std::make_unique<LLIBuiltinFunctionGenerator>(GenerateBuiltinFunctions,
                                                       Mangle));
 
+  if (P == LLJITPlatform::ORC) {
+    if (auto *OLL = llvm::dyn_cast<llvm::orc::ObjectLinkingLayer>(ObjLayer)) {
+      auto &ES = J->getExecutionSession();
+      if (TT->isOSBinFormatMachO()) {
+        if (auto P = llvm::orc::MachOPlatform::Create(
+                ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str()))
+          ES.setPlatform(std::move(*P));
+        else
+          ExitOnErr(P.takeError());
+      } else if (TT->isOSBinFormatELF()) {
+        if (auto P = llvm::orc::ELFNixPlatform::Create(
+                ES, *OLL, J->getMainJITDylib(), OrcRuntime.c_str()))
+          ES.setPlatform(std::move(*P));
+        else
+          ExitOnErr(P.takeError());
+      } else {
+        errs() << "No ORC platform support\n";
+        exit(1);
+      }
+    } else {
+      errs() << "ORC platform requires JITLink\n";
+      exit(1);
+    }
+  }
+
   // Regular modules are greedy: They materialize as a whole and trigger
   // materialization for all required symbols recursively. Lazy modules go
   // through partitioning and they replace outgoing calls with reexport stubs


        


More information about the llvm-commits mailing list