forked from OSchip/llvm-project
[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
This commit is contained in:
parent
87c4268329
commit
1aa71f8679
|
@ -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.
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
; RUN: %lli_orc_jitlink -relocation-model=pic %s | FileCheck %s
|
||||
|
||||
; CHECK: constructor
|
||||
; CHECK-NEXT: main
|
||||
; CHECK-NEXT: destructor
|
||||
|
||||
@__dso_handle = external hidden global i8
|
||||
@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
|
||||
@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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
; RUN: %lli_orc_jitlink %s | FileCheck %s
|
||||
|
||||
; CHECK: constructor
|
||||
; CHECK-NEXT: main
|
||||
; CHECK-NEXT: destructor
|
||||
|
||||
@__dso_handle = external hidden global i8
|
||||
@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
|
||||
@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
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
; RUN: %lli_orc_jitlink %s | FileCheck %s
|
||||
|
||||
; CHECK: constructor
|
||||
; CHECK-NEXT: main
|
||||
; CHECK-NEXT: destructor
|
||||
|
||||
@__dso_handle = external hidden global i8
|
||||
@.str = private unnamed_addr constant [5 x i8] c"main\00", align 1
|
||||
@.str.1 = private unnamed_addr constant [12 x i8] c"constructor\00", align 1
|
||||
@.str.2 = private unnamed_addr constant [11 x i8] c"destructor\00", align 1
|
||||
@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
|
||||
}
|
|
@ -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 @@ config.substitutions.append(
|
|||
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']
|
||||
|
|
|
@ -125,7 +125,7 @@ public:
|
|||
/// 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) {
|
||||
|
|
|
@ -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 *>>(
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 *>>(
|
||||
|
|
|
@ -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 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
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
|
||||
|
|
Loading…
Reference in New Issue