[llvm] 7260cdd - [ORC][COFF] Introduce COFFVCRuntimeBootstrapper.

Sunho Kim via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 10 23:27:55 PDT 2022


Author: Sunho Kim
Date: 2022-08-11T15:27:47+09:00
New Revision: 7260cdd2e13a3a8970fe106c3d705609029640b5

URL: https://github.com/llvm/llvm-project/commit/7260cdd2e13a3a8970fe106c3d705609029640b5
DIFF: https://github.com/llvm/llvm-project/commit/7260cdd2e13a3a8970fe106c3d705609029640b5.diff

LOG: [ORC][COFF] Introduce COFFVCRuntimeBootstrapper.

Introduces COFFVCRuntimeBootstrapper that loads/initialize vc runtime libraries. In COFF, we *must* jit-link vc runtime libraries as COFF relocation types have no proper way to deal with out-of-reach data symbols ragardless of linking mode. (even dynamic version msvcrt.lib have tons of static data symbols that must be jit-linked) This class tries to load vc runtime library files from msvc installations with an option to override the path.

There are some complications when dealing with static version of vc runtimes. First, they need static initializers to be ran that requires COFFPlatform support but orc runtime will not be usable before vc runtimes are fully initialized. (as orc runtime will use msvc stl libraries) COFFPlatform that will be introduced in a following up patch will collect static initializers and run them manually in host before boostrapping itself. So, the user will have to do the following.
1. Create COFFPlatform that addes static initializer collecting passes.
2. LoadVCRuntime
3. InitializeVCRuntime
4. COFFPlatform.bootstrap()
Second, the internal crt initialization function had to be reimplemented in orc side. There are other ways of doing this, but this is the simplest implementation that makes platform fully responsible for static initializer. The complication comes from the fact that crt initialization functions (such as acrt_initialize or dllmain_crt_process_attach) actually run all static initializers by traversing from `__xi_a` symbol to `__xi_z`. This requires symbols to be contiguously allocated in sections alphabetically sorted in memory, which is not possible right now and not practical in jit setting. We might ignore emission of `__xi_a` and `__xi_z` symbol and allocate them ourselves, but we have to take extra care after orc runtime boostrap has been done -- as that point orc runtime should be the one running the static initializers.

Reviewed By: lhames

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

Added: 
    llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h
    llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp

Modified: 
    llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
    llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
    llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
    llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
    llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
    llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
    llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
    llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
    llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
    llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h
new file mode 100644
index 0000000000000..e3904717f1b26
--- /dev/null
+++ b/llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h
@@ -0,0 +1,89 @@
+//===----- COFFVCRuntimeSupport.h -- VC runtime support in ORC --*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Utilities for loading and initializaing vc runtime in Orc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_COFFCRUNTIMESUPPORT_H
+#define LLVM_EXECUTIONENGINE_ORC_COFFCRUNTIMESUPPORT_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ExecutionEngine/Orc/Core.h"
+#include "llvm/ExecutionEngine/Orc/ExecutorProcessControl.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/Shared/ExecutorAddress.h"
+
+#include <future>
+#include <memory>
+#include <thread>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+/// Bootstraps the vc runtime within jitdylibs.
+class COFFVCRuntimeBootstrapper {
+public:
+  /// Try to create a COFFVCRuntimeBootstrapper instance. An optional
+  /// RuntimePath can be given to specify the location of directory that
+  /// contains all vc runtime library files such as ucrt.lib and msvcrt.lib. If
+  /// not path was given, it will try to search the MSVC toolchain and Windows
+  /// SDK installation and use the found library files automatically.
+  ///
+  /// Note that depending on the build setting, a 
diff erent library
+  /// file must be used. In general, if vc runtime was statically linked to the
+  /// object file that is to be jit-linked, LoadStaticVCRuntime and
+  /// InitializeStaticVCRuntime must be used with libcmt.lib, libucrt.lib,
+  /// libvcruntimelib. If vc runtime was dynamically linked LoadDynamicVCRuntime
+  /// must be used along with msvcrt.lib, ucrt.lib, vcruntime.lib.
+  ///
+  /// More information is on:
+  /// https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features
+  static Expected<std::unique_ptr<COFFVCRuntimeBootstrapper>>
+  Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+         const char *RuntimePath = nullptr);
+
+  /// Adds symbol definitions of static version of msvc runtime libraries.
+  Expected<std::vector<std::string>>
+  loadStaticVCRuntime(JITDylib &JD, bool DebugVersion = false);
+
+  /// Runs the initializer of static version of msvc runtime libraries.
+  /// This must be called before calling any functions requiring c runtime (e.g.
+  /// printf) within the jit session. Note that proper initialization of vc
+  /// runtime requires ability of running static initializers. Cosider setting
+  /// up COFFPlatform.
+  Error initializeStaticVCRuntime(JITDylib &JD);
+
+  /// Adds symbol definitions of dynamic versino of msvc runtie libraries.
+  Expected<std::vector<std::string>>
+  loadDynamicVCRuntime(JITDylib &JD, bool DebugVersion = false);
+
+private:
+  COFFVCRuntimeBootstrapper(ExecutionSession &ES,
+                            ObjectLinkingLayer &ObjLinkingLayer,
+                            const char *RuntimePath);
+
+  ExecutionSession &ES;
+  ObjectLinkingLayer &ObjLinkingLayer;
+  std::string RuntimePath;
+
+  struct MSVCToolchainPath {
+    SmallString<256> VCToolchainLib;
+    SmallString<256> UCRTSdkLib;
+  };
+
+  static Expected<MSVCToolchainPath> getMSVCToolchainPath();
+  Error loadVCRuntime(JITDylib &JD, std::vector<std::string> &ImportedLibraries,
+                      ArrayRef<StringRef> VCLibs, ArrayRef<StringRef> UCRTLibs);
+};
+
+} // namespace orc
+} // namespace llvm
+
+#endif

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
index 88a2796ed23ba..20f5c9812dea6 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/ExecutorProcessControl.h
@@ -259,6 +259,15 @@ class ExecutorProcessControl {
   virtual Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
                                       ArrayRef<std::string> Args) = 0;
 
+  // TODO: move this to ORC runtime.
+  /// Run function with a int (*)(void) signature.
+  virtual Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) = 0;
+
+  // TODO: move this to ORC runtime.
+  /// Run function with a int (*)(int) signature.
+  virtual Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr,
+                                             int Arg) = 0;
+
   /// Run a wrapper function in the executor. The given WFRHandler will be
   /// called on the result when it is returned.
   ///
@@ -397,6 +406,14 @@ class UnsupportedExecutorProcessControl : public ExecutorProcessControl {
     llvm_unreachable("Unsupported");
   }
 
+  Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override {
+    llvm_unreachable("Unsupported");
+  }
+
+  Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override {
+    llvm_unreachable("Unsupported");
+  }
+
   void callWrapperAsync(ExecutorAddr WrapperFnAddr,
                         IncomingWFRHandler OnComplete,
                         ArrayRef<char> ArgBuffer) override {
@@ -434,6 +451,10 @@ class SelfExecutorProcessControl
   Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
                               ArrayRef<std::string> Args) override;
 
+  Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override;
+
+  Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override;
+
   void callWrapperAsync(ExecutorAddr WrapperFnAddr,
                         IncomingWFRHandler OnComplete,
                         ArrayRef<char> ArgBuffer) override;

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
index 2aedf1e44ad8b..82d6901c08153 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h
@@ -47,6 +47,8 @@ extern const char *RegisterEHFrameSectionWrapperName;
 extern const char *DeregisterEHFrameSectionWrapperName;
 
 extern const char *RunAsMainWrapperName;
+extern const char *RunAsVoidFunctionWrapperName;
+extern const char *RunAsIntFunctionWrapperName;
 
 using SPSSimpleExecutorDylibManagerOpenSignature =
     shared::SPSExpected<uint64_t>(shared::SPSExecutorAddr, shared::SPSString,
@@ -81,7 +83,8 @@ using SPSExecutorSharedMemoryMapperServiceReleaseSignature = shared::SPSError(
 
 using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddr,
                                       shared::SPSSequence<shared::SPSString>);
-
+using SPSRunAsVoidFunctionSignature = int32_t(shared::SPSExecutorAddr);
+using SPSRunAsIntFunctionSignature = int32_t(shared::SPSExecutorAddr, int32_t);
 } // end namespace rt
 } // end namespace orc
 } // end namespace llvm

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
index bd72e45353256..25b79be48810c 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/SimpleRemoteEPC.h
@@ -77,6 +77,10 @@ class SimpleRemoteEPC : public ExecutorProcessControl,
   Expected<int32_t> runAsMain(ExecutorAddr MainFnAddr,
                               ArrayRef<std::string> Args) override;
 
+  Expected<int32_t> runAsVoidFunction(ExecutorAddr VoidFnAddr) override;
+
+  Expected<int32_t> runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override;
+
   void callWrapperAsync(ExecutorAddr WrapperFnAddr,
                         IncomingWFRHandler OnComplete,
                         ArrayRef<char> ArgBuffer) override;
@@ -129,6 +133,8 @@ class SimpleRemoteEPC : public ExecutorProcessControl,
 
   std::unique_ptr<EPCGenericDylibManager> DylibMgr;
   ExecutorAddr RunAsMainAddr;
+  ExecutorAddr RunAsVoidFunctionAddr;
+  ExecutorAddr RunAsIntFunctionAddr;
 
   uint64_t NextSeqNo = 0;
   PendingCallWrapperResultsMap PendingCallWrapperResults;

diff  --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
index 1d2f6d2be089a..e01bb50d06d6d 100644
--- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
+++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h
@@ -32,6 +32,9 @@ namespace orc {
 int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
               Optional<StringRef> ProgramName = None);
 
+int runAsVoidFunction(int (*Func)(void));
+int runAsIntFunction(int (*Func)(int), int Arg);
+
 } // end namespace orc
 } // end namespace llvm
 

diff  --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
index 5a03102f1bdfc..8b8eaac93d8a1 100644
--- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -3,6 +3,7 @@ if( CMAKE_HOST_UNIX AND HAVE_LIBRT )
 endif()
 
 add_llvm_component_library(LLVMOrcJIT
+  COFFVCRuntimeSupport.cpp
   CompileOnDemandLayer.cpp
   CompileUtils.cpp
   Core.cpp
@@ -59,6 +60,7 @@ add_llvm_component_library(LLVMOrcJIT
   Object
   OrcShared
   OrcTargetProcess
+  WindowsDriver
   MC
   MCDisassembler
   Passes

diff  --git a/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
new file mode 100644
index 0000000000000..f5be80c4affe2
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/Orc/COFFVCRuntimeSupport.cpp
@@ -0,0 +1,184 @@
+//===------- COFFVCRuntimeSupport.cpp - VC runtime support in ORC ---------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
+
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h"
+#include "llvm/Support/VirtualFileSystem.h"
+#include "llvm/WindowsDriver/MSVCPaths.h"
+
+#define DEBUG_TYPE "orc"
+
+using namespace llvm;
+using namespace llvm::orc;
+using namespace llvm::orc::shared;
+
+Expected<std::unique_ptr<COFFVCRuntimeBootstrapper>>
+COFFVCRuntimeBootstrapper::Create(ExecutionSession &ES,
+                                  ObjectLinkingLayer &ObjLinkingLayer,
+                                  const char *RuntimePath) {
+  return std::unique_ptr<COFFVCRuntimeBootstrapper>(
+      new COFFVCRuntimeBootstrapper(ES, ObjLinkingLayer, RuntimePath));
+}
+
+COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper(
+    ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer,
+    const char *RuntimePath)
+    : ES(ES), ObjLinkingLayer(ObjLinkingLayer) {
+  if (RuntimePath)
+    this->RuntimePath = RuntimePath;
+}
+
+Expected<std::vector<std::string>>
+COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib &JD,
+                                               bool DebugVersion) {
+  StringRef VCLibs[] = {"libvcruntime.lib", "libcmt.lib", "libcpmt.lib"};
+  StringRef UCRTLibs[] = {"libucrt.lib"};
+  std::vector<std::string> ImportedLibraries;
+  if (auto Err = loadVCRuntime(JD, ImportedLibraries, makeArrayRef(VCLibs),
+                               makeArrayRef(UCRTLibs)))
+    return Err;
+  return ImportedLibraries;
+}
+
+Expected<std::vector<std::string>>
+COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib &JD,
+                                                bool DebugVersion) {
+  StringRef VCLibs[] = {"vcruntime.lib", "msvcrt.lib", "msvcprt.lib"};
+  StringRef UCRTLibs[] = {"ucrt.lib"};
+  std::vector<std::string> ImportedLibraries;
+  if (auto Err = loadVCRuntime(JD, ImportedLibraries, makeArrayRef(VCLibs),
+                               makeArrayRef(UCRTLibs)))
+    return Err;
+  return ImportedLibraries;
+}
+
+Error COFFVCRuntimeBootstrapper::loadVCRuntime(
+    JITDylib &JD, std::vector<std::string> &ImportedLibraries,
+    ArrayRef<StringRef> VCLibs, ArrayRef<StringRef> UCRTLibs) {
+  MSVCToolchainPath Path;
+  if (!RuntimePath.empty()) {
+    Path.UCRTSdkLib = RuntimePath;
+    Path.VCToolchainLib = RuntimePath;
+  } else {
+    auto ToolchainPath = getMSVCToolchainPath();
+    if (!ToolchainPath)
+      return ToolchainPath.takeError();
+    Path = *ToolchainPath;
+  }
+  LLVM_DEBUG({
+    dbgs() << "Using VC toolchain pathes\n";
+    dbgs() << "  VC toolchain path: " << Path.VCToolchainLib << "\n";
+    dbgs() << "  UCRT path: " << Path.UCRTSdkLib << "\n";
+  });
+
+  auto LoadLibrary = [&](SmallString<256> LibPath, StringRef LibName) -> Error {
+    sys::path::append(LibPath, LibName);
+
+    auto G = StaticLibraryDefinitionGenerator::Load(ObjLinkingLayer,
+                                                    LibPath.c_str());
+    if (!G)
+      return G.takeError();
+
+    for (auto &Lib : (*G)->getImportedDynamicLibraries())
+      ImportedLibraries.push_back(Lib);
+
+    JD.addGenerator(std::move(*G));
+
+    return Error::success();
+  };
+  for (auto &Lib : UCRTLibs)
+    if (auto Err = LoadLibrary(Path.UCRTSdkLib, Lib))
+      return Err;
+
+  for (auto &Lib : VCLibs)
+    if (auto Err = LoadLibrary(Path.VCToolchainLib, Lib))
+      return Err;
+  ImportedLibraries.push_back("ntdll.dll");
+  ImportedLibraries.push_back("Kernel32.dll");
+
+  return Error::success();
+}
+
+Error COFFVCRuntimeBootstrapper::initializeStaticVCRuntime(JITDylib &JD) {
+  ExecutorAddr jit_scrt_initialize, jit_scrt_dllmain_before_initialize_c,
+      jit_scrt_initialize_type_info,
+      jit_scrt_initialize_default_local_stdio_options;
+  if (auto Err = lookupAndRecordAddrs(
+          ES, LookupKind::Static, makeJITDylibSearchOrder(&JD),
+          {{ES.intern("__scrt_initialize_crt"), &jit_scrt_initialize},
+           {ES.intern("__scrt_dllmain_before_initialize_c"),
+            &jit_scrt_dllmain_before_initialize_c},
+           {ES.intern("?__scrt_initialize_type_info@@YAXXZ"),
+            &jit_scrt_initialize_type_info},
+           {ES.intern("__scrt_initialize_default_local_stdio_options"),
+            &jit_scrt_initialize_default_local_stdio_options}}))
+    return Err;
+
+  auto RunVoidInitFunc = [&](ExecutorAddr Addr) -> Error {
+    if (auto Res = ES.getExecutorProcessControl().runAsVoidFunction(Addr))
+      return Error::success();
+    else
+      return Res.takeError();
+  };
+
+  auto R =
+      ES.getExecutorProcessControl().runAsIntFunction(jit_scrt_initialize, 0);
+  if (!R)
+    return R.takeError();
+
+  if (auto Err = RunVoidInitFunc(jit_scrt_dllmain_before_initialize_c))
+    return Err;
+
+  if (auto Err = RunVoidInitFunc(jit_scrt_initialize_type_info))
+    return Err;
+
+  if (auto Err =
+          RunVoidInitFunc(jit_scrt_initialize_default_local_stdio_options))
+    return Err;
+
+  SymbolAliasMap Alias;
+  Alias[ES.intern("__run_after_c_init")] = {
+      ES.intern("__scrt_dllmain_after_initialize_c"), JITSymbolFlags::Exported};
+  if (auto Err = JD.define(symbolAliases(Alias)))
+    return Err;
+
+  return Error::success();
+}
+
+Expected<COFFVCRuntimeBootstrapper::MSVCToolchainPath>
+COFFVCRuntimeBootstrapper::getMSVCToolchainPath() {
+  std::string VCToolChainPath;
+  ToolsetLayout VSLayout;
+  IntrusiveRefCntPtr<vfs::FileSystem> VFS = vfs::getRealFileSystem();
+  if (!findVCToolChainViaCommandLine(*VFS, None, None, None, VCToolChainPath,
+                                     VSLayout) &&
+      !findVCToolChainViaEnvironment(*VFS, VCToolChainPath, VSLayout) &&
+      !findVCToolChainViaSetupConfig(*VFS, VCToolChainPath, VSLayout) &&
+      !findVCToolChainViaRegistry(VCToolChainPath, VSLayout))
+    return make_error<StringError>("Couldn't find msvc toolchain.",
+                                   inconvertibleErrorCode());
+
+  std::string UniversalCRTSdkPath;
+  std::string UCRTVersion;
+  if (!getUniversalCRTSdkDir(*VFS, None, None, None, UniversalCRTSdkPath,
+                             UCRTVersion))
+    return make_error<StringError>("Couldn't find universal sdk.",
+                                   inconvertibleErrorCode());
+
+  MSVCToolchainPath ToolchainPath;
+  SmallString<256> VCToolchainLib(VCToolChainPath);
+  sys::path::append(VCToolchainLib, "lib", "x64");
+  ToolchainPath.VCToolchainLib = VCToolchainLib;
+
+  SmallString<256> UCRTSdkLib(UniversalCRTSdkPath);
+  sys::path::append(UCRTSdkLib, "Lib", UCRTVersion, "ucrt", "x64");
+  ToolchainPath.UCRTSdkLib = UCRTSdkLib;
+  return ToolchainPath;
+}

diff  --git a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
index 412b9f95ea627..8f3bd92cb3b4f 100644
--- a/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ExecutorProcessControl.cpp
@@ -121,6 +121,18 @@ SelfExecutorProcessControl::runAsMain(ExecutorAddr MainFnAddr,
   return orc::runAsMain(MainFnAddr.toPtr<MainTy>(), Args);
 }
 
+Expected<int32_t>
+SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
+  using VoidTy = int (*)();
+  return orc::runAsVoidFunction(VoidFnAddr.toPtr<VoidTy>());
+}
+
+Expected<int32_t>
+SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) {
+  using IntTy = int (*)(int);
+  return orc::runAsIntFunction(IntFnAddr.toPtr<IntTy>(), Arg);
+}
+
 void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr,
                                                   IncomingWFRHandler SendResult,
                                                   ArrayRef<char> ArgBuffer) {

diff  --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
index dfdd846c46a75..86e31c52100ea 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp
@@ -56,6 +56,10 @@ const char *DeregisterEHFrameSectionWrapperName =
     "__llvm_orc_bootstrap_deregister_ehframe_section_wrapper";
 
 const char *RunAsMainWrapperName = "__llvm_orc_bootstrap_run_as_main_wrapper";
+const char *RunAsVoidFunctionWrapperName =
+    "__llvm_orc_bootstrap_run_as_void_function_wrapper";
+const char *RunAsIntFunctionWrapperName =
+    "__llvm_orc_bootstrap_run_as_int_function_wrapper";
 
 } // end namespace rt
 } // end namespace orc

diff  --git a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
index 47364a92a4517..c69df4f45588f 100644
--- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp
@@ -54,6 +54,23 @@ Expected<int32_t> SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr,
   return Result;
 }
 
+Expected<int32_t> SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) {
+  int32_t Result = 0;
+  if (auto Err = callSPSWrapper<rt::SPSRunAsVoidFunctionSignature>(
+          RunAsVoidFunctionAddr, Result, ExecutorAddr(VoidFnAddr)))
+    return std::move(Err);
+  return Result;
+}
+
+Expected<int32_t> SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr,
+                                                    int Arg) {
+  int32_t Result = 0;
+  if (auto Err = callSPSWrapper<rt::SPSRunAsIntFunctionSignature>(
+          RunAsIntFunctionAddr, Result, ExecutorAddr(IntFnAddr), Arg))
+    return std::move(Err);
+  return Result;
+}
+
 void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr,
                                        IncomingWFRHandler OnComplete,
                                        ArrayRef<char> ArgBuffer) {
@@ -312,7 +329,9 @@ Error SimpleRemoteEPC::setup(Setup S) {
   if (auto Err = getBootstrapSymbols(
           {{JDI.JITDispatchContext, ExecutorSessionObjectName},
            {JDI.JITDispatchFunction, DispatchFnName},
-           {RunAsMainAddr, rt::RunAsMainWrapperName}}))
+           {RunAsMainAddr, rt::RunAsMainWrapperName},
+           {RunAsVoidFunctionAddr, rt::RunAsVoidFunctionWrapperName},
+           {RunAsIntFunctionAddr, rt::RunAsIntFunctionWrapperName}}))
     return Err;
 
   if (auto DM =

diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
index 909d47deef59d..b38877955282e 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/OrcRTBootstrap.cpp
@@ -56,6 +56,27 @@ runAsMainWrapper(const char *ArgData, size_t ArgSize) {
       .release();
 }
 
+static llvm::orc::shared::CWrapperFunctionResult
+runAsVoidFunctionWrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<rt::SPSRunAsVoidFunctionSignature>::handle(
+             ArgData, ArgSize,
+             [](ExecutorAddr MainAddr) -> int32_t {
+               return runAsVoidFunction(MainAddr.toPtr<int32_t (*)(void)>());
+             })
+      .release();
+}
+
+static llvm::orc::shared::CWrapperFunctionResult
+runAsIntFunctionWrapper(const char *ArgData, size_t ArgSize) {
+  return WrapperFunction<rt::SPSRunAsIntFunctionSignature>::handle(
+             ArgData, ArgSize,
+             [](ExecutorAddr MainAddr, int32_t Arg) -> int32_t {
+               return runAsIntFunction(MainAddr.toPtr<int32_t (*)(int32_t)>(),
+                                       Arg);
+             })
+      .release();
+}
+
 void addTo(StringMap<ExecutorAddr> &M) {
   M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddr::fromPtr(
       &writeUIntsWrapper<tpctypes::UInt8Write,
@@ -76,6 +97,10 @@ void addTo(StringMap<ExecutorAddr> &M) {
   M[rt::DeregisterEHFrameSectionWrapperName] =
       ExecutorAddr::fromPtr(&llvm_orc_deregisterEHFrameSectionWrapper);
   M[rt::RunAsMainWrapperName] = ExecutorAddr::fromPtr(&runAsMainWrapper);
+  M[rt::RunAsVoidFunctionWrapperName] =
+      ExecutorAddr::fromPtr(&runAsVoidFunctionWrapper);
+  M[rt::RunAsIntFunctionWrapperName] =
+      ExecutorAddr::fromPtr(&runAsIntFunctionWrapper);
 }
 
 } // end namespace rt_bootstrap

diff  --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
index a8e6c049cf4b7..b76b745cee9bc 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.cpp
@@ -39,5 +39,9 @@ int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
   return Main(Args.size() + !!ProgramName, ArgV.data());
 }
 
+int runAsVoidFunction(int (*Func)(void)) { return Func(); }
+
+int runAsIntFunction(int (*Func)(int), int Arg) { return Func(Arg); }
+
 } // End namespace orc.
 } // End namespace llvm.


        


More information about the llvm-commits mailing list