Răsfoiți Sursa

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.
Wenyong Huang 4 ani în urmă
părinte
comite
4b0d6083a3

+ 8 - 0
build-scripts/config_common.cmake

@@ -83,6 +83,9 @@ endif ()
 if (WAMR_BUILD_JIT EQUAL 1)
   if (WAMR_BUILD_AOT EQUAL 1)
     add_definitions("-DWASM_ENABLE_JIT=1")
+    if (WAMR_BUILD_LAZY_JIT EQUAL 1)
+      add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
+    endif ()
     if (NOT DEFINED LLVM_DIR)
       set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
       set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
@@ -122,6 +125,11 @@ else ()
 endif ()
 if (WAMR_BUILD_JIT EQUAL 1)
   message ("     WAMR JIT enabled")
+  if (WAMR_BUILD_LAZY_JIT EQUAL 1)
+    message ("     WAMR LazyJIT enabled")
+  else ()
+    message ("     WAMR LazyJIT disabled")
+  endif ()
 else ()
   message ("     WAMR JIT disabled")
 endif ()

+ 8 - 1
core/config.h

@@ -75,10 +75,17 @@
 #define WASM_ENABLE_JIT 0
 #endif
 
+#ifndef WASM_ENABLE_LAZY_JIT
+#define WASM_ENABLE_LAZY_JIT 0
+#endif
+
 #if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0)
-/* JIT can only be enabled when AOT is enabled */
+/* LazyJIT or MCJIT can only be enabled when AOT is enabled */
 #undef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0
+
+#undef WASM_ENABLE_LAZY_JIT
+#define WASM_ENABLE_LAZY_JIT 0
 #endif
 
 #ifndef WASM_ENABLE_WAMR_COMPILER

+ 54 - 0
core/iwasm/aot/aot_loader.c

@@ -2535,6 +2535,13 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
     char func_name[32];
     AOTModule *module;
 
+#if WASM_ENABLE_LAZY_JIT != 0
+    LLVMOrcThreadSafeModuleRef ts_module;
+    LLVMOrcJITDylibRef main_dylib;
+    LLVMErrorRef error;
+    LLVMOrcJITTargetAddress func_addr = 0;
+#endif
+
     /* Allocate memory for module */
     if (!(module =
             loader_malloc(sizeof(AOTModule), error_buf, error_buf_size))) {
@@ -2597,6 +2604,47 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
         goto fail2;
     }
 
+#if WASM_ENABLE_LAZY_JIT != 0
+    bh_assert(comp_ctx->lazy_orcjit);
+
+    main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->lazy_orcjit);
+    if (!main_dylib) {
+        set_error_buf(error_buf, error_buf_size,
+                      "failed to get dynmaic library reference");
+        goto fail3;
+    }
+
+    ts_module = LLVMOrcCreateNewThreadSafeModule(comp_ctx->module,
+                                                 comp_ctx->ts_context);
+    if (!ts_module) {
+        set_error_buf(error_buf, error_buf_size,
+                      "failed to create thread safe module");
+        goto fail3;
+    }
+
+    if ((error = LLVMOrcLLLazyJITAddLLVMIRModule(comp_ctx->lazy_orcjit,
+                                                 main_dylib, ts_module))) {
+        /*
+         * If adding the ThreadSafeModule fails then we need to clean it up
+         * ourselves. If adding it succeeds the JIT will manage the memory.
+         */
+        aot_handle_llvm_errmsg(error_buf, error_buf_size,
+                               "failed to addIRModule: ", error);
+        goto fail4;
+    }
+
+    for (i = 0; i < comp_data->func_count; i++) {
+        snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
+        if ((error = LLVMOrcLLLazyJITLookup(comp_ctx->lazy_orcjit,
+                                            &func_addr, func_name))) {
+            aot_handle_llvm_errmsg(error_buf, error_buf_size,
+                                   "cannot lookup: ", error);
+            goto fail3;
+        }
+        module->func_ptrs[i] = (void *)func_addr;
+        func_addr = 0;
+    }
+#else
     /* Resolve function addresses */
     bh_assert(comp_ctx->exec_engine);
     for (i = 0; i < comp_data->func_count; i++) {
@@ -2609,6 +2657,7 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
             goto fail3;
         }
     }
+#endif /* WASM_ENABLE_LAZY_JIT != 0 */
 
     /* Allocation memory for function type indexes */
     size = (uint64)module->func_count * sizeof(uint32);
@@ -2662,6 +2711,11 @@ aot_load_from_comp_data(AOTCompData *comp_data, AOTCompContext *comp_ctx,
 
     return module;
 
+#if WASM_ENABLE_LAZY_JIT != 0
+fail4:
+    LLVMOrcDisposeThreadSafeModule(ts_module);
+#endif
+
 fail3:
     if (module->func_ptrs)
         wasm_runtime_free(module->func_ptrs);

+ 228 - 3
core/iwasm/compilation/aot_llvm.c

@@ -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,

+ 22 - 0
core/iwasm/compilation/aot_llvm.h

@@ -18,6 +18,14 @@
 #include "llvm-c/Transforms/Scalar.h"
 #include "llvm-c/Transforms/Vectorize.h"
 
+#if WASM_ENABLE_LAZY_JIT != 0
+#include "aot_llvm_lazyjit.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/Error.h"
+#include "llvm-c/Initialization.h"
+#include "llvm-c/Support.h"
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -227,7 +235,13 @@ typedef struct AOTCompContext {
   uint64 flags[8];
 
   /* LLVM execution engine required by JIT */
+#if WASM_ENABLE_LAZY_JIT != 0
+  LLVMOrcLLLazyJITRef lazy_orcjit;
+  LLVMOrcThreadSafeContextRef ts_context;
+  LLVMOrcJITTargetMachineBuilderRef tm_builder;
+#else
   LLVMExecutionEngineRef exec_engine;
+#endif
   bool is_jit_mode;
 
   /* AOT indirect mode flag & symbol list */
@@ -403,6 +417,14 @@ aot_get_func_from_table(const AOTCompContext *comp_ctx,
 bool
 aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
 
+#if WASM_ENABLE_LAZY_JIT != 0
+void 
+aot_handle_llvm_errmsg(char *error_buf,
+                       uint32 error_buf_size,
+                       const char *string,
+                       LLVMErrorRef error);
+#endif
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 128 - 0
core/iwasm/compilation/aot_llvm_lazyjit.cpp

@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_llvm_lazyjit.h"
+
+LLVMOrcJITTargetMachineBuilderRef
+LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM);
+
+LLVMOrcLLJITBuilderRef
+LLVMOrcCreateLLJITBuilder(void);
+
+void
+LLVMOrcDisposeLLJITBuilder(LLVMOrcLLJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcCreateLLJIT(LLVMOrcLLJITRef *Result,
+                   LLVMOrcLLJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcDisposeLLJIT(LLVMOrcLLJITRef J);
+
+LLVMOrcJITDylibRef
+LLVMOrcLLJITGetMainJITDylib(LLVMOrcLLJITRef J);
+
+const char *
+LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
+
+char
+LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
+
+LLVMErrorRef
+LLVMOrcLLJITAddLLVMIRModule(LLVMOrcLLJITRef J,
+                            LLVMOrcJITDylibRef JD,
+                            LLVMOrcThreadSafeModuleRef TSM);
+
+LLVMErrorRef
+LLVMOrcLLJITLookup(LLVMOrcLLJITRef J,
+                   LLVMOrcJITTargetAddress *Result,
+                   const char *Name);
+
+const char *
+LLVMOrcLLJITGetTripleString(LLVMOrcLLJITRef J);
+
+void
+LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(
+                        LLVMOrcLLJITBuilderRef Builder,
+                        LLVMOrcJITTargetMachineBuilderRef JTMB);
+
+char
+LLVMOrcLLJITGetGlobalPrefix(LLVMOrcLLJITRef J);
+
+#if LLVM_VERSION_MAJOR < 12
+LLVMOrcJITTargetMachineBuilderRef
+LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM)
+{
+    return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM);
+}
+#endif
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J)
+{
+    return LLVMOrcLLJITGetMainJITDylib(J);
+}
+
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void)
+{
+    return LLVMOrcCreateLLJITBuilder();
+}
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder)
+{
+    return LLVMOrcDisposeLLJITBuilder(Builder);
+}
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+                       LLVMOrcLLLazyJITBuilderRef Builder)
+{
+    return LLVMOrcCreateLLJIT(Result, Builder);
+}
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J)
+{
+    return LLVMOrcDisposeLLJIT(J);
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J,
+                                LLVMOrcJITDylibRef JD,
+                                LLVMOrcThreadSafeModuleRef TSM)
+{
+    return LLVMOrcLLJITAddLLVMIRModule(J, JD, TSM);
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J,
+                       LLVMOrcJITTargetAddress *Result,
+                       const char *Name)
+{
+    return LLVMOrcLLJITLookup(J, Result, Name);
+}
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J)
+{
+    return LLVMOrcLLJITGetTripleString(J);
+}
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+                    LLVMOrcLLLazyJITBuilderRef Builder,
+                    LLVMOrcJITTargetMachineBuilderRef JTMB)
+{
+    return LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(Builder, JTMB);
+}
+
+char
+LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J)
+{
+    return LLVMOrcLLJITGetGlobalPrefix(J);
+}
+

+ 77 - 0
core/iwasm/compilation/aot_llvm_lazyjit.h

@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef AOT_LLVM_LAZYJIT_H
+#define AOT_LLVM_LAZYJIT_H
+
+#include "llvm-c/Error.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/TargetMachine.h"
+#include "llvm-c/Types.h"
+#if LLVM_VERSION_MAJOR >= 12
+#include "llvm-c/LLJIT.h"
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef LLVMOrcLLJITBuilderRef LLVMOrcLLLazyJITBuilderRef;
+
+typedef LLVMOrcLLJITRef LLVMOrcLLLazyJITRef;
+
+LLVMOrcJITTargetMachineBuilderRef
+LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
+
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void);
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+                       LLVMOrcLLLazyJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J);
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
+
+char
+LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J,
+                                LLVMOrcJITDylibRef JD,
+                                LLVMOrcThreadSafeModuleRef TSM);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J,
+                       LLVMOrcJITTargetAddress *Result,
+                       const char *Name);
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+                        LLVMOrcLLLazyJITBuilderRef Builder,
+                        LLVMOrcJITTargetMachineBuilderRef JTMB);
+
+char
+LLVMOrcLLLazyJITGetGlobalPrefix(LLVMOrcLLLazyJITRef J);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of AOT_LLVM_LAZYJIT_H */
+

+ 8 - 2
doc/build_wamr.md

@@ -41,6 +41,7 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
 
 - **WAMR_BUILD_AOT**=1/0, default to enable if not set
 - **WAMR_BUILD_JIT**=1/0, default to disable if not set
+- **WAMR_BUILD_LAZY_JIT**=1/0, default to disable if not set
 
 #### **Configure LIBC**
 
@@ -198,8 +199,8 @@ make
 ```
 
 
-By default in Linux, the interpreter, AOT and WASI are enabled, and JIT is disabled. And the build target is
-set to X86_64 or X86_32 depending on the platform's bitwidth.
+By default in Linux, the interpreter, AOT and WASI are enabled, and JIT and LazyJIT are disabled. 
+And the build target is set to X86_64 or X86_32 depending on the platform's bitwidth.
 
 To enable WASM JIT, firstly we should build LLVM:
 
@@ -217,6 +218,11 @@ cmake .. -DWAMR_BUILD_JIT=1
 make
 ```
 
+Moreover, pass arguments `-DWAMR_BUILD_JIT=1` and `-DWAMR_BUILD_LAZY_JIT=1` together to cmake to enable WASM Lazy JIT.
+If Lazy JIT is enabled, then jit function bodies in the module will not be compiled until they are first called,
+so compile time reduces significantly.
+
+
 Linux SGX (Intel Software Guard Extension)
 -------------------------
 

+ 2 - 0
product-mini/platforms/linux/build_jit.sh

@@ -5,6 +5,8 @@
 
 rm -fr build && mkdir build
 cd build
+# Build With LazyJIT
+# cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1
 cmake .. -DWAMR_BUILD_JIT=1
 make
 cd ..