diff --git a/llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h b/llvm/include/llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h new file mode 100644 index 00000000000000..e3904717f1b267 --- /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 +#include +#include +#include + +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 different 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> + Create(ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + const char *RuntimePath = nullptr); + + /// Adds symbol definitions of static version of msvc runtime libraries. + Expected> + 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> + 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 getMSVCToolchainPath(); + Error loadVCRuntime(JITDylib &JD, std::vector &ImportedLibraries, + ArrayRef VCLibs, ArrayRef 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 88a2796ed23bad..20f5c9812dea62 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 runAsMain(ExecutorAddr MainFnAddr, ArrayRef Args) = 0; + // TODO: move this to ORC runtime. + /// Run function with a int (*)(void) signature. + virtual Expected runAsVoidFunction(ExecutorAddr VoidFnAddr) = 0; + + // TODO: move this to ORC runtime. + /// Run function with a int (*)(int) signature. + virtual Expected 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 runAsVoidFunction(ExecutorAddr VoidFnAddr) override { + llvm_unreachable("Unsupported"); + } + + Expected runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override { + llvm_unreachable("Unsupported"); + } + void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef ArgBuffer) override { @@ -434,6 +451,10 @@ class SelfExecutorProcessControl Expected runAsMain(ExecutorAddr MainFnAddr, ArrayRef Args) override; + Expected runAsVoidFunction(ExecutorAddr VoidFnAddr) override; + + Expected runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override; + void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef ArgBuffer) override; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h b/llvm/include/llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h index 2aedf1e44ad8ba..82d6901c081531 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(shared::SPSExecutorAddr, shared::SPSString, @@ -81,7 +83,8 @@ using SPSExecutorSharedMemoryMapperServiceReleaseSignature = shared::SPSError( using SPSRunAsMainSignature = int64_t(shared::SPSExecutorAddr, shared::SPSSequence); - +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 bd72e45353256c..25b79be48810c6 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 runAsMain(ExecutorAddr MainFnAddr, ArrayRef Args) override; + Expected runAsVoidFunction(ExecutorAddr VoidFnAddr) override; + + Expected runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) override; + void callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef ArgBuffer) override; @@ -129,6 +133,8 @@ class SimpleRemoteEPC : public ExecutorProcessControl, std::unique_ptr 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 1d2f6d2be089a8..e01bb50d06d6d4 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 Args, Optional 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 5a03102f1bdfce..8b8eaac93d8a1e 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 00000000000000..f5be80c4affe20 --- /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> +COFFVCRuntimeBootstrapper::Create(ExecutionSession &ES, + ObjectLinkingLayer &ObjLinkingLayer, + const char *RuntimePath) { + return std::unique_ptr( + new COFFVCRuntimeBootstrapper(ES, ObjLinkingLayer, RuntimePath)); +} + +COFFVCRuntimeBootstrapper::COFFVCRuntimeBootstrapper( + ExecutionSession &ES, ObjectLinkingLayer &ObjLinkingLayer, + const char *RuntimePath) + : ES(ES), ObjLinkingLayer(ObjLinkingLayer) { + if (RuntimePath) + this->RuntimePath = RuntimePath; +} + +Expected> +COFFVCRuntimeBootstrapper::loadStaticVCRuntime(JITDylib &JD, + bool DebugVersion) { + StringRef VCLibs[] = {"libvcruntime.lib", "libcmt.lib", "libcpmt.lib"}; + StringRef UCRTLibs[] = {"libucrt.lib"}; + std::vector ImportedLibraries; + if (auto Err = loadVCRuntime(JD, ImportedLibraries, makeArrayRef(VCLibs), + makeArrayRef(UCRTLibs))) + return Err; + return ImportedLibraries; +} + +Expected> +COFFVCRuntimeBootstrapper::loadDynamicVCRuntime(JITDylib &JD, + bool DebugVersion) { + StringRef VCLibs[] = {"vcruntime.lib", "msvcrt.lib", "msvcprt.lib"}; + StringRef UCRTLibs[] = {"ucrt.lib"}; + std::vector ImportedLibraries; + if (auto Err = loadVCRuntime(JD, ImportedLibraries, makeArrayRef(VCLibs), + makeArrayRef(UCRTLibs))) + return Err; + return ImportedLibraries; +} + +Error COFFVCRuntimeBootstrapper::loadVCRuntime( + JITDylib &JD, std::vector &ImportedLibraries, + ArrayRef VCLibs, ArrayRef 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::getMSVCToolchainPath() { + std::string VCToolChainPath; + ToolsetLayout VSLayout; + IntrusiveRefCntPtr 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("Couldn't find msvc toolchain.", + inconvertibleErrorCode()); + + std::string UniversalCRTSdkPath; + std::string UCRTVersion; + if (!getUniversalCRTSdkDir(*VFS, None, None, None, UniversalCRTSdkPath, + UCRTVersion)) + return make_error("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 412b9f95ea6278..8f3bd92cb3b4f4 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(), Args); } +Expected +SelfExecutorProcessControl::runAsVoidFunction(ExecutorAddr VoidFnAddr) { + using VoidTy = int (*)(); + return orc::runAsVoidFunction(VoidFnAddr.toPtr()); +} + +Expected +SelfExecutorProcessControl::runAsIntFunction(ExecutorAddr IntFnAddr, int Arg) { + using IntTy = int (*)(int); + return orc::runAsIntFunction(IntFnAddr.toPtr(), Arg); +} + void SelfExecutorProcessControl::callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler SendResult, ArrayRef ArgBuffer) { diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcRTBridge.cpp index dfdd846c46a75c..86e31c52100ea6 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 47364a92a4517b..c69df4f45588f4 100644 --- a/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp +++ b/llvm/lib/ExecutionEngine/Orc/SimpleRemoteEPC.cpp @@ -54,6 +54,23 @@ Expected SimpleRemoteEPC::runAsMain(ExecutorAddr MainFnAddr, return Result; } +Expected SimpleRemoteEPC::runAsVoidFunction(ExecutorAddr VoidFnAddr) { + int32_t Result = 0; + if (auto Err = callSPSWrapper( + RunAsVoidFunctionAddr, Result, ExecutorAddr(VoidFnAddr))) + return std::move(Err); + return Result; +} + +Expected SimpleRemoteEPC::runAsIntFunction(ExecutorAddr IntFnAddr, + int Arg) { + int32_t Result = 0; + if (auto Err = callSPSWrapper( + RunAsIntFunctionAddr, Result, ExecutorAddr(IntFnAddr), Arg)) + return std::move(Err); + return Result; +} + void SimpleRemoteEPC::callWrapperAsync(ExecutorAddr WrapperFnAddr, IncomingWFRHandler OnComplete, ArrayRef 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 909d47deef59df..b38877955282e9 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::handle( + ArgData, ArgSize, + [](ExecutorAddr MainAddr) -> int32_t { + return runAsVoidFunction(MainAddr.toPtr()); + }) + .release(); +} + +static llvm::orc::shared::CWrapperFunctionResult +runAsIntFunctionWrapper(const char *ArgData, size_t ArgSize) { + return WrapperFunction::handle( + ArgData, ArgSize, + [](ExecutorAddr MainAddr, int32_t Arg) -> int32_t { + return runAsIntFunction(MainAddr.toPtr(), + Arg); + }) + .release(); +} + void addTo(StringMap &M) { M[rt::MemoryWriteUInt8sWrapperName] = ExecutorAddr::fromPtr( &writeUIntsWrapper &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 a8e6c049cf4b74..b76b745cee9bcf 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 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.