Enable lazy Orc JIT feature (#732)

The feature is disabled by default, to enable it, please use
`cmake -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1`
to build iwasm.
This commit is contained in:
Wenyong Huang
2021-09-07 11:39:57 +08:00
committed by GitHub
parent 7e60b8608e
commit 4b0d6083a3
9 changed files with 535 additions and 6 deletions

View File

@ -1207,13 +1207,174 @@ WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
void LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
#if WASM_ENABLE_LAZY_JIT != 0
void
aot_handle_llvm_errmsg(char *error_buf,
uint32 error_buf_size,
const char *string,
LLVMErrorRef error)
{
char *err_msg = LLVMGetErrorMessage(error);
if (error_buf != NULL) {
snprintf(error_buf, error_buf_size,
"%s: %s", string, err_msg);
}
LLVMDisposeErrorMessage(err_msg);
}
static bool
llvm_orcjit_create(AOTCompContext *comp_ctx)
{
char *err_msg = NULL;
char *cpu = NULL;
char *features = NULL;
char *llvm_triple = NULL;
char buf[128] = {0};
LLVMErrorRef error;
LLVMTargetRef llvm_targetref = NULL;
LLVMTargetMachineRef tm_opt = NULL;
LLVMTargetMachineRef tm_opt2 = NULL;
LLVMOrcLLLazyJITRef lazy_orcjit = NULL;
LLVMOrcJITTargetMachineBuilderRef tm_builder = NULL;
LLVMOrcLLLazyJITBuilderRef lazy_orcjit_builder = NULL;
#if LLVM_VERSION_MAJOR < 12
LLVMOrcJITDylibDefinitionGeneratorRef main_gen = NULL;
#else
LLVMOrcDefinitionGeneratorRef main_gen = NULL;
#endif
llvm_triple = LLVMGetDefaultTargetTriple();
if (llvm_triple == NULL) {
snprintf(buf, sizeof(buf), "failed to get default target triple.");
goto fail;
}
if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &err_msg) != 0) {
snprintf(buf, sizeof(buf),
"failed to get target reference from triple %s.", err_msg);
LLVMDisposeMessage(err_msg);
goto fail;
}
if (!LLVMTargetHasJIT(llvm_targetref)) {
snprintf(buf, sizeof(buf), "unspported JIT on this platform.");
goto fail;
}
cpu = LLVMGetHostCPUName();
if (cpu == NULL) {
snprintf(buf, sizeof(buf), "failed to get host cpu information.");
goto fail;
}
features = LLVMGetHostCPUFeatures();
if (features == NULL) {
snprintf(buf, sizeof(buf), "failed to get host cpu features.");
goto fail;
}
LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n",
cpu, features);
tm_opt = LLVMCreateTargetMachine(llvm_targetref, llvm_triple,
cpu, features,
LLVMCodeGenLevelAggressive,
LLVMRelocDefault,
LLVMCodeModelJITDefault);
if (!tm_opt) {
snprintf(buf, sizeof(buf), "failed to create target machine.");
goto fail;
}
tm_opt2 = LLVMCreateTargetMachine(llvm_targetref, llvm_triple,
cpu, features,
LLVMCodeGenLevelAggressive,
LLVMRelocDefault,
LLVMCodeModelJITDefault);
if (!tm_opt2) {
snprintf(buf, sizeof(buf), "failed to create target machine2.");
goto fail;
}
/* if success, it will dispose tm_opt2 memory. */
tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm_opt2);
if (!tm_builder) {
snprintf(buf, sizeof(buf), "failed to create target machine builder.");
goto fail;
}
tm_opt2 = NULL;
lazy_orcjit_builder = LLVMOrcCreateLLLazyJITBuilder();
if (!lazy_orcjit_builder) {
snprintf(buf, sizeof(buf), "failed to create lazy jit builder.");
goto fail;
}
LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(lazy_orcjit_builder,
tm_builder);
/* if success, it will dispose lazy_orcjit_builder memory */
error = LLVMOrcCreateLLLazyJIT(&lazy_orcjit, lazy_orcjit_builder);
if (error) {
aot_handle_llvm_errmsg(buf, sizeof(buf),
"failed to create llvm lazy orcjit instance",
error);
goto fail;
}
lazy_orcjit_builder = NULL;
error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(
&main_gen, LLVMOrcLLLazyJITGetGlobalPrefix(lazy_orcjit),
0, NULL);
if (error) {
aot_handle_llvm_errmsg(buf, sizeof(buf),
"failed to create dynmaic library search generator", error);
goto fail;
}
LLVMOrcJITDylibAddGenerator(LLVMOrcLLLazyJITGetMainJITDylib(lazy_orcjit),
main_gen);
comp_ctx->lazy_orcjit = lazy_orcjit;
comp_ctx->target_machine = tm_opt;
comp_ctx->tm_builder = tm_builder;
LLVMDisposeMessage(llvm_triple);
LLVMDisposeMessage(cpu);
LLVMDisposeMessage(features);
return true;
fail:
if (lazy_orcjit)
LLVMOrcDisposeLLLazyJIT(lazy_orcjit);
if (tm_builder)
LLVMOrcDisposeJITTargetMachineBuilder(tm_builder);
if (lazy_orcjit_builder)
LLVMOrcDisposeLLLazyJITBuilder(lazy_orcjit_builder);
if (tm_opt2)
LLVMDisposeTargetMachine(tm_opt2);
if (tm_opt)
LLVMDisposeTargetMachine(tm_opt);
if (features)
LLVMDisposeMessage(features);
if (cpu)
LLVMDisposeMessage(cpu);
if (llvm_triple)
LLVMDisposeMessage(llvm_triple);
aot_set_last_error(buf);
return false;
}
#endif /* WASM_ENABLE_LAZY_JIT != 0 */
AOTCompContext *
aot_create_comp_context(AOTCompData *comp_data,
aot_comp_option_t option)
{
AOTCompContext *comp_ctx, *ret = NULL;
/*LLVMTypeRef elem_types[8];*/
#if WASM_ENABLE_LAZY_JIT == 0
struct LLVMMCJITCompilerOptions jit_options;
#endif
LLVMTargetRef target;
char *triple = NULL, *triple_norm, *arch, *abi;
char *cpu = NULL, *features, buf[128];
@ -1225,11 +1386,18 @@ aot_create_comp_context(AOTCompData *comp_data,
LLVMTargetDataRef target_data_ref;
/* Initialize LLVM environment */
#if WASM_ENABLE_LAZY_JIT != 0
LLVMInitializeCore(LLVMGetGlobalPassRegistry());
LLVMInitializeNativeTarget();
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
#else
LLVMInitializeAllTargetInfos();
LLVMInitializeAllTargets();
LLVMInitializeAllTargetMCs();
LLVMInitializeAllAsmPrinters();
LLVMLinkInMCJIT();
#endif
/* Allocate memory */
if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) {
@ -1241,10 +1409,24 @@ aot_create_comp_context(AOTCompData *comp_data,
comp_ctx->comp_data = comp_data;
/* Create LLVM context, module and builder */
#if WASM_ENABLE_LAZY_JIT != 0
comp_ctx->ts_context = LLVMOrcCreateNewThreadSafeContext();
if (!comp_ctx->ts_context) {
aot_set_last_error("create LLVM ThreadSafeContext failed.");
return NULL;
}
/* Get a reference to the underlying LLVMContext */
if (!(comp_ctx->context =
LLVMOrcThreadSafeContextGetContext(comp_ctx->ts_context))) {
aot_set_last_error("get context from LLVM ThreadSafeContext failed.");
goto fail;
}
#else
if (!(comp_ctx->context = LLVMContextCreate())) {
aot_set_last_error("create LLVM context failed.");
goto fail;
}
#endif
if (!(comp_ctx->builder = LLVMCreateBuilderInContext(comp_ctx->context))) {
aot_set_last_error("create LLVM builder failed.");
@ -1288,6 +1470,14 @@ aot_create_comp_context(AOTCompData *comp_data,
if (option->is_jit_mode) {
char *triple_jit = NULL;
#if WASM_ENABLE_LAZY_JIT != 0
/* Create LLLazyJIT Instance */
if (!llvm_orcjit_create(comp_ctx)) {
aot_set_last_error("create LLVM Lazy JIT Compiler failed.");
goto fail;
}
#else
/* Create LLVM execution engine */
LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options));
jit_options.OptLevel = LLVMCodeGenLevelAggressive;
@ -1303,15 +1493,28 @@ aot_create_comp_context(AOTCompData *comp_data,
aot_set_last_error("create LLVM JIT compiler failed.");
goto fail;
}
comp_ctx->is_jit_mode = true;
comp_ctx->target_machine =
LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine);
#endif
comp_ctx->is_jit_mode = true;
#ifndef OS_ENABLE_HW_BOUND_CHECK
comp_ctx->enable_bound_check = true;
#else
comp_ctx->enable_bound_check = false;
#endif
#if WASM_ENABLE_LAZY_JIT != 0
if (!(triple_jit =
(char *)LLVMOrcLLLazyJITGetTripleString(comp_ctx->lazy_orcjit))) {
aot_set_last_error("can not get triple from the target machine");
goto fail;
}
/* Save target arch */
get_target_arch_from_triple(triple_jit, comp_ctx->target_arch,
sizeof(comp_ctx->target_arch));
#else
if (!(triple_jit =
LLVMGetTargetMachineTriple(comp_ctx->target_machine))) {
aot_set_last_error("can not get triple from the target machine");
@ -1322,6 +1525,7 @@ aot_create_comp_context(AOTCompData *comp_data,
get_target_arch_from_triple(triple_jit, comp_ctx->target_arch,
sizeof(comp_ctx->target_arch));
LLVMDisposeMessage(triple_jit);
#endif
}
else {
/* Create LLVM target machine */
@ -1706,9 +1910,29 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
if (!comp_ctx)
return;
if (comp_ctx->pass_mgr)
if (comp_ctx->pass_mgr) {
LLVMFinalizeFunctionPassManager(comp_ctx->pass_mgr);
LLVMDisposePassManager(comp_ctx->pass_mgr);
}
#if WASM_ENABLE_LAZY_JIT != 0
if (comp_ctx->target_machine && comp_ctx->is_jit_mode)
LLVMDisposeTargetMachine(comp_ctx->target_machine);
if (comp_ctx->builder)
LLVMDisposeBuilder(comp_ctx->builder);
if (comp_ctx->lazy_orcjit)
LLVMOrcDisposeLLLazyJIT(comp_ctx->lazy_orcjit);
if (comp_ctx->ts_context)
LLVMOrcDisposeThreadSafeContext(comp_ctx->ts_context);
if (comp_ctx->tm_builder)
LLVMOrcDisposeJITTargetMachineBuilder(comp_ctx->tm_builder);
LLVMShutdown();
#else
if (comp_ctx->target_machine && !comp_ctx->is_jit_mode)
LLVMDisposeTargetMachine(comp_ctx->target_machine);
@ -1725,6 +1949,7 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
if (comp_ctx->context)
LLVMContextDispose(comp_ctx->context);
#endif
if (comp_ctx->func_ctxes)
aot_destroy_func_contexts(comp_ctx->func_ctxes,