Quellcode durchsuchen

Refactor LLVM JIT (#1613)

Refactor LLVM JIT for some purposes:
- To simplify the source code of JIT compilation
- To simplify the JIT modes
- To align with LLVM latest changes
- To prepare for the Multi-tier JIT compilation, refer to #1302

The changes mainly include:
- Remove the MCJIT mode, replace it with ORC JIT eager mode
- Remove the LLVM legacy pass manager (only keep the LLVM new pass manager)
- Change the lazy mode's LLVM module/function binding:
  change each function in an individual LLVM module into all functions in a single LLVM module
- Upgraded ORC JIT to ORCv2 JIT to enable lazy compilation

Refer to #1468
Wenyong Huang vor 3 Jahren
Ursprung
Commit
e87a554616

+ 16 - 16
.github/workflows/compilation_on_android_ubuntu.yml

@@ -34,8 +34,8 @@ env:
   AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
-  LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
-  MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
   # LLVM
   LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
   # For Spec Test
@@ -184,8 +184,8 @@ jobs:
             $AOT_BUILD_OPTIONS,
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
-            $LAZY_JIT_BUILD_OPTIONS,
-            $MC_JIT_BUILD_OPTIONS,
+            $LLVM_EAGER_JIT_BUILD_OPTIONS,
+            $LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         make_options_feature: [
             # Features
@@ -210,11 +210,11 @@ jobs:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
           # MULTI_MODULE only on INTERP mode
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # SIMD only on JIT/AOT mode
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
@@ -224,9 +224,9 @@ jobs:
           # DEBUG_INTERP only on CLASSIC INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
           - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
@@ -236,16 +236,16 @@ jobs:
           - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           # TODO: DEBUG_AOT on JIT
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           # MINI_LOADER only on INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
         include:
           - os: ubuntu-20.04
@@ -293,11 +293,11 @@ jobs:
       matrix:
         make_options: [
             # Running mode
+            $AOT_BUILD_OPTIONS,
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
-            $LAZY_JIT_BUILD_OPTIONS,
-            $MC_JIT_BUILD_OPTIONS,
-            $AOT_BUILD_OPTIONS,
+            $LLVM_EAGER_JIT_BUILD_OPTIONS,
+            $LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         os: [ubuntu-20.04, ubuntu-22.04]
         include:

+ 17 - 15
.github/workflows/compilation_on_macos.yml

@@ -30,11 +30,13 @@ concurrency:
   cancel-in-progress: true
 
 env:
+  # For BUILD
   AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
-  LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
-  MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
+  # LLVM
   LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
 
 jobs:
@@ -160,8 +162,8 @@ jobs:
             $AOT_BUILD_OPTIONS,
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
-            $LAZY_JIT_BUILD_OPTIONS,
-            $MC_JIT_BUILD_OPTIONS,
+            $LLVM_EAGER_JIT_BUILD_OPTIONS,
+            $LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         make_options_feature: [
             # Features
@@ -187,11 +189,11 @@ jobs:
           # uncompatiable feature and platform
           # uncompatiable mode and feature
           # MULTI_MODULE only on INTERP mode
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
-          - make_options_run_mode: $AOT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # SIMD only on JIT/AOT mode
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
@@ -201,9 +203,9 @@ jobs:
           # DEBUG_INTERP only on CLASSIC INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
           - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
@@ -213,16 +215,16 @@ jobs:
           - make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           # TODO: DEBUG_AOT on JIT
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           # MINI_LOADER only on INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
-          - make_options_run_mode: $LAZY_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
-          - make_options_run_mode: $MC_JIT_BUILD_OPTIONS
+          - make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
         include:
           - os: macos-latest
@@ -271,9 +273,9 @@ jobs:
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
             # doesn't support
-            #$LAZY_JIT_BUILD_OPTIONS,
-            #$MC_JIT_BUILD_OPTIONS,
             #$AOT_BUILD_OPTIONS,
+            #$LLVM_EAGER_JIT_BUILD_OPTIONS,
+            #$LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         os: [macos-latest]
         include:

+ 8 - 6
.github/workflows/compilation_on_sgx.yml

@@ -30,11 +30,13 @@ concurrency:
   cancel-in-progress: true
 
 env:
+  # For BUILD
   AOT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   CLASSIC_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
-  LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
-  MC_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
+  LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
+  # LLVM
   LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
 
 jobs:
@@ -119,8 +121,8 @@ jobs:
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
             # doesn't support
-            # $LAZY_JIT_BUILD_OPTIONS,
-            # $MC_JIT_BUILD_OPTIONS,
+            #$LLVM_EAGER_JIT_BUILD_OPTIONS,
+            #$LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         make_options_feature: [
             # Features
@@ -251,9 +253,9 @@ jobs:
             $CLASSIC_INTERP_BUILD_OPTIONS,
             $FAST_INTERP_BUILD_OPTIONS,
             # doesn't support
-            #$LAZY_JIT_BUILD_OPTIONS,
-            #$MC_JIT_BUILD_OPTIONS,
             #$AOT_BUILD_OPTIONS,
+            #$LLVM_EAGER_JIT_BUILD_OPTIONS,
+            #$LLVM_LAZY_JIT_BUILD_OPTIONS,
           ]
         os: [ubuntu-20.04]
         include:

+ 0 - 1
.gitignore

@@ -30,5 +30,4 @@ samples/socket-api/wasm-src/inc/pthread.h
 
 **/__pycache__
 
-# ignore benchmarks generated
 tests/benchmarks/coremark/coremark*

+ 5 - 5
build-scripts/config_common.cmake

@@ -84,11 +84,9 @@ endif ()
 endif ()
 
 if (WAMR_BUILD_JIT EQUAL 1)
-  add_definitions("-DWASM_ENABLE_JIT=1")
   if (NOT WAMR_BUILD_LAZY_JIT EQUAL 0)
     # Enable Lazy JIT by default
     set (WAMR_BUILD_LAZY_JIT 1)
-    add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
   endif ()
   if (NOT DEFINED LLVM_DIR)
     set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
@@ -148,13 +146,15 @@ else ()
   message ("     WAMR Fast JIT disabled")
 endif ()
 if (WAMR_BUILD_JIT EQUAL 1)
+  add_definitions("-DWASM_ENABLE_JIT=1")
   if (WAMR_BUILD_LAZY_JIT EQUAL 1)
-    message ("     WAMR LLVM Orc Lazy JIT enabled")
+    add_definitions("-DWASM_ENABLE_LAZY_JIT=1")
+    message ("     WAMR LLVM ORC JIT enabled with Lazy Compilation")
   else ()
-    message ("     WAMR LLVM MC JIT enabled")
+    message ("     WAMR LLVM ORC JIT enabled with Eager Compilation")
   endif ()
 else ()
-  message ("     WAMR LLVM JIT disabled")
+  message ("     WAMR LLVM ORC JIT disabled")
 endif ()
 if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
   message ("     Libc builtin enabled")

+ 17 - 11
core/config.h

@@ -81,12 +81,26 @@
 #define WASM_ENABLE_LAZY_JIT 0
 #endif
 
-#ifndef WASM_LAZY_JIT_COMPILE_THREAD_NUM
-#define WASM_LAZY_JIT_COMPILE_THREAD_NUM 4
+#ifndef WASM_ORC_JIT_BACKEND_THREAD_NUM
+/* The number of backend threads created by runtime */
+#define WASM_ORC_JIT_BACKEND_THREAD_NUM 4
+#endif
+
+#if WASM_ORC_JIT_BACKEND_THREAD_NUM < 1
+#error "WASM_ORC_JIT_BACKEND_THREAD_NUM must be greater than 0"
+#endif
+
+#ifndef WASM_ORC_JIT_COMPILE_THREAD_NUM
+/* The number of compilation threads created by LLVM JIT */
+#define WASM_ORC_JIT_COMPILE_THREAD_NUM 4
+#endif
+
+#if WASM_ORC_JIT_COMPILE_THREAD_NUM < 1
+#error "WASM_ORC_JIT_COMPILE_THREAD_NUM must be greater than 0"
 #endif
 
 #if (WASM_ENABLE_AOT == 0) && (WASM_ENABLE_JIT != 0)
-/* LazyJIT or MCJIT can only be enabled when AOT is enabled */
+/* LLVM JIT can only be enabled when AOT is enabled */
 #undef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0
 
@@ -110,14 +124,6 @@
 #define WASM_ENABLE_WAMR_COMPILER 0
 #endif
 
-#if WASM_ENABLE_WAMR_COMPILER != 0
-#ifndef WASM_ENABLE_LLVM_LEGACY_PM
-/* Whether to use LLVM legacy pass manager when building wamrc,
-   by default it is disabled and LLVM new pass manager is used */
-#define WASM_ENABLE_LLVM_LEGACY_PM 0
-#endif
-#endif
-
 #ifndef WASM_ENABLE_LIBC_BUILTIN
 #define WASM_ENABLE_LIBC_BUILTIN 0
 #endif

+ 8 - 0
core/iwasm/aot/aot_runtime.c

@@ -1321,6 +1321,9 @@ aot_call_function(WASMExecEnv *exec_env, AOTFunctionInstance *function,
     }
     argc = func_type->param_cell_num;
 
+    /* func pointer was looked up previously */
+    bh_assert(function->u.func.func_ptr != NULL);
+
     /* set thread handle and stack boundary */
     wasm_exec_env_set_thread_info(exec_env);
 
@@ -1828,6 +1831,11 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
     func_type_idx = func_type_indexes[func_idx];
     func_type = aot_module->func_types[func_type_idx];
 
+    if (func_idx >= aot_module->import_func_count) {
+        /* func pointer was looked up previously */
+        bh_assert(func_ptrs[func_idx] != NULL);
+    }
+
     if (!(func_ptr = func_ptrs[func_idx])) {
         bh_assert(func_idx < aot_module->import_func_count);
         import_func = aot_module->import_funcs + func_idx;

+ 2 - 2
core/iwasm/aot/aot_runtime.h

@@ -148,9 +148,9 @@ typedef struct AOTModule {
 
     /* function info */
     uint32 func_count;
-    /* point to AOTed functions */
+    /* func pointers of AOTed (un-imported) functions */
     void **func_ptrs;
-    /* function type indexes */
+    /* func type indexes of AOTed (un-imported) functions */
     uint32 *func_type_indexes;
 
     /* export info */

+ 44 - 201
core/iwasm/compilation/aot_compiler.c

@@ -2602,7 +2602,6 @@ veriy_module(AOTCompContext *comp_ctx)
     char *msg = NULL;
     bool ret;
 
-#if WASM_ENABLE_LAZY_JIT == 0
     ret = LLVMVerifyModule(comp_ctx->module, LLVMPrintMessageAction, &msg);
     if (!ret && msg) {
         if (msg[0] != '\0') {
@@ -2612,134 +2611,9 @@ veriy_module(AOTCompContext *comp_ctx)
         }
         LLVMDisposeMessage(msg);
     }
-#else
-    uint32 i;
-
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        ret = LLVMVerifyModule(comp_ctx->modules[i], LLVMPrintMessageAction,
-                               &msg);
-        if (!ret && msg) {
-            if (msg[0] != '\0') {
-                aot_set_last_error(msg);
-                LLVMDisposeMessage(msg);
-                return false;
-            }
-            LLVMDisposeMessage(msg);
-        }
-    }
-#endif
-
-    return true;
-}
-
-static bool
-apply_func_passes(AOTCompContext *comp_ctx)
-{
-    LLVMPassManagerRef pass_mgr;
-    uint32 i;
-
-#if WASM_ENABLE_LAZY_JIT == 0
-    pass_mgr = LLVMCreateFunctionPassManagerForModule(comp_ctx->module);
-#else
-    pass_mgr = LLVMCreatePassManager();
-#endif
-
-    if (!pass_mgr) {
-        aot_set_last_error("create LLVM pass manager failed.");
-        return false;
-    }
-
-    LLVMAddPromoteMemoryToRegisterPass(pass_mgr);
-    LLVMAddInstructionCombiningPass(pass_mgr);
-    LLVMAddCFGSimplificationPass(pass_mgr);
-    LLVMAddJumpThreadingPass(pass_mgr);
-#if LLVM_VERSION_MAJOR < 12
-    LLVMAddConstantPropagationPass(pass_mgr);
-#endif
-    LLVMAddIndVarSimplifyPass(pass_mgr);
-
-    if (!comp_ctx->is_jit_mode) {
-        /* Put Vectorize passes before GVN/LICM passes as the former
-           might gain more performance improvement and the latter might
-           break the optimizations for the former */
-        LLVMAddLoopVectorizePass(pass_mgr);
-        LLVMAddSLPVectorizePass(pass_mgr);
-        LLVMAddLoopRotatePass(pass_mgr);
-#if LLVM_VERSION_MAJOR < 15
-        LLVMAddLoopUnswitchPass(pass_mgr);
-#else
-        aot_add_simple_loop_unswitch_pass(pass_mgr);
-#endif
-        LLVMAddInstructionCombiningPass(pass_mgr);
-        LLVMAddCFGSimplificationPass(pass_mgr);
-        if (!comp_ctx->enable_thread_mgr) {
-            /* These two passes may destroy the volatile semantics,
-               disable them when building as multi-thread mode */
-            LLVMAddGVNPass(pass_mgr);
-            LLVMAddLICMPass(pass_mgr);
-            LLVMAddInstructionCombiningPass(pass_mgr);
-            LLVMAddCFGSimplificationPass(pass_mgr);
-        }
-    }
-
-#if WASM_ENABLE_LAZY_JIT == 0
-    LLVMInitializeFunctionPassManager(pass_mgr);
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        LLVMRunFunctionPassManager(pass_mgr, comp_ctx->func_ctxes[i]->func);
-    }
-    LLVMFinalizeFunctionPassManager(pass_mgr);
-#else
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        LLVMRunPassManager(pass_mgr, comp_ctx->modules[i]);
-    }
-#endif
-
-    LLVMDisposePassManager(pass_mgr);
-    return true;
-}
-
-#if WASM_ENABLE_LLVM_LEGACY_PM != 0 || LLVM_VERSION_MAJOR < 12
-static bool
-apply_lto_passes(AOTCompContext *comp_ctx)
-{
-    LLVMPassManagerRef common_pass_mgr;
-    LLVMPassManagerBuilderRef pass_mgr_builder;
-#if WASM_ENABLE_LAZY_JIT != 0
-    uint32 i;
-#endif
-
-    if (!(common_pass_mgr = LLVMCreatePassManager())) {
-        aot_set_last_error("create LLVM pass manager failed");
-        return false;
-    }
 
-    if (!(pass_mgr_builder = LLVMPassManagerBuilderCreate())) {
-        aot_set_last_error("create LLVM pass manager builder failed");
-        LLVMDisposePassManager(common_pass_mgr);
-        return false;
-    }
-
-    LLVMPassManagerBuilderSetOptLevel(pass_mgr_builder, comp_ctx->opt_level);
-    LLVMPassManagerBuilderPopulateModulePassManager(pass_mgr_builder,
-                                                    common_pass_mgr);
-#if LLVM_VERSION_MAJOR < 15
-    LLVMPassManagerBuilderPopulateLTOPassManager(pass_mgr_builder,
-                                                 common_pass_mgr, true, true);
-#endif
-
-#if WASM_ENABLE_LAZY_JIT == 0
-    LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
-#else
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
-    }
-#endif
-
-    LLVMDisposePassManager(common_pass_mgr);
-    LLVMPassManagerBuilderDispose(pass_mgr_builder);
     return true;
 }
-#endif /* end of WASM_ENABLE_LLVM_LEGACY_PM != 0 || LLVM_VERSION_MAJOR < 12 */
 
 /* Check whether the target supports hardware atomic instructions */
 static bool
@@ -2779,9 +2653,6 @@ static bool
 apply_passes_for_indirect_mode(AOTCompContext *comp_ctx)
 {
     LLVMPassManagerRef common_pass_mgr;
-#if WASM_ENABLE_LAZY_JIT != 0
-    uint32 i;
-#endif
 
     if (!(common_pass_mgr = LLVMCreatePassManager())) {
         aot_set_last_error("create pass manager failed");
@@ -2796,13 +2667,7 @@ apply_passes_for_indirect_mode(AOTCompContext *comp_ctx)
     if (aot_require_lower_switch_pass(comp_ctx))
         LLVMAddLowerSwitchPass(common_pass_mgr);
 
-#if WASM_ENABLE_LAZY_JIT == 0
     LLVMRunPassManager(common_pass_mgr, comp_ctx->module);
-#else
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        LLVMRunPassManager(common_pass_mgr, comp_ctx->modules[i]);
-    }
-#endif
 
     LLVMDisposePassManager(common_pass_mgr);
     return true;
@@ -2812,11 +2677,6 @@ bool
 aot_compile_wasm(AOTCompContext *comp_ctx)
 {
     uint32 i;
-#if WASM_ENABLE_LAZY_JIT != 0
-    LLVMErrorRef err;
-    LLVMOrcJITDylibRef orc_main_dylib;
-    LLVMOrcThreadSafeModuleRef orc_thread_safe_module;
-#endif
 
     if (!aot_validate_wasm(comp_ctx)) {
         return false;
@@ -2833,87 +2693,72 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
     LLVMDIBuilderFinalize(comp_ctx->debug_builder);
 #endif
 
-    bh_print_time("Begin to verify LLVM module");
-    if (!veriy_module(comp_ctx)) {
-        return false;
+    /* Disable LLVM module verification for jit mode to speedup
+       the compilation process */
+    if (!comp_ctx->is_jit_mode) {
+        bh_print_time("Begin to verify LLVM module");
+        if (!veriy_module(comp_ctx)) {
+            return false;
+        }
     }
 
+    /* Run IR optimization before feeding in ORCJIT and AOT codegen */
     if (comp_ctx->optimize) {
-        if (comp_ctx->is_jit_mode) {
-            /* Only run func passes for JIT mode */
-            bh_print_time("Begin to run func optimization passes");
-            if (!apply_func_passes(comp_ctx)) {
+        /* Run specific passes for AOT indirect mode */
+        if (!comp_ctx->is_jit_mode && comp_ctx->is_indirect_mode) {
+            bh_print_time("Begin to run optimization passes "
+                          "for indirect mode");
+            if (!apply_passes_for_indirect_mode(comp_ctx)) {
                 return false;
             }
         }
-        else {
-#if WASM_ENABLE_LLVM_LEGACY_PM == 0 && LLVM_VERSION_MAJOR >= 12
-            /* Run llvm new pass manager for AOT compiler if llvm
-               legacy pass manager isn't used */
-            bh_print_time("Begin to run llvm optimization passes");
-            aot_apply_llvm_new_pass_manager(comp_ctx);
-#else
-            /* Run func passes and lto passes for AOT compiler if llvm
-               legacy pass manager is used */
-            bh_print_time("Begin to run func optimization passes");
-            if (!apply_func_passes(comp_ctx)) {
-                return false;
-            }
-            if (!comp_ctx->disable_llvm_lto) {
-                bh_print_time("Begin to run lto optimization passes");
-                if (!apply_lto_passes(comp_ctx)) {
-                    return false;
-                }
-            }
-#endif
-            /* Run passes for AOT indirect mode */
-            if (comp_ctx->is_indirect_mode) {
-                bh_print_time("Begin to run optimization passes "
-                              "for indirect mode");
-                if (!apply_passes_for_indirect_mode(comp_ctx)) {
-                    return false;
-                }
-            }
-        }
-    }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-    orc_main_dylib = LLVMOrcLLJITGetMainJITDylib(comp_ctx->orc_lazyjit);
-    if (!orc_main_dylib) {
-        aot_set_last_error("failed to get orc jit main dynmaic library");
-        return false;
+        /* Run passes for AOT/JIT mode.
+           TODO: Apply these passes in the do_ir_transform callback of
+           TransformLayer when compiling each jit function, so as to
+           speedup the launch process. Now there are two issues in the
+           JIT: one is memory leak in do_ir_transform, the other is
+           possible core dump. */
+        bh_print_time("Begin to run llvm optimization passes");
+        aot_apply_llvm_new_pass_manager(comp_ctx, comp_ctx->module);
+        bh_print_time("Finish llvm optimization passes");
     }
 
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
+#ifdef DUMP_MODULE
+    LLVMDumpModule(comp_ctx->module);
+    os_printf("\n");
+#endif
+
+    if (comp_ctx->is_jit_mode) {
+        LLVMErrorRef err;
+        LLVMOrcJITDylibRef orc_main_dylib;
+        LLVMOrcThreadSafeModuleRef orc_thread_safe_module;
+
+        orc_main_dylib = LLVMOrcLLLazyJITGetMainJITDylib(comp_ctx->orc_jit);
+        if (!orc_main_dylib) {
+            aot_set_last_error(
+                "failed to get orc orc_jit main dynmaic library");
+            return false;
+        }
+
         orc_thread_safe_module = LLVMOrcCreateNewThreadSafeModule(
-            comp_ctx->modules[i], comp_ctx->orc_thread_safe_context);
+            comp_ctx->module, comp_ctx->orc_thread_safe_context);
         if (!orc_thread_safe_module) {
             aot_set_last_error("failed to create thread safe module");
             return false;
         }
 
-        if ((err = LLVMOrcLLJITAddLLVMIRModule(comp_ctx->orc_lazyjit,
-                                               orc_main_dylib,
-                                               orc_thread_safe_module))) {
+        if ((err = LLVMOrcLLLazyJITAddLLVMIRModule(
+                 comp_ctx->orc_jit, orc_main_dylib, orc_thread_safe_module))) {
             /* If adding the ThreadSafeModule fails then we need to clean it up
-               by ourselves, otherwise the orc jit will manage the memory. */
+               by ourselves, otherwise the orc orc_jit will manage the memory.
+             */
             LLVMOrcDisposeThreadSafeModule(orc_thread_safe_module);
             aot_handle_llvm_errmsg("failed to addIRModule", err);
             return false;
         }
     }
-#endif
 
-#if 0
-#if WASM_ENABLE_LAZY_JIT == 0
-    LLVMDumpModule(comp_ctx->module);
-#else
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        LLVMDumpModule(comp_ctx->modules[i]);
-        os_printf("\n");
-    }
-#endif
-#endif
     return true;
 }
 
@@ -2947,7 +2792,6 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
 }
 #endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
 
-#if WASM_ENABLE_LAZY_JIT == 0
 bool
 aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
 {
@@ -3071,4 +2915,3 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
 
     return true;
 }
-#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */

+ 11 - 12
core/iwasm/compilation/aot_emit_aot_file.c

@@ -6,8 +6,6 @@
 #include "aot_compiler.h"
 #include "../aot/aot_runtime.h"
 
-#if WASM_ENABLE_LAZY_JIT == 0
-
 #define PUT_U64_TO_ADDR(addr, value)        \
     do {                                    \
         union {                             \
@@ -2794,16 +2792,18 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
         }
 #endif /* end of defined(_WIN32) || defined(_WIN32_) */
     }
-    else if (LLVMTargetMachineEmitToMemoryBuffer(
-                 comp_ctx->target_machine, comp_ctx->module, LLVMObjectFile,
-                 &err, &obj_data->mem_buf)
-             != 0) {
-        if (err) {
-            LLVMDisposeMessage(err);
-            err = NULL;
+    else {
+        if (LLVMTargetMachineEmitToMemoryBuffer(
+                comp_ctx->target_machine, comp_ctx->module, LLVMObjectFile,
+                &err, &obj_data->mem_buf)
+            != 0) {
+            if (err) {
+                LLVMDisposeMessage(err);
+                err = NULL;
+            }
+            aot_set_last_error("llvm emit to memory buffer failed.");
+            goto fail;
         }
-        aot_set_last_error("llvm emit to memory buffer failed.");
-        goto fail;
     }
 
     if (!(obj_data->binary = LLVMCreateBinary(obj_data->mem_buf, NULL, &err))) {
@@ -2928,4 +2928,3 @@ fail1:
 
     return ret;
 }
-#endif /* end of WASM_ENABLE_LAZY_JIT == 0 */

+ 1 - 163
core/iwasm/compilation/aot_emit_function.c

@@ -267,131 +267,6 @@ call_aot_invoke_native_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     return true;
 }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-static bool
-lookup_orcjit_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                   LLVMValueRef func_idx, LLVMValueRef *p_func)
-{
-    LLVMBasicBlockRef block_curr, block_resolve_func, block_func_resolved;
-    LLVMValueRef param_values[3], func, value, func_ptr, cmp, phi;
-    LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
-
-    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-
-    if (!(block_resolve_func = LLVMAppendBasicBlockInContext(
-              comp_ctx->context, func_ctx->func, "resolve_func"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        return false;
-    }
-    if (!(block_func_resolved = LLVMAppendBasicBlockInContext(
-              comp_ctx->context, func_ctx->func, "func_resolved"))) {
-        aot_set_last_error("llvm add basic block failed.");
-        return false;
-    }
-    LLVMMoveBasicBlockAfter(block_resolve_func, block_curr);
-    LLVMMoveBasicBlockAfter(block_func_resolved, block_resolve_func);
-
-    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_func_resolved);
-    if (!(phi = LLVMBuildPhi(comp_ctx->builder, INT8_PTR_TYPE, "phi"))) {
-        aot_set_last_error("llvm build phi failed.");
-        return false;
-    }
-
-    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
-
-    /* Load function pointer */
-    if (!(func_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE,
-                                           func_ctx->func_ptrs, &func_idx, 1,
-                                           "func_ptr_tmp"))) {
-        aot_set_last_error("llvm build inbounds gep failed.");
-        return false;
-    }
-
-    if (!(func = LLVMBuildLoad2(comp_ctx->builder, OPQ_PTR_TYPE, func_ptr,
-                                "func_ptr"))) {
-        aot_set_last_error("llvm build load failed.");
-        return false;
-    }
-
-    /* If func ptr is NULL, call aot_lookup_orcjit_func to resolve it */
-    if (!(cmp = LLVMBuildIsNull(comp_ctx->builder, func, "cmp"))) {
-        aot_set_last_error("llvm build is null failed");
-        return false;
-    }
-
-    /* Create condition br */
-    if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_resolve_func,
-                         block_func_resolved)) {
-        aot_set_last_error("llvm build cond br failed.");
-        return false;
-    }
-    LLVMAddIncoming(phi, &func, &block_curr, 1);
-
-    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_resolve_func);
-
-    param_types[0] = INT8_PTR_TYPE;
-    param_types[1] = comp_ctx->aot_inst_type;
-    param_types[2] = I32_TYPE;
-    ret_type = INT8_PTR_TYPE;
-
-    if (!(func_type = LLVMFunctionType(ret_type, param_types, 3, false))
-        || !(func_ptr_type = LLVMPointerType(func_type, 0))) {
-        aot_set_last_error("llvm add function type failed.");
-        return false;
-    }
-
-    if (!(value = I64_CONST((uint64)(uintptr_t)aot_lookup_orcjit_func))
-        || !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
-        aot_set_last_error("create LLVM value failed.");
-        return false;
-    }
-
-    param_values[0] = I64_CONST((uintptr_t)comp_ctx->orc_lazyjit);
-    if (!param_values[0]) {
-        aot_set_last_error("llvm build const failed.");
-        return false;
-    }
-    if (!(param_values[0] =
-              LLVMConstIntToPtr(param_values[0], INT8_PTR_TYPE))) {
-        aot_set_last_error("llvm build bit cast failed.");
-        return false;
-    }
-
-    param_values[1] = func_ctx->aot_inst;
-
-    param_values[2] = func_idx;
-    if (!param_values[2]) {
-        aot_set_last_error("llvm build const failed.");
-        return false;
-    }
-
-    /* Call the function */
-    if (!(func = LLVMBuildCall2(comp_ctx->builder, func_type, func,
-                                param_values, 3, "call_orcjit_lookup"))) {
-        aot_set_last_error("LLVM build call failed.");
-        return false;
-    }
-
-    /* Check whether exception was thrown when looking up func */
-    if (!check_exception_thrown(comp_ctx, func_ctx)) {
-        return false;
-    }
-
-    block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-    LLVMAddIncoming(phi, &func, &block_curr, 1);
-
-    if (!LLVMBuildBr(comp_ctx->builder, block_func_resolved)) {
-        aot_set_last_error("llvm build br failed.");
-        return false;
-    }
-
-    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_func_resolved);
-
-    *p_func = phi;
-    return true;
-}
-#endif
-
 #if (WASM_ENABLE_DUMP_CALL_STACK != 0) || (WASM_ENABLE_PERF_PROFILING != 0)
 static bool
 call_aot_alloc_frame_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
@@ -909,43 +784,13 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             }
         }
         else {
-#if WASM_ENABLE_LAZY_JIT == 0
-            func = func_ctxes[func_idx - import_func_count]->func;
-#else
             if (func_ctxes[func_idx - import_func_count] == func_ctx) {
                 /* recursive call */
                 func = func_ctx->func;
             }
             else {
-                LLVMTypeRef func_ptr_type;
-                LLVMValueRef func_idx_const = I32_CONST(func_idx);
-
-                if (!func_idx_const) {
-                    aot_set_last_error("llvm build const failed.");
-                    goto fail;
-                }
-
-                /* For LAZY JIT, each function belongs to its own module,
-                   we call aot_lookup_orcjit_func to get the func pointer */
-                if (!lookup_orcjit_func(comp_ctx, func_ctx, func_idx_const,
-                                        &func)) {
-                    goto fail;
-                }
-
-                if (!(func_ptr_type = LLVMPointerType(
-                          func_ctxes[func_idx - import_func_count]->func_type,
-                          0))) {
-                    aot_set_last_error("construct func ptr type failed.");
-                    goto fail;
-                }
-
-                if (!(func = LLVMBuildBitCast(comp_ctx->builder, func,
-                                              func_ptr_type, "aot_func"))) {
-                    aot_set_last_error("llvm bit cast failed.");
-                    goto fail;
-                }
+                func = func_ctxes[func_idx - import_func_count]->func;
             }
-#endif
         }
 
         aot_func = func_ctxes[func_idx - import_func_count]->aot_func;
@@ -1574,7 +1419,6 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                      + 16))
         goto fail;
 
-#if WASM_ENABLE_LAZY_JIT == 0
     /* Load function pointer */
     if (!(func_ptr = LLVMBuildInBoundsGEP2(comp_ctx->builder, OPQ_PTR_TYPE,
                                            func_ctx->func_ptrs, &func_idx, 1,
@@ -1588,12 +1432,6 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         aot_set_last_error("llvm build load failed.");
         goto fail;
     }
-#else
-    /* For LAZY JIT, each function belongs to its own module,
-       we call aot_lookup_orcjit_func to get the func pointer */
-    if (!lookup_orcjit_func(comp_ctx, func_ctx, func_idx, &func_ptr))
-        goto fail;
-#endif
 
     if (!(llvm_func_type =
               LLVMFunctionType(ret_type, param_types, total_param_count, false))

+ 18 - 31
core/iwasm/compilation/aot_emit_memory.c

@@ -977,14 +977,6 @@ fail:
     return false;
 }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-static void *
-jit_memmove(void *dest, const void *src, size_t n)
-{
-    return memmove(dest, src, n);
-}
-#endif
-
 bool
 aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
@@ -1001,18 +993,10 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
     if (!(dst_addr = check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
         return false;
 
-#if WASM_ENABLE_LAZY_JIT != 0
-    call_aot_memmove = true;
-#endif
-    if (comp_ctx->is_indirect_mode)
-        call_aot_memmove = true;
-
+    call_aot_memmove = comp_ctx->is_indirect_mode || comp_ctx->is_jit_mode;
     if (call_aot_memmove) {
         LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
         LLVMValueRef func, params[3];
-#if WASM_ENABLE_LAZY_JIT == 0
-        int32 func_idx;
-#endif
 
         param_types[0] = INT8_PTR_TYPE;
         param_types[1] = INT8_PTR_TYPE;
@@ -1029,22 +1013,25 @@ aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
             return false;
         }
 
-#if WASM_ENABLE_LAZY_JIT == 0
-        func_idx = aot_get_native_symbol_index(comp_ctx, "memmove");
-        if (func_idx < 0) {
-            return false;
-        }
-        if (!(func = aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
-                                             func_ptr_type, func_idx))) {
-            return false;
+        if (comp_ctx->is_jit_mode) {
+            if (!(func = I64_CONST((uint64)(uintptr_t)aot_memmove))
+                || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
+                aot_set_last_error("create LLVM value failed.");
+                return false;
+            }
         }
-#else
-        if (!(func = I64_CONST((uint64)(uintptr_t)jit_memmove))
-            || !(func = LLVMConstIntToPtr(func, func_ptr_type))) {
-            aot_set_last_error("create LLVM value failed.");
-            return false;
+        else {
+            int32 func_index;
+            func_index = aot_get_native_symbol_index(comp_ctx, "memmove");
+            if (func_index < 0) {
+                return false;
+            }
+            if (!(func =
+                      aot_get_func_from_table(comp_ctx, func_ctx->native_symbol,
+                                              func_ptr_type, func_index))) {
+                return false;
+            }
         }
-#endif
 
         params[0] = dst_addr;
         params[1] = src_addr;

+ 160 - 302
core/iwasm/compilation/aot_llvm.c

@@ -48,7 +48,10 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
     LLVMValueRef func = NULL;
     LLVMTypeRef *param_types, ret_type, func_type;
     LLVMValueRef local_value;
-    char func_name[32];
+    LLVMTypeRef func_type_wrapper;
+    LLVMValueRef func_wrapper;
+    LLVMBasicBlockRef func_begin;
+    char func_name[48];
     uint64 size;
     uint32 i, j = 0, param_count = (uint64)aot_func_type->param_count;
 
@@ -116,6 +119,34 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
     if (p_func_type)
         *p_func_type = func_type;
 
+    if (comp_ctx->is_jit_mode) {
+        func_type_wrapper = LLVMFunctionType(VOID_TYPE, NULL, 0, false);
+        if (!func_type_wrapper) {
+            aot_set_last_error("create LLVM function type failed.");
+            goto fail;
+        }
+
+        snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX,
+                 func_index, "_wrapper");
+        if (!(func_wrapper =
+                  LLVMAddFunction(module, func_name, func_type_wrapper))) {
+            aot_set_last_error("add LLVM function failed.");
+            goto fail;
+        }
+
+        if (!(func_begin = LLVMAppendBasicBlockInContext(
+                  comp_ctx->context, func_wrapper, "func_begin"))) {
+            aot_set_last_error("add LLVM basic block failed.");
+            goto fail;
+        }
+
+        LLVMPositionBuilderAtEnd(comp_ctx->builder, func_begin);
+        if (!LLVMBuildRetVoid(comp_ctx->builder)) {
+            aot_set_last_error("llvm build ret failed.");
+            goto fail;
+        }
+    }
+
 fail:
     wasm_runtime_free(param_types);
     return func;
@@ -646,11 +677,7 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
     memset(func_ctx, 0, (uint32)size);
     func_ctx->aot_func = func;
 
-#if WASM_ENABLE_LAZY_JIT == 0
     func_ctx->module = comp_ctx->module;
-#else
-    func_ctx->module = comp_ctx->modules[func_index];
-#endif
 
     /* Add LLVM function */
     if (!(func_ctx->func =
@@ -1244,16 +1271,6 @@ get_target_arch_from_triple(const char *triple, char *arch_buf, uint32 buf_size)
     bh_assert(*triple == '-' || *triple == '\0');
 }
 
-LLVMBool
-WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
-                                 LLVMModuleRef M,
-                                 struct LLVMMCJITCompilerOptions *Options,
-                                 size_t SizeOfOptions, char **OutError);
-
-void
-LLVMAddPromoteMemoryToRegisterPass(LLVMPassManagerRef PM);
-
-#if WASM_ENABLE_LAZY_JIT != 0
 void
 aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err)
 {
@@ -1262,41 +1279,67 @@ aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err)
     LLVMDisposeErrorMessage(err_msg);
 }
 
+#ifndef NDEBUG
+static LLVMErrorRef
+run_pass(void *ctx, LLVMModuleRef module)
+{
+    /*AOTCompContext *comp_ctx = (AOTCompContext *)ctx;*/
+
+    size_t len;
+    LOG_VERBOSE("--- In IRTransformLayer @ T#%ld---",
+                LLVMGetModuleIdentifier(module, &len), pthread_self());
+
+    /* TODO: enable this for JIT mode after fixing LLVM issues */
+    /*aot_apply_llvm_new_pass_manager(comp_ctx, module);*/
+
+    bh_print_time("Begin to generate machine code");
+    return LLVMErrorSuccess;
+}
+
+static LLVMErrorRef
+do_ir_transform(void *ctx, LLVMOrcThreadSafeModuleRef *module,
+                LLVMOrcMaterializationResponsibilityRef mr)
+{
+    (void)mr;
+    return LLVMOrcThreadSafeModuleWithModuleDo(*module, run_pass, ctx);
+}
+
+static LLVMErrorRef
+do_obj_transform(void *Ctx, LLVMMemoryBufferRef *ObjInOut)
+{
+    bh_print_time("Finish generating machine code");
+    LOG_VERBOSE("--- In ObjectTransformLayer @ T#%ld ---", pthread_self());
+    (void)Ctx;
+    (void)ObjInOut;
+    return LLVMErrorSuccess;
+}
+#endif
+
 static bool
-orc_lazyjit_create(AOTCompContext *comp_ctx, uint32 func_count)
+create_target_machine_detect_host(AOTCompContext *comp_ctx)
 {
-    uint32 i;
+    char *triple = NULL;
+    LLVMTargetRef target = NULL;
     char *err_msg = NULL;
     char *cpu = NULL;
     char *features = NULL;
-    char *llvm_triple = NULL;
-    char func_name[32] = { 0 };
-    LLVMErrorRef err;
-    LLVMTargetRef llvm_targetref = NULL;
-    LLVMTargetMachineRef target_machine_for_orcjit = NULL;
-    LLVMOrcLLJITRef orc_lazyjit = NULL;
-    LLVMOrcJITTargetMachineBuilderRef target_machine_builder = NULL;
-    LLVMOrcLLJITBuilderRef orc_lazyjit_builder = NULL;
-    LLVMOrcMaterializationUnitRef orc_material_unit = NULL;
-    LLVMOrcExecutionSessionRef orc_execution_session = NULL;
-    LLVMOrcLazyCallThroughManagerRef orc_call_through_mgr = NULL;
-    LLVMOrcIndirectStubsManagerRef orc_indirect_stub_mgr = NULL;
-    LLVMOrcCSymbolAliasMapPair *orc_symbol_map_pairs = NULL;
-
-    llvm_triple = LLVMGetDefaultTargetTriple();
-    if (llvm_triple == NULL) {
+    LLVMTargetMachineRef target_machine = NULL;
+    bool ret = false;
+
+    triple = LLVMGetDefaultTargetTriple();
+    if (triple == NULL) {
         aot_set_last_error("failed to get default target triple.");
         goto fail;
     }
 
-    if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &err_msg) != 0) {
+    if (LLVMGetTargetFromTriple(triple, &target, &err_msg) != 0) {
         aot_set_last_error_v("failed to get llvm target from triple %s.",
                              err_msg);
         LLVMDisposeMessage(err_msg);
         goto fail;
     }
 
-    if (!LLVMTargetHasJIT(llvm_targetref)) {
+    if (!LLVMTargetHasJIT(target)) {
         aot_set_last_error("unspported JIT on this platform.");
         goto fail;
     }
@@ -1316,161 +1359,98 @@ orc_lazyjit_create(AOTCompContext *comp_ctx, uint32 func_count)
     LOG_VERBOSE("LLVM ORCJIT detected CPU \"%s\", with features \"%s\"\n", cpu,
                 features);
 
-    comp_ctx->target_machine = LLVMCreateTargetMachine(
-        llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelDefault,
+    /* create TargetMachine */
+    target_machine = LLVMCreateTargetMachine(
+        target, triple, cpu, features, LLVMCodeGenLevelDefault,
         LLVMRelocDefault, LLVMCodeModelJITDefault);
-    if (!comp_ctx->target_machine) {
+    if (!target_machine) {
         aot_set_last_error("failed to create target machine.");
         goto fail;
     }
+    comp_ctx->target_machine = target_machine;
 
-    target_machine_for_orcjit = LLVMCreateTargetMachine(
-        llvm_targetref, llvm_triple, cpu, features, LLVMCodeGenLevelDefault,
-        LLVMRelocDefault, LLVMCodeModelJITDefault);
-    if (!target_machine_for_orcjit) {
-        aot_set_last_error("failed to create target machine.");
-        goto fail;
-    }
+    /* Save target arch */
+    get_target_arch_from_triple(triple, comp_ctx->target_arch,
+                                sizeof(comp_ctx->target_arch));
+    ret = true;
+
+fail:
+    if (triple)
+        LLVMDisposeMessage(triple);
+    if (features)
+        LLVMDisposeMessage(features);
+    if (cpu)
+        LLVMDisposeMessage(cpu);
+
+    return ret;
+}
 
-    target_machine_builder =
-        LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(
-            target_machine_for_orcjit);
-    if (!target_machine_builder) {
-        aot_set_last_error("failed to create target machine builder.");
+static bool
+orc_jit_create(AOTCompContext *comp_ctx)
+{
+    LLVMErrorRef err;
+    LLVMOrcLLLazyJITRef orc_jit = NULL;
+    LLVMOrcLLLazyJITBuilderRef builder = NULL;
+    LLVMOrcJITTargetMachineBuilderRef jtmb = NULL;
+    bool ret = false;
+
+    builder = LLVMOrcCreateLLLazyJITBuilder();
+    if (builder == NULL) {
+        aot_set_last_error("failed to create jit builder.");
         goto fail;
     }
-    /* The target_machine_for_orcjit has been disposed before
-       LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine() returns */
-    target_machine_for_orcjit = NULL;
 
-    orc_lazyjit_builder = LLVMOrcCreateLLJITBuilder();
-    if (!orc_lazyjit_builder) {
-        aot_set_last_error("failed to create lazy jit builder.");
+    err = LLVMOrcJITTargetMachineBuilderDetectHost(&jtmb);
+    if (err != LLVMErrorSuccess) {
+        aot_handle_llvm_errmsg(
+            "quited to create LLVMOrcJITTargetMachineBuilderRef", err);
         goto fail;
     }
-    LLVMOrcLLJITBuilderSetNumCompileThreads(orc_lazyjit_builder,
-                                            WASM_LAZY_JIT_COMPILE_THREAD_NUM);
-    LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(orc_lazyjit_builder,
-                                                  target_machine_builder);
-    /* Should not dispose of the JITTargetMachineBuilder after calling
-       LLVMOrcLLJITBuilderSetJITTargetMachineBuilder() */
-    target_machine_builder = NULL;
-
-    err = LLVMOrcCreateLLJIT(&orc_lazyjit, orc_lazyjit_builder);
-    if (err) {
-        aot_handle_llvm_errmsg("failed to create llvm lazy orcjit instance",
+
+    LLVMOrcLLLazyJITBuilderSetNumCompileThreads(
+        builder, WASM_ORC_JIT_COMPILE_THREAD_NUM);
+
+    /* Ownership transfer:
+       LLVMOrcJITTargetMachineBuilderRef -> LLVMOrcLLJITBuilderRef */
+    LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(builder, jtmb);
+    err = LLVMOrcCreateLLLazyJIT(&orc_jit, builder);
+    if (err != LLVMErrorSuccess) {
+        aot_handle_llvm_errmsg("quited to create llvm lazy orcjit instance",
                                err);
         goto fail;
     }
-    /* The orc_lazyjit_builder is managed by orc_lazyjit after calling
-       LLVMOrcCreateLLJIT(), here we should not dispose it again */
-    orc_lazyjit_builder = NULL;
+    /* Ownership transfer: LLVMOrcLLJITBuilderRef -> LLVMOrcLLJITRef */
+    builder = NULL;
 
-    if (func_count > 0) {
-        orc_execution_session = LLVMOrcLLJITGetExecutionSession(orc_lazyjit);
-        if (!orc_execution_session) {
-            aot_set_last_error("failed to get orc execution session");
-            goto fail;
-        }
+#ifndef NDEBUG
+    /* Setup TransformLayer */
+    LLVMOrcIRTransformLayerSetTransform(
+        LLVMOrcLLLazyJITGetIRTransformLayer(orc_jit), *do_ir_transform,
+        comp_ctx);
 
-        err = LLVMOrcCreateLocalLazyCallThroughManager(
-            llvm_triple, orc_execution_session, 0, &orc_call_through_mgr);
-        if (err) {
-            aot_handle_llvm_errmsg("failed to create orc call through manager",
-                                   err);
-            goto fail;
-        }
-
-        orc_indirect_stub_mgr =
-            LLVMOrcCreateLocalIndirectStubsManager(llvm_triple);
-        if (!orc_indirect_stub_mgr) {
-            aot_set_last_error("failed to create orc indirect stub manager");
-            goto fail;
-        }
-
-        if (!(orc_symbol_map_pairs = wasm_runtime_malloc(
-                  sizeof(LLVMOrcCSymbolAliasMapPair) * func_count))) {
-            aot_set_last_error("failed to allocate memory");
-            goto fail;
-        }
-        memset(orc_symbol_map_pairs, 0,
-               sizeof(LLVMOrcCSymbolAliasMapPair) * func_count);
-
-        for (i = 0; i < func_count; i++) {
-            snprintf(func_name, sizeof(func_name), "orcjit_%s%d",
-                     AOT_FUNC_PREFIX, i);
-            orc_symbol_map_pairs[i].Name =
-                LLVMOrcExecutionSessionIntern(orc_execution_session, func_name);
-            snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
-            orc_symbol_map_pairs[i].Entry.Name =
-                LLVMOrcExecutionSessionIntern(orc_execution_session, func_name);
-            orc_symbol_map_pairs[i].Entry.Flags.GenericFlags =
-                LLVMJITSymbolGenericFlagsExported
-                | LLVMJITSymbolGenericFlagsCallable;
-            orc_symbol_map_pairs[i].Entry.Flags.TargetFlags =
-                LLVMJITSymbolGenericFlagsExported
-                | LLVMJITSymbolGenericFlagsCallable;
-
-            if (!orc_symbol_map_pairs[i].Name
-                || !orc_symbol_map_pairs[i].Entry.Name) {
-                aot_set_last_error("failed to allocate memory");
-                goto fail;
-            }
-        }
-
-        orc_material_unit =
-            LLVMOrcLazyReexports(orc_call_through_mgr, orc_indirect_stub_mgr,
-                                 LLVMOrcLLJITGetMainJITDylib(orc_lazyjit),
-                                 orc_symbol_map_pairs, func_count);
-        if (!orc_material_unit) {
-            aot_set_last_error("failed to orc re-exports");
-            goto fail;
-        }
-    }
+    LLVMOrcObjectTransformLayerSetTransform(
+        LLVMOrcLLLazyJITGetObjTransformLayer(orc_jit), *do_obj_transform,
+        comp_ctx);
+#endif
 
-    comp_ctx->orc_lazyjit = orc_lazyjit;
-    comp_ctx->orc_material_unit = orc_material_unit;
-    comp_ctx->orc_symbol_map_pairs = orc_symbol_map_pairs;
-    comp_ctx->orc_call_through_mgr = orc_call_through_mgr;
-    comp_ctx->orc_indirect_stub_mgr = orc_indirect_stub_mgr;
-
-    LLVMDisposeMessage(llvm_triple);
-    LLVMDisposeMessage(cpu);
-    LLVMDisposeMessage(features);
-    return true;
+    /* Ownership transfer: local -> AOTCompContext */
+    comp_ctx->orc_jit = orc_jit;
+    orc_jit = NULL;
+    ret = true;
 
 fail:
-    if (orc_symbol_map_pairs)
-        wasm_runtime_free(orc_symbol_map_pairs);
-    if (orc_call_through_mgr)
-        LLVMOrcDisposeLazyCallThroughManager(orc_call_through_mgr);
-    if (orc_indirect_stub_mgr)
-        LLVMOrcDisposeIndirectStubsManager(orc_indirect_stub_mgr);
-    if (orc_lazyjit)
-        LLVMOrcDisposeLLJIT(orc_lazyjit);
-    if (target_machine_builder)
-        LLVMOrcDisposeJITTargetMachineBuilder(target_machine_builder);
-    if (orc_lazyjit_builder)
-        LLVMOrcDisposeLLJITBuilder(orc_lazyjit_builder);
-    if (target_machine_for_orcjit)
-        LLVMDisposeTargetMachine(target_machine_for_orcjit);
-    if (features)
-        LLVMDisposeMessage(features);
-    if (cpu)
-        LLVMDisposeMessage(cpu);
-    if (llvm_triple)
-        LLVMDisposeMessage(llvm_triple);
-    return false;
+    if (builder)
+        LLVMOrcDisposeLLLazyJITBuilder(builder);
+
+    if (orc_jit)
+        LLVMOrcDisposeLLLazyJIT(orc_jit);
+    return ret;
 }
-#endif /* WASM_ENABLE_LAZY_JIT != 0 */
 
 AOTCompContext *
 aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
 {
     AOTCompContext *comp_ctx, *ret = NULL;
-#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];
@@ -1483,18 +1463,13 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
     LLVMTargetDataRef target_data_ref;
 
     /* Initialize LLVM environment */
-#if WASM_ENABLE_LAZY_JIT != 0
     LLVMInitializeCore(LLVMGetGlobalPassRegistry());
-    LLVMInitializeNativeTarget();
-    LLVMInitializeNativeAsmPrinter();
-    LLVMInitializeNativeAsmParser();
-#else
+    /* To all available target */
     LLVMInitializeAllTargetInfos();
     LLVMInitializeAllTargets();
     LLVMInitializeAllTargetMCs();
     LLVMInitializeAllAsmPrinters();
-    LLVMLinkInMCJIT();
-#endif
+    LLVMInitializeAllAsmParsers();
 
     /* Allocate memory */
     if (!(comp_ctx = wasm_runtime_malloc(sizeof(AOTCompContext)))) {
@@ -1506,7 +1481,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
     comp_ctx->comp_data = comp_data;
 
     /* Create LLVM context, module and builder */
-#if WASM_ENABLE_LAZY_JIT != 0
     comp_ctx->orc_thread_safe_context = LLVMOrcCreateNewThreadSafeContext();
     if (!comp_ctx->orc_thread_safe_context) {
         aot_set_last_error("create LLVM ThreadSafeContext failed.");
@@ -1521,53 +1495,26 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
         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.");
         goto fail;
     }
 
-#if WASM_ENABLE_LAZY_JIT == 0
+    /* Create LLVM module for each jit function, note:
+       different from non ORC JIT mode, no need to dispose it,
+       it will be disposed when the thread safe context is disposed */
     if (!(comp_ctx->module = LLVMModuleCreateWithNameInContext(
               "WASM Module", comp_ctx->context))) {
         aot_set_last_error("create LLVM module failed.");
         goto fail;
     }
-#else
-    if (comp_data->func_count > 0) {
-        if (!(comp_ctx->modules = wasm_runtime_malloc(
-                  sizeof(LLVMModuleRef) * comp_data->func_count))) {
-            aot_set_last_error("allocate memory failed.");
-            goto fail;
-        }
-        memset(comp_ctx->modules, 0,
-               sizeof(LLVMModuleRef) * comp_data->func_count);
-        for (i = 0; i < comp_data->func_count; i++) {
-            char module_name[32];
-            snprintf(module_name, sizeof(module_name), "WASM Module %d", i);
-            /* Create individual modules for each aot function, note:
-               different from non LAZY JIT mode, no need to dispose them,
-               they will be disposed when the thread safe context is disposed */
-            if (!(comp_ctx->modules[i] = LLVMModuleCreateWithNameInContext(
-                      module_name, comp_ctx->context))) {
-                aot_set_last_error("create LLVM module failed.");
-                goto fail;
-            }
-        }
-    }
-#endif
 
     if (BH_LIST_ERROR == bh_list_init(&comp_ctx->native_symbols)) {
         goto fail;
     }
 
-#if WASM_ENABLE_DEBUG_AOT != 0 && WASM_ENABLE_LAZY_JIT == 0
+#if WASM_ENABLE_DEBUG_AOT != 0
     if (!(comp_ctx->debug_builder = LLVMCreateDIBuilder(comp_ctx->module))) {
         aot_set_last_error("create LLVM Debug Infor builder failed.");
         goto fail;
@@ -1624,65 +1571,21 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
     comp_ctx->custom_sections_count = option->custom_sections_count;
 
     if (option->is_jit_mode) {
-        char *triple_jit = NULL;
-
         comp_ctx->is_jit_mode = true;
 
-#if WASM_ENABLE_LAZY_JIT != 0
-        /* Create LLJIT Instance */
-        if (!orc_lazyjit_create(comp_ctx, comp_data->func_count)) {
+        /* Create TargetMachine */
+        if (!create_target_machine_detect_host(comp_ctx))
             goto fail;
-        }
 
-#else
-        /* Create LLVM execution engine */
-        LLVMInitializeMCJITCompilerOptions(&jit_options, sizeof(jit_options));
-        jit_options.OptLevel = LLVMCodeGenLevelAggressive;
-        jit_options.EnableFastISel = true;
-        /*jit_options.CodeModel = LLVMCodeModelSmall;*/
-        if (WAMRCreateMCJITCompilerForModule(&comp_ctx->exec_engine,
-                                             comp_ctx->module, &jit_options,
-                                             sizeof(jit_options), &err)
-            != 0) {
-            if (err) {
-                LLVMDisposeMessage(err);
-                err = NULL;
-            }
-            aot_set_last_error("create LLVM JIT compiler failed.");
+        /* Create LLJIT Instance */
+        if (!orc_jit_create(comp_ctx))
             goto fail;
-        }
-        comp_ctx->target_machine =
-            LLVMGetExecutionEngineTargetMachine(comp_ctx->exec_engine);
-#endif
 
 #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 *)LLVMOrcLLJITGetTripleString(comp_ctx->orc_lazyjit))) {
-            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");
-            goto fail;
-        }
-
-        /* Save target arch */
-        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 */
@@ -1942,17 +1845,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
                 aot_set_last_error("create metadata string failed.");
                 goto fail;
             }
-#if WASM_ENABLE_LAZY_JIT == 0
             LLVMAddModuleFlag(comp_ctx->module, LLVMModuleFlagBehaviorError,
                               "target-abi", strlen("target-abi"),
                               meta_target_abi);
-#else
-            for (i = 0; i < comp_data->func_count; i++) {
-                LLVMAddModuleFlag(comp_ctx->modules[i],
-                                  LLVMModuleFlagBehaviorError, "target-abi",
-                                  strlen("target-abi"), meta_target_abi);
-            }
-#endif
 
             if (!strcmp(abi, "lp64d") || !strcmp(abi, "ilp32d")) {
                 if (features) {
@@ -2059,10 +1954,6 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
             aot_set_last_error("create LLVM target machine failed.");
             goto fail;
         }
-
-#if WASM_ENABLE_LAZY_JIT == 0
-        LLVMSetTarget(comp_ctx->module, triple_norm);
-#endif
     }
 
     if (option->enable_simd && strcmp(comp_ctx->target_arch, "x86_64") != 0
@@ -2171,56 +2062,23 @@ aot_destroy_comp_context(AOTCompContext *comp_ctx)
     if (!comp_ctx)
         return;
 
-#if WASM_ENABLE_LAZY_JIT != 0
-    if (comp_ctx->orc_symbol_map_pairs)
-        wasm_runtime_free(comp_ctx->orc_symbol_map_pairs);
-
-    if (comp_ctx->orc_call_through_mgr)
-        LLVMOrcDisposeLazyCallThroughManager(comp_ctx->orc_call_through_mgr);
-
-    if (comp_ctx->orc_indirect_stub_mgr)
-        LLVMOrcDisposeIndirectStubsManager(comp_ctx->orc_indirect_stub_mgr);
-
-    if (comp_ctx->orc_material_unit)
-        LLVMOrcDisposeMaterializationUnit(comp_ctx->orc_material_unit);
-
     if (comp_ctx->target_machine)
         LLVMDisposeTargetMachine(comp_ctx->target_machine);
 
     if (comp_ctx->builder)
         LLVMDisposeBuilder(comp_ctx->builder);
 
-    if (comp_ctx->orc_lazyjit)
-        LLVMOrcDisposeLLJIT(comp_ctx->orc_lazyjit);
-
     if (comp_ctx->orc_thread_safe_context)
         LLVMOrcDisposeThreadSafeContext(comp_ctx->orc_thread_safe_context);
 
-    if (comp_ctx->modules)
-        wasm_runtime_free(comp_ctx->modules);
-
-    /* Note: don't dispose comp_ctx->context and comp_ctx->modules[i] as
+    /* Note: don't dispose comp_ctx->context and comp_ctx->module as
        they are disposed when disposing the thread safe context */
 
-    LLVMShutdown();
-#else
-    if (comp_ctx->target_machine && !comp_ctx->is_jit_mode)
-        LLVMDisposeTargetMachine(comp_ctx->target_machine);
-
-    if (comp_ctx->builder)
-        LLVMDisposeBuilder(comp_ctx->builder);
+    /* Has to be the last one */
+    if (comp_ctx->orc_jit)
+        LLVMOrcDisposeLLLazyJIT(comp_ctx->orc_jit);
 
-    if (comp_ctx->exec_engine) {
-        LLVMDisposeExecutionEngine(comp_ctx->exec_engine);
-        /* The LLVM module is freed when disposing execution engine,
-           no need to dispose it again. */
-    }
-    else if (comp_ctx->module)
-        LLVMDisposeModule(comp_ctx->module);
-
-    if (comp_ctx->context)
-        LLVMContextDispose(comp_ctx->context);
-#endif
+    LLVMShutdown();
 
     if (comp_ctx->func_ctxes)
         aot_destroy_func_contexts(comp_ctx->func_ctxes,

+ 18 - 36
core/iwasm/compilation/aot_llvm.h

@@ -20,20 +20,18 @@
 #include "llvm-c/Transforms/Vectorize.h"
 #include "llvm-c/Transforms/PassManagerBuilder.h"
 
-#if WASM_ENABLE_LAZY_JIT != 0
 #include "llvm-c/Orc.h"
 #include "llvm-c/Error.h"
 #include "llvm-c/Support.h"
 #include "llvm-c/Initialization.h"
 #include "llvm-c/TargetMachine.h"
-#if LLVM_VERSION_MAJOR >= 12
 #include "llvm-c/LLJIT.h"
-#endif
-#endif
 #if WASM_ENABLE_DEBUG_AOT != 0
 #include "llvm-c/DebugInfo.h"
 #endif
 
+#include "aot_orc_extra.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -52,6 +50,16 @@ extern "C" {
 #define OPQ_PTR_TYPE INT8_PTR_TYPE
 #endif
 
+#ifndef NDEBUG
+#undef DEBUG_PASS
+#undef DUMP_MODULE
+// #define DEBUG_PASS
+// #define DUMP_MODULE
+#else
+#undef DEBUG_PASS
+#undef DUMP_MODULE
+#endif
+
 /**
  * Value in the WASM operation stack, each stack element
  * is an LLVM value
@@ -270,12 +278,6 @@ typedef struct AOTCompContext {
 
     /* LLVM variables required to emit LLVM IR */
     LLVMContextRef context;
-#if WASM_ENABLE_LAZY_JIT == 0
-    /* Create one module only for non LAZY JIT mode,
-       for LAZY JIT mode, modules are created, each
-       aot function has its own module */
-    LLVMModuleRef module;
-#endif
     LLVMBuilderRef builder;
 #if WASM_ENABLE_DEBUG_AOT
     LLVMDIBuilderRef debug_builder;
@@ -290,19 +292,11 @@ typedef struct AOTCompContext {
     /* Hardware intrinsic compability flags */
     uint64 flags[8];
 
-    /* LLVM execution engine required by JIT */
-#if WASM_ENABLE_LAZY_JIT != 0
-    LLVMOrcLLJITRef orc_lazyjit;
-    LLVMOrcMaterializationUnitRef orc_material_unit;
-    LLVMOrcLazyCallThroughManagerRef orc_call_through_mgr;
-    LLVMOrcIndirectStubsManagerRef orc_indirect_stub_mgr;
-    LLVMOrcCSymbolAliasMapPairs orc_symbol_map_pairs;
+    /* required by JIT */
+    LLVMOrcLLLazyJITRef orc_jit;
     LLVMOrcThreadSafeContextRef orc_thread_safe_context;
-    /* Each aot function has its own module */
-    LLVMModuleRef *modules;
-#else
-    LLVMExecutionEngineRef exec_engine;
-#endif
+
+    LLVMModuleRef module;
 
     bool is_jit_mode;
 
@@ -361,6 +355,7 @@ typedef struct AOTCompContext {
     AOTLLVMConsts llvm_consts;
 
     /* Function contexts */
+    /* TODO: */
     AOTFuncContext **func_ctxes;
     uint32 func_ctx_count;
     char **custom_sections_wp;
@@ -503,24 +498,11 @@ void
 aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass);
 
 void
-aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx);
-
-#if WASM_ENABLE_LAZY_JIT != 0
-LLVMOrcJITTargetMachineBuilderRef
-LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM);
-
-void
-LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef orcjit_builder,
-                                        unsigned num_compile_threads);
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module);
 
 void
 aot_handle_llvm_errmsg(const char *string, LLVMErrorRef err);
 
-void *
-aot_lookup_orcjit_func(LLVMOrcLLJITRef orc_lazyjit, void *module_inst,
-                       uint32 func_idx);
-#endif
-
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 43 - 211
core/iwasm/compilation/aot_llvm_extra.cpp

@@ -3,6 +3,8 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
+#include <llvm/Passes/StandardInstrumentations.h>
+#include <llvm/Support/Error.h>
 #include <llvm/ADT/SmallVector.h>
 #include <llvm/ADT/Twine.h>
 #include <llvm/ADT/Triple.h>
@@ -42,23 +44,15 @@
 #if LLVM_VERSION_MAJOR >= 12
 #include <llvm/Analysis/AliasAnalysis.h>
 #endif
+
 #include <cstring>
-#if WASM_ENABLE_LAZY_JIT != 0
 #include "../aot/aot_runtime.h"
-#endif
-
 #include "aot_llvm.h"
 
 using namespace llvm;
 using namespace llvm::orc;
 
-extern "C" {
-
-LLVMBool
-WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
-                                 LLVMModuleRef M,
-                                 LLVMMCJITCompilerOptions *PassedOptions,
-                                 size_t SizeOfPassedOptions, char **OutError);
+LLVM_C_EXTERN_C_BEGIN
 
 bool
 aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
@@ -70,93 +64,11 @@ void
 aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass);
 
 void
-aot_func_disable_tce(LLVMValueRef func);
-
-void
-aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx);
-}
-
-static TargetMachine *
-unwrap(LLVMTargetMachineRef P)
-{
-    return reinterpret_cast<TargetMachine *>(P);
-}
-
-LLVMBool
-WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
-                                 LLVMModuleRef M,
-                                 LLVMMCJITCompilerOptions *PassedOptions,
-                                 size_t SizeOfPassedOptions, char **OutError)
-{
-    LLVMMCJITCompilerOptions options;
-    // If the user passed a larger sized options struct, then they were compiled
-    // against a newer LLVM. Tell them that something is wrong.
-    if (SizeOfPassedOptions > sizeof(options)) {
-        *OutError = strdup("Refusing to use options struct that is larger than "
-                           "my own; assuming LLVM library mismatch.");
-        return 1;
-    }
-
-    // Defend against the user having an old version of the API by ensuring that
-    // any fields they didn't see are cleared. We must defend against fields
-    // being set to the bitwise equivalent of zero, and assume that this means
-    // "do the default" as if that option hadn't been available.
-    LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
-    memcpy(&options, PassedOptions, SizeOfPassedOptions);
-
-    TargetOptions targetOptions;
-    targetOptions.EnableFastISel = options.EnableFastISel;
-    std::unique_ptr<Module> Mod(unwrap(M));
-
-    if (Mod) {
-        // Set function attribute "frame-pointer" based on
-        // NoFramePointerElim.
-        for (auto &F : *Mod) {
-            auto Attrs = F.getAttributes();
-            StringRef Value = options.NoFramePointerElim ? "all" : "none";
-#if LLVM_VERSION_MAJOR <= 13
-            Attrs =
-                Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex,
-                                   "frame-pointer", Value);
-#else
-            Attrs = Attrs.addAttributeAtIndex(F.getContext(),
-                                              AttributeList::FunctionIndex,
-                                              "frame-pointer", Value);
-#endif
-            F.setAttributes(Attrs);
-        }
-    }
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module);
 
-    std::string Error;
-    bool JIT;
-    char *host_cpu = LLVMGetHostCPUName();
+LLVM_C_EXTERN_C_END
 
-    if (!host_cpu) {
-        *OutError = NULL;
-        return false;
-    }
-
-    std::string mcpu(host_cpu);
-    LLVMDisposeMessage(host_cpu);
-
-    EngineBuilder builder(std::move(Mod));
-    builder.setEngineKind(EngineKind::JIT)
-        .setErrorStr(&Error)
-        .setMCPU(mcpu)
-        .setOptLevel((CodeGenOpt::Level)options.OptLevel)
-        .setTargetOptions(targetOptions);
-    if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))
-        builder.setCodeModel(*CM);
-    if (options.MCJMM)
-        builder.setMCJITMemoryManager(
-            std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
-    if (ExecutionEngine *JIT = builder.create()) {
-        *OutJIT = wrap(JIT);
-        return 0;
-    }
-    *OutError = strdup(Error.c_str());
-    return 1;
-}
+ExitOnError ExitOnErr;
 
 class ExpandMemoryOpPass : public llvm::ModulePass
 {
@@ -258,13 +170,15 @@ ExpandMemoryOpPass::runOnModule(Module &M)
 void
 aot_add_expand_memory_op_pass(LLVMPassManagerRef pass)
 {
-    unwrap(pass)->add(new ExpandMemoryOpPass());
+    reinterpret_cast<legacy::PassManager *>(pass)->add(
+        new ExpandMemoryOpPass());
 }
 
 void
 aot_add_simple_loop_unswitch_pass(LLVMPassManagerRef pass)
 {
-    unwrap(pass)->add(createSimpleLoopUnswitchLegacyPass());
+    reinterpret_cast<legacy::PassManager *>(pass)->add(
+        createSimpleLoopUnswitchLegacyPass());
 }
 
 bool
@@ -308,123 +222,54 @@ aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
 #endif /* WASM_ENABLE_SIMD */
 }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-
-#if LLVM_VERSION_MAJOR < 12
-LLVMOrcJITTargetMachineBuilderRef
-LLVMOrcJITTargetMachineBuilderFromTargetMachine(LLVMTargetMachineRef TM);
-
-LLVMOrcJITTargetMachineBuilderRef
-LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(LLVMTargetMachineRef TM)
-{
-    return LLVMOrcJITTargetMachineBuilderFromTargetMachine(TM);
-}
-#endif
-
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
-
-void
-LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef orcjit_builder,
-                                        unsigned num_compile_threads)
-{
-    unwrap(orcjit_builder)->setNumCompileThreads(num_compile_threads);
-}
-
-void *
-aot_lookup_orcjit_func(LLVMOrcLLJITRef orc_lazyjit, void *module_inst,
-                       uint32 func_idx)
-{
-    char func_name[32], buf[128], *err_msg = NULL;
-    LLVMErrorRef error;
-    LLVMOrcJITTargetAddress func_addr = 0;
-    AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
-    AOTModule *aot_module = (AOTModule *)aot_inst->module;
-    void **func_ptrs = aot_inst->func_ptrs;
-
-    /**
-     * No need to lock the func_ptr[func_idx] here as it is basic
-     * data type, the load/store for it can be finished by one cpu
-     * instruction, and there can be only one cpu instruction
-     * loading/storing at the same time.
-     */
-    if (func_ptrs[func_idx])
-        return func_ptrs[func_idx];
-
-    snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX,
-             func_idx - aot_module->import_func_count);
-    if ((error = LLVMOrcLLJITLookup(orc_lazyjit, &func_addr, func_name))) {
-        err_msg = LLVMGetErrorMessage(error);
-        snprintf(buf, sizeof(buf), "failed to lookup orcjit function: %s",
-                 err_msg);
-        aot_set_exception(aot_inst, buf);
-        LLVMDisposeErrorMessage(err_msg);
-        return NULL;
-    }
-    func_ptrs[func_idx] = (void *)func_addr;
-    return (void *)func_addr;
-}
-#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
-
-void
-aot_func_disable_tce(LLVMValueRef func)
-{
-    Function *F = unwrap<Function>(func);
-    auto Attrs = F->getAttributes();
-
-#if LLVM_VERSION_MAJOR <= 13
-    Attrs = Attrs.addAttribute(F->getContext(), AttributeList::FunctionIndex,
-                               "disable-tail-calls", "true");
-#else
-    Attrs =
-        Attrs.addAttributeAtIndex(F->getContext(), AttributeList::FunctionIndex,
-                                  "disable-tail-calls", "true");
-#endif
-    F->setAttributes(Attrs);
-}
-
-#if LLVM_VERSION_MAJOR >= 12
 void
-aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx)
+aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx, LLVMModuleRef module)
 {
-    Module *M;
-    TargetMachine *TM = unwrap(comp_ctx->target_machine);
-    bool disable_llvm_lto = false;
-
-    LoopAnalysisManager LAM;
-    FunctionAnalysisManager FAM;
-    CGSCCAnalysisManager CGAM;
-    ModuleAnalysisManager MAM;
-
+    TargetMachine *TM =
+        reinterpret_cast<TargetMachine *>(comp_ctx->target_machine);
     PipelineTuningOptions PTO;
     PTO.LoopVectorization = true;
     PTO.SLPVectorization = true;
     PTO.LoopUnrolling = true;
 
+#ifdef DEBUG_PASS
+    PassInstrumentationCallbacks PIC;
+    PassBuilder PB(TM, PTO, None, &PIC);
+#else
 #if LLVM_VERSION_MAJOR == 12
     PassBuilder PB(false, TM, PTO);
 #else
     PassBuilder PB(TM, PTO);
 #endif
+#endif
+
+    /* Register all the basic analyses with the managers */
+    LoopAnalysisManager LAM;
+    FunctionAnalysisManager FAM;
+    CGSCCAnalysisManager CGAM;
+    ModuleAnalysisManager MAM;
 
-    // Register the target library analysis directly and give it a
-    // customized preset TLI.
+    /* Register the target library analysis directly and give it a
+       customized preset TLI */
     std::unique_ptr<TargetLibraryInfoImpl> TLII(
         new TargetLibraryInfoImpl(Triple(TM->getTargetTriple())));
     FAM.registerPass([&] { return TargetLibraryAnalysis(*TLII); });
 
-    // Register the AA manager first so that our version is the one used.
+    /* Register the AA manager first so that our version is the one used */
     AAManager AA = PB.buildDefaultAAPipeline();
     FAM.registerPass([&] { return std::move(AA); });
 
-    // Register all the basic analyses with the managers.
-    PB.registerModuleAnalyses(MAM);
-    PB.registerCGSCCAnalyses(CGAM);
+#ifdef DEBUG_PASS
+    StandardInstrumentations SI(true, false);
+    SI.registerCallbacks(PIC, &FAM);
+#endif
+
     PB.registerFunctionAnalyses(FAM);
     PB.registerLoopAnalyses(LAM);
+    PB.registerModuleAnalyses(MAM);
+    PB.registerCGSCCAnalyses(CGAM);
     PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
 
-    ModulePassManager MPM;
-
 #if LLVM_VERSION_MAJOR <= 13
     PassBuilder::OptimizationLevel OL;
 
@@ -463,25 +308,23 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx)
     }
 #endif /* end of LLVM_VERSION_MAJOR */
 
-    if (comp_ctx->disable_llvm_lto) {
-        disable_llvm_lto = true;
-    }
+    bool disable_llvm_lto = comp_ctx->disable_llvm_lto;
 #if WASM_ENABLE_SPEC_TEST != 0
     disable_llvm_lto = true;
 #endif
 
+    Module *M = reinterpret_cast<Module *>(module);
     if (disable_llvm_lto) {
-        uint32 i;
-
-        for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-            aot_func_disable_tce(comp_ctx->func_ctxes[i]->func);
+        for (Function &F : *M) {
+            F.addFnAttr("disable-tail-calls", "true");
         }
     }
 
+    ModulePassManager MPM;
     if (comp_ctx->is_jit_mode) {
-        /* Apply normal pipeline for JIT mode, without
-           Vectorize related passes, without LTO */
-        MPM.addPass(PB.buildPerModuleDefaultPipeline(OL));
+        const char *Passes =
+            "mem2reg,instcombine,simplifycfg,jump-threading,indvars";
+        ExitOnErr(PB.parsePassPipeline(MPM, Passes));
     }
     else {
         FunctionPassManager FPM;
@@ -512,16 +355,5 @@ aot_apply_llvm_new_pass_manager(AOTCompContext *comp_ctx)
         }
     }
 
-#if WASM_ENABLE_LAZY_JIT == 0
-    M = unwrap(comp_ctx->module);
     MPM.run(*M, MAM);
-#else
-    uint32 i;
-
-    for (i = 0; i < comp_ctx->func_ctx_count; i++) {
-        M = unwrap(comp_ctx->modules[i]);
-        MPM.run(*M, MAM);
-    }
-#endif
 }
-#endif /* end of LLVM_VERSION_MAJOR >= 12 */

+ 289 - 0
core/iwasm/compilation/aot_orc_extra.cpp

@@ -0,0 +1,289 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "llvm-c/LLJIT.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/OrcEE.h"
+#include "llvm-c/TargetMachine.h"
+
+#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
+#include "llvm/ExecutionEngine/Orc/LLJIT.h"
+#include "llvm/ExecutionEngine/Orc/ObjectTransformLayer.h"
+#include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/SectionMemoryManager.h"
+#include "llvm/Support/CBindingWrapping.h"
+
+#include "aot_orc_extra.h"
+#include "aot.h"
+
+using namespace llvm;
+using namespace llvm::orc;
+using GlobalValueSet = std::set<const GlobalValue *>;
+
+namespace llvm {
+namespace orc {
+
+class InProgressLookupState;
+
+class OrcV2CAPIHelper
+{
+  public:
+    using PoolEntry = SymbolStringPtr::PoolEntry;
+    using PoolEntryPtr = SymbolStringPtr::PoolEntryPtr;
+
+    // Move from SymbolStringPtr to PoolEntryPtr (no change in ref count).
+    static PoolEntryPtr moveFromSymbolStringPtr(SymbolStringPtr S)
+    {
+        PoolEntryPtr Result = nullptr;
+        std::swap(Result, S.S);
+        return Result;
+    }
+
+    // Move from a PoolEntryPtr to a SymbolStringPtr (no change in ref count).
+    static SymbolStringPtr moveToSymbolStringPtr(PoolEntryPtr P)
+    {
+        SymbolStringPtr S;
+        S.S = P;
+        return S;
+    }
+
+    // Copy a pool entry to a SymbolStringPtr (increments ref count).
+    static SymbolStringPtr copyToSymbolStringPtr(PoolEntryPtr P)
+    {
+        return SymbolStringPtr(P);
+    }
+
+    static PoolEntryPtr getRawPoolEntryPtr(const SymbolStringPtr &S)
+    {
+        return S.S;
+    }
+
+    static void retainPoolEntry(PoolEntryPtr P)
+    {
+        SymbolStringPtr S(P);
+        S.S = nullptr;
+    }
+
+    static void releasePoolEntry(PoolEntryPtr P)
+    {
+        SymbolStringPtr S;
+        S.S = P;
+    }
+
+    static InProgressLookupState *extractLookupState(LookupState &LS)
+    {
+        return LS.IPLS.release();
+    }
+
+    static void resetLookupState(LookupState &LS, InProgressLookupState *IPLS)
+    {
+        return LS.reset(IPLS);
+    }
+};
+
+} // namespace orc
+} // namespace llvm
+
+// ORC.h
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ExecutionSession, LLVMOrcExecutionSessionRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRTransformLayer, LLVMOrcIRTransformLayerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITDylib, LLVMOrcJITDylibRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(JITTargetMachineBuilder,
+                                   LLVMOrcJITTargetMachineBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ObjectTransformLayer,
+                                   LLVMOrcObjectTransformLayerRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcV2CAPIHelper::PoolEntry,
+                                   LLVMOrcSymbolStringPoolEntryRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(SymbolStringPool, LLVMOrcSymbolStringPoolRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(ThreadSafeModule, LLVMOrcThreadSafeModuleRef)
+
+// LLJIT.h
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLJITBuilder, LLVMOrcLLJITBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLLazyJITBuilder, LLVMOrcLLLazyJITBuilderRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(LLLazyJIT, LLVMOrcLLLazyJITRef)
+
+void
+LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef Builder,
+                                        unsigned NumCompileThreads)
+{
+    unwrap(Builder)->setNumCompileThreads(NumCompileThreads);
+}
+
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void)
+{
+    return wrap(new LLLazyJITBuilder());
+}
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder)
+{
+    delete unwrap(Builder);
+}
+
+void
+LLVMOrcLLLazyJITBuilderSetNumCompileThreads(LLVMOrcLLLazyJITBuilderRef Builder,
+                                            unsigned NumCompileThreads)
+{
+    unwrap(Builder)->setNumCompileThreads(NumCompileThreads);
+}
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+    LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMP)
+{
+    unwrap(Builder)->setJITTargetMachineBuilder(*unwrap(JTMP));
+    /* Destroy the JTMP, similar to
+       LLVMOrcLLJITBuilderSetJITTargetMachineBuilder */
+    LLVMOrcDisposeJITTargetMachineBuilder(JTMP);
+}
+
+static Optional<CompileOnDemandLayer::GlobalValueSet>
+PartitionFunction(GlobalValueSet Requested)
+{
+    std::vector<const GlobalValue *> GVsToAdd;
+
+    for (auto *GV : Requested) {
+        if (isa<Function>(GV) && GV->hasName()) {
+            auto &F = cast<Function>(*GV);       /* get LLVM function */
+            const Module *M = F.getParent();     /* get LLVM module */
+            auto GVName = GV->getName();         /* get the function name */
+            const char *gvname = GVName.begin(); /* C function name */
+            const char *wrapper;
+            uint32 prefix_len = strlen(AOT_FUNC_PREFIX);
+
+            /* Convert "aot_func#n_wrapper" to "aot_func#n" */
+            if (strstr(gvname, AOT_FUNC_PREFIX)
+                && (wrapper = strstr(gvname + prefix_len, "_wrapper"))) {
+                char buf[16] = { 0 };
+                char func_name[64];
+                int group_stride, i, j;
+
+                bh_assert(wrapper - (gvname + prefix_len) > 0);
+                /* Get AOT function index */
+                bh_memcpy_s(buf, (uint32)sizeof(buf), gvname + prefix_len,
+                            (uint32)(wrapper - (gvname + prefix_len)));
+                i = atoi(buf);
+
+                group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+
+                /* Compile some functions each time */
+                for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+                    snprintf(func_name, sizeof(func_name), "%s%d",
+                             AOT_FUNC_PREFIX, i + j * group_stride);
+                    Function *F1 = M->getFunction(func_name);
+                    if (F1) {
+                        LOG_DEBUG("compile func %s", func_name);
+                        GVsToAdd.push_back(cast<GlobalValue>(F1));
+                    }
+                }
+            }
+        }
+    }
+
+    for (auto *GV : GVsToAdd) {
+        Requested.insert(GV);
+    }
+
+    return Requested;
+}
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+                       LLVMOrcLLLazyJITBuilderRef Builder)
+{
+    assert(Result && "Result can not be null");
+
+    if (!Builder)
+        Builder = LLVMOrcCreateLLLazyJITBuilder();
+
+    auto J = unwrap(Builder)->create();
+    LLVMOrcDisposeLLLazyJITBuilder(Builder);
+
+    if (!J) {
+        Result = nullptr;
+        return 0;
+    }
+
+    LLLazyJIT *lazy_jit = J->release();
+    lazy_jit->setPartitionFunction(PartitionFunction);
+
+    *Result = wrap(lazy_jit);
+    return LLVMErrorSuccess;
+}
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J)
+{
+    delete unwrap(J);
+    return LLVMErrorSuccess;
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
+                                LLVMOrcThreadSafeModuleRef TSM)
+{
+    std::unique_ptr<ThreadSafeModule> TmpTSM(unwrap(TSM));
+    return wrap(unwrap(J)->addLazyIRModule(*unwrap(JD), std::move(*TmpTSM)));
+}
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcExecutorAddress *Result,
+                       const char *Name)
+{
+    assert(Result && "Result can not be null");
+
+    auto Sym = unwrap(J)->lookup(Name);
+    if (!Sym) {
+        *Result = 0;
+        return wrap(Sym.takeError());
+    }
+
+#if LLVM_VERSION_MAJOR < 15
+    *Result = Sym->getAddress();
+#else
+    *Result = Sym->getValue();
+#endif
+    return LLVMErrorSuccess;
+}
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLLazyJITMangleAndIntern(LLVMOrcLLLazyJITRef J,
+                                const char *UnmangledName)
+{
+    return wrap(OrcV2CAPIHelper::moveFromSymbolStringPtr(
+        unwrap(J)->mangleAndIntern(UnmangledName)));
+}
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J)
+{
+    return wrap(&unwrap(J)->getMainJITDylib());
+}
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J)
+{
+    return unwrap(J)->getTargetTriple().str().c_str();
+}
+
+LLVMOrcExecutionSessionRef
+LLVMOrcLLLazyJITGetExecutionSession(LLVMOrcLLLazyJITRef J)
+{
+    return wrap(&unwrap(J)->getExecutionSession());
+}
+
+LLVMOrcIRTransformLayerRef
+LLVMOrcLLLazyJITGetIRTransformLayer(LLVMOrcLLLazyJITRef J)
+{
+    return wrap(&unwrap(J)->getIRTransformLayer());
+}
+
+LLVMOrcObjectTransformLayerRef
+LLVMOrcLLLazyJITGetObjTransformLayer(LLVMOrcLLLazyJITRef J)
+{
+    return wrap(&unwrap(J)->getObjTransformLayer());
+}

+ 75 - 0
core/iwasm/compilation/aot_orc_extra.h

@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_ORC_LAZINESS_H_
+#define _AOT_ORC_LAZINESS_H_
+
+#include "llvm-c/Error.h"
+#include "llvm-c/ExternC.h"
+#include "llvm-c/LLJIT.h"
+#include "llvm-c/Orc.h"
+#include "llvm-c/Types.h"
+
+LLVM_C_EXTERN_C_BEGIN
+
+typedef struct LLVMOrcOpaqueLLLazyJITBuilder *LLVMOrcLLLazyJITBuilderRef;
+typedef struct LLVMOrcOpaqueLLLazyJIT *LLVMOrcLLLazyJITRef;
+
+// Extra bindings for LLJIT
+void
+LLVMOrcLLJITBuilderSetNumCompileThreads(LLVMOrcLLJITBuilderRef Builder,
+                                        unsigned NumCompileThreads);
+
+// Extra bindings for LLLazyJIT
+LLVMOrcLLLazyJITBuilderRef
+LLVMOrcCreateLLLazyJITBuilder(void);
+
+void
+LLVMOrcDisposeLLLazyJITBuilder(LLVMOrcLLLazyJITBuilderRef Builder);
+
+void
+LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
+    LLVMOrcLLLazyJITBuilderRef Builder, LLVMOrcJITTargetMachineBuilderRef JTMP);
+
+void
+LLVMOrcLLLazyJITBuilderSetNumCompileThreads(LLVMOrcLLLazyJITBuilderRef Builder,
+                                            unsigned NumCompileThreads);
+
+LLVMErrorRef
+LLVMOrcCreateLLLazyJIT(LLVMOrcLLLazyJITRef *Result,
+                       LLVMOrcLLLazyJITBuilderRef Builder);
+
+LLVMErrorRef
+LLVMOrcDisposeLLLazyJIT(LLVMOrcLLLazyJITRef J);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITAddLLVMIRModule(LLVMOrcLLLazyJITRef J, LLVMOrcJITDylibRef JD,
+                                LLVMOrcThreadSafeModuleRef TSM);
+
+LLVMErrorRef
+LLVMOrcLLLazyJITLookup(LLVMOrcLLLazyJITRef J, LLVMOrcExecutorAddress *Result,
+                       const char *Name);
+
+LLVMOrcSymbolStringPoolEntryRef
+LLVMOrcLLLazyJITMangleAndIntern(LLVMOrcLLLazyJITRef J,
+                                const char *UnmangledName);
+
+LLVMOrcJITDylibRef
+LLVMOrcLLLazyJITGetMainJITDylib(LLVMOrcLLLazyJITRef J);
+
+const char *
+LLVMOrcLLLazyJITGetTripleString(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcExecutionSessionRef
+LLVMOrcLLLazyJITGetExecutionSession(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcIRTransformLayerRef
+LLVMOrcLLLazyJITGetIRTransformLayer(LLVMOrcLLLazyJITRef J);
+
+LLVMOrcObjectTransformLayerRef
+LLVMOrcLLLazyJITGetObjTransformLayer(LLVMOrcLLLazyJITRef J);
+
+LLVM_C_EXTERN_C_END
+#endif

+ 14 - 1
core/iwasm/interpreter/wasm.h

@@ -369,6 +369,13 @@ typedef struct WASMCustomSection {
 #if WASM_ENABLE_JIT != 0
 struct AOTCompData;
 struct AOTCompContext;
+
+/* Orc JIT thread arguments */
+typedef struct OrcJitThreadArg {
+    struct AOTCompContext *comp_ctx;
+    struct WASMModule *module;
+    uint32 group_idx;
+} OrcJitThreadArg;
 #endif
 
 struct WASMModule {
@@ -501,14 +508,20 @@ struct WASMModule {
 #endif
 
 #if WASM_ENABLE_FAST_JIT != 0
-    /* point to JITed functions */
+    /* func pointers of Fast JITed (un-imported) functions */
     void **fast_jit_func_ptrs;
 #endif
 
 #if WASM_ENABLE_JIT != 0
     struct AOTCompData *comp_data;
     struct AOTCompContext *comp_ctx;
+    /* func pointers of LLVM JITed (un-imported) functions */
     void **func_ptrs;
+    /* whether the func pointers are compiled */
+    bool *func_ptrs_compiled;
+    bool orcjit_stop_compiling;
+    korp_tid orcjit_threads[WASM_ORC_JIT_BACKEND_THREAD_NUM];
+    OrcJitThreadArg orcjit_thread_args[WASM_ORC_JIT_BACKEND_THREAD_NUM];
 #endif
 };
 

+ 132 - 31
core/iwasm/interpreter/wasm_loader.c

@@ -2953,20 +2953,91 @@ calculate_global_data_offset(WASMModule *module)
 }
 
 #if WASM_ENABLE_JIT != 0
+static void *
+orcjit_thread_callback(void *arg)
+{
+    LLVMOrcJITTargetAddress func_addr = 0;
+    OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
+    AOTCompContext *comp_ctx = thread_arg->comp_ctx;
+    WASMModule *module = thread_arg->module;
+    uint32 group_idx = thread_arg->group_idx;
+    uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+    uint32 func_count = module->function_count;
+    uint32 i, j;
+    typedef void (*F)(void);
+    LLVMErrorRef error;
+    char func_name[48];
+    union {
+        F f;
+        void *v;
+    } u;
+
+    /* Compile jit functions of this group */
+    for (i = group_idx; i < func_count;
+         i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+        snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
+                 "_wrapper");
+        LOG_DEBUG("compile func %s", func_name);
+        error =
+            LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
+        if (error != LLVMErrorSuccess) {
+            char *err_msg = LLVMGetErrorMessage(error);
+            os_printf("failed to compile orc jit function: %s", err_msg);
+            LLVMDisposeErrorMessage(err_msg);
+            continue;
+        }
+
+        /* Call the jit wrapper function to trigger its compilation, so as
+           to compile the actual jit functions, since we add the latter to
+           function list in the PartitionFunction callback */
+        u.v = (void *)func_addr;
+        u.f();
+
+        for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+            if (i + j * group_stride < func_count)
+                module->func_ptrs_compiled[i + j * group_stride] = true;
+        }
+
+        if (module->orcjit_stop_compiling) {
+            break;
+        }
+    }
+
+    return NULL;
+}
+
+static void
+orcjit_stop_compile_threads(WASMModule *module)
+{
+    uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
+                                    / sizeof(OrcJitThreadArg));
+
+    module->orcjit_stop_compiling = true;
+    for (i = 0; i < thread_num; i++) {
+        if (module->orcjit_threads[i])
+            os_thread_join(module->orcjit_threads[i], NULL);
+    }
+}
+
 static bool
 compile_llvm_jit_functions(WASMModule *module, char *error_buf,
                            uint32 error_buf_size)
 {
     AOTCompOption option = { 0 };
-    char func_name[32], *aot_last_error;
+    char *aot_last_error;
     uint64 size;
-    uint32 i;
+    uint32 thread_num, i;
 
-    size = sizeof(void *) * (uint64)module->function_count;
-    if (size > 0
-        && !(module->func_ptrs =
-                 loader_malloc(size, error_buf, error_buf_size))) {
-        return false;
+    if (module->function_count > 0) {
+        size = sizeof(void *) * (uint64)module->function_count
+               + sizeof(bool) * (uint64)module->function_count;
+        if (!(module->func_ptrs =
+                  loader_malloc(size, error_buf, error_buf_size))) {
+            return false;
+        }
+        module->func_ptrs_compiled =
+            (bool *)((uint8 *)module->func_ptrs
+                     + sizeof(void *) * module->function_count);
     }
 
     module->comp_data = aot_create_comp_data(module);
@@ -3015,20 +3086,24 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
         return false;
     }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-    for (i = 0; i < module->comp_data->func_count; i++) {
-        LLVMErrorRef error;
+    bh_print_time("Begin to lookup jit functions");
+
+    for (i = 0; i < module->function_count; i++) {
         LLVMOrcJITTargetAddress func_addr = 0;
+        LLVMErrorRef error;
+        char func_name[48];
 
         snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
-        if ((error = LLVMOrcLLJITLookup(module->comp_ctx->orc_lazyjit,
-                                        &func_addr, func_name))) {
+        error = LLVMOrcLLLazyJITLookup(module->comp_ctx->orc_jit, &func_addr,
+                                       func_name);
+        if (error != LLVMErrorSuccess) {
             char *err_msg = LLVMGetErrorMessage(error);
             set_error_buf_v(error_buf, error_buf_size,
                             "failed to compile orc jit function: %s", err_msg);
             LLVMDisposeErrorMessage(err_msg);
             return false;
         }
+
         /**
          * No need to lock the func_ptr[func_idx] here as it is basic
          * data type, the load/store for it can be finished by one cpu
@@ -3038,20 +3113,43 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
         module->func_ptrs[i] = (void *)func_addr;
         module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
     }
-#else
-    /* Resolve function addresses */
-    bh_assert(module->comp_ctx->exec_engine);
-    for (i = 0; i < module->comp_data->func_count; i++) {
-        snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
-        if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress(
-                  module->comp_ctx->exec_engine, func_name))) {
+
+    bh_print_time("Begin to compile jit functions");
+
+    thread_num =
+        (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
+
+    /* Create threads to compile the jit functions */
+    for (i = 0; i < thread_num; i++) {
+        module->orcjit_thread_args[i].comp_ctx = module->comp_ctx;
+        module->orcjit_thread_args[i].module = module;
+        module->orcjit_thread_args[i].group_idx = i;
+
+        if (os_thread_create(&module->orcjit_threads[i], orcjit_thread_callback,
+                             (void *)&module->orcjit_thread_args[i],
+                             APP_THREAD_STACK_SIZE_DEFAULT)
+            != 0) {
+            uint32 j;
+
             set_error_buf(error_buf, error_buf_size,
-                          "failed to compile llvm mc jit function");
+                          "create orcjit compile thread failed");
+            /* Terminate the threads created */
+            module->orcjit_stop_compiling = true;
+            for (j = 0; j < i; j++) {
+                os_thread_join(module->orcjit_threads[j], NULL);
+            }
             return false;
         }
-        module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i];
     }
-#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
+
+#if WASM_ENABLE_LAZY_JIT == 0
+    /* Wait until all jit functions are compiled for eager mode */
+    for (i = 0; i < thread_num; i++) {
+        os_thread_join(module->orcjit_threads[i], NULL);
+    }
+#endif
+
+    bh_print_time("End compile jit functions");
 
     return true;
 }
@@ -3893,6 +3991,18 @@ wasm_loader_unload(WASMModule *module)
     if (!module)
         return;
 
+#if WASM_ENABLE_JIT != 0
+    /* Stop LLVM JIT compilation firstly to avoid accessing
+       module internal data after they were freed */
+    orcjit_stop_compile_threads(module);
+    if (module->func_ptrs)
+        wasm_runtime_free(module->func_ptrs);
+    if (module->comp_ctx)
+        aot_destroy_comp_context(module->comp_ctx);
+    if (module->comp_data)
+        aot_destroy_comp_data(module->comp_data);
+#endif
+
     if (module->types) {
         for (i = 0; i < module->type_count; i++) {
             if (module->types[i])
@@ -4018,15 +4128,6 @@ wasm_loader_unload(WASMModule *module)
     }
 #endif
 
-#if WASM_ENABLE_JIT != 0
-    if (module->func_ptrs)
-        wasm_runtime_free(module->func_ptrs);
-    if (module->comp_ctx)
-        aot_destroy_comp_context(module->comp_ctx);
-    if (module->comp_data)
-        aot_destroy_comp_data(module->comp_data);
-#endif
-
     wasm_runtime_free(module);
 }
 

+ 136 - 33
core/iwasm/interpreter/wasm_mini_loader.c

@@ -1784,20 +1784,91 @@ calculate_global_data_offset(WASMModule *module)
 }
 
 #if WASM_ENABLE_JIT != 0
+static void *
+orcjit_thread_callback(void *arg)
+{
+    LLVMOrcJITTargetAddress func_addr = 0;
+    OrcJitThreadArg *thread_arg = (OrcJitThreadArg *)arg;
+    AOTCompContext *comp_ctx = thread_arg->comp_ctx;
+    WASMModule *module = thread_arg->module;
+    uint32 group_idx = thread_arg->group_idx;
+    uint32 group_stride = WASM_ORC_JIT_BACKEND_THREAD_NUM;
+    uint32 func_count = module->function_count;
+    uint32 i, j;
+    typedef void (*F)(void);
+    LLVMErrorRef error;
+    char func_name[48];
+    union {
+        F f;
+        void *v;
+    } u;
+
+    /* Compile jit functions of this group */
+    for (i = group_idx; i < func_count;
+         i += group_stride * WASM_ORC_JIT_COMPILE_THREAD_NUM) {
+        snprintf(func_name, sizeof(func_name), "%s%d%s", AOT_FUNC_PREFIX, i,
+                 "_wrapper");
+        LOG_DEBUG("compile func %s", func_name);
+        error =
+            LLVMOrcLLLazyJITLookup(comp_ctx->orc_jit, &func_addr, func_name);
+        if (error != LLVMErrorSuccess) {
+            char *err_msg = LLVMGetErrorMessage(error);
+            os_printf("failed to compile orc jit function: %s", err_msg);
+            LLVMDisposeErrorMessage(err_msg);
+            continue;
+        }
+
+        /* Call the jit wrapper function to trigger its compilation, so as
+           to compile the actual jit functions, since we add the latter to
+           function list in the PartitionFunction callback */
+        u.v = (void *)func_addr;
+        u.f();
+
+        for (j = 0; j < WASM_ORC_JIT_COMPILE_THREAD_NUM; j++) {
+            if (i + j * group_stride < func_count)
+                module->func_ptrs_compiled[i + j * group_stride] = true;
+        }
+
+        if (module->orcjit_stop_compiling) {
+            break;
+        }
+    }
+
+    return NULL;
+}
+
+static void
+orcjit_stop_compile_threads(WASMModule *module)
+{
+    uint32 i, thread_num = (uint32)(sizeof(module->orcjit_thread_args)
+                                    / sizeof(OrcJitThreadArg));
+
+    module->orcjit_stop_compiling = true;
+    for (i = 0; i < thread_num; i++) {
+        if (module->orcjit_threads[i])
+            os_thread_join(module->orcjit_threads[i], NULL);
+    }
+}
+
 static bool
 compile_llvm_jit_functions(WASMModule *module, char *error_buf,
                            uint32 error_buf_size)
 {
     AOTCompOption option = { 0 };
-    char func_name[32], *aot_last_error;
+    char *aot_last_error;
     uint64 size;
-    uint32 i;
+    uint32 thread_num, i;
 
-    size = sizeof(void *) * (uint64)module->function_count;
-    if (size > 0
-        && !(module->func_ptrs =
-                 loader_malloc(size, error_buf, error_buf_size))) {
-        return false;
+    if (module->function_count > 0) {
+        size = sizeof(void *) * (uint64)module->function_count
+               + sizeof(bool) * (uint64)module->function_count;
+        if (!(module->func_ptrs =
+                  loader_malloc(size, error_buf, error_buf_size))) {
+            return false;
+        }
+        module->func_ptrs_compiled =
+            (bool *)((uint8 *)module->func_ptrs
+                     + sizeof(void *) * module->function_count);
     }
 
     module->comp_data = aot_create_comp_data(module);
@@ -1846,20 +1917,26 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
         return false;
     }
 
-#if WASM_ENABLE_LAZY_JIT != 0
-    for (i = 0; i < module->comp_data->func_count; i++) {
-        LLVMErrorRef error;
+    bh_print_time("Begin to lookup jit functions");
+
+    for (i = 0; i < module->function_count; i++) {
         LLVMOrcJITTargetAddress func_addr = 0;
+        LLVMErrorRef error;
+        char func_name[48];
 
         snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
-        if ((error = LLVMOrcLLJITLookup(module->comp_ctx->orc_lazyjit,
-                                        &func_addr, func_name))) {
+        error = LLVMOrcLLLazyJITLookup(module->comp_ctx->orc_jit, &func_addr,
+                                       func_name);
+        if (error != LLVMErrorSuccess) {
             char *err_msg = LLVMGetErrorMessage(error);
-            set_error_buf_v(error_buf, error_buf_size,
-                            "failed to compile orc jit function: %s", err_msg);
+            char buf[128];
+            snprintf(buf, sizeof(buf), "failed to compile orc jit function: %s",
+                     err_msg);
+            set_error_buf(error_buf, error_buf_size, buf);
             LLVMDisposeErrorMessage(err_msg);
             return false;
         }
+
         /**
          * No need to lock the func_ptr[func_idx] here as it is basic
          * data type, the load/store for it can be finished by one cpu
@@ -1869,20 +1946,43 @@ compile_llvm_jit_functions(WASMModule *module, char *error_buf,
         module->func_ptrs[i] = (void *)func_addr;
         module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
     }
-#else
-    /* Resolve function addresses */
-    bh_assert(module->comp_ctx->exec_engine);
-    for (i = 0; i < module->comp_data->func_count; i++) {
-        snprintf(func_name, sizeof(func_name), "%s%d", AOT_FUNC_PREFIX, i);
-        if (!(module->func_ptrs[i] = (void *)LLVMGetFunctionAddress(
-                  module->comp_ctx->exec_engine, func_name))) {
+
+    bh_print_time("Begin to compile jit functions");
+
+    thread_num =
+        (uint32)(sizeof(module->orcjit_thread_args) / sizeof(OrcJitThreadArg));
+
+    /* Create threads to compile the jit functions */
+    for (i = 0; i < thread_num; i++) {
+        module->orcjit_thread_args[i].comp_ctx = module->comp_ctx;
+        module->orcjit_thread_args[i].module = module;
+        module->orcjit_thread_args[i].group_idx = i;
+
+        if (os_thread_create(&module->orcjit_threads[i], orcjit_thread_callback,
+                             (void *)&module->orcjit_thread_args[i],
+                             APP_THREAD_STACK_SIZE_DEFAULT)
+            != 0) {
+            uint32 j;
+
             set_error_buf(error_buf, error_buf_size,
-                          "failed to compile llvm mc jit function");
+                          "create orcjit compile thread failed");
+            /* Terminate the threads created */
+            module->orcjit_stop_compiling = true;
+            for (j = 0; j < i; j++) {
+                os_thread_join(module->orcjit_threads[j], NULL);
+            }
             return false;
         }
-        module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i];
     }
-#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
+
+#if WASM_ENABLE_LAZY_JIT == 0
+    /* Wait until all jit functions are compiled for eager mode */
+    for (i = 0; i < thread_num; i++) {
+        os_thread_join(module->orcjit_threads[i], NULL);
+    }
+#endif
+
+    bh_print_time("End compile jit functions");
 
     return true;
 }
@@ -2586,6 +2686,18 @@ wasm_loader_unload(WASMModule *module)
     if (!module)
         return;
 
+#if WASM_ENABLE_JIT != 0
+    /* Stop LLVM JIT compilation firstly to avoid accessing
+       module internal data after they were freed */
+    orcjit_stop_compile_threads(module);
+    if (module->func_ptrs)
+        wasm_runtime_free(module->func_ptrs);
+    if (module->comp_ctx)
+        aot_destroy_comp_context(module->comp_ctx);
+    if (module->comp_data)
+        aot_destroy_comp_data(module->comp_data);
+#endif
+
     if (module->types) {
         for (i = 0; i < module->type_count; i++) {
             if (module->types[i])
@@ -2673,15 +2785,6 @@ wasm_loader_unload(WASMModule *module)
     }
 #endif
 
-#if WASM_ENABLE_JIT != 0
-    if (module->func_ptrs)
-        wasm_runtime_free(module->func_ptrs);
-    if (module->comp_ctx)
-        aot_destroy_comp_context(module->comp_ctx);
-    if (module->comp_data)
-        aot_destroy_comp_data(module->comp_data);
-#endif
-
     wasm_runtime_free(module);
 }
 

+ 14 - 13
doc/build_wamr.md

@@ -41,7 +41,6 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
 
 - **WAMR_BUILD_AOT**=1/0, enable AOT or not, default to enable if not set
 - **WAMR_BUILD_JIT**=1/0, enable LLVM JIT or not, default to disable if not set
-- **WAMR_BUILD_LAZY_JIT**=1/0, whether to use Lazy JIT mode or not when *WAMR_BUILD_JIT* is set, default to enable if not set
 - **WAMR_BUILD_FAST_JIT**=1/0, enable Fast JIT or not, default to disable if not set
 
 #### **Configure LIBC**
@@ -224,7 +223,7 @@ make
 By default in Linux, the `fast interpreter`, `AOT` and `Libc 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.
 
-There are total 6 running modes supported: fast interpreter, classi interpreter, AOT, LLVM Lazy JIT, LLVM MC JIT and Fast JIT.
+There are total 5 running modes supported: fast interpreter, classi interpreter, AOT, LLVM JIT and Fast JIT.
 
 (1) To run a wasm file with `fast interpreter` mode - build iwasm with default build and then:
 ```Bash
@@ -250,32 +249,34 @@ wamrc -o <AOT file> <WASM file>
 iwasm <AOT file>
 ```
 
-(4) To enable the `LLVM Lazy JIT` mode, firstly we should build LLVM library:
+(4) To enable the `LLVM JIT` mode, firstly we should build the LLVM library:
 ``` Bash
 cd product-mini/platforms/linux/
 ./build_llvm.sh     (The llvm source code is cloned under <wamr_root_dir>/core/deps/llvm and auto built)
 ```
 
-Then pass argument `-DWAMR_BUILD_JIT=1` to cmake to enable LLVM Lazy JIT:
+Then pass argument `-DWAMR_BUILD_JIT=1` to cmake to enable LLVM JIT:
 ``` Bash
 mkdir build && cd build
 cmake .. -DWAMR_BUILD_JIT=1
 make
 ```
 
-(5) Or disable `LLVM Lazy JIT` and enable `LLVM MC JIT` instead:
-```Bash
+Note:
+By default, the LLVM Orc JIT with Lazy compilation is enabled to speedup the lanuching process and reduce
+the JIT compilation time by creating backend threads to compile the WASM functions parallely, and for the
+main thread, the functions in the module will not be compiled until they are firstly called and haven't been
+compiled by the compilation threads.
+
+If developer wants to disable the Lazy compilation, we can:
+``` Bash
 mkdir build && cd build
 cmake .. -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0
 make
 ```
+In which all the WASM functions will be previously compiled before main thread starts to run the wasm module.
 
-By default, the LLVM Orc Lazy JIT is enabled to speedup the lanuching process and reduce the JIT compilation time
-by creating threads to compile the WASM functions parallely, and for the main thread, the functions in the
-module will not be compiled until they are firstly called and haven't been compiled by the compilation threads.
-To disable it and enable LLVM MC JIT instead, please pass argument `-DWAMR_BUILD_LAZY_JIT=0` to cmake.
-
-(6) To enable the `Fast JIT` mode:
+(5) To enable the `Fast JIT` mode:
 ``` Bash
 mkdir build && cd build
 cmake .. -DWAMR_BUILD_FAST_JIT=1
@@ -588,7 +589,7 @@ In order to use this, you need at least version 4.3.1 of ESP-IDF.
 If you don't have it installed, follow the instructions [here](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/#get-started-get-prerequisites).
 ESP-IDF also installs the toolchains needed for compiling WAMR and ESP-IDF.
 A small demonstration of how to use WAMR and ESP-IDF can be found under [product_mini](/product-mini/platforms/esp-idf).
-The demo builds WAMR for ESP-IDF and runs a small wasm program. 
+The demo builds WAMR for ESP-IDF and runs a small wasm program.
 In order to run it for your specific Espressif chip, edit the [build_and_run.sh](/product-mini/platforms/esp-idf/build_and_run.sh) file and put the correct toolchain file (see #Cross-compilation) and `IDF_TARGET`.
 Before compiling it is also necessary to call ESP-IDF's `export.sh` script to bring all compile time relevant information in scope.
 

+ 21 - 5
tests/wamr-test-suites/test_wamr.sh

@@ -173,10 +173,18 @@ readonly FAST_INTERP_COMPILE_FLAGS="\
 
 # jit: report linking error if set COLLECT_CODE_COVERAGE,
 #      now we don't collect code coverage of jit type
-readonly JIT_COMPILE_FLAGS="\
+readonly ORC_EAGER_JIT_COMPILE_FLAGS="\
     -DWAMR_BUILD_TARGET=${TARGET} \
     -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \
     -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \
+    -DWAMR_BUILD_LAZY_JIT=0 \
+    -DWAMR_BUILD_SPEC_TEST=1"
+
+readonly ORC_LAZY_JIT_COMPILE_FLAGS="\
+    -DWAMR_BUILD_TARGET=${TARGET} \
+    -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_INTERP=0 \
+    -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_AOT=1 \
+    -DWAMR_BUILD_LAZY_JIT=1 \
     -DWAMR_BUILD_SPEC_TEST=1"
 
 readonly AOT_COMPILE_FLAGS="\
@@ -196,7 +204,8 @@ readonly FAST_JIT_COMPILE_FLAGS="\
 readonly COMPILE_FLAGS=(
         "${CLASSIC_INTERP_COMPILE_FLAGS}"
         "${FAST_INTERP_COMPILE_FLAGS}"
-        "${JIT_COMPILE_FLAGS}"
+        "${ORC_EAGER_JIT_COMPILE_FLAGS}"
+        "${ORC_LAZY_JIT_COMPILE_FLAGS}"
         "${AOT_COMPILE_FLAGS}"
         "${FAST_JIT_COMPILE_FLAGS}"
     )
@@ -600,9 +609,16 @@ function trigger()
                     continue
                 fi
 
-                echo "work in jit mode"
-                # jit
-                BUILD_FLAGS="$JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                echo "work in orc jit eager compilation mode"
+                BUILD_FLAGS="$ORC_EAGER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
+                build_iwasm_with_cfg $BUILD_FLAGS
+                build_wamrc
+                for suite in "${TEST_CASE_ARR[@]}"; do
+                    $suite"_test" jit
+                done
+
+                echo "work in orc jit lazy compilation mode"
+                BUILD_FLAGS="$ORC_EAGER_JIT_COMPILE_FLAGS $EXTRA_COMPILE_FLAGS"
                 build_iwasm_with_cfg $BUILD_FLAGS
                 build_wamrc
                 for suite in "${TEST_CASE_ARR[@]}"; do