Bladeren bron

Merge pull request #3511 from bytecodealliance/main

Merge branch main into dev/checkpoint_and_restore
Wenyong Huang 1 jaar geleden
bovenliggende
commit
ac308c4fa9
100 gewijzigde bestanden met toevoegingen van 5900 en 415 verwijderingen
  1. 67 2
      .github/workflows/compilation_on_android_ubuntu.yml
  2. 2 2
      .github/workflows/compilation_on_nuttx.yml
  3. 2 2
      .github/workflows/spec_test_on_nuttx.yml
  4. 1 1
      ATTRIBUTIONS.md
  5. 98 0
      RELEASE_NOTES.md
  6. 1 1
      build-scripts/requirements.txt
  7. 13 0
      core/config.h
  8. 7 7
      core/iwasm/aot/aot_loader.c
  9. 6 7
      core/iwasm/aot/aot_runtime.c
  10. 0 6
      core/iwasm/common/gc/gc_type.c
  11. 25 3
      core/iwasm/common/wasm_application.c
  12. 8 8
      core/iwasm/common/wasm_c_api.c
  13. 55 26
      core/iwasm/common/wasm_runtime_common.c
  14. 10 14
      core/iwasm/compilation/aot.c
  15. 3 15
      core/iwasm/compilation/aot.h
  16. 6 2
      core/iwasm/compilation/aot_compiler.c
  17. 1 2
      core/iwasm/compilation/aot_compiler.h
  18. 4 4
      core/iwasm/compilation/aot_emit_aot_file.c
  19. 1 1
      core/iwasm/compilation/aot_emit_control.c
  20. 5 6
      core/iwasm/compilation/aot_emit_memory.c
  21. 1 1
      core/iwasm/compilation/aot_llvm.c
  22. 4 2
      core/iwasm/fast-jit/jit_frontend.c
  23. 36 0
      core/iwasm/include/wasm_export.h
  24. 2 5
      core/iwasm/interpreter/wasm.h
  25. 6 6
      core/iwasm/interpreter/wasm_interp_fast.c
  26. 108 50
      core/iwasm/interpreter/wasm_loader.c
  27. 98 41
      core/iwasm/interpreter/wasm_mini_loader.c
  28. 7 6
      core/iwasm/interpreter/wasm_runtime.c
  29. 55 18
      core/iwasm/libraries/wasi-nn/README.md
  30. 10 13
      core/iwasm/libraries/wasi-nn/include/wasi_nn.h
  31. 4 1
      core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h
  32. 8 8
      core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
  33. 4 4
      core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
  34. 22 22
      core/iwasm/libraries/wasi-nn/src/wasi_nn.c
  35. 17 15
      core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
  36. 6 6
      core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
  37. 57 0
      core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example
  38. 7 7
      core/iwasm/libraries/wasi-nn/test/utils.c
  39. 5 5
      core/iwasm/libraries/wasi-nn/test/utils.h
  40. 5 0
      core/shared/platform/common/posix/platform_api_posix.cmake
  41. 8 0
      core/shared/platform/riot/platform_internal.h
  42. 6 0
      core/shared/platform/riot/riot_platform.c
  43. 1 1
      core/version.h
  44. 2 0
      product-mini/platforms/android/CMakeLists.txt
  45. 13 11
      product-mini/platforms/posix/main.c
  46. 6 6
      test-tools/aot-analyzer/src/main.cc
  47. 1 0
      test-tools/wamr-ide/VSCode-Extension/tsconfig.json
  48. 5 5
      tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt
  49. 43 33
      tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh
  50. 3 3
      tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt
  51. BIN
      tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm
  52. BIN
      tests/regression/ba-issues/issues/issue-3468/i64.add.wasm
  53. BIN
      tests/regression/ba-issues/issues/issue-3491/nop_0LM_592_17171016522810388.wasm
  54. 49 1
      tests/regression/ba-issues/running_config.json
  55. 37 36
      tests/unit/CMakeLists.txt
  56. 55 0
      tests/unit/aot-stack-frame/CMakeLists.txt
  57. 288 0
      tests/unit/aot-stack-frame/aot_stack_frame_test.cc
  58. 27 0
      tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt
  59. 36 0
      tests/unit/aot-stack-frame/wasm-apps/test.wast
  60. 59 0
      tests/unit/aot/CMakeLists.txt
  61. 1190 0
      tests/unit/aot/aot_test.cc
  62. 89 0
      tests/unit/common/mock_allocator.h
  63. 325 0
      tests/unit/common/test_helper.h
  64. 72 0
      tests/unit/compilation/CMakeLists.txt
  65. 203 0
      tests/unit/compilation/aot_compiler_test.cc
  66. 104 0
      tests/unit/compilation/aot_emit_aot_file_test.cc
  67. 112 0
      tests/unit/compilation/aot_emit_compare_test.cc
  68. 196 0
      tests/unit/compilation/aot_emit_control_test.cc
  69. 101 0
      tests/unit/compilation/aot_emit_function_test.cc
  70. 335 0
      tests/unit/compilation/aot_emit_memory_test.cc
  71. 119 0
      tests/unit/compilation/aot_emit_numberic_test.cc
  72. 143 0
      tests/unit/compilation/aot_emit_parametric_test.cc
  73. 105 0
      tests/unit/compilation/aot_emit_table_test.cc
  74. 97 0
      tests/unit/compilation/aot_emit_variable_test.cc
  75. 305 0
      tests/unit/compilation/aot_llvm_test.cc
  76. BIN
      tests/unit/compilation/wasm-apps/main.wasm
  77. 65 0
      tests/unit/custom-section/CMakeLists.txt
  78. 161 0
      tests/unit/custom-section/custom_section_test.cc
  79. 14 0
      tests/unit/custom-section/wasm-apps/CMakeLists.txt
  80. 10 0
      tests/unit/custom-section/wasm-apps/app.c
  81. 51 0
      tests/unit/gc/CMakeLists.txt
  82. 102 0
      tests/unit/gc/gc_test.cc
  83. BIN
      tests/unit/gc/wasm-apps/func1.wasm
  84. 35 0
      tests/unit/gc/wasm-apps/func1.wast
  85. BIN
      tests/unit/gc/wasm-apps/func2.wasm
  86. 78 0
      tests/unit/gc/wasm-apps/func2.wast
  87. BIN
      tests/unit/gc/wasm-apps/global1.wasm
  88. 91 0
      tests/unit/gc/wasm-apps/global1.wast
  89. BIN
      tests/unit/gc/wasm-apps/struct1.wasm
  90. 10 0
      tests/unit/gc/wasm-apps/struct1.wast
  91. BIN
      tests/unit/gc/wasm-apps/struct2.wasm
  92. 33 0
      tests/unit/gc/wasm-apps/struct2.wast
  93. BIN
      tests/unit/gc/wasm-apps/struct3.wasm
  94. 9 0
      tests/unit/gc/wasm-apps/struct3.wast
  95. BIN
      tests/unit/gc/wasm-apps/table1.wasm
  96. 108 0
      tests/unit/gc/wasm-apps/table1.wast
  97. BIN
      tests/unit/gc/wasm-apps/test1.wasm
  98. 117 0
      tests/unit/gc/wasm-apps/test1.wast
  99. BIN
      tests/unit/gc/wasm-apps/test2.wasm
  100. 104 0
      tests/unit/gc/wasm-apps/test2.wast

+ 67 - 2
.github/workflows/compilation_on_android_ubuntu.yml

@@ -19,6 +19,7 @@ on:
       - "samples/**"
       - "!samples/workload/**"
       - "tests/wamr-test-suites/**"
+      - "tests/unit/**"
       - "wamr-compiler/**"
       - "test-tools/wamr-ide/**"
   # will be triggered on push events
@@ -36,6 +37,7 @@ on:
       - "samples/**"
       - "!samples/workload/**"
       - "tests/wamr-test-suites/**"
+      - "tests/unit/**"
       - "wamr-compiler/**"
       - "test-tools/wamr-ide/**"
   # allow to be triggered manually
@@ -272,10 +274,73 @@ jobs:
           cmake --build . --config Release --parallel 4
         working-directory: product-mini/platforms/${{ matrix.platform }}
 
+  build_unit_tests:
+    needs:
+      [
+        build_llvm_libraries_on_ubuntu_2204,
+        build_wamrc
+      ]
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        os: [ubuntu-22.04]
+        wasi_sdk_release:
+          [
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz",
+          ]
+        wabt_release:
+          [
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
+          ]
+        include:
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
+    steps:
+      - name: checkout
+        uses: actions/checkout@v4
+
+      - name: Get LLVM libraries
+        id: retrieve_llvm_libs
+        uses: actions/cache@v4
+        with:
+          path: |
+            ./core/deps/llvm/build/bin
+            ./core/deps/llvm/build/include
+            ./core/deps/llvm/build/lib
+            ./core/deps/llvm/build/libexec
+            ./core/deps/llvm/build/share
+          key: ${{ matrix.llvm_cache_key }}
+
+      - name: Quit if cache miss
+        if: (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
+        run: echo "::error::can not get prebuilt llvm libraries" && exit 1
+
+      - name: download and install wasi-sdk
+        run: |
+          cd /opt
+          sudo wget ${{ matrix.wasi_sdk_release }}
+          sudo tar -xzf wasi-sdk-*.tar.gz
+          sudo ln -sf wasi-sdk-20.0 wasi-sdk
+
+      - name: download and install wabt
+        run: |
+          cd /opt
+          sudo wget ${{ matrix.wabt_release }}
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
+
+      - name: Build wamrc
+        run: |
+          mkdir build && cd build
+          cmake ..
+          cmake --build . --config Release --parallel 4
+        working-directory: wamr-compiler
+
       - name: Build and run unit tests
         run: |
-          mkdir build-unittests && cd build-unittests
-          cmake .. ${{ matrix.make_options_run_mode }} ${{ matrix.make_options_feature }}
+          mkdir build && cd build
+          cmake ..
           cmake --build . --config Release --parallel 4
           ctest
         working-directory: tests/unit

+ 2 - 2
.github/workflows/compilation_on_nuttx.yml

@@ -85,14 +85,14 @@ jobs:
       - name: Checkout NuttX
         uses: actions/checkout@v4
         with:
-          repository: apache/incubator-nuttx
+          repository: apache/nuttx
           ref: releases/12.4
           path: nuttx
 
       - name: Checkout NuttX Apps
         uses: actions/checkout@v4
         with:
-          repository: apache/incubator-nuttx-apps
+          repository: apache/nuttx-apps
           ref: releases/12.4
           path: apps
 

+ 2 - 2
.github/workflows/spec_test_on_nuttx.yml

@@ -112,14 +112,14 @@ jobs:
       - name: Checkout NuttX
         uses: actions/checkout@v4
         with:
-          repository: apache/incubator-nuttx
+          repository: apache/nuttx
           ref: releases/12.4
           path: nuttx
 
       - name: Checkout NuttX Apps
         uses: actions/checkout@v4
         with:
-          repository: apache/incubator-nuttx-apps
+          repository: apache/nuttx-apps
           ref: releases/12.4
           path: apps
 

+ 1 - 1
ATTRIBUTIONS.md

@@ -35,7 +35,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
 | uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | |
 | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | |
 | zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | |
-| NuttX ELF headers | 72313301e23f9c2de969fb64b9a0f67bb4c284df | 10.3.0 | https://github.com/apache/incubator-nuttx | |
+| NuttX ELF headers | 72313301e23f9c2de969fb64b9a0f67bb4c284df | 10.3.0 | https://github.com/apache/nuttx | |
 | Dhrystone | 2.1 | 2.1 | https://fossies.org/linux/privat/old/ | |
 
 ## Licenses

+ 98 - 0
RELEASE_NOTES.md

@@ -1,3 +1,101 @@
+## WAMR-2.1.0
+
+### Breaking Changes
+
+### New Features
+ - Add wasm_export.h APIs to expose memory type (#3496)
+ - Add api to get export global instance (#3452)
+ - Add wasm-mutator-fuzz test (#3420)
+ - Implement Memory64 support for AOT (#3362)
+ - Add wasm module global type information APIs (#3406)
+ - Add aot binary analysis tool aot-analyzer (#3379)
+ - Expose API to get import/export function's param/result valkind (#3363)
+ - Add WASI support for esp-idf platform (#3348)
+
+### Bug Fixes
+ - Fix posix build when libc wasi is disabled and debug interp is enabled (#3503)
+ - Fix wasm_mini_loader.c build when jit or multi-module is enabled (#3502)
+ - Fix wasm loader check data segment count (#3492)
+ - Fix loader parse block type and calculate dynamic offset for loop args (#3482)
+ - Fix memory64 handling find_block_addr and execute_main (#3480)
+ - Fix two issues to make fuzzing test quit earlier (#3471)
+ - Fix test-wamr-ide CI failure (#3485)
+ - NuttX: Fix a dbus-related crash on esp32s3 (#3470)
+ - Clone data segments when specified with load args (#3463)
+ - Fix codeql compilation error (#3461)
+ - Fix several typos and fix bh_log calculate mills (#3441)
+ - ssp_config.h: Fix ifdef for android random api (#3444)
+ - libc-wasi: Fix a locking botch (#3437)
+ - Fix fast interp RECOVER_BR_INFO and local set/tee (#3434)
+ - aot compiler: Fix a type mismatch in compile_op_float_min_max (#3423)
+ - Correct Exception Handling tag type when GC is enabled (#3413)
+ - wasm loader: Fix handling if block without op else (#3404)
+ - ref-types: Correct default value for function local variables (#3397)
+ - aot compiler: Fix the length type passed to aot_memmove/aot_memset (#3378)
+ - Fix loader and mini-loader select potiential error (#3374)
+ - Fix aot debugger compilation error on windows (#3370)
+ - A few native stack detection fixes for macOS/arm64 (#3368)
+ - Fix ESP32-S3 compiling error (#3359)
+ - Fix a few native stack address calculations (#3351)
+
+### Enhancements
+ - Modify logging for windows exception handler and remove unused function (#3489)
+ - posix iwasm: Make the timeout logic a bit more robust (#3478)
+ - libc-builtin: Enhance buffered print for printf_wrapper (#3460)
+ - Enhance GC const initializer expression to support nested struct/array new (#3447)
+ - wasi: Tweak the configuration for nuttx and explain why (#3451)
+ - NuttX: Replace esp32s3 bits with the OS-provided APIs (#3439)
+ - Allow not copying the wasm binary in wasm-c-api and not referring to the binary in wasm/aot loader (#3389)
+ - aot: Make precheck functions use short-call for xtensa (#3418)
+ - Add wasm_runtime_detect_native_stack_overflow_size (#3355)
+ - Enhance wasm loader checks for opcode br_table (#3352)
+
+### Others
+ - Bump requests from 2.32.2 to 2.32.3 in /build-scripts (#3494)
+ - Enable building static library on Android platform (#3488)
+ - wasm-mutator-fuzz: Generate more kinds of corpus (#3487)
+ - Correct nuttx repo names (#3484)
+ - Bump requests from 2.31.0 to 2.32.2 in /build-scripts (#3474)
+ - wasm-mutator-fuzz: Adapt to oss-fuzz compilation (#3464)
+ - Add regression tests of BA issue cases (#3462)
+ - Add malformed test cases (#3459)
+ - NuttX: Rename a few recently-added nuttx options (#3449)
+ - wamr-test-suites: Enable AOT multi-module spec tests (#3450)
+ - Remove install_wasi_sdk from workload preparation script (#3445)
+ - Add cmake static/shared library build settings (#3443)
+ - Update spec test to latest commit (#3293)
+ - Fix typo of WAMR_CONFIGUABLE_BOUNDS_CHECKS (#3424)
+ - ci/coding_guidelines_check.py: Allow some well-known file names to contain '-' (#3428)
+ - product-mini/platforms/posix/main.c: Adapt to WASM_MEM_DUAL_BUS_MIRROR (#3427)
+ - Add comments to global type function declarations (#3431)
+ - nuttx/esp32s3: Apply ibus/dbus adjustment to internal ram 1 as well (#3421)
+ - Change WASM_ANYREF to WASM_EXTERNREF (#3426)
+ - Remove unused macros which were moved to wamr-app-framework (#3425)
+ - Add WASM_V128 in wasm_valkind_enum (#3412)
+ - Fix basic example, parameter missmatch between host and wasm (#3415)
+ - Fix workspaces path in build_wamr.sh (#3414)
+ - core/iwasm/compilation: Remove stale function prototypes (#3408)
+ - Add test cases for the requirements of "gc-aot" feature (#3399)
+ - append_aot_to_wasm.py: Add --ver-str option to emit more info in custom section name (#3398)
+ - Fix clang compile warnings (#3396)
+ - Fix some more spelling issues (#3393)
+ - Fix some spelling issues (#3385)
+ - samples/native-stack-overflow: Examine native functions with signature (#3382)
+ - Add some more comments on WASM_STACK_GUARD_SIZE (#3380)
+ - Fix typo for 'native' in wasm_export.h (#3376)
+ - CI: Use macos-13 instead of macos-latest (#3366)
+ - Test more samples in nightly-run CI (#3358)
+ - Random improvements to samples/native-stack-overflow (#3353)
+ - Reduce WASM_STACK_GUARD_SIZE a bit for posix-like platforms (#3350)
+ - doc: Add ADOPTERS.md (#3324)
+ - Update binary size info in README.md (#3030)
+ - core/config.h: Bump the default WASM_STACK_GUARD_SIZE (#3344)
+ - Add unit test suites (#3490)
+ - Fix internal global getter types (#3495)
+ - Fix CI build and run unit tests (#3499)
+
+---
+
 ## WAMR-2.0.0
 
 ### Breaking Changes

+ 1 - 1
build-scripts/requirements.txt

@@ -1 +1 @@
-requests==2.31.0
+requests==2.32.3

+ 13 - 0
core/config.h

@@ -663,4 +663,17 @@
 #define WASM_MEM_ALLOC_WITH_USAGE 0
 #endif
 
+#ifndef WASM_ENABLE_FUZZ_TEST
+#define WASM_ENABLE_FUZZ_TEST 0
+#endif
+
+#ifndef WASM_MEM_ALLOC_MAX_SIZE
+#if WASM_ENABLE_FUZZ_TEST != 0
+/* In oss-fuzz, the maximum RAM is ~2.5G */
+#define WASM_MEM_ALLOC_MAX_SIZE (2U * 1024 * 1024 * 1024)
+#else
+#define WASM_MEM_ALLOC_MAX_SIZE UINT32_MAX
+#endif
+#endif
+
 #endif /* end of _CONFIG_H_ */

+ 7 - 7
core/iwasm/aot/aot_loader.c

@@ -1043,16 +1043,16 @@ load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
     }
 
     for (i = 0; i < module->memory_count; i++) {
-        read_uint32(buf, buf_end, module->memories[i].memory_flags);
+        read_uint32(buf, buf_end, module->memories[i].flags);
 
-        if (!wasm_memory_check_flags(module->memories[i].memory_flags,
-                                     error_buf, error_buf_size, true)) {
+        if (!wasm_memory_check_flags(module->memories[i].flags, error_buf,
+                                     error_buf_size, true)) {
             return false;
         }
 
         read_uint32(buf, buf_end, module->memories[i].num_bytes_per_page);
-        read_uint32(buf, buf_end, module->memories[i].mem_init_page_count);
-        read_uint32(buf, buf_end, module->memories[i].mem_max_page_count);
+        read_uint32(buf, buf_end, module->memories[i].init_page_count);
+        read_uint32(buf, buf_end, module->memories[i].max_page_count);
     }
 
     read_uint32(buf, buf_end, module->mem_init_data_count);
@@ -3637,9 +3637,9 @@ has_module_memory64(AOTModule *module)
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
     if (module->import_memory_count > 0)
-        return !!(module->import_memories[0].memory_flags & MEMORY64_FLAG);
+        return !!(module->import_memories[0].mem_type.flags & MEMORY64_FLAG);
     else if (module->memory_count > 0)
-        return !!(module->memories[0].memory_flags & MEMORY64_FLAG);
+        return !!(module->memories[0].flags & MEMORY64_FLAG);
 
     return false;
 }

+ 6 - 7
core/iwasm/aot/aot_runtime.c

@@ -789,10 +789,9 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
 {
     void *heap_handle;
     uint32 num_bytes_per_page = memory->num_bytes_per_page;
-    uint32 init_page_count = memory->mem_init_page_count;
-    uint32 max_page_count =
-        wasm_runtime_get_max_mem(max_memory_pages, memory->mem_init_page_count,
-                                 memory->mem_max_page_count);
+    uint32 init_page_count = memory->init_page_count;
+    uint32 max_page_count = wasm_runtime_get_max_mem(
+        max_memory_pages, memory->init_page_count, memory->max_page_count);
     uint32 default_max_pages;
     uint32 inc_page_count, global_idx;
     uint32 bytes_of_last_page, bytes_to_page_end;
@@ -800,11 +799,11 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
         heap_offset = (uint64)num_bytes_per_page * init_page_count;
     uint64 memory_data_size, max_memory_data_size;
     uint8 *p = NULL, *global_addr;
-    bool is_memory64 = memory->memory_flags & MEMORY64_FLAG;
+    bool is_memory64 = memory->flags & MEMORY64_FLAG;
 
     bool is_shared_memory = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    is_shared_memory = memory->memory_flags & SHARED_MEMORY_FLAG ? true : false;
+    is_shared_memory = memory->flags & SHARED_MEMORY_FLAG ? true : false;
     /* Shared memory */
     if (is_shared_memory && parent != NULL) {
         AOTMemoryInstance *shared_memory_instance;
@@ -1946,7 +1945,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 
     if (!is_sub_inst) {
 #if WASM_ENABLE_WASI_NN != 0
-        wasi_nn_destroy(module_inst);
+        wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst);
 #endif
         wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
     }

+ 0 - 6
core/iwasm/common/gc/gc_type.c

@@ -846,12 +846,6 @@ wasm_is_reftype_supers_of_func(uint8 type)
     return (type == REF_TYPE_FUNCREF) ? true : false;
 }
 
-inline static bool
-wasm_is_reftype_supers_of_extern(uint8 type)
-{
-    return (type == REF_TYPE_EXTERNREF) ? true : false;
-}
-
 #if WASM_ENABLE_STRINGREF != 0
 inline static bool
 wasm_is_reftype_supers_of_string(uint8 type)

+ 25 - 3
core/iwasm/common/wasm_application.c

@@ -201,9 +201,23 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
     if (func_type->param_count) {
         for (i = 0; i < argc; i++)
             total_argv_size += (uint32)(strlen(argv[i]) + 1);
-        total_argv_size = align_uint(total_argv_size, 4);
+#if WASM_ENABLE_MEMORY64 != 0
+        if (is_memory64)
+            /* `char **argv` is an array of 64-bit elements in memory64 */
+            total_argv_size = align_uint(total_argv_size, 8);
+        else
+#endif
+            total_argv_size = align_uint(total_argv_size, 4);
 
-        total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc;
+#if WASM_ENABLE_MEMORY64 != 0
+        if (is_memory64)
+            /* `char **argv` is an array of 64-bit elements in memory64 */
+            total_size =
+                (uint64)total_argv_size + sizeof(uint64) * (uint64)argc;
+        else
+#endif
+            total_size =
+                (uint64)total_argv_size + sizeof(uint32) * (uint64)argc;
 
         if (total_size >= UINT32_MAX
             || !(argv_buf_offset = wasm_runtime_module_malloc(
@@ -219,7 +233,15 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
         for (i = 0; i < argc; i++) {
             bh_memcpy_s(p, (uint32)(p_end - p), argv[i],
                         (uint32)(strlen(argv[i]) + 1));
-            argv_offsets[i] = (uint32)argv_buf_offset + (uint32)(p - argv_buf);
+#if WASM_ENABLE_MEMORY64 != 0
+            if (is_memory64)
+                /* `char **argv` is an array of 64-bit elements in memory64 */
+                ((uint64 *)argv_offsets)[i] =
+                    (uint32)argv_buf_offset + (uint32)(p - argv_buf);
+            else
+#endif
+                argv_offsets[i] =
+                    (uint32)argv_buf_offset + (uint32)(p - argv_buf);
             p += strlen(argv[i]) + 1;
         }
 

+ 8 - 8
core/iwasm/common/wasm_c_api.c

@@ -2580,8 +2580,8 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
                     + (i - import_func_count - import_global_count);
                 module_name_rt = import->u.names.module_name;
                 field_name_rt = import->u.names.field_name;
-                min_page = import->u.memory.init_page_count;
-                max_page = import->u.memory.max_page_count;
+                min_page = import->u.memory.mem_type.init_page_count;
+                max_page = import->u.memory.mem_type.max_page_count;
             }
 #endif
 
@@ -2592,8 +2592,8 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
                     + (i - import_func_count - import_global_count);
                 module_name_rt = import->module_name;
                 field_name_rt = import->memory_name;
-                min_page = import->mem_init_page_count;
-                max_page = import->mem_max_page_count;
+                min_page = import->mem_type.init_page_count;
+                max_page = import->mem_type.max_page_count;
             }
 #endif
 
@@ -4308,12 +4308,12 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
         AOTModule *module_aot = (AOTModule *)inst_aot->module;
 
         if (memory_idx_rt < module_aot->import_memory_count) {
-            min_pages = module_aot->import_memories->mem_init_page_count;
-            max_pages = module_aot->import_memories->mem_max_page_count;
+            min_pages = module_aot->import_memories->mem_type.init_page_count;
+            max_pages = module_aot->import_memories->mem_type.max_page_count;
         }
         else {
-            min_pages = module_aot->memories->mem_init_page_count;
-            max_pages = module_aot->memories->mem_max_page_count;
+            min_pages = module_aot->memories->init_page_count;
+            max_pages = module_aot->memories->max_page_count;
         }
         init_flag = true;
     }

+ 55 - 26
core/iwasm/common/wasm_runtime_common.c

@@ -384,12 +384,14 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
                 return ret;
         }
 #endif
+        else {
+            LOG_WARNING("Unhandled exception thrown:  exception code: 0x%lx, "
+                        "exception address: %p, exception information: %p\n",
+                        ExceptionRecord->ExceptionCode,
+                        ExceptionRecord->ExceptionAddress, sig_addr);
+        }
     }
 
-    LOG_ERROR("Unhandled exception thrown:  exception code: 0x%lx, "
-              "exception address: %p, exception information: %p\n",
-              ExceptionRecord->ExceptionCode, ExceptionRecord->ExceptionAddress,
-              sig_addr);
     return EXCEPTION_CONTINUE_SEARCH;
 }
 #endif /* end of BH_PLATFORM_WINDOWS */
@@ -3871,7 +3873,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
             import_type->kind = WASM_IMPORT_EXPORT_KIND_FUNC;
             import_type->linked =
                 aot_import_func->func_ptr_linked ? true : false;
-            import_type->u.func_type = aot_import_func->func_type;
+            import_type->u.func_type =
+                (WASMFuncType *)aot_import_func->func_type;
             return;
         }
 
@@ -3907,6 +3910,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
             import_type->name = aot_import_memory->memory_name;
             import_type->kind = WASM_IMPORT_EXPORT_KIND_MEMORY;
             import_type->linked = false;
+            import_type->u.memory_type =
+                (WASMMemoryType *)&aot_import_memory->mem_type;
             return;
         }
 
@@ -3931,7 +3936,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
         switch (import_type->kind) {
             case WASM_IMPORT_EXPORT_KIND_FUNC:
                 import_type->linked = wasm_import->u.function.func_ptr_linked;
-                import_type->u.func_type = wasm_import->u.function.func_type;
+                import_type->u.func_type =
+                    (WASMFuncType *)wasm_import->u.function.func_type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_GLOBAL:
                 import_type->linked = wasm_import->u.global.is_linked;
@@ -3939,12 +3945,12 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
                     (WASMGlobalType *)&wasm_import->u.global.type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                import_type->linked = false;
+                import_type->linked = false; /* not supported */
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
-                /* not supported */
-                import_type->linked = false;
+                import_type->linked = false; /* not supported */
+                import_type->u.memory_type =
+                    (WASMMemoryType *)&wasm_import->u.memory.mem_type;
                 break;
             default:
                 bh_assert(0);
@@ -4024,12 +4030,11 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                // export_type->linked = false;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
-                /* not supported */
-                // export_type->linked = false;
+                export_type->u.memory_type =
+                    &aot_module->memories[aot_export->index
+                                          - aot_module->import_memory_count];
                 break;
             default:
                 bh_assert(0);
@@ -4066,13 +4071,13 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                // export_type->linked = false;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
-                /* not supported */
-                // export_type->linked = false;
+                export_type->u.memory_type =
+                    &wasm_module->memories[wasm_export->index
+                                           - wasm_module->import_memory_count];
                 break;
+            default:
                 bh_assert(0);
                 break;
         }
@@ -4168,7 +4173,7 @@ wasm_func_type_get_result_valkind(WASMFuncType *const func_type,
 }
 
 wasm_valkind_t
-wasm_global_type_get_valkind(const wasm_global_type_t global_type)
+wasm_global_type_get_valkind(WASMGlobalType *const global_type)
 {
     bh_assert(global_type);
 
@@ -4176,13 +4181,37 @@ wasm_global_type_get_valkind(const wasm_global_type_t global_type)
 }
 
 bool
-wasm_global_type_get_mutable(const wasm_global_type_t global_type)
+wasm_global_type_get_mutable(WASMGlobalType *const global_type)
 {
     bh_assert(global_type);
 
     return global_type->is_mutable;
 }
 
+bool
+wasm_memory_type_get_shared(WASMMemoryType *const memory_type)
+{
+    bh_assert(memory_type);
+
+    return (memory_type->flags & SHARED_MEMORY_FLAG) ? true : false;
+}
+
+uint32
+wasm_memory_type_get_init_page_count(WASMMemoryType *const memory_type)
+{
+    bh_assert(memory_type);
+
+    return memory_type->init_page_count;
+}
+
+uint32
+wasm_memory_type_get_max_page_count(WASMMemoryType *const memory_type)
+{
+    bh_assert(memory_type);
+
+    return memory_type->max_page_count;
+}
+
 bool
 wasm_runtime_register_natives(const char *module_name,
                               NativeSymbol *native_symbols,
@@ -6517,8 +6546,8 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
         if (export->index < module->import_memory_count) {
             WASMMemoryImport *import_memory =
                 &((module->import_memories + export->index)->u.memory);
-            *out_min_page = import_memory->init_page_count;
-            *out_max_page = import_memory->max_page_count;
+            *out_min_page = import_memory->mem_type.init_page_count;
+            *out_max_page = import_memory->mem_type.max_page_count;
         }
         else {
             WASMMemory *memory =
@@ -6538,14 +6567,14 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
         if (export->index < module->import_memory_count) {
             AOTImportMemory *import_memory =
                 module->import_memories + export->index;
-            *out_min_page = import_memory->mem_init_page_count;
-            *out_max_page = import_memory->mem_max_page_count;
+            *out_min_page = import_memory->mem_type.init_page_count;
+            *out_max_page = import_memory->mem_type.max_page_count;
         }
         else {
             AOTMemory *memory = module->memories
                                 + (export->index - module->import_memory_count);
-            *out_min_page = memory->mem_init_page_count;
-            *out_max_page = memory->mem_max_page_count;
+            *out_min_page = memory->init_page_count;
+            *out_max_page = memory->max_page_count;
         }
         return true;
     }

+ 10 - 14
core/iwasm/compilation/aot.c

@@ -558,28 +558,24 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     /* Set memory page count */
     for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
         if (i < module->import_memory_count) {
-            comp_data->memories[i].memory_flags =
-                module->import_memories[i].u.memory.flags;
+            comp_data->memories[i].flags =
+                module->import_memories[i].u.memory.mem_type.flags;
             comp_data->memories[i].num_bytes_per_page =
-                module->import_memories[i].u.memory.num_bytes_per_page;
-            comp_data->memories[i].mem_init_page_count =
-                module->import_memories[i].u.memory.init_page_count;
-            comp_data->memories[i].mem_max_page_count =
-                module->import_memories[i].u.memory.max_page_count;
-            comp_data->memories[i].num_bytes_per_page =
-                module->import_memories[i].u.memory.num_bytes_per_page;
+                module->import_memories[i].u.memory.mem_type.num_bytes_per_page;
+            comp_data->memories[i].init_page_count =
+                module->import_memories[i].u.memory.mem_type.init_page_count;
+            comp_data->memories[i].max_page_count =
+                module->import_memories[i].u.memory.mem_type.max_page_count;
         }
         else {
             j = i - module->import_memory_count;
-            comp_data->memories[i].memory_flags = module->memories[j].flags;
+            comp_data->memories[i].flags = module->memories[j].flags;
             comp_data->memories[i].num_bytes_per_page =
                 module->memories[j].num_bytes_per_page;
-            comp_data->memories[i].mem_init_page_count =
+            comp_data->memories[i].init_page_count =
                 module->memories[j].init_page_count;
-            comp_data->memories[i].mem_max_page_count =
+            comp_data->memories[i].max_page_count =
                 module->memories[j].max_page_count;
-            comp_data->memories[i].num_bytes_per_page =
-                module->memories[j].num_bytes_per_page;
         }
     }
 

+ 3 - 15
core/iwasm/compilation/aot.h

@@ -46,6 +46,8 @@ typedef WASMStructType AOTStructType;
 typedef WASMArrayType AOTArrayType;
 #endif
 typedef WASMExport AOTExport;
+typedef WASMMemory AOTMemory;
+typedef WASMMemoryType AOTMemoryType;
 
 #if WASM_ENABLE_DEBUG_AOT != 0
 typedef void *dwarf_extractor_handle_t;
@@ -81,23 +83,9 @@ typedef enum AOTFloatCond {
 typedef struct AOTImportMemory {
     char *module_name;
     char *memory_name;
-    uint32 memory_flags;
-    uint32 num_bytes_per_page;
-    uint32 mem_init_page_count;
-    uint32 mem_max_page_count;
+    AOTMemoryType mem_type;
 } AOTImportMemory;
 
-/**
- * Memory information
- */
-typedef struct AOTMemory {
-    /* memory info */
-    uint32 memory_flags;
-    uint32 num_bytes_per_page;
-    uint32 mem_init_page_count;
-    uint32 mem_max_page_count;
-} AOTMemory;
-
 /**
  * A segment of memory init data
  */

+ 6 - 2
core/iwasm/compilation/aot_compiler.c

@@ -1028,7 +1028,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
                 }
                 else {
                     frame_ip--;
-                    read_leb_uint32(frame_ip, frame_ip_end, type_index);
+                    read_leb_int32(frame_ip, frame_ip_end, type_index);
+                    /* type index was checked in wasm loader */
+                    bh_assert(type_index < comp_ctx->comp_data->type_count);
                     func_type =
                         (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                     param_count = func_type->param_count;
@@ -1048,7 +1050,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
             case EXT_OP_LOOP:
             case EXT_OP_IF:
             {
-                read_leb_uint32(frame_ip, frame_ip_end, type_index);
+                read_leb_int32(frame_ip, frame_ip_end, type_index);
+                /* type index was checked in wasm loader */
+                bh_assert(type_index < comp_ctx->comp_data->type_count);
                 func_type =
                     (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                 param_count = func_type->param_count;

+ 1 - 2
core/iwasm/compilation/aot_compiler.h

@@ -520,8 +520,7 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
     } while (0)
 
 #if WASM_ENABLE_MEMORY64 != 0
-#define IS_MEMORY64 \
-    (comp_ctx->comp_data->memories[0].memory_flags & MEMORY64_FLAG)
+#define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG)
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
 #else

+ 4 - 4
core/iwasm/compilation/aot_emit_aot_file.c

@@ -189,7 +189,7 @@ get_import_memory_size(AOTCompData *comp_data)
 static uint32
 get_memory_size(AOTCompData *comp_data)
 {
-    /* memory_count + count * (memory_flags + num_bytes_per_page +
+    /* memory_count + count * (flags + num_bytes_per_page +
                                init_page_count + max_page_count) */
     return (uint32)(sizeof(uint32)
                     + comp_data->memory_count * sizeof(uint32) * 4);
@@ -1762,10 +1762,10 @@ aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     EMIT_U32(comp_data->memory_count);
     /* Emit memory items */
     for (i = 0; i < comp_data->memory_count; i++) {
-        EMIT_U32(comp_data->memories[i].memory_flags);
+        EMIT_U32(comp_data->memories[i].flags);
         EMIT_U32(comp_data->memories[i].num_bytes_per_page);
-        EMIT_U32(comp_data->memories[i].mem_init_page_count);
-        EMIT_U32(comp_data->memories[i].mem_max_page_count);
+        EMIT_U32(comp_data->memories[i].init_page_count);
+        EMIT_U32(comp_data->memories[i].max_page_count);
     }
 
     /* Emit mem init data count */

+ 1 - 1
core/iwasm/compilation/aot_emit_control.c

@@ -853,7 +853,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMBasicBlockRef terminate_block, non_terminate_block;
     AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
     bool is_shared_memory =
-        comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false;
+        comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false;
 
     /* Only need to check the suspend flags when memory is shared since
        shared memory must be enabled for multi-threading */

+ 5 - 6
core/iwasm/compilation/aot_emit_memory.c

@@ -109,7 +109,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     bool is_target_64bit, is_local_of_aot_value = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
     bool is_shared_memory =
-        comp_ctx->comp_data->memories[0].memory_flags & SHARED_MEMORY_FLAG;
+        comp_ctx->comp_data->memories[0].flags & SHARED_MEMORY_FLAG;
 #endif
 
     is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
@@ -177,7 +177,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         uint32 num_bytes_per_page =
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
         uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].mem_init_page_count;
+            comp_ctx->comp_data->memories[0].init_page_count;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
 
         if (mem_offset + bytes <= mem_data_size) {
@@ -224,7 +224,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
              && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value,
                                            offset, bytes))) {
         uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].mem_init_page_count;
+            comp_ctx->comp_data->memories[0].init_page_count;
         if (init_page_count == 0) {
             LLVMValueRef mem_size;
 
@@ -932,8 +932,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* Get memory base address and memory data size */
 #if WASM_ENABLE_SHARED_MEMORY != 0
-    bool is_shared_memory =
-        comp_ctx->comp_data->memories[0].memory_flags & 0x02;
+    bool is_shared_memory = comp_ctx->comp_data->memories[0].flags & 0x02;
 
     if (func_ctx->mem_space_unchanged || is_shared_memory) {
 #else
@@ -961,7 +960,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         uint32 num_bytes_per_page =
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
         uint32 init_page_count =
-            comp_ctx->comp_data->memories[0].mem_init_page_count;
+            comp_ctx->comp_data->memories[0].init_page_count;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
         if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) {
             /* inside memory space */

+ 1 - 1
core/iwasm/compilation/aot_llvm.c

@@ -1219,7 +1219,7 @@ create_memory_info(const AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Load memory base address */
 #if WASM_ENABLE_SHARED_MEMORY != 0
     is_shared_memory =
-        comp_ctx->comp_data->memories[0].memory_flags & 0x02 ? true : false;
+        comp_ctx->comp_data->memories[0].flags & 0x02 ? true : false;
     if (is_shared_memory) {
         LLVMValueRef shared_mem_addr;
         offset = I32_CONST(offsetof(AOTModuleInstance, memories));

+ 4 - 2
core/iwasm/fast-jit/jit_frontend.c

@@ -234,7 +234,7 @@ is_shared_memory(WASMModule *module, uint32 mem_idx)
 
     if (mem_idx < module->import_memory_count) {
         memory_import = &(module->import_memories[mem_idx].u.memory);
-        is_shared = memory_import->flags & 0x02 ? true : false;
+        is_shared = memory_import->mem_type.flags & 0x02 ? true : false;
     }
     else {
         memory = &module->memories[mem_idx - module->import_memory_count];
@@ -1510,7 +1510,9 @@ jit_compile_func(JitCompContext *cc)
             case EXT_OP_LOOP:
             case EXT_OP_IF:
             {
-                read_leb_uint32(frame_ip, frame_ip_end, type_idx);
+                read_leb_int32(frame_ip, frame_ip_end, type_idx);
+                /* type index was checked in wasm loader */
+                bh_assert(type_idx < cc->cur_wasm_module->type_count);
                 func_type = cc->cur_wasm_module->types[type_idx];
                 param_count = func_type->param_count;
                 param_types = func_type->types;

+ 36 - 0
core/iwasm/include/wasm_export.h

@@ -78,6 +78,10 @@ typedef struct WASMFuncType *wasm_func_type_t;
 struct WASMGlobalType;
 typedef struct WASMGlobalType *wasm_global_type_t;
 
+struct WASMMemory;
+typedef struct WASMMemory WASMMemoryType;
+typedef WASMMemoryType *wasm_memory_type_t;
+
 typedef struct wasm_import_t {
     const char *module_name;
     const char *name;
@@ -86,6 +90,7 @@ typedef struct wasm_import_t {
     union {
         wasm_func_type_t func_type;
         wasm_global_type_t global_type;
+        wasm_memory_type_t memory_type;
     } u;
 } wasm_import_t;
 
@@ -95,6 +100,7 @@ typedef struct wasm_export_t {
     union {
         wasm_func_type_t func_type;
         wasm_global_type_t global_type;
+        wasm_memory_type_t memory_type;
     } u;
 } wasm_export_t;
 
@@ -1350,6 +1356,36 @@ wasm_global_type_get_valkind(const wasm_global_type_t global_type);
 WASM_RUNTIME_API_EXTERN bool
 wasm_global_type_get_mutable(const wasm_global_type_t global_type);
 
+/**
+ * Get the shared setting for a memory type
+ *
+ * @param memory_type the memory type
+ *
+ * @return true if shared, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_memory_type_get_shared(const wasm_memory_type_t memory_type);
+
+/**
+ * Get the initial page count for a memory type
+ *
+ * @param memory_type the memory type
+ *
+ * @return the initial memory page count
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_memory_type_get_init_page_count(const wasm_memory_type_t memory_type);
+
+/**
+ * Get the maximum page count for a memory type
+ *
+ * @param memory_type the memory type
+ *
+ * @return the maximum memory page count
+ */
+WASM_RUNTIME_API_EXTERN uint32_t
+wasm_memory_type_get_max_page_count(const wasm_memory_type_t memory_type);
+
 /**
  * Register native functions with same module name
  *

+ 2 - 5
core/iwasm/interpreter/wasm.h

@@ -512,7 +512,7 @@ typedef struct WASMMemory {
     uint32 num_bytes_per_page;
     uint32 init_page_count;
     uint32 max_page_count;
-} WASMMemory;
+} WASMMemory, WASMMemoryType;
 
 typedef struct WASMTableImport {
     char *module_name;
@@ -536,10 +536,7 @@ typedef struct WASMTableImport {
 typedef struct WASMMemoryImport {
     char *module_name;
     char *field_name;
-    uint32 flags;
-    uint32 num_bytes_per_page;
-    uint32 init_page_count;
-    uint32 max_page_count;
+    WASMMemoryType mem_type;
 #if WASM_ENABLE_MULTI_MODULE != 0
     WASMModule *import_module;
     WASMMemory *import_memory_linked;

+ 6 - 6
core/iwasm/interpreter/wasm_interp_fast.c

@@ -3446,10 +3446,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
             {
                 /* clang-format off */
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
-                    local_offset = *frame_ip++;
+                local_offset = *frame_ip++;
 #else
-                    local_offset = *frame_ip;
-                    frame_ip += 2;
+                local_offset = *frame_ip;
+                frame_ip += 2;
 #endif
                 /* clang-format on */
                 *(uint32 *)(frame_lp + local_offset) =
@@ -3463,10 +3463,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
             {
                 /* clang-format off */
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
-                    local_offset = *frame_ip++;
+                local_offset = *frame_ip++;
 #else
-                    local_offset = *frame_ip;
-                    frame_ip += 2;
+                local_offset = *frame_ip;
+                frame_ip += 2;
 #endif
                 /* clang-format on */
                 PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),

+ 108 - 50
core/iwasm/interpreter/wasm_loader.c

@@ -44,7 +44,8 @@ has_module_memory64(WASMModule *module)
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
     if (module->import_memory_count > 0)
-        return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
+        return !!(module->import_memories[0].u.memory.mem_type.flags
+                  & MEMORY64_FLAG);
     else if (module->memory_count > 0)
         return !!(module->memories[0].flags & MEMORY64_FLAG);
 
@@ -379,7 +380,8 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
 {
     void *mem;
 
-    if (size >= UINT32_MAX || !(mem = wasm_runtime_malloc((uint32)size))) {
+    if (size >= WASM_MEM_ALLOC_MAX_SIZE
+        || !(mem = wasm_runtime_malloc((uint32)size))) {
         set_error_buf(error_buf, error_buf_size, "allocate memory failed");
         return NULL;
     }
@@ -2934,10 +2936,10 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
     }
 
     /* now we believe all declaration are ok */
-    memory->flags = mem_flag;
-    memory->init_page_count = declare_init_page_count;
-    memory->max_page_count = declare_max_page_count;
-    memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+    memory->mem_type.flags = mem_flag;
+    memory->mem_type.init_page_count = declare_init_page_count;
+    memory->mem_type.max_page_count = declare_max_page_count;
+    memory->mem_type.num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
 
     *p_buf = p;
 
@@ -3052,7 +3054,12 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
 
 #if WASM_ENABLE_GC == 0
     CHECK_BUF(p, p_end, 2);
+    /* global type */
     declare_type = read_uint8(p);
+    if (!is_value_type(declare_type)) {
+        set_error_buf(error_buf, error_buf_size, "type mismatch");
+        return false;
+    }
     declare_mutable = read_uint8(p);
 #else
     if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
@@ -4034,7 +4041,12 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         for (i = 0; i < global_count; i++, global++) {
 #if WASM_ENABLE_GC == 0
             CHECK_BUF(p, p_end, 2);
+            /* global type */
             global->type.val_type = read_uint8(p);
+            if (!is_value_type(global->type.val_type)) {
+                set_error_buf(error_buf, error_buf_size, "type mismatch");
+                return false;
+            }
             mutable = read_uint8(p);
 #else
             if (!resolve_value_type(&p, p_end, module, module->type_count,
@@ -4705,8 +4717,12 @@ fail:
 
 static bool
 load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
-                          WASMModule *module, bool clone_data_seg,
-                          char *error_buf, uint32 error_buf_size)
+                          WASMModule *module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                          bool has_datacount_section,
+#endif
+                          bool clone_data_seg, char *error_buf,
+                          uint32 error_buf_size)
 {
     const uint8 *p = buf, *p_end = buf_end;
     uint32 data_seg_count, i, mem_index, data_seg_len;
@@ -4722,8 +4738,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
     read_leb_uint32(p, p_end, data_seg_count);
 
 #if WASM_ENABLE_BULK_MEMORY != 0
-    if ((module->data_seg_count1 != 0)
-        && (data_seg_count != module->data_seg_count1)) {
+    if (has_datacount_section && data_seg_count != module->data_seg_count1) {
         set_error_buf(error_buf, error_buf_size,
                       "data count and data section have inconsistent lengths");
         return false;
@@ -4791,8 +4806,8 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
                 /* This memory_flag is from memory instead of data segment */
                 uint8 memory_flag;
                 if (module->import_memory_count > 0) {
-                    memory_flag =
-                        module->import_memories[mem_index].u.memory.flags;
+                    memory_flag = module->import_memories[mem_index]
+                                      .u.memory.mem_type.flags;
                 }
                 else {
                     memory_flag =
@@ -5231,10 +5246,11 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
         module->name_section_buf = buf;
         module->name_section_buf_end = buf_end;
         p += name_len;
-        handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
-                            error_buf_size);
+        if (!handle_name_section(p, p_end, module, is_load_from_file_buf,
+                                 error_buf, error_buf_size)) {
+            return false;
+        }
         LOG_VERBOSE("Load custom name section success.");
-        return true;
     }
 #endif
 
@@ -5778,6 +5794,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable;
+#if WASM_ENABLE_BULK_MEMORY != 0
+    bool has_datacount_section = false;
+#endif
 
     /* Find code and function sections if have */
     while (section) {
@@ -5870,6 +5889,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 break;
             case SECTION_TYPE_DATA:
                 if (!load_data_segment_section(buf, buf_end, module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                                               has_datacount_section,
+#endif
                                                clone_data_seg, error_buf,
                                                error_buf_size))
                     return false;
@@ -5879,6 +5901,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                                             error_buf_size))
                     return false;
+                has_datacount_section = true;
                 break;
 #endif
 #if WASM_ENABLE_STRINGREF != 0
@@ -6131,13 +6154,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             if (shrunk_memory_size <= UINT32_MAX) {
                 if (module->import_memory_count) {
                     memory_import = &module->import_memories[0].u.memory;
-                    init_memory_size = (uint64)memory_import->num_bytes_per_page
-                                       * memory_import->init_page_count;
+                    init_memory_size =
+                        (uint64)memory_import->mem_type.num_bytes_per_page
+                        * memory_import->mem_type.init_page_count;
                     if (shrunk_memory_size <= init_memory_size) {
                         /* Reset memory info to decrease memory usage */
-                        memory_import->num_bytes_per_page =
+                        memory_import->mem_type.num_bytes_per_page =
                             (uint32)shrunk_memory_size;
-                        memory_import->init_page_count = 1;
+                        memory_import->mem_type.init_page_count = 1;
                         LOG_VERBOSE("Shrink import memory size to %" PRIu64,
                                     shrunk_memory_size);
                     }
@@ -6163,16 +6187,16 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             memory_import = &module->import_memories[0].u.memory;
             /* Only resize the memory to one big page if num_bytes_per_page is
              * in valid range of uint32 */
-            if (memory_import->init_page_count < DEFAULT_MAX_PAGES) {
-                memory_import->num_bytes_per_page *=
-                    memory_import->init_page_count;
+            if (memory_import->mem_type.init_page_count < DEFAULT_MAX_PAGES) {
+                memory_import->mem_type.num_bytes_per_page *=
+                    memory_import->mem_type.init_page_count;
 
-                if (memory_import->init_page_count > 0)
-                    memory_import->init_page_count =
-                        memory_import->max_page_count = 1;
+                if (memory_import->mem_type.init_page_count > 0)
+                    memory_import->mem_type.init_page_count =
+                        memory_import->mem_type.max_page_count = 1;
                 else
-                    memory_import->init_page_count =
-                        memory_import->max_page_count = 0;
+                    memory_import->mem_type.init_page_count =
+                        memory_import->mem_type.max_page_count = 0;
             }
         }
         if (module->memory_count) {
@@ -6403,7 +6427,7 @@ create_sections(const uint8 *buf, uint32 size, WASMSection **p_section_list,
                 char *error_buf, uint32 error_buf_size)
 {
     WASMSection *section_list_end = NULL, *section;
-    const uint8 *p = buf, *p_end = buf + size /*, *section_body*/;
+    const uint8 *p = buf, *p_end = buf + size;
     uint8 section_type, section_index, last_section_index = (uint8)-1;
     uint32 section_size;
 
@@ -7075,7 +7099,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                 }
                 else {
                     p--;
-                    skip_leb_uint32(p, p_end);
+                    /* block type */
+                    skip_leb_int32(p, p_end);
                 }
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
@@ -7090,7 +7115,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
             case EXT_OP_LOOP:
             case EXT_OP_IF:
                 /* block type */
-                skip_leb_uint32(p, p_end);
+                skip_leb_int32(p, p_end);
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     block_stack[block_nested_depth].start_addr = p;
@@ -7647,7 +7672,6 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
 #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
             case WASM_OP_SIMD_PREFIX:
             {
-                /* TODO: memory64 offset type changes */
                 uint32 opcode1;
 
                 read_leb_uint32(p, p_end, opcode1);
@@ -7672,8 +7696,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                     case SIMD_v128_store:
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         break;
 
                     case SIMD_v128_const:
@@ -7712,8 +7736,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                     case SIMD_v128_store64_lane:
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         /* ImmLaneId */
                         CHECK_BUF(p, p_end, 1);
                         p++;
@@ -7723,8 +7747,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                     case SIMD_v128_load64_zero:
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         break;
 
                     default:
@@ -7840,7 +7864,11 @@ typedef struct BranchBlock {
     BranchBlockPatch *patch_list;
     /* This is used to save params frame_offset of of if block */
     int16 *param_frame_offsets;
-    /* This is used to recover dynamic offset for else branch */
+    /* This is used to recover the dynamic offset for else branch,
+     * and also to remember the start offset of dynamic space which
+     * stores the block arguments for loop block, so we can use it
+     * to copy the stack operands to the loop block's arguments in
+     * wasm_loader_emit_br_info for opcode br. */
     uint16 start_dynamic_offset;
 #endif
 
@@ -7991,13 +8019,26 @@ static void
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 {
     BranchBlock *tmp_csp = frame_csp;
+    uint32 i;
 
-    for (uint32 i = 0; i < csp_num; i++) {
+    for (i = 0; i < csp_num; i++) {
         free_label_patch_list(tmp_csp);
         tmp_csp++;
     }
 }
 
+static void
+free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num)
+{
+    BranchBlock *tmp_csp = frame_csp;
+    uint32 i;
+
+    for (i = 0; i < csp_num; i++) {
+        if (tmp_csp->param_frame_offsets)
+            wasm_runtime_free(tmp_csp->param_frame_offsets);
+        tmp_csp++;
+    }
+}
 #endif /* end of WASM_ENABLE_FAST_INTERP */
 
 #if WASM_ENABLE_GC != 0
@@ -8116,6 +8157,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
         if (ctx->frame_csp_bottom) {
 #if WASM_ENABLE_FAST_INTERP != 0
             free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
+            free_all_label_param_frame_offsets(ctx->frame_csp_bottom,
+                                               ctx->csp_num);
 #endif
 #if WASM_ENABLE_GC != 0
             wasm_loader_clean_all_local_use_masks(ctx);
@@ -9228,8 +9271,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
             emit_operand(ctx, *(int16 *)(frame_offset));
         }
         /* Part e */
-        dynamic_offset =
-            frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
+        if (frame_csp->label_type == LABEL_TYPE_LOOP)
+            /* Use start_dynamic_offset which was set in
+               copy_params_to_dynamic_space */
+            dynamic_offset = frame_csp->start_dynamic_offset
+                             + wasm_get_cell_num(types, arity);
+        else
+            dynamic_offset =
+                frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
         if (is_br)
             ctx->dynamic_offset = dynamic_offset;
         for (i = (int32)arity - 1; i >= 0; i--) {
@@ -10613,8 +10662,8 @@ fail:
  *   Part e: each param's dst offset
  */
 static bool
-copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
-                             char *error_buf, uint32 error_buf_size)
+copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf,
+                             uint32 error_buf_size)
 {
     bool ret = false;
     int16 *frame_offset = NULL;
@@ -10628,6 +10677,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
     uint32 param_count = block_type->u.type->param_count;
     int16 condition_offset = 0;
     bool disable_emit = false;
+    bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false);
     int16 operand_offset = 0;
 
     uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
@@ -10680,6 +10730,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
     if (is_if_block)
         emit_operand(loader_ctx, condition_offset);
 
+    /* Since the start offset to save the block's params and
+     * the start offset to save the block's results may be
+     * different, we remember the dynamic offset for loop block
+     * so that we can use it to copy the stack operands to the
+     * loop block's params in wasm_loader_emit_br_info. */
+    if (block->label_type == LABEL_TYPE_LOOP)
+        block->start_dynamic_offset = loader_ctx->dynamic_offset;
+
     /* Part e) */
     /* Push to dynamic space. The push will emit the dst offset. */
     for (i = 0; i < param_count; i++)
@@ -11052,12 +11110,12 @@ re_scan:
 #endif /* end of WASM_ENABLE_GC != 0 */
                 }
                 else {
-                    uint32 type_index;
+                    int32 type_index;
                     /* Resolve the leb128 encoded type index as block type */
                     p--;
                     p_org = p - 1;
-                    read_leb_uint32(p, p_end, type_index);
-                    if (type_index >= module->type_count) {
+                    read_leb_int32(p, p_end, type_index);
+                    if ((uint32)type_index >= module->type_count) {
                         set_error_buf(error_buf, error_buf_size,
                                       "unknown type");
                         goto fail;
@@ -11161,8 +11219,8 @@ re_scan:
 
                     if (BLOCK_HAS_PARAM(block_type)) {
                         /* Make sure params are in dynamic space */
-                        if (!copy_params_to_dynamic_space(
-                                loader_ctx, false, error_buf, error_buf_size))
+                        if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
+                                                          error_buf_size))
                             goto fail;
                     }
 
@@ -11208,8 +11266,8 @@ re_scan:
                         /* skip the if label */
                         skip_label();
                         /* Emit a copy instruction */
-                        if (!copy_params_to_dynamic_space(
-                                loader_ctx, true, error_buf, error_buf_size))
+                        if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
+                                                          error_buf_size))
                             goto fail;
 
                         /* Emit the if instruction */

+ 98 - 41
core/iwasm/interpreter/wasm_mini_loader.c

@@ -33,7 +33,7 @@ has_module_memory64(WASMModule *module)
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
     if (module->import_memory_count > 0)
-        return !!(module->import_memories[0].u.memory.flags & MEMORY64_FLAG);
+        return !!(module->import_memories[0].u.mem_type.flags & MEMORY64_FLAG);
     else if (module->memory_count > 0)
         return !!(module->memories[0].flags & MEMORY64_FLAG);
 
@@ -761,10 +761,10 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
     }
 
     /* now we believe all declaration are ok */
-    memory->flags = mem_flag;
-    memory->init_page_count = declare_init_page_count;
-    memory->max_page_count = declare_max_page_count;
-    memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
+    memory->mem_type.flags = mem_flag;
+    memory->mem_type.init_page_count = declare_init_page_count;
+    memory->mem_type.max_page_count = declare_max_page_count;
+    memory->mem_type.num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
 
     *p_buf = p;
     return true;
@@ -1740,8 +1740,12 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
 
 static bool
 load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
-                          WASMModule *module, bool clone_data_seg,
-                          char *error_buf, uint32 error_buf_size)
+                          WASMModule *module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                          bool has_datacount_section,
+#endif
+                          bool clone_data_seg, char *error_buf,
+                          uint32 error_buf_size)
 {
     const uint8 *p = buf, *p_end = buf_end;
     uint32 data_seg_count, i, mem_index, data_seg_len;
@@ -1757,7 +1761,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
     read_leb_uint32(p, p_end, data_seg_count);
 
 #if WASM_ENABLE_BULK_MEMORY != 0
-    bh_assert(module->data_seg_count1 == 0
+    bh_assert(!has_datacount_section
               || data_seg_count == module->data_seg_count1);
 #endif
 
@@ -1808,7 +1812,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
                 uint8 memory_flag;
                 if (module->import_memory_count > 0) {
                     memory_flag =
-                        module->import_memories[mem_index].u.memory.flags;
+                        module->import_memories[mem_index].u.mem_type.flags;
                 }
                 else {
                     memory_flag =
@@ -2029,8 +2033,10 @@ load_user_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
 #if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
     if (name_len == 4 && memcmp(p, "name", 4) == 0) {
         p += name_len;
-        handle_name_section(p, p_end, module, is_load_from_file_buf, error_buf,
-                            error_buf_size);
+        if (!handle_name_section(p, p_end, module, is_load_from_file_buf,
+                                 error_buf, error_buf_size)) {
+            return false;
+        }
     }
 #endif
     LOG_VERBOSE("Load custom section success.\n");
@@ -2108,7 +2114,7 @@ static bool
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
                                uint32 error_buf_size)
 {
-    LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
+    LLVMJITOptions *llvm_jit_options = wasm_runtime_get_llvm_jit_options();
     AOTCompOption option = { 0 };
     char *aot_last_error;
     uint64 size;
@@ -2579,6 +2585,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool clone_data_seg = is_load_from_file_buf && wasm_binary_freeable;
+#if WASM_ENABLE_BULK_MEMORY != 0
+    bool has_datacount_section = false;
+#endif
 
     /* Find code and function sections if have */
     while (section) {
@@ -2660,6 +2669,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 break;
             case SECTION_TYPE_DATA:
                 if (!load_data_segment_section(buf, buf_end, module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                                               has_datacount_section,
+#endif
                                                clone_data_seg, error_buf,
                                                error_buf_size))
                     return false;
@@ -2669,6 +2681,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                                             error_buf_size))
                     return false;
+                has_datacount_section = true;
                 break;
 #endif
             default:
@@ -2909,12 +2922,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             if (shrunk_memory_size <= UINT32_MAX) {
                 if (module->import_memory_count) {
                     memory_import = &module->import_memories[0].u.memory;
-                    init_memory_size = (uint64)memory_import->num_bytes_per_page
-                                       * memory_import->init_page_count;
+                    init_memory_size =
+                        (uint64)memory_import->mem_type.num_bytes_per_page
+                        * memory_import->mem_type.init_page_count;
                     if (shrunk_memory_size <= init_memory_size) {
                         /* Reset memory info to decrease memory usage */
-                        memory_import->num_bytes_per_page = shrunk_memory_size;
-                        memory_import->init_page_count = 1;
+                        memory_import->mem_type.num_bytes_per_page =
+                            shrunk_memory_size;
+                        memory_import->mem_type.init_page_count = 1;
                         LOG_VERBOSE("Shrink import memory size to %" PRIu64,
                                     shrunk_memory_size);
                     }
@@ -2937,15 +2952,15 @@ load_from_sections(WASMModule *module, WASMSection *sections,
 
         if (module->import_memory_count) {
             memory_import = &module->import_memories[0].u.memory;
-            if (memory_import->init_page_count < DEFAULT_MAX_PAGES) {
-                memory_import->num_bytes_per_page *=
-                    memory_import->init_page_count;
-                if (memory_import->init_page_count > 0)
-                    memory_import->init_page_count =
-                        memory_import->max_page_count = 1;
+            if (memory_import->mem_type.init_page_count < DEFAULT_MAX_PAGES) {
+                memory_import->mem_type.num_bytes_per_page *=
+                    memory_import->mem_type.init_page_count;
+                if (memory_import->mem_type.init_page_count > 0)
+                    memory_import->mem_type.init_page_count =
+                        memory_import->mem_type.max_page_count = 1;
                 else
-                    memory_import->init_page_count =
-                        memory_import->max_page_count = 0;
+                    memory_import->mem_type.init_page_count =
+                        memory_import->mem_type.max_page_count = 0;
             }
         }
 
@@ -3220,8 +3235,11 @@ load(const uint8 *buf, uint32 size, WASMModule *module,
 }
 
 WASMModule *
-wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf,
-                 uint32 error_buf_size)
+wasm_loader_load(uint8 *buf, uint32 size,
+#if WASM_ENABLE_MULTI_MODULE != 0
+                 bool main_module,
+#endif
+                 const LoadArgs *args, char *error_buf, uint32 error_buf_size)
 {
     WASMModule *module = create_module(args->name, error_buf, error_buf_size);
     if (!module) {
@@ -3239,6 +3257,10 @@ wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf,
         goto fail;
     }
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+    (void)main_module;
+#endif
+
     LOG_VERBOSE("Load module success.\n");
     return module;
 
@@ -3451,7 +3473,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
             case EXT_OP_LOOP:
             case EXT_OP_IF:
                 /* block type */
-                skip_leb_uint32(p, p_end);
+                skip_leb_int32(p, p_end);
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     block_stack[block_nested_depth].start_addr = p;
@@ -3921,7 +3943,11 @@ typedef struct BranchBlock {
     /* This is used to store available param num for if/else branch, so the else
      * opcode can know how many parameters should be copied to the stack */
     uint32 available_param_num;
-    /* This is used to recover dynamic offset for else branch */
+    /* This is used to recover the dynamic offset for else branch,
+     * and also to remember the start offset of dynamic space which
+     * stores the block arguments for loop block, so we can use it
+     * to copy the stack operands to the loop block's arguments in
+     * wasm_loader_emit_br_info for opcode br. */
     uint16 start_dynamic_offset;
 #endif
 
@@ -4050,13 +4076,26 @@ static void
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 {
     BranchBlock *tmp_csp = frame_csp;
+    uint32 i;
 
-    for (uint32 i = 0; i < csp_num; i++) {
+    for (i = 0; i < csp_num; i++) {
         free_label_patch_list(tmp_csp);
         tmp_csp++;
     }
 }
 
+static void
+free_all_label_param_frame_offsets(BranchBlock *frame_csp, uint32 csp_num)
+{
+    BranchBlock *tmp_csp = frame_csp;
+    uint32 i;
+
+    for (i = 0; i < csp_num; i++) {
+        if (tmp_csp->param_frame_offsets)
+            wasm_runtime_free(tmp_csp->param_frame_offsets);
+        tmp_csp++;
+    }
+}
 #endif
 
 static bool
@@ -4120,6 +4159,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
         if (ctx->frame_csp_bottom) {
 #if WASM_ENABLE_FAST_INTERP != 0
             free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
+            free_all_label_param_frame_offsets(ctx->frame_csp_bottom,
+                                               ctx->csp_num);
 #endif
             wasm_runtime_free(ctx->frame_csp_bottom);
         }
@@ -4798,8 +4839,14 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
             emit_operand(ctx, *(int16 *)(frame_offset));
         }
         /* Part e */
-        dynamic_offset =
-            frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
+        if (frame_csp->label_type == LABEL_TYPE_LOOP)
+            /* Use start_dynamic_offset which was set in
+               copy_params_to_dynamic_space */
+            dynamic_offset = frame_csp->start_dynamic_offset
+                             + wasm_get_cell_num(types, arity);
+        else
+            dynamic_offset =
+                frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
         if (is_br)
             ctx->dynamic_offset = dynamic_offset;
         for (i = (int32)arity - 1; i >= 0; i--) {
@@ -5778,8 +5825,8 @@ fail:
  *   Part e: each param's dst offset
  */
 static bool
-copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
-                             char *error_buf, uint32 error_buf_size)
+copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, char *error_buf,
+                             uint32 error_buf_size)
 {
     bool ret = false;
     int16 *frame_offset = NULL;
@@ -5793,6 +5840,7 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
     uint32 param_count = block_type->u.type->param_count;
     int16 condition_offset = 0;
     bool disable_emit = false;
+    bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false);
     int16 operand_offset = 0;
 
     uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
@@ -5845,6 +5893,14 @@ copy_params_to_dynamic_space(WASMLoaderContext *loader_ctx, bool is_if_block,
     if (is_if_block)
         emit_operand(loader_ctx, condition_offset);
 
+    /* Since the start offset to save the block's params and
+     * the start offset to save the block's results may be
+     * different, we remember the dynamic offset for loop block
+     * so that we can use it to copy the stack operands to the
+     * loop block's params in wasm_loader_emit_br_info. */
+    if (block->label_type == LABEL_TYPE_LOOP)
+        block->start_dynamic_offset = loader_ctx->dynamic_offset;
+
     /* Part e) */
     /* Push to dynamic space. The push will emit the dst offset. */
     for (i = 0; i < param_count; i++)
@@ -6043,11 +6099,11 @@ re_scan:
                     block_type.u.value_type.type = value_type;
                 }
                 else {
-                    uint32 type_index;
+                    int32 type_index;
                     /* Resolve the leb128 encoded type index as block type */
                     p--;
-                    read_leb_uint32(p, p_end, type_index);
-                    bh_assert(type_index < module->type_count);
+                    read_leb_int32(p, p_end, type_index);
+                    bh_assert((uint32)type_index < module->type_count);
                     block_type.is_value_type = false;
                     block_type.u.type = module->types[type_index];
 #if WASM_ENABLE_FAST_INTERP == 0
@@ -6134,8 +6190,8 @@ re_scan:
                     skip_label();
                     if (BLOCK_HAS_PARAM(block_type)) {
                         /* Make sure params are in dynamic space */
-                        if (!copy_params_to_dynamic_space(
-                                loader_ctx, false, error_buf, error_buf_size))
+                        if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
+                                                          error_buf_size))
                             goto fail;
                     }
                     if (opcode == WASM_OP_LOOP) {
@@ -6175,8 +6231,8 @@ re_scan:
                         /* skip the if label */
                         skip_label();
                         /* Emit a copy instruction */
-                        if (!copy_params_to_dynamic_space(
-                                loader_ctx, true, error_buf, error_buf_size))
+                        if (!copy_params_to_dynamic_space(loader_ctx, error_buf,
+                                                          error_buf_size))
                             goto fail;
 
                         /* Emit the if instruction */
@@ -6942,7 +6998,8 @@ re_scan:
                     uint32 j;
 
                     for (i = 0; i < module->global_count; i++) {
-                        if (module->globals[i].type == VALUE_TYPE_FUNCREF
+                        if (module->globals[i].type.val_type
+                                == VALUE_TYPE_FUNCREF
                             && module->globals[i].init_expr.init_expr_type
                                    == INIT_EXPR_TYPE_FUNCREF_CONST
                             && module->globals[i].init_expr.u.u32 == func_idx) {

+ 7 - 6
core/iwasm/interpreter/wasm_runtime.c

@@ -396,12 +396,13 @@ memories_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
     /* instantiate memories from import section */
     import = module->import_memories;
     for (i = 0; i < module->import_memory_count; i++, import++, memory++) {
-        uint32 num_bytes_per_page = import->u.memory.num_bytes_per_page;
-        uint32 init_page_count = import->u.memory.init_page_count;
+        uint32 num_bytes_per_page =
+            import->u.memory.mem_type.num_bytes_per_page;
+        uint32 init_page_count = import->u.memory.mem_type.init_page_count;
         uint32 max_page_count = wasm_runtime_get_max_mem(
-            max_memory_pages, import->u.memory.init_page_count,
-            import->u.memory.max_page_count);
-        uint32 flags = import->u.memory.flags;
+            max_memory_pages, import->u.memory.mem_type.init_page_count,
+            import->u.memory.mem_type.max_page_count);
+        uint32 flags = import->u.memory.mem_type.flags;
         uint32 actual_heap_size = heap_size;
 
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -3181,7 +3182,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
 
     if (!is_sub_inst) {
 #if WASM_ENABLE_WASI_NN != 0
-        wasi_nn_destroy(module_inst);
+        wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst);
 #endif
         wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
     }

+ 55 - 18
core/iwasm/libraries/wasi-nn/README.md

@@ -16,23 +16,22 @@ By only including this file in your WASM application you will bind WASI-NN into
 
 To run the tests we assume that the current directory is the root of the repository.
 
-
 ### Build the runtime
 
 Build the runtime image for your execution target type.
 
 `EXECUTION_TYPE` can be:
-* `cpu`
-* `nvidia-gpu`
-* `vx-delegate`
-* `tpu`
+
+- `cpu`
+- `nvidia-gpu`
+- `vx-delegate`
+- `tpu`
 
 ```
 EXECUTION_TYPE=cpu
 docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
 ```
 
-
 ### Build wasm app
 
 ```
@@ -43,7 +42,6 @@ docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile.
 docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile
 ```
 
-
 ### Run wasm app
 
 If all the tests have run properly you will the the following message in the terminal,
@@ -52,7 +50,7 @@ If all the tests have run properly you will the the following message in the ter
 Tests: passed!
 ```
 
-* CPU
+- CPU
 
 ```
 docker run \
@@ -64,9 +62,9 @@ docker run \
     /assets/test_tensorflow.wasm
 ```
 
-* (NVIDIA) GPU
-    * Requirements:
-        * [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
+- (NVIDIA) GPU
+  - Requirements:
+    - [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
 
 ```
 docker run \
@@ -79,7 +77,7 @@ docker run \
     /assets/test_tensorflow.wasm
 ```
 
-* vx-delegate for NPU (x86 simulator)
+- vx-delegate for NPU (x86 simulator)
 
 ```
 docker run \
@@ -90,9 +88,9 @@ docker run \
     /assets/test_tensorflow_quantized.wasm
 ```
 
-* (Coral) TPU
-    * Requirements:
-        * [Coral USB](https://coral.ai/products/accelerator/).
+- (Coral) TPU
+  - Requirements:
+    - [Coral USB](https://coral.ai/products/accelerator/).
 
 ```
 docker run \
@@ -109,6 +107,45 @@ docker run \
 
 Supported:
 
-* Graph encoding: `tensorflowlite`.
-* Execution target: `cpu`, `gpu` and `tpu`.
-* Tensor type: `fp32`.
+- Graph encoding: `tensorflowlite`.
+- Execution target: `cpu`, `gpu` and `tpu`.
+- Tensor type: `fp32`.
+
+## Smoke test
+
+Use [classification-example](https://github.com/bytecodealliance/wasi-nn/tree/main/rust/examples/classification-example) as a smoke test case to make sure the wasi-nn support in WAMR is working properly.
+
+> [!Important]
+> It requires openvino.
+
+### Prepare the model and the wasm
+
+``` bash
+$ pwd
+/workspaces/wasm-micro-runtime/core/iwasm/libraries/wasi-nn/test
+
+$ docker build -t wasi-nn-example:v1.0 -f Dockerfile.wasi-nn-example .
+```
+
+There are model files(*mobilenet\**) and wasm files(*wasi-nn-example.wasm*) in the directory */workspaces/wasi-nn/rust/examples/classification-example/build* in the image of wasi-nn-example:v1.0.
+
+### build iwasm and test
+
+*TODO: May need alternative steps to build the iwasm and test in the container of wasi-nn-example:v1.0*
+
+``` bash
+$ pwd
+/workspaces/wasm-micro-runtime
+
+$ docker run --rm -it -v $(pwd):/workspaces/wasm-micro-runtime wasi-nn-example:v1.0 /bin/bash
+```
+
+> [!Caution]
+> The following steps are executed in the container of wasi-nn-example:v1.0.
+
+``` bash
+$ cd /workspaces/wasm-micro-runtime/product-mini/platforms/linux
+$ cmake -S . -B build -DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_EPHEMERAL_NN=1
+$ cmake --build build
+$ ./build/iwasm -v=5 --map-dir=/workspaces/wasi-nn/rust/examples/classification-example/build/::fixture /workspaces/wasi-nn/rust/examples/classification-example/build/wasi-nn-example.wasm
+```

+ 10 - 13
core/iwasm/libraries/wasi-nn/include/wasi_nn.h

@@ -22,9 +22,9 @@
  * @param encoding  Model encoding.
  * @param target    Execution target.
  * @param g         Graph.
- * @return error    Execution status.
+ * @return wasi_nn_error    Execution status.
  */
-error
+wasi_nn_error
 load(graph_builder_array *builder, graph_encoding encoding,
      execution_target target, graph *g)
     __attribute__((import_module("wasi_nn")));
@@ -34,17 +34,14 @@ load(graph_builder_array *builder, graph_encoding encoding,
  *
  */
 
-// Bind a `graph` to the input and output tensors for an inference.
-typedef uint32_t graph_execution_context;
-
 /**
  * @brief Create an execution instance of a loaded graph.
  *
  * @param g         Graph.
  * @param ctx       Execution context.
- * @return error    Execution status.
+ * @return wasi_nn_error    Execution status.
  */
-error
+wasi_nn_error
 init_execution_context(graph g, graph_execution_context *ctx)
     __attribute__((import_module("wasi_nn")));
 
@@ -54,9 +51,9 @@ init_execution_context(graph g, graph_execution_context *ctx)
  * @param ctx       Execution context.
  * @param index     Input tensor index.
  * @param tensor    Input tensor.
- * @return error    Execution status.
+ * @return wasi_nn_error    Execution status.
  */
-error
+wasi_nn_error
 set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
     __attribute__((import_module("wasi_nn")));
 
@@ -64,9 +61,9 @@ set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
  * @brief Compute the inference on the given inputs.
  *
  * @param ctx       Execution context.
- * @return error    Execution status.
+ * @return wasi_nn_error    Execution status.
  */
-error
+wasi_nn_error
 compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
 
 /**
@@ -79,9 +76,9 @@ compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
  * @param output_tensor_size    Pointer to `output_tensor` maximum size.
  *                              After the function call it is updated with the
  * copied number of bytes.
- * @return error                Execution status.
+ * @return wasi_nn_error                Execution status.
  */
-error
+wasi_nn_error
 get_output(graph_execution_context ctx, uint32_t index,
            tensor_data output_tensor, uint32_t *output_tensor_size)
     __attribute__((import_module("wasi_nn")));

+ 4 - 1
core/iwasm/libraries/wasi-nn/include/wasi_nn_types.h

@@ -28,7 +28,7 @@ typedef enum {
     busy,
     // Runtime Error.
     runtime_error,
-} error;
+} wasi_nn_error;
 
 /**
  * TENSOR
@@ -106,4 +106,7 @@ typedef enum {
 // Define where the graph should be executed.
 typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
 
+// Bind a `graph` to the input and output tensors for an inference.
+typedef uint32_t graph_execution_context;
+
 #endif

+ 8 - 8
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c

@@ -5,7 +5,7 @@
 
 #include "wasi_nn_app_native.h"
 
-static error
+static wasi_nn_error
 graph_builder_app_native(wasm_module_inst_t instance,
                          graph_builder_wasm *builder_wasm,
                          graph_builder *builder)
@@ -27,12 +27,12 @@ graph_builder_app_native(wasm_module_inst_t instance,
  * builder_array_wasm is consisted of {builder_wasm, size}
  */
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_wasm *builder_wasm, uint32_t size,
                                graph_builder_array *builder_array)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_array_wasm *builder_array_wasm,
                                graph_builder_array *builder_array)
@@ -79,7 +79,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance,
         return missing_memory;
 
     for (uint32_t i = 0; i < array_size; ++i) {
-        error res;
+        wasi_nn_error res;
         if (success
             != (res = graph_builder_app_native(instance, &builder_wasm[i],
                                                &builder[i]))) {
@@ -97,7 +97,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance,
 #undef array_size
 }
 
-static error
+static wasi_nn_error
 tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
                        tensor_wasm *input_tensor_wasm, tensor_data *data)
 {
@@ -119,7 +119,7 @@ tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
 #undef data_size
 }
 
-static error
+static wasi_nn_error
 tensor_dimensions_app_native(wasm_module_inst_t instance,
                              tensor_wasm *input_tensor_wasm,
                              tensor_dimensions **dimensions)
@@ -159,7 +159,7 @@ tensor_dimensions_app_native(wasm_module_inst_t instance,
     return success;
 }
 
-error
+wasi_nn_error
 tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
                   tensor *input_tensor)
 {
@@ -170,7 +170,7 @@ tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
         return invalid_argument;
     }
 
-    error res;
+    wasi_nn_error res;
 
     tensor_dimensions *dimensions = NULL;
     if (success

+ 4 - 4
core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h

@@ -12,7 +12,7 @@
 #include <errno.h>
 #include <string.h>
 
-#include "wasi_nn.h"
+#include "wasi_nn_types.h"
 #include "logger.h"
 
 #include "bh_platform.h"
@@ -47,18 +47,18 @@ typedef struct {
 } tensor_wasm;
 
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_wasm *builder_wasm, uint32_t size,
                                graph_builder_array *builder_array);
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_array_wasm *builder,
                                graph_builder_array *builder_native);
 #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
 
-error
+wasi_nn_error
 tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor,
                   tensor *input_tensor_native);
 

+ 22 - 22
core/iwasm/libraries/wasi-nn/src/wasi_nn.c

@@ -11,7 +11,6 @@
 #include <string.h>
 #include <stdint.h>
 
-#include "wasi_nn.h"
 #include "wasi_nn_private.h"
 #include "wasi_nn_app_native.h"
 #include "wasi_nn_tensorflowlite.hpp"
@@ -24,14 +23,15 @@
 
 /* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
 
-typedef error (*LOAD)(void *, graph_builder_array *, graph_encoding,
-                      execution_target, graph *);
-typedef error (*INIT_EXECUTION_CONTEXT)(void *, graph,
-                                        graph_execution_context *);
-typedef error (*SET_INPUT)(void *, graph_execution_context, uint32_t, tensor *);
-typedef error (*COMPUTE)(void *, graph_execution_context);
-typedef error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
-                            tensor_data, uint32_t *);
+typedef wasi_nn_error (*LOAD)(void *, graph_builder_array *, graph_encoding,
+                              execution_target, graph *);
+typedef wasi_nn_error (*INIT_EXECUTION_CONTEXT)(void *, graph,
+                                                graph_execution_context *);
+typedef wasi_nn_error (*SET_INPUT)(void *, graph_execution_context, uint32_t,
+                                   tensor *);
+typedef wasi_nn_error (*COMPUTE)(void *, graph_execution_context);
+typedef wasi_nn_error (*GET_OUTPUT)(void *, graph_execution_context, uint32_t,
+                                    tensor_data, uint32_t *);
 
 typedef struct {
     LOAD load;
@@ -177,7 +177,7 @@ is_encoding_implemented(graph_encoding encoding)
            && lookup[encoding].get_output;
 }
 
-static error
+static wasi_nn_error
 is_model_initialized(WASINNContext *wasi_nn_ctx)
 {
     if (!wasi_nn_ctx->is_model_loaded) {
@@ -190,12 +190,12 @@ is_model_initialized(WASINNContext *wasi_nn_ctx)
 /* WASI-NN implementation */
 
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder,
              uint32_t builder_wasm_size, graph_encoding encoding,
              execution_target target, graph *g)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
-error
+wasi_nn_error
 wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
              graph_encoding encoding, execution_target target, graph *g)
 #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
@@ -211,7 +211,7 @@ wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
     wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
     bh_assert(instance);
 
-    error res;
+    wasi_nn_error res;
     graph_builder_array builder_native = { 0 };
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
     if (success
@@ -249,7 +249,7 @@ fail:
     return res;
 }
 
-error
+wasi_nn_error
 wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
                                graph_execution_context *ctx)
 {
@@ -259,7 +259,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
 
@@ -278,7 +278,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
     return res;
 }
 
-error
+wasi_nn_error
 wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
                   uint32_t index, tensor_wasm *input_tensor)
 {
@@ -289,7 +289,7 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
 
@@ -310,7 +310,7 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
     return res;
 }
 
-error
+wasi_nn_error
 wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
 {
     NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx);
@@ -319,7 +319,7 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
 
@@ -330,12 +330,12 @@ wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
 }
 
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t output_tensor_len, uint32_t *output_tensor_size)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
-error
+wasi_nn_error
 wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t *output_tensor_size)
@@ -348,7 +348,7 @@ wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
 

+ 17 - 15
core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp

@@ -3,7 +3,7 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
-#include "wasi_nn.h"
+#include "wasi_nn_types.h"
 #include "wasi_nn_tensorflowlite.hpp"
 #include "logger.h"
 
@@ -50,7 +50,7 @@ typedef struct {
 
 /* Utils */
 
-static error
+static wasi_nn_error
 initialize_g(TFLiteContext *tfl_ctx, graph *g)
 {
     os_mutex_lock(&tfl_ctx->g_lock);
@@ -63,7 +63,7 @@ initialize_g(TFLiteContext *tfl_ctx, graph *g)
     os_mutex_unlock(&tfl_ctx->g_lock);
     return success;
 }
-static error
+static wasi_nn_error
 initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
                      graph_execution_context *ctx)
 {
@@ -78,7 +78,7 @@ initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
     return success;
 }
 
-static error
+static wasi_nn_error
 is_valid_graph(TFLiteContext *tfl_ctx, graph g)
 {
     if (g >= MAX_GRAPHS_PER_INST) {
@@ -96,7 +96,7 @@ is_valid_graph(TFLiteContext *tfl_ctx, graph g)
     return success;
 }
 
-static error
+static wasi_nn_error
 is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
                                  graph_execution_context ctx)
 {
@@ -114,7 +114,7 @@ is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
 
 /* WASI-NN (tensorflow) implementation */
 
-error
+wasi_nn_error
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
                     graph_encoding encoding, execution_target target, graph *g)
 {
@@ -135,7 +135,7 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
         return invalid_argument;
     }
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = initialize_g(tfl_ctx, g)))
         return res;
 
@@ -168,13 +168,13 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
     return success;
 }
 
-error
+wasi_nn_error
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
                                       graph_execution_context *ctx)
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph(tfl_ctx, g)))
         return res;
 
@@ -257,13 +257,13 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
     return success;
 }
 
-error
+wasi_nn_error
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
                          uint32_t index, tensor *input_tensor)
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
 
@@ -328,12 +328,12 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
     return success;
 }
 
-error
+wasi_nn_error
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
 
@@ -341,14 +341,14 @@ tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
     return success;
 }
 
-error
+wasi_nn_error
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t *output_tensor_size)
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
 
@@ -472,6 +472,8 @@ tensorflowlite_destroy(void *tflite_ctx)
 #endif
                         break;
                     }
+                    default:
+                        break;
                 }
             }
             wasm_runtime_free(tfl_ctx->models[i].model_pointer);

+ 6 - 6
core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp

@@ -6,28 +6,28 @@
 #ifndef WASI_NN_TENSORFLOWLITE_HPP
 #define WASI_NN_TENSORFLOWLITE_HPP
 
-#include "wasi_nn.h"
+#include "wasi_nn_types.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-error
+wasi_nn_error
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
                     graph_encoding encoding, execution_target target, graph *g);
 
-error
+wasi_nn_error
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
                                       graph_execution_context *ctx);
 
-error
+wasi_nn_error
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
                          uint32_t index, tensor *input_tensor);
 
-error
+wasi_nn_error
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx);
 
-error
+wasi_nn_error
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t *output_tensor_size);

+ 57 - 0
core/iwasm/libraries/wasi-nn/test/Dockerfile.wasi-nn-example

@@ -0,0 +1,57 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye
+
+ARG DEBIAN_FRONTEND=noninteractive
+ENV TZ=Asian/Shanghai
+
+# hadolint ignore=DL3009
+RUN apt-get update \
+  && apt-get upgrade -y
+
+#
+# Rust targets
+RUN rustup target add wasm32-wasi wasm32-unknown-unknown
+
+#
+# Openvino
+# Refer to
+#   - https://docs.openvino.ai/2022.3/openvino_docs_install_guides_installing_openvino_from_archive_linux.html
+#   - https://docs.openvino.ai/2023.3/openvino_docs_install_guides_installing_openvino_from_archive_linux.html
+#   - https://docs.openvino.ai/2024/get-started/install-openvino/install-openvino-archive-linux.html
+#
+# FIXME: upgrade to 2024.1 or latest after wasi-nn(rust binding) is ready
+WORKDIR /opt/intel
+RUN wget -q https://storage.openvinotoolkit.org/repositories/openvino/packages/2022.3.2/linux/l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz
+RUN tar -xf l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz \
+  && rm l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64.tgz \
+  && mv l_openvino_toolkit_ubuntu20_2022.3.2.9279.e2c7e4d7b4d_x86_64 /opt/intel/openvino
+
+WORKDIR /opt/intel/openvino
+RUN ./install_dependencies/install_openvino_dependencies.sh -y \
+  && ./setupvars.sh
+
+#
+# wasmtime
+WORKDIR /opt
+RUN wget -q https://github.com/bytecodealliance/wasmtime/releases/download/v21.0.0/wasmtime-v21.0.0-x86_64-linux.tar.xz
+RUN tar -xf wasmtime-v21.0.0-x86_64-linux.tar.xz \
+  && rm wasmtime-v21.0.0-x86_64-linux.tar.xz \
+  && ln -sf "$(realpath ./wasmtime-v21.0.0-x86_64-linux/wasmtime)" /usr/local/bin/wasmtime
+
+#
+# wasi-nn
+WORKDIR /workspaces/wasi-nn
+RUN git clone --depth 1 https://github.com/bytecodealliance/wasi-nn.git .
+# hadolint ignore=DL3059
+RUN ./build.sh rust
+
+# There are model files(mobilenet*) and wasm files(wasi-nn-example.wasm) in the directory,
+# /workspaces/wasi-nn/rust/examples/classification-example/build
+
+RUN apt-get autoremove -y \
+  && apt-get clean -y \
+  && rm -rf /tmp/*
+
+WORKDIR /workspaces

+ 7 - 7
core/iwasm/libraries/wasi-nn/test/utils.c

@@ -9,7 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 
-error
+wasi_nn_error
 wasm_load(char *model_name, graph *g, execution_target target)
 {
     FILE *pFile = fopen(model_name, "r");
@@ -46,7 +46,7 @@ wasm_load(char *model_name, graph *g, execution_target target)
     arr.buf[0].size = result;
     arr.buf[0].buf = buffer;
 
-    error res = load(&arr, tensorflowlite, target, g);
+    wasi_nn_error res = load(&arr, tensorflowlite, target, g);
 
     fclose(pFile);
     free(buffer);
@@ -54,13 +54,13 @@ wasm_load(char *model_name, graph *g, execution_target target)
     return res;
 }
 
-error
+wasi_nn_error
 wasm_init_execution_context(graph g, graph_execution_context *ctx)
 {
     return init_execution_context(g, ctx);
 }
 
-error
+wasi_nn_error
 wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
 {
     tensor_dimensions dims;
@@ -75,19 +75,19 @@ wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
         tensor.dimensions->buf[i] = dim[i];
     tensor.type = fp32;
     tensor.data = (uint8_t *)input_tensor;
-    error err = set_input(ctx, 0, &tensor);
+    wasi_nn_error err = set_input(ctx, 0, &tensor);
 
     free(dims.buf);
     return err;
 }
 
-error
+wasi_nn_error
 wasm_compute(graph_execution_context ctx)
 {
     return compute(ctx);
 }
 
-error
+wasi_nn_error
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
                 uint32_t *out_size)
 {

+ 5 - 5
core/iwasm/libraries/wasi-nn/test/utils.h

@@ -23,19 +23,19 @@ typedef struct {
 
 /* wasi-nn wrappers */
 
-error
+wasi_nn_error
 wasm_load(char *model_name, graph *g, execution_target target);
 
-error
+wasi_nn_error
 wasm_init_execution_context(graph g, graph_execution_context *ctx);
 
-error
+wasi_nn_error
 wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim);
 
-error
+wasi_nn_error
 wasm_compute(graph_execution_context ctx);
 
-error
+wasi_nn_error
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
                 uint32_t *out_size);
 

+ 5 - 0
core/shared/platform/common/posix/platform_api_posix.cmake

@@ -9,6 +9,11 @@ if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
     list(REMOVE_ITEM source_all
         ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c
         ${PLATFORM_COMMON_POSIX_DIR}/posix_clock.c
+    )
+endif()
+
+if ((NOT WAMR_BUILD_LIBC_WASI EQUAL 1) AND (NOT WAMR_BUILD_DEBUG_INTERP EQUAL 1))
+    list(REMOVE_ITEM source_all
         ${PLATFORM_COMMON_POSIX_DIR}/posix_socket.c
     )
 else()

+ 8 - 0
core/shared/platform/riot/platform_internal.h

@@ -94,4 +94,12 @@ os_get_invalid_handle()
     return -1;
 }
 
+/* There is no MMU in RIOT so the function return 1024 to make the compiler
+   happy */
+static inline int
+os_getpagesize()
+{
+    return 1024;
+}
+
 #endif /* end of _BH_PLATFORM_H */

+ 6 - 0
core/shared/platform/riot/riot_platform.c

@@ -57,6 +57,12 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
     return BH_MALLOC((unsigned)size);
 }
 
+void *
+os_mremap(void *old_addr, size_t old_size, size_t new_size)
+{
+    return os_mremap_slow(old_addr, old_size, new_size);
+}
+
 void
 os_munmap(void *addr, size_t size)
 {

+ 1 - 1
core/version.h

@@ -6,6 +6,6 @@
 #ifndef _WAMR_VERSION_H_
 #define _WAMR_VERSION_H_
 #define WAMR_VERSION_MAJOR 2
-#define WAMR_VERSION_MINOR 0
+#define WAMR_VERSION_MINOR 1
 #define WAMR_VERSION_PATCH 0
 #endif

+ 2 - 0
product-mini/platforms/android/CMakeLists.txt

@@ -105,6 +105,8 @@ set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
 
 include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
 
+add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
+
 set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
 
 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")

+ 13 - 11
product-mini/platforms/posix/main.c

@@ -535,21 +535,23 @@ void *
 timeout_thread(void *vp)
 {
     const struct timeout_arg *arg = vp;
-    uint32 left = arg->timeout_ms;
+    const uint64 end_time =
+        os_time_get_boot_us() + (uint64)arg->timeout_ms * 1000;
     while (!arg->cancel) {
-        uint32 ms;
-        if (left >= 100) {
-            ms = 100;
-        }
-        else {
-            ms = left;
-        }
-        os_usleep((uint64)ms * 1000);
-        left -= ms;
-        if (left == 0) {
+        const uint64 now = os_time_get_boot_us();
+        if ((int64)(now - end_time) > 0) {
             wasm_runtime_terminate(arg->inst);
             break;
         }
+        const uint64 left_us = end_time - now;
+        uint32 us;
+        if (left_us >= 100 * 1000) {
+            us = 100 * 1000;
+        }
+        else {
+            us = left_us;
+        }
+        os_usleep(us);
     }
     return NULL;
 }

+ 6 - 6
test-tools/aot-analyzer/src/main.cc

@@ -272,9 +272,9 @@ DumpDetails(AoTFile *aot)
         AOTImportMemory memory = import_memories[index];
         printf("    -[%u] num_bytes_per_page:%5u    init_page_count:%5u    "
                "max_page_count:%5u    module_name: %s    memory_name: %s\n",
-               index, memory.num_bytes_per_page, memory.mem_init_page_count,
-               memory.mem_max_page_count, memory.module_name,
-               memory.memory_name);
+               index, memory.memory.num_bytes_per_page,
+               memory.memory.init_page_count, memory.memory.max_page_count,
+               memory.module_name, memory.memory_name);
     }
     printf("\n");
 
@@ -365,10 +365,10 @@ DumpDetails(AoTFile *aot)
 
     for (uint32_t index = 0; index < memory_count; index++) {
         AOTMemory memory = memories[index];
-        printf("  -[%u] memory_flags:%5u    bytes_per_page:%5u    "
+        printf("  -[%u] flags:%5u    bytes_per_page:%5u    "
                "init_page_count:%5u    max_page_count:%5u\n",
-               index, memory.memory_flags, memory.num_bytes_per_page,
-               memory.mem_init_page_count, memory.mem_max_page_count);
+               index, memory.flags, memory.num_bytes_per_page,
+               memory.init_page_count, memory.max_page_count);
     }
     printf("\n\n");
 

+ 1 - 0
test-tools/wamr-ide/VSCode-Extension/tsconfig.json

@@ -1,6 +1,7 @@
 {
     "compilerOptions": {
         "module": "commonjs",
+        "moduleResolution": "node16",
         "target": "es6",
         "outDir": "out",
         "lib": ["es6"],

+ 5 - 5
tests/fuzz/wasm-mutator-fuzz/CMakeLists.txt

@@ -58,12 +58,12 @@ endif ()
 
 if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
   # Enable libc builtin support by default
-  set (WAMR_BUILD_LIBC_BUILTIN 1)
+  set (WAMR_BUILD_LIBC_BUILTIN 0)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
   # Enable libc wasi support by default
-  set (WAMR_BUILD_LIBC_WASI 1)
+  set (WAMR_BUILD_LIBC_WASI 0)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
@@ -92,8 +92,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_REF_TYPES)
-  # Disable reference types by default
-  set (WAMR_BUILD_REF_TYPES 0)
+  # Enable reference type by default
+  set (WAMR_BUILD_REF_TYPES 1)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
@@ -113,7 +113,7 @@ message([ceith]:REPO_ROOT_DIR, ${REPO_ROOT_DIR})
 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
-add_definitions(-DWAMR_USE_MEM_POOL=0)
+add_definitions(-DWAMR_USE_MEM_POOL=0 -DWASM_ENABLE_FUZZ_TEST=1)
 
 # Enable fuzzer
 add_compile_options(-fsanitize=fuzzer)

+ 43 - 33
tests/fuzz/wasm-mutator-fuzz/smith_wasm.sh

@@ -8,51 +8,61 @@
 # 1.check parameter
 if [ ! $1 ]; then
 	echo "Parameter is empty, please enter parameter !"
-    exit 
+    exit
 fi
+EXPECTED_NUM=$1
 
 # 2.check dir
 buildPath="./build"
 corpusPath="$buildPath/CORPUS_DIR"
-if [[ ! -d "$buildPath" ]]; then
-    echo "auto create the build folder !"
-    mkdir build
-else # build Folder exists
-    if [[ -d "$buildPath" ]]; then # CORPUS_DIR exists
-        rm -rf $corpusPath
-    fi
-fi
+rm -rf "${corpusPath}"
+mkdir -p "${corpusPath}"
 
 # 3.change dir
-# cd build && mkdir CORPUS_DIR && cd CORPUS_DIR
-cd build && mkdir CORPUS_DIR && cd CORPUS_DIR
+cd "${corpusPath}"
 
 # 4.generate *.wasm file
-echo "Generate $@ files according to user requirements"
+echo "Generating $EXPECTED_NUM Wasm files for each kind as required"
 
-for((i=1; i<($@+1); i++));
-do
-head -c 100 /dev/urandom | wasm-tools smith -o test_$i.wasm
-done
+# Generate wasm files with different features
+# Try on and on until the generated wasm file exists
+function try_generate_wasm()
+{
+    SMITH_OPTIONS=$1
+    GENERATED_WASM_NAME=$2
+
+    local try_i=0
+    until [[ -f $GENERATED_WASM_NAME ]]; do
+        head -c 100 /dev/urandom | wasm-tools smith $SMITH_OPTIONS -o $GENERATED_WASM_NAME  >/dev/null 2>&1
+        try_i=$((try_i+1))
+    done
+
+    printf -- "-- output ${GENERATED_WASM_NAME} in %d retries\n" $try_i
+}
 
-# 5.check wasm file
-dir=$(pwd)              
-d=$(find . ! -name "." -type d -prune -o -type f -name "*.wasm" -print) 
-#echo "current dir=$dir" 
-num=0
+# try_generate_wasm "--min-memories=1 --min-tables=1" "test_min.wasm"
 
-for((i=1; i<($@+1); i++));
+for i in $(seq 1 $EXPECTED_NUM)
 do
-    wasmFile="test_$i.wasm"
-    if [[ ! -f "$wasmFile" ]]; then
-        echo "The file $wasmFile is not exists !"
-    else
-        let "num++"
-    fi
-done
+    # by default
+    try_generate_wasm "" test_$i.wasm
 
-echo "$@ user requirements, $num actually generated !"
+    # with different features
+    # mvp
+    try_generate_wasm "--min-memories=1 --min-tables=1" test_min_$i.wasm
+    try_generate_wasm "--min-memories=1 --min-tables=1 --bulk-memory-enabled true" test_bulk_$i.wasm
+    try_generate_wasm "--min-memories=1 --min-tables=1 --reference-types-enabled true" test_ref_$i.wasm
+    try_generate_wasm "--min-memories=1 --min-tables=1 --multi-value-enabled true" test_multi_$i.wasm
+    try_generate_wasm "--min-memories=1 --min-tables=1 --simd-enabled true" test_simd_$i.wasm
+    try_generate_wasm "--min-memories=1 --min-tables=1 --tail-call-enabled true " test_tail_$i.wasm
 
-if [ $num == $@ ]; then echo "Wasm file generated successfully !"
-else echo "Wasm file generated faild !"
-fi
+    # enable me when compiling iwasm with those features
+    #try_generate_wasm "--min-memories=1 --min-tables=1 --threads-enabled true" test_thread_$i.wasm
+    #try_generate_wasm "--min-memories=1 --min-tables=1 --memory64-enabled true" test_memory64_$i.wasm
+    #try_generate_wasm "--min-memories=1 --min-tables=1 --exceptions-enabled true" test_exception_$i.wasm
+    #try_generate_wasm "--min-memories=1 --min-tables=1 --gc-enabled true" test_gc_$i.wasm
+    # with custom-section
+    try_generate_wasm "--min-memories=1 --min-tables=1 --generate-custom-sections true" test_custom_$i.wasm
+done
+
+printf "Done\n"

+ 3 - 3
tests/fuzz/wasm-mutator-fuzz/workspace/CMakeLists.txt

@@ -92,8 +92,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_REF_TYPES)
-  # Disable reference types by default
-  set (WAMR_BUILD_REF_TYPES 0)
+  # Enable reference type by default
+  set (WAMR_BUILD_REF_TYPES 1)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
@@ -113,7 +113,7 @@ message([ceith]:REPO_ROOT_DIR, ${REPO_ROOT_DIR})
 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
 
-add_definitions(-DWAMR_USE_MEM_POOL=0)
+add_definitions(-DWAMR_USE_MEM_POOL=0 -DWASM_ENABLE_FUZZ_TEST=1)
 
 # Enable fuzzer
 add_compile_options(-fsanitize=fuzzer)

BIN
tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm


BIN
tests/regression/ba-issues/issues/issue-3468/i64.add.wasm


BIN
tests/regression/ba-issues/issues/issue-3491/nop_0LM_592_17171016522810388.wasm


+ 49 - 1
tests/regression/ba-issues/running_config.json

@@ -912,7 +912,7 @@
             "options": "",
             "argument": "",
             "expected return": {
-                "ret code": 57,
+                "ret code": 8,
                 "stdout content": "",
                 "description": "sock_shutdown on a non-socket file descriptor should fail with 57 notsock"
             }
@@ -1674,6 +1674,54 @@
                 "stdout content": "Hello from Kotlin via WASI\nCurrent 'realtime' timestamp is:",
                 "description": "no 'type mismatch: expect (ref null ht) but got other1 unknown type'"
             }
+        },
+        {
+            "deprecated": false,
+            "ids": [
+                3467
+            ],
+            "runtime": "iwasm-default-wasi-disabled",
+            "file": "tt_unreachable.wasm",
+            "mode": "fast-interp",
+            "options": "--heap-size=0 -f to_test",
+            "argument": "",
+            "expected return": {
+                "ret code": 1,
+                "stdout content": "Exception: unreachable",
+                "description": "no '-1.861157e+19:f32'"
+            }
+        },
+        {
+            "deprecated": false,
+            "ids": [
+                3468
+            ],
+            "runtime": "iwasm-default-wasi-disabled",
+            "file": "i64.add.wasm",
+            "mode": "fast-interp",
+            "options": "--heap-size=0 -f to_test",
+            "argument": "",
+            "expected return": {
+                "ret code": 255,
+                "stdout content": "WASM module load failed: unknown type",
+                "description": "no '0x0:i64'"
+            }
+        },
+        {
+            "deprecated": false,
+            "ids": [
+                3491
+            ],
+            "runtime": "iwasm-default-wasi-disabled",
+            "file": "nop_0LM_592_17171016522810388.wasm",
+            "mode": "fast-interp",
+            "options": "",
+            "argument": "",
+            "expected return": {
+                "ret code": 255,
+                "stdout content": "WASM module load failed: data count and data section have inconsistent lengths",
+                "description": "Check data segment count"
+            }
         }
     ]
 }

+ 37 - 36
tests/unit/CMakeLists.txt

@@ -1,51 +1,52 @@
-# Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved.
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
 # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-cmake_minimum_required (VERSION 3.14)
+cmake_minimum_required(VERSION 2.9)
 
-project (wamr_unit_tests)
+project(unit-test)
 
-include (CTest)
+SET(CMAKE_BUILD_TYPE Debug)
 
-if (NOT DEFINED WAMR_BUILD_INTERP)
-  # Enable Interpreter by default
-  set (WAMR_BUILD_INTERP 1)
-endif ()
+# add_definitions (-m32)
+set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
+set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
 
-if (NOT DEFINED WAMR_BUILD_PLATFORM)
-  string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
-endif ()
+if(WAMR_BUILD_TARGET STREQUAL "X86_32")
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
+  set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
+endif()
 
-set (WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
-include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
-add_library (vmlib ${WAMR_RUNTIME_LIB_SOURCE})
+# Prevent overriding the parent project's compiler/linker
+# settings on Windows
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 
+# Fetch Google test
 include (FetchContent)
 FetchContent_Declare (
     googletest
     URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
 )
-# For Windows: Prevent overriding the parent project's compiler/linker settings
-set (gtest_force_shared_crt ON CACHE BOOL "" FORCE)
 FetchContent_MakeAvailable (googletest)
 
-include (GoogleTest)
-
-add_library (wamr_gtest_main main.cpp)
-target_link_libraries (wamr_gtest_main PUBLIC gtest vmlib)
-
-function (create_wamr_unit_test test_name)
-    set (sources ${ARGN})
-    add_executable (${test_name} ${sources})
-    target_link_libraries (
-        ${test_name}
-        wamr_gtest_main
-        vmlib
-        ${LLVM_AVAILABLE_LIBS}
-    )
-    gtest_discover_tests (${test_name})
-    endfunction ()
-
-if (WAMR_BUILD_LIB_WASI_THREADS EQUAL 1)
-    include (${IWASM_DIR}/libraries/lib-wasi-threads/unit-test/lib_wasi_threads_unit_tests.cmake)
-endif ()
+SET(GOOGLETEST_INCLUDED 1)
+
+include(GoogleTest)
+enable_testing()
+
+add_subdirectory(wasm-vm)
+add_subdirectory(interpreter)
+add_subdirectory(aot)
+add_subdirectory(wasm-c-api)
+add_subdirectory(libc-builtin)
+add_subdirectory(shared-utils)
+add_subdirectory(running-modes)
+add_subdirectory(runtime-common)
+add_subdirectory(custom-section)
+add_subdirectory(compilation)
+add_subdirectory(linear-memory-wasm)
+add_subdirectory(linear-memory-aot)
+add_subdirectory(aot-stack-frame)
+add_subdirectory(linux-perf)
+add_subdirectory(gc)
+add_subdirectory(memory64)
+add_subdirectory(tid-allocator)

+ 55 - 0
tests/unit/aot-stack-frame/CMakeLists.txt

@@ -0,0 +1,55 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-aot-stack-frame)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_AOT 1)
+set (WAMR_BUILD_INTERP 0)
+set (WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_SIMD 1)
+set (WAMR_BUILD_REF_TYPES 1)
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_LIBC_BUILTIN 0)
+set (WAMR_BUILD_MULTI_MODULE 0)
+set (WAMR_DISABLE_HW_BOUND_CHECK 1)
+set (WAMR_DISABLE_WRITE_GS_BASE 1)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+add_definitions (-DAOT_STACK_FRAME_DEBUG)
+#add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Automatically build wasm-apps for this test
+add_subdirectory(wasm-apps)
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (aot_stack_frame_test ${unit_test_sources})
+
+add_dependencies (aot_stack_frame_test aot-stack-frame-test-wasm)
+
+target_link_libraries (aot_stack_frame_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+#gtest_discover_tests(aot_stack_frame_test)

+ 288 - 0
tests/unit/aot-stack-frame/aot_stack_frame_test.cc

@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "wasm_runtime_common.h"
+#include "aot_runtime.h"
+#include "test_helper.h"
+
+#ifndef __aligned
+#define __aligned(n)
+#endif
+#include "wasm-apps/test_aot.h"
+
+typedef struct MyAOTFrame {
+    uintptr_t func_index;
+
+    /* Instruction pointer: offset to the bytecode array */
+    uintptr_t ip_offset;
+
+    /* Operand stack top pointer of the current frame */
+    uint32 *sp;
+
+#if WASM_ENABLE_GC != 0
+    /* Frame ref flags (GC only) */
+    uint8 *frame_ref;
+#endif
+
+    uint32 lp[1];
+} MyAOTFrame;
+
+class AOTStackFrameTest : public testing::Test
+{
+  protected:
+    virtual void SetUp()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+    }
+
+    virtual void TearDown()
+    {
+        DestroyFrames();
+        wasm_runtime_destroy();
+    }
+
+  public:
+    static void DestroyFrames()
+    {
+        if (my_frames) {
+            for (uint32 i = 0; i < my_frame_num; i++) {
+                if (my_frames[i])
+                    wasm_runtime_free(my_frames[i]);
+            }
+            wasm_runtime_free(my_frames);
+            my_frames = NULL;
+            my_frame_num = 0;
+        }
+    }
+
+  public:
+    RuntimeInitArgs init_args;
+    wasm_module_t module = NULL;
+    wasm_module_inst_t module_inst = NULL;
+    wasm_function_inst_t func_inst = NULL;
+    wasm_exec_env_t exec_env = NULL;
+    static MyAOTFrame **my_frames;
+    static uint32 my_frame_num;
+    char error_buf[128];
+    char global_heap_buf[512 * 1024];
+    unsigned char test_aot_buf[16 * 1024];
+    unsigned argv[8];
+};
+
+MyAOTFrame **AOTStackFrameTest::my_frames = NULL;
+uint32 AOTStackFrameTest::my_frame_num = 0;
+
+extern "C" {
+
+typedef void (*stack_frame_callback_t)(struct WASMExecEnv *exec_env);
+
+void
+aot_set_stack_frame_callback(stack_frame_callback_t callback);
+
+void
+aot_stack_frame_cb(struct WASMExecEnv *exec_env)
+{
+    AOTModuleInstance *module_inst = (AOTModuleInstance *)exec_env->module_inst;
+    AOTModule *module = (AOTModule *)module_inst->module;
+    AOTFrame *frame = (AOTFrame *)exec_env->cur_frame;
+    MyAOTFrame *my_frame, **my_frames;
+    uint32 all_cell_num, max_local_cell_num, max_stack_cell_num;
+    uint32 frame_size_old, frame_size, i, frame_num = 0, aot_func_idx;
+
+    AOTStackFrameTest::DestroyFrames();
+
+    while (frame) {
+        frame_num++;
+        frame = frame->prev_frame;
+    }
+
+    my_frames =
+        (MyAOTFrame **)wasm_runtime_malloc(sizeof(MyAOTFrame *) * frame_num);
+    bh_assert(my_frames);
+
+    frame = (AOTFrame *)exec_env->cur_frame;
+    for (i = 0; i < frame_num; i++) {
+        aot_func_idx = frame->func_index;
+        max_local_cell_num = module->max_local_cell_nums[aot_func_idx];
+        max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx];
+        all_cell_num = max_local_cell_num + max_stack_cell_num;
+
+        frame_size_old = (uint32)offsetof(AOTFrame, lp) + all_cell_num * 4;
+        frame_size = (uint32)offsetof(MyAOTFrame, lp) + all_cell_num * 4;
+
+        my_frames[frame_num - 1 - i] = my_frame =
+            (MyAOTFrame *)wasm_runtime_malloc(frame_size);
+
+        my_frame->func_index = aot_func_idx;
+        my_frame->ip_offset = frame->ip_offset;
+        my_frame->sp = my_frame->lp + (frame->sp - frame->lp);
+#if WASM_ENABLE_GC != 0
+        my_frame->frame_ref =
+            (uint8 *)my_frame->lp + (frame->frame_ref - (uint8 *)frame->lp);
+#endif
+
+        bh_memcpy_s(my_frame->lp, all_cell_num * 4, frame->lp,
+                    all_cell_num * 4);
+
+        frame = frame->prev_frame;
+    }
+
+    AOTStackFrameTest::my_frames = my_frames;
+    AOTStackFrameTest::my_frame_num = frame_num;
+}
+}
+
+TEST_F(AOTStackFrameTest, test1)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test1");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 33;
+    argv[1] = 44;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 1);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 33);
+    ASSERT_TRUE(frames[0]->lp[1] == 44);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322);
+
+    wasm_runtime_destroy_exec_env(exec_env);
+    exec_env = NULL;
+
+    wasm_runtime_deinstantiate(module_inst);
+    module_inst = NULL;
+
+    wasm_runtime_unload(module);
+    module = NULL;
+}
+
+TEST_F(AOTStackFrameTest, test2)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test2");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 1234;
+    argv[1] = 5678;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 1);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 1234);
+    ASSERT_TRUE(frames[0]->lp[1] == 5678);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[0]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[0]->lp + 6) == 99887766.55443322);
+    ASSERT_TRUE(frames[0]->lp[8] == 0x1234);
+    ASSERT_TRUE(frames[0]->lp[9] == 0x5678);
+}
+
+TEST_F(AOTStackFrameTest, test3)
+{
+    MyAOTFrame *frame, **frames;
+    uint32 frame_num;
+
+    aot_set_stack_frame_callback(aot_stack_frame_cb);
+
+    bh_memcpy_s(test_aot_buf, sizeof(test_aot_buf), test_aot, sizeof(test_aot));
+
+    module = wasm_runtime_load(test_aot_buf, sizeof(test_aot), error_buf,
+                               sizeof(error_buf));
+    ASSERT_TRUE(module != NULL);
+
+    module_inst = wasm_runtime_instantiate(module, 16384, 0, error_buf,
+                                           sizeof(error_buf));
+    ASSERT_TRUE(module_inst != NULL);
+
+    exec_env = wasm_runtime_create_exec_env(module_inst, 8 * 1024);
+    ASSERT_TRUE(exec_env != NULL);
+
+    func_inst = wasm_runtime_lookup_function(module_inst, "test3");
+    ASSERT_TRUE(func_inst != NULL);
+
+    argv[0] = 1234;
+    argv[1] = 5678;
+    wasm_runtime_call_wasm(exec_env, func_inst, 2, argv);
+    ASSERT_TRUE(wasm_runtime_get_exception(module_inst));
+
+    frames = AOTStackFrameTest::my_frames;
+    frame_num = AOTStackFrameTest::my_frame_num;
+
+    ASSERT_TRUE(frames != NULL);
+    ASSERT_TRUE(frame_num == 2);
+
+    ASSERT_TRUE(frames[0]->sp - frames[0]->lp == 5);
+    ASSERT_TRUE(frames[0]->ip_offset == 24);
+
+    ASSERT_TRUE(frames[0]->lp[0] == 1234);
+    ASSERT_TRUE(frames[0]->lp[1] == 5678);
+    ASSERT_TRUE(frames[0]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[0]->lp + 3) == 0x12345678ABCDEF99LL);
+
+    ASSERT_TRUE(frames[1]->lp[0] == 0x1234);
+    ASSERT_TRUE(frames[1]->lp[1] == 0x5678);
+    ASSERT_TRUE(frames[1]->lp[2] == 0x11223344);
+    ASSERT_TRUE(*(uint64 *)(frames[1]->lp + 3) == 0x12345678ABCDEF99LL);
+    ASSERT_TRUE(*(float *)(frames[1]->lp + 5) == 5566.7788f);
+    ASSERT_TRUE(*(double *)(frames[1]->lp + 6) == 99887766.55443322);
+}

+ 27 - 0
tests/unit/aot-stack-frame/wasm-apps/CMakeLists.txt

@@ -0,0 +1,27 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project(wasm-apps-aot-stack-frame)
+
+add_custom_target(aot-stack-frame-test-wasm ALL
+    COMMAND cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc
+                  -S ${WAMR_ROOT_DIR}/wamr-compiler
+            && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc
+            && /opt/wabt/bin/wat2wasm
+                  -o ${CMAKE_CURRENT_BINARY_DIR}/test.wasm
+                  ${CMAKE_CURRENT_LIST_DIR}/test.wast
+            && ${CMAKE_CURRENT_BINARY_DIR}/build-wamrc/wamrc
+                  --enable-dump-call-stack --bounds-checks=1
+                  -o ${CMAKE_CURRENT_BINARY_DIR}/test.aot
+                  ${CMAKE_CURRENT_BINARY_DIR}/test.wasm
+            && cmake -B ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump
+                  -S ${WAMR_ROOT_DIR}/test-tools/binarydump-tool
+            && cmake --build ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump
+            && ${CMAKE_CURRENT_BINARY_DIR}/build-binarydump/binarydump
+                  -o ${CMAKE_CURRENT_LIST_DIR}/test_aot.h -n test_aot
+                  ${CMAKE_CURRENT_BINARY_DIR}/test.aot
+
+)
+

+ 36 - 0
tests/unit/aot-stack-frame/wasm-apps/test.wast

@@ -0,0 +1,36 @@
+(module
+  (func $test1 (export "test1") (param i32 i32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+    f32.const 5566.7788
+    f64.const 99887766.55443322
+    unreachable
+  )
+
+  (func $test2 (export "test2") (param f32 f32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+    f32.const 5566.7788
+    f64.const 99887766.55443322
+
+    loop
+      i32.const 0x1234
+      i32.const 0x5678
+      unreachable
+    end
+
+    unreachable
+  )
+
+  (func $test3 (export "test3") (param i32 i32) (result i32)
+    i32.const 0x11223344
+    i64.const 0x1234_5678_ABCD_EF99
+
+    i32.const 0x1234
+    i32.const 0x5678
+    call $test1
+
+    drop
+    drop
+  )
+)

+ 59 - 0
tests/unit/aot/CMakeLists.txt

@@ -0,0 +1,59 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-aot)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${LIBC_BUILTIN_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+    )
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (aot_test ${unit_test_sources})
+
+target_link_libraries (aot_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+gtest_discover_tests(aot_test)
+

+ 1190 - 0
tests/unit/aot/aot_test.cc

@@ -0,0 +1,1190 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <limits.h>
+#include "gtest/gtest.h"
+#include "wasm_export.h"
+#include "bh_platform.h"
+#include "aot_llvm.h"
+#include "aot_intrinsic.h"
+#include "aot.h"
+
+#define G_INTRINSIC_COUNT (50u)
+#define CONS(num) ("f##num##.const")
+
+const char *llvm_intrinsic_tmp[G_INTRINSIC_COUNT] = {
+    "llvm.experimental.constrained.fadd.f32",
+    "llvm.experimental.constrained.fadd.f64",
+    "llvm.experimental.constrained.fsub.f32",
+    "llvm.experimental.constrained.fsub.f64",
+    "llvm.experimental.constrained.fmul.f32",
+    "llvm.experimental.constrained.fmul.f64",
+    "llvm.experimental.constrained.fdiv.f32",
+    "llvm.experimental.constrained.fdiv.f64",
+    "llvm.fabs.f32",
+    "llvm.fabs.f64",
+    "llvm.ceil.f32",
+    "llvm.ceil.f64",
+    "llvm.floor.f32",
+    "llvm.floor.f64",
+    "llvm.trunc.f32",
+    "llvm.trunc.f64",
+    "llvm.rint.f32",
+    "llvm.rint.f64",
+    "llvm.sqrt.f32",
+    "llvm.sqrt.f64",
+    "llvm.copysign.f32",
+    "llvm.copysign.f64",
+    "llvm.minnum.f32",
+    "llvm.minnum.f64",
+    "llvm.maxnum.f32",
+    "llvm.maxnum.f64",
+    "llvm.ctlz.i32",
+    "llvm.ctlz.i64",
+    "llvm.cttz.i32",
+    "llvm.cttz.i64",
+    "llvm.ctpop.i32",
+    "llvm.ctpop.i64",
+    "f64_convert_i32_s",
+    "f64_convert_i32_u",
+    "f32_convert_i32_s",
+    "f32_convert_i32_u",
+    "f64_convert_i64_s",
+    "f64_convert_i64_u",
+    "f32_convert_i64_s",
+    "f32_convert_i64_u",
+    "i32_trunc_f32_u",
+    "i32_trunc_f32_s",
+    "i32_trunc_f64_u",
+    "i32_trunc_f64_s",
+    "f32_demote_f64",
+    "f64_promote_f32",
+    "f32_cmp",
+    "f64_cmp",
+    "f32.const",
+    "f64.const",
+};
+
+uint64 g_intrinsic_flag[G_INTRINSIC_COUNT] = {
+    AOT_INTRINSIC_FLAG_F32_FADD,     AOT_INTRINSIC_FLAG_F64_FADD,
+    AOT_INTRINSIC_FLAG_F32_FSUB,     AOT_INTRINSIC_FLAG_F64_FSUB,
+    AOT_INTRINSIC_FLAG_F32_FMUL,     AOT_INTRINSIC_FLAG_F64_FMUL,
+    AOT_INTRINSIC_FLAG_F32_FDIV,     AOT_INTRINSIC_FLAG_F64_FDIV,
+    AOT_INTRINSIC_FLAG_F32_FABS,     AOT_INTRINSIC_FLAG_F64_FABS,
+    AOT_INTRINSIC_FLAG_F32_CEIL,     AOT_INTRINSIC_FLAG_F64_CEIL,
+    AOT_INTRINSIC_FLAG_F32_FLOOR,    AOT_INTRINSIC_FLAG_F64_FLOOR,
+    AOT_INTRINSIC_FLAG_F32_TRUNC,    AOT_INTRINSIC_FLAG_F64_TRUNC,
+    AOT_INTRINSIC_FLAG_F32_RINT,     AOT_INTRINSIC_FLAG_F64_RINT,
+    AOT_INTRINSIC_FLAG_F32_SQRT,     AOT_INTRINSIC_FLAG_F64_SQRT,
+    AOT_INTRINSIC_FLAG_F32_COPYSIGN, AOT_INTRINSIC_FLAG_F64_COPYSIGN,
+    AOT_INTRINSIC_FLAG_F32_MIN,      AOT_INTRINSIC_FLAG_F64_MIN,
+    AOT_INTRINSIC_FLAG_F32_MAX,      AOT_INTRINSIC_FLAG_F64_MAX,
+    AOT_INTRINSIC_FLAG_I32_CLZ,      AOT_INTRINSIC_FLAG_I64_CLZ,
+    AOT_INTRINSIC_FLAG_I32_CTZ,      AOT_INTRINSIC_FLAG_I64_CTZ,
+    AOT_INTRINSIC_FLAG_I32_POPCNT,   AOT_INTRINSIC_FLAG_I64_POPCNT,
+    AOT_INTRINSIC_FLAG_I32_TO_F64,   AOT_INTRINSIC_FLAG_U32_TO_F64,
+    AOT_INTRINSIC_FLAG_I32_TO_F32,   AOT_INTRINSIC_FLAG_U32_TO_F32,
+    AOT_INTRINSIC_FLAG_I32_TO_F64,   AOT_INTRINSIC_FLAG_U64_TO_F64,
+    AOT_INTRINSIC_FLAG_I64_TO_F32,   AOT_INTRINSIC_FLAG_U64_TO_F32,
+    AOT_INTRINSIC_FLAG_F32_TO_U32,   AOT_INTRINSIC_FLAG_F32_TO_I32,
+    AOT_INTRINSIC_FLAG_F64_TO_U32,   AOT_INTRINSIC_FLAG_F64_TO_I32,
+    AOT_INTRINSIC_FLAG_F64_TO_F32,   AOT_INTRINSIC_FLAG_F32_TO_F64,
+    AOT_INTRINSIC_FLAG_F32_CMP,      AOT_INTRINSIC_FLAG_F64_CMP,
+    AOT_INTRINSIC_FLAG_F32_CONST,    AOT_INTRINSIC_FLAG_F64_CONST,
+};
+
+// To use a test fixture, derive a class from testing::Test.
+class AOTTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() { wasm_runtime_destroy(); }
+
+  public:
+    char global_heap_buf[512 * 1024];
+    RuntimeInitArgs init_args;
+};
+
+TEST_F(AOTTest, aot_value_stack_push_pop)
+{
+    AOTValueStack *stack;
+    AOTValue *value1, *value2, *value3;
+    AOTCompContext comp_ctx = { 0 };
+
+    stack = (AOTValueStack *)wasm_runtime_malloc(sizeof(AOTValueStack));
+    EXPECT_TRUE(stack != NULL);
+
+    memset(stack, 0, sizeof(AOTValueStack));
+
+    value1 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue));
+    EXPECT_TRUE(value1 != NULL);
+
+    memset(value1, 0, sizeof(AOTValue));
+    value1->type = VALUE_TYPE_I32;
+
+    aot_value_stack_push(&comp_ctx, stack, value1);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value1);
+
+    value2 = (AOTValue *)wasm_runtime_malloc(sizeof(AOTValue));
+    EXPECT_TRUE(value2 != NULL);
+
+    memset(value2, 0, sizeof(AOTValue));
+    value2->type = VALUE_TYPE_I64;
+
+    aot_value_stack_push(&comp_ctx, stack, value2);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value2);
+    EXPECT_EQ(value2->prev, value1);
+
+    value3 = aot_value_stack_pop(&comp_ctx, stack);
+    EXPECT_EQ(value3, value2);
+    EXPECT_EQ(stack->value_list_head, value1);
+    EXPECT_EQ(stack->value_list_end, value1);
+    EXPECT_TRUE(value3->prev == NULL);
+
+    aot_value_stack_destroy(&comp_ctx, stack);
+    wasm_runtime_free(value3);
+    wasm_runtime_free(stack);
+}
+
+TEST_F(AOTTest, aot_block_stack_push_pop)
+{
+    AOTBlockStack *stack;
+    AOTBlock *block1, *block2, *block3;
+    AOTCompContext comp_ctx = { 0 };
+
+    stack = (AOTBlockStack *)wasm_runtime_malloc(sizeof(AOTBlockStack));
+    EXPECT_TRUE(stack != NULL);
+
+    memset(stack, 0, sizeof(AOTBlockStack));
+
+    block1 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock));
+    EXPECT_TRUE(block1 != NULL);
+
+    memset(block1, 0, sizeof(AOTBlock));
+    block1->label_type = LABEL_TYPE_LOOP;
+
+    aot_block_stack_push(stack, block1);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block1);
+
+    block2 = (AOTBlock *)wasm_runtime_malloc(sizeof(AOTBlock));
+    EXPECT_TRUE(block2 != NULL);
+
+    memset(block2, 0, sizeof(AOTBlock));
+    block2->label_type = LABEL_TYPE_IF;
+
+    aot_block_stack_push(stack, block2);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block2);
+    EXPECT_EQ(block2->prev, block1);
+
+    block3 = aot_block_stack_pop(stack);
+    EXPECT_EQ(block3, block2);
+    EXPECT_EQ(stack->block_list_head, block1);
+    EXPECT_EQ(stack->block_list_end, block1);
+    EXPECT_TRUE(block3->prev == NULL);
+
+    aot_block_stack_destroy(&comp_ctx, stack);
+    wasm_runtime_free(block3);
+    wasm_runtime_free(stack);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fadd_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f32(a, b), (a + b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fadd_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fadd_f64(a, b), (a + b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fsub_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f32(a, b), (a - b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fsub_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fsub_f64(a, b), (a - b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmul_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f32(a, b), (a * b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmul_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fmul_f64(a, b), (a * b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fdiv_f32)
+{
+    float32 a = 1.0;
+    float32 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+
+    a = -1.0;
+    b = 0.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f32(a, b), (a / b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fdiv_f64)
+{
+    float64 a = 1.0;
+    float64 b = 1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+
+    a = -1.0;
+    b = -1.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+
+    a = -1.0;
+    b = 0.0;
+    EXPECT_EQ(aot_intrinsic_fdiv_f64(a, b), (a / b));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fabs_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+
+    a = -1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+
+    a = -1.5;
+    EXPECT_EQ(aot_intrinsic_fabs_f32(a), fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fabs_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+
+    a = -1.0;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+
+    a = -1.5;
+    EXPECT_EQ(aot_intrinsic_fabs_f64(a), fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_ceil_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), ceilf(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f32(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_ceil_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), ceil(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_ceil_f64(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_floor_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), floorf(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f32(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_floor_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), floor(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_floor_f64(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_trunc_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), trunc(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f32(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_trunc_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), trunc(a));
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), 1);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_trunc_f64(a), -1);
+}
+
+TEST_F(AOTTest, aot_intrinsic_rint_f32)
+{
+    float32 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), rint(a));
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 1);
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f32(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_rint_f64)
+{
+    float64 a = 1.0;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), rint(a));
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 1);
+
+    a = 1.1;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 1);
+
+    a = 1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), 2);
+
+    a = -1.9;
+    EXPECT_EQ(aot_intrinsic_rint_f64(a), -2);
+}
+
+TEST_F(AOTTest, aot_intrinsic_sqrt_f32)
+{
+    float32 a = 2.0;
+    EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a));
+
+    a = 2;
+    EXPECT_EQ(aot_intrinsic_sqrt_f32(a), sqrt(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_sqrt_f64)
+{
+    float64 a = 2.0;
+    EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a));
+
+    a = 2;
+    EXPECT_EQ(aot_intrinsic_sqrt_f64(a), sqrt(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_copysign_f32)
+{
+    float32 a = 20.0;
+    float32 b = 2.0;
+
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a));
+
+    b = 1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), fabs(a));
+
+    b = -2.0;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a));
+
+    a = -20.0;
+    b = -1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f32(a, b), -fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_copysign_f64)
+{
+    float64 a = 20.0;
+    float64 b = 2.0;
+
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a));
+
+    b = 1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), fabs(a));
+
+    b = -2.0;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a));
+
+    a = -20.0;
+    b = -1.5;
+    EXPECT_EQ(aot_intrinsic_copysign_f64(a, b), -fabs(a));
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmin_f32)
+{
+    float32 a = 1.2;
+    float32 b = 2.5;
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a);
+
+    a = -3;
+    b = -1;
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, b), a);
+
+    b = 1;
+    EXPECT_EQ(aot_intrinsic_fmin_f32('a', b), b);
+
+    a = 3;
+    EXPECT_EQ(aot_intrinsic_fmin_f32(a, 'b'), a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32('a', 'b'), 'a');
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32('b', 'c'), 'b');
+    EXPECT_EQ(aot_intrinsic_fmin_f32('c', 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmin_f32(true, 2.5), 1);
+    EXPECT_EQ(aot_intrinsic_fmin_f32(1.0, false), 0);
+
+    EXPECT_NE(aot_intrinsic_fmin_f32(sqrt(-1), 3), 3);
+    EXPECT_NE(aot_intrinsic_fmin_f32(3, sqrt(-1)), 3);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmin_f64)
+{
+    float64 a = 1.00000000;
+    float64 b = 3.00000000;
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, b), a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, b), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -b), -b);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, -b), -b);
+
+    EXPECT_EQ(aot_intrinsic_fmin_f64(a, a), a);
+
+    a = 0.0000;
+    EXPECT_EQ(aot_intrinsic_fmin_f64(-a, -a), -a);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmax_f32)
+{
+    float32 a = 1.2;
+    float32 b = 2.5;
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b);
+
+    a = -3;
+    b = -1;
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, b), b);
+
+    b = 1;
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', b), 'a');
+
+    a = 3;
+    EXPECT_EQ(aot_intrinsic_fmax_f32(a, 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', 'b'), 'b');
+
+    EXPECT_EQ(aot_intrinsic_fmax_f32(' ', 'b'), 'b');
+    EXPECT_EQ(aot_intrinsic_fmax_f32('a', ' '), 'a');
+
+    EXPECT_NE(aot_intrinsic_fmax_f32(sqrt(-1), 3), 3);
+    EXPECT_NE(aot_intrinsic_fmax_f32(3, sqrt(-1)), 3);
+}
+
+TEST_F(AOTTest, aot_intrinsic_fmax_f64)
+{
+    float64 a = 1.00000000;
+    float64 b = 3.00000000;
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, b), b);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, b), b);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -b), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, -b), a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(a, a), a);
+
+    a = 0.0000;
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-a, -a), -a);
+
+    EXPECT_EQ(aot_intrinsic_fmax_f64(-0, -0), -0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_clz_i32)
+{
+    uint32 type = 0;
+    uint32 data = 0;
+    uint32 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_clz_i32(0), 32);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        /* Generate random numbers [1,0xFFFFFFFF] */
+        type = 1 + (rand() % (0xFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 0x80000000)) {
+            num++;
+            type <<= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_clz_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_clz_i32(0xFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_clz_i64)
+{
+    uint64 type = 0;
+    uint64 data = 0;
+    uint64 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_clz_i64(0), 64);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        /* Generate random numbers [1,0xFFFFFFFFFFFFFFFF] */
+        type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 0x8000000000000000LL)) {
+            num++;
+            type <<= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_clz_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_clz_i64(0xFFFFFFFFFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, ast_intrinsic_ctz_i32)
+{
+    uint32 type = 0;
+    uint32 data = 0;
+    uint32 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_ctz_i32(0), 32);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        type = 1 + (rand() % (0xFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 1)) {
+            num++;
+            type >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_ctz_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_ctz_i32(0xFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, ast_intrinsic_ctz_i64)
+{
+    uint64 type = 0;
+    uint64 data = 0;
+    uint64 num = 0;
+
+    EXPECT_EQ(aot_intrinsic_ctz_i64(0), 64);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        type = 1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1));
+        data = type;
+        while (!(type & 1)) {
+            num++;
+            type >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_ctz_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_ctz_i64(0xFFFFFFFFFFFFFFFF), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_popcnt_i32)
+{
+    uint32 data = 0;
+    uint32 num = 0;
+    uint32 temp = 0;
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i32(0), 0);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        temp = 1 + (rand() % (0x100000000 - 1 + 1));
+        data = temp;
+
+        while (temp) {
+            if (temp & 0x01)
+                num++;
+            temp >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_popcnt_i32(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i32(0xFFFFFFFF), 32);
+}
+
+TEST_F(AOTTest, aot_intrinsic_popcnt_i64)
+{
+    uint64 data = 0;
+    uint64 num = 0;
+    uint64 temp = 0;
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i64(0x00), 0);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        temp = 1 + (rand() % (0xFFFFFFFFFFFFFFFFLL - 1 + 1));
+        data = temp;
+
+        while (temp) {
+            if (temp & 0x01)
+                num++;
+            temp >>= 1;
+        }
+        EXPECT_EQ(aot_intrinsic_popcnt_i64(data), num);
+        num = 0;
+    }
+
+    EXPECT_EQ(aot_intrinsic_popcnt_i64(0xFFFFFFFFFFFFFFFF), 64);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i32_to_f32)
+{
+    int32 idata = 0;
+
+    EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+    }
+
+    idata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_i32_to_f32(idata), (float32)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u32_to_f32)
+{
+    uint32 udata = 0;
+
+    EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+    }
+
+    udata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_u32_to_f32(udata), (float32)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i32_to_f64)
+{
+    int32 idata = 0;
+
+    EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        idata = (int32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+    }
+
+    idata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_i32_to_f64(idata), (float64)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u32_to_f64)
+{
+    uint32 udata = 0;
+
+    EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        udata = (uint32)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+    }
+
+    udata = 0xFFFFFFFF;
+    EXPECT_EQ(aot_intrinsic_u32_to_f64(udata), (float64)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i64_to_f32)
+{
+    int64 idata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        idata = (int64)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+    }
+
+    idata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_i64_to_f32(idata), (float32)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u64_to_f32)
+{
+    uint64 udata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+
+    for (uint32 i = 0; i < 0xFFFFF; i++) {
+        udata = (uint64)(1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+    }
+
+    udata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_u64_to_f32(udata), (float32)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_i64_to_f64)
+{
+    int64 idata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), float64(idata));
+
+    for (uint32_t i = 0; i < 0xFFFFF; i++) {
+        idata = (int64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata);
+    }
+
+    idata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_i64_to_f64(idata), (float64)idata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_u64_to_f64)
+{
+    uint64 udata = 0LL;
+
+    EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), float64(udata));
+
+    for (uint32_t i = 0; i < 0xFFFFF; i++) {
+        udata = (uint64)(1 + (rand() % (0xFFFFFFFFFFFFFFFLL - 1 + 1)));
+        EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata);
+    }
+
+    udata = 0xFFFFFFFFFFFFFFFFLL;
+    EXPECT_EQ(aot_intrinsic_u64_to_f64(udata), (float64)udata);
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_i32)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (100 - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_i32(data), (int32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_u32)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_u32(data), (uint32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_i64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_i64(data), (int64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_u64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_u64(data), (uint64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_i32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_i32(data), (int32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_u32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_u32(data), (uint32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_i64)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_i64(data), (int64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_u64)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f64_to_u64(data), (uint64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_to_f64)
+{
+    float32 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data);
+
+    for (uint32 i = 0; i < 0xFFFF; i++) {
+        data = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float64)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_to_f32)
+{
+    float64 data = 0.0;
+
+    EXPECT_EQ(aot_intrinsic_f64_to_f32(data), (float32)data);
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        data = (float64)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.06);
+        EXPECT_EQ(aot_intrinsic_f32_to_f64(data), (float32)data);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_f32_cmp)
+{
+    float32 lhs = 0.0;
+    float32 rhs = 0.0;
+    AOTFloatCond index = FLOAT_EQ;
+    uint32 res = 0;
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1)));
+        lhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+        rhs = (float32)((1 + (rand() % (0xFFFFFFFF - 1 + 1))) - 0.05);
+
+        /* cond : 0 */
+        EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_EQ, lhs, rhs),
+                  lhs == rhs ? 1 : 0);
+
+        /* cond : 1-6 */
+        switch (index) {
+            case FLOAT_LT: // 2
+                res = (lhs < rhs ? 1 : 0);
+                break;
+            case FLOAT_GT: // 3
+                res = (lhs > rhs ? 1 : 0);
+                break;
+            case FLOAT_LE: // 4
+                res = (lhs <= rhs ? 1 : 0);
+                break;
+            case FLOAT_GE: // 5
+                res = (lhs >= rhs ? 1 : 0);
+                break;
+            case FLOAT_NE: // 1
+                res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+                break;
+            case FLOAT_UNO: // 6
+                res = (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+                break;
+
+            default:
+                break;
+        }
+
+        EXPECT_EQ(aot_intrinsic_f32_cmp(index, lhs, rhs), res);
+        index = FLOAT_EQ;
+
+        /* cond : > 6 */
+        EXPECT_EQ(aot_intrinsic_f32_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0);
+    }
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, false), 1);
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_NE, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, false), 0);
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f32_cmp(FLOAT_UNO, 'a', 'b'), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_f64_cmp)
+{
+    float64 lhs = 0.0;
+    float64 rhs = 0.0;
+    AOTFloatCond index = FLOAT_EQ;
+    uint32 res = 0;
+
+    for (uint32 i = 0; i < 0xFFFFFF; i++) {
+        index = (AOTFloatCond)(1 + (rand() % (6 - 1 + 1)));
+        lhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05);
+        rhs = (float32)((1 + (rand() % (0xFFFFFFFFFFFFFFFF - 1 + 1))) - 0.05);
+
+        /* cond : 0 */
+        EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_EQ, lhs, rhs),
+                  lhs == rhs ? 1 : 0);
+
+        /* cond : 1-6 */
+        switch (index) {
+            case FLOAT_LT: // 2
+                res = (lhs < rhs ? 1 : 0);
+                break;
+            case FLOAT_GT: // 3
+                res = (lhs > rhs ? 1 : 0);
+                break;
+            case FLOAT_LE: // 4
+                res = (lhs <= rhs ? 1 : 0);
+                break;
+            case FLOAT_GE: // 5
+                res = (lhs >= rhs ? 1 : 0);
+                break;
+            case FLOAT_NE: // 1
+                res = (isnan(lhs) || isnan(rhs) || lhs != rhs) ? 1 : 0;
+                break;
+            case FLOAT_UNO: // 6
+                res = (isnan(lhs) || isnan(rhs)) ? 1 : 0;
+                break;
+
+            default:
+                break;
+        }
+
+        EXPECT_EQ(aot_intrinsic_f64_cmp(index, lhs, rhs), res);
+        index = FLOAT_EQ;
+
+        /* cond : > 6 */
+        EXPECT_EQ(aot_intrinsic_f64_cmp((AOTFloatCond)(i + 7), lhs, rhs), 0);
+    }
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, false), 1);
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_NE, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, false), 0);
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, true, true), 0);
+
+    EXPECT_EQ(aot_intrinsic_f64_cmp(FLOAT_UNO, 'a', 'b'), 0);
+}
+
+TEST_F(AOTTest, aot_intrinsic_get_symbol)
+{
+    const char *llvm_intrinsic_t = NULL;
+
+    for (int i = 0; i < 2; i++) {
+        if (i == 0)
+            llvm_intrinsic_t = CONS(32);
+        else
+            llvm_intrinsic_t = CONS(64);
+
+        EXPECT_EQ((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_t),
+                  (const char *)NULL);
+    }
+
+    for (int i = 0; i < G_INTRINSIC_COUNT - 2; i++) {
+        EXPECT_NE((const char *)aot_intrinsic_get_symbol(llvm_intrinsic_tmp[i]),
+                  (const char *)NULL);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_check_capability)
+{
+    AOTCompContext *comp_ctx = NULL;
+    AOTCompContext scomp_ctx = { 0 };
+    const char *llvm_intrinsic_t = "f64_cmp";
+    bool res = false;
+    uint64 flag = 0;
+    uint64 group = 0;
+
+    comp_ctx = &scomp_ctx;
+    memset(comp_ctx->flags, 0, sizeof(comp_ctx->flags));
+
+    /*
+        EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, (const char
+       *)NULL)); EXPECT_FALSE(aot_intrinsic_check_capability((const
+       AOTCompContext *)NULL, llvm_intrinsic_t));
+    */
+
+    EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t));
+    for (int i = 0; i < G_INTRINSIC_COUNT; i++) {
+        EXPECT_FALSE(
+            aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]));
+    }
+
+    memset(comp_ctx->flags, 1, sizeof(comp_ctx->flags));
+    EXPECT_FALSE(aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_t));
+    for (int i = 0; i < G_INTRINSIC_COUNT; i++) {
+        flag = g_intrinsic_flag[i];
+        group = AOT_INTRINSIC_GET_GROUP_FROM_FLAG(flag);
+        flag &= AOT_INTRINSIC_FLAG_MASK;
+
+        res = aot_intrinsic_check_capability(comp_ctx, llvm_intrinsic_tmp[i]);
+        if ((flag & 0x01) || (flag & 0x100) || (flag & 0x10000)
+            || (flag & 0x1000000))
+            EXPECT_TRUE(res);
+        else
+            EXPECT_FALSE(res);
+    }
+}
+
+TEST_F(AOTTest, aot_intrinsic_fill_capability_flags)
+{
+    // AOTCompContext *comp_ctx = NULL;
+    AOTCompContext scomp_ctx = { 0 };
+
+    // comp_ctx = &scomp_ctx;
+    aot_intrinsic_fill_capability_flags(&scomp_ctx);
+
+    AOTCompContext scomp_ctx_1{
+        .target_cpu = (char *)"cortex-m7",
+    };
+    strncpy(scomp_ctx_1.target_arch, "thumb", strlen("thumb"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_1);
+
+    AOTCompContext scomp_ctx_2{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_2.target_arch, "thumb", strlen("thumb"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_2);
+
+    AOTCompContext scomp_ctx_3{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_3.target_arch, "riscv", strlen("riscv"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_3);
+
+    AOTCompContext scomp_ctx_4{
+        .target_cpu = (char *)"cortex-m4",
+    };
+    strncpy(scomp_ctx_4.target_arch, "intrinsic", strlen("intrinsic"));
+    aot_intrinsic_fill_capability_flags(&scomp_ctx_4);
+}

+ 89 - 0
tests/unit/common/mock_allocator.h

@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#pragma once
+
+#include "wasm_export.h"
+#include <functional>
+
+template<int MaxAllocCount>
+class MockAllocator
+{
+  private:
+    RuntimeInitArgs init_args;
+
+  public:
+    MockAllocator()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Allocator;
+        init_args.mem_alloc_option.allocator.malloc_func = (void *)my_malloc;
+        init_args.mem_alloc_option.allocator.realloc_func = (void *)realloc;
+        init_args.mem_alloc_option.allocator.free_func = (void *)free;
+
+        /* Set count to INT32_MIN so the initialization will not fail */
+        alloc_count = INT32_MIN;
+
+        wasm_runtime_full_init(&init_args);
+        reset_count();
+    }
+
+    ~MockAllocator() { wasm_runtime_destroy(); }
+
+    void reset_count() { alloc_count = 0; }
+
+  protected:
+    static int32_t alloc_count;
+    static void *my_malloc(int32_t size)
+    {
+        if (alloc_count >= MaxAllocCount) {
+            return nullptr;
+        }
+
+        alloc_count++;
+
+        return malloc(size);
+    }
+};
+
+template<int MaxAllocCount>
+int32_t MockAllocator<MaxAllocCount>::alloc_count = 0;
+
+class DumpAllocUsage : public MockAllocator<INT32_MAX>
+{
+  public:
+    DumpAllocUsage()
+      : MockAllocator<INT32_MAX>()
+    {}
+
+    ~DumpAllocUsage()
+    {
+        std::cout << "Alloc usage count: " << alloc_count << std::endl;
+    }
+};
+
+template<int AllocRequired>
+void
+LIMIT_MALLOC_COUNT(std::function<void()> func)
+{
+    {
+        MockAllocator<AllocRequired> allocator;
+        func();
+    }
+
+    if (AllocRequired > 1)
+        LIMIT_MALLOC_COUNT<AllocRequired - 1>(func);
+}
+
+template<>
+void
+LIMIT_MALLOC_COUNT<0>(std::function<void()> func)
+{
+    {
+        MockAllocator<0> allocator;
+        func();
+    }
+}

+ 325 - 0
tests/unit/common/test_helper.h

@@ -0,0 +1,325 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#pragma once
+
+#include "wasm_export.h"
+#include "gtest/gtest.h"
+
+#include <iostream>
+#include <memory>
+#include <fstream>
+
+template<int Size = 512 * 1024>
+class WAMRRuntimeRAII
+{
+  private:
+    char global_heap_buf[Size];
+    RuntimeInitArgs init_args;
+
+  public:
+    WAMRRuntimeRAII()
+    {
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        wasm_runtime_full_init(&init_args);
+    }
+
+    ~WAMRRuntimeRAII() { wasm_runtime_destroy(); }
+};
+
+class WAMRModule
+{
+  private:
+    wasm_module_t module_;
+
+  public:
+    WAMRModule(uint8_t *buffer, uint32_t size)
+    {
+        module_ = wasm_runtime_load(buffer, size, NULL, 0);
+    }
+
+    ~WAMRModule() { wasm_runtime_unload(module_); }
+
+    wasm_module_t get() const { return module_; }
+};
+
+class WAMRInstance
+{
+  private:
+    wasm_module_inst_t module_inst_;
+
+  public:
+    WAMRInstance(WAMRModule &module, uint32_t stack_size = 8192,
+                 uint32_t heap_size = 8192)
+    {
+        module_inst_ = wasm_runtime_instantiate(module.get(), stack_size,
+                                                heap_size, NULL, 0);
+    }
+
+    ~WAMRInstance() { wasm_runtime_deinstantiate(module_inst_); }
+
+    wasm_module_inst_t get() const { return module_inst_; }
+};
+
+class WAMRExecEnv
+{
+  private:
+    wasm_exec_env_t exec_env_;
+
+  public:
+    WAMRExecEnv(WAMRInstance &instance, uint32_t stack_size = 8192)
+    {
+        exec_env_ = wasm_runtime_create_exec_env(instance.get(), stack_size);
+    }
+
+    ~WAMRExecEnv() { wasm_runtime_destroy_exec_env(exec_env_); }
+
+    wasm_exec_env_t get() const { return exec_env_; }
+    wasm_module_inst_t get_inst() const
+    {
+        return wasm_runtime_get_module_inst(exec_env_);
+    }
+};
+
+static uint8_t dummy_wasm_buffer[] = {
+    0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x05, 0x03, 0x01, 0x00,
+    0x02, 0x06, 0x08, 0x01, 0x7F, 0x01, 0x41, 0x80, 0x88, 0x04, 0x0B, 0x07,
+    0x0A, 0x01, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x00,
+    0x19, 0x04, 0x6E, 0x61, 0x6D, 0x65, 0x07, 0x12, 0x01, 0x00, 0x0F, 0x5F,
+    0x5F, 0x73, 0x74, 0x61, 0x63, 0x6B, 0x5F, 0x70, 0x6F, 0x69, 0x6E, 0x74,
+    0x65, 0x72, 0x00, 0x76, 0x09, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x65,
+    0x72, 0x73, 0x01, 0x0C, 0x70, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x65,
+    0x64, 0x2D, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6C, 0x61, 0x6E, 0x67, 0x56,
+    0x31, 0x33, 0x2E, 0x30, 0x2E, 0x30, 0x20, 0x28, 0x68, 0x74, 0x74, 0x70,
+    0x73, 0x3A, 0x2F, 0x2F, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2E, 0x63,
+    0x6F, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D, 0x2F, 0x6C, 0x6C, 0x76, 0x6D,
+    0x2D, 0x70, 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x20, 0x66, 0x64, 0x31,
+    0x64, 0x38, 0x63, 0x32, 0x66, 0x30, 0x34, 0x64, 0x64, 0x65, 0x32, 0x33,
+    0x62, 0x65, 0x65, 0x30, 0x66, 0x62, 0x33, 0x61, 0x37, 0x64, 0x30, 0x36,
+    0x39, 0x61, 0x39, 0x62, 0x31, 0x30, 0x34, 0x36, 0x64, 0x61, 0x39, 0x37,
+    0x39, 0x29
+};
+
+class DummyExecEnv
+{
+  private:
+    std::shared_ptr<WAMRExecEnv> dummy_exec_env_;
+    std::shared_ptr<WAMRInstance> inst_;
+    std::shared_ptr<WAMRModule> mod_;
+    std::vector<uint8_t> my_wasm_buffer;
+
+  private:
+    void construct(uint8_t *buf, uint32_t len)
+    {
+        std::vector<uint8_t> buffer(buf, buf + len);
+        my_wasm_buffer = buffer;
+
+        mod_ = std::make_shared<WAMRModule>(my_wasm_buffer.data(),
+                                            my_wasm_buffer.size());
+        EXPECT_NE(mod_.get(), nullptr);
+        inst_ = std::make_shared<WAMRInstance>(*mod_);
+        EXPECT_NE(inst_.get(), nullptr);
+        dummy_exec_env_ = std::make_shared<WAMRExecEnv>(*inst_);
+        EXPECT_NE(dummy_exec_env_.get(), nullptr);
+    }
+
+  public:
+    DummyExecEnv() { construct(dummy_wasm_buffer, sizeof(dummy_wasm_buffer)); }
+
+    DummyExecEnv(uint8_t *buf, uint32_t len) { construct(buf, len); }
+
+    DummyExecEnv(std::string filename)
+    {
+        std::ifstream wasm_file(filename, std::ios::binary);
+        std::vector<uint8_t> buffer(std::istreambuf_iterator<char>(wasm_file),
+                                    {});
+
+        construct(buffer.data(), buffer.size());
+    }
+
+    ~DummyExecEnv() {}
+
+    wasm_exec_env_t get() const { return dummy_exec_env_->get(); }
+
+    void *app_to_native(uint32_t app_addr) const
+    {
+        return wasm_runtime_addr_app_to_native(inst_->get(), app_addr);
+    }
+
+    uint32_t native_to_app(void *ptr) const
+    {
+        return wasm_runtime_addr_native_to_app(inst_->get(), ptr);
+    }
+
+    const char *get_exception() const
+    {
+        return wasm_runtime_get_exception(inst_->get());
+    }
+
+    void set_exception(std::string str) const
+    {
+        wasm_runtime_set_exception(inst_->get(), str.c_str());
+    }
+
+    void clear_exception() const { wasm_runtime_clear_exception(inst_->get()); }
+
+    bool execute(const char *func_name, uint32_t argc, uint32_t argv[])
+    {
+        wasm_function_inst_t func;
+
+        if (!(func = wasm_runtime_lookup_function(inst_->get(), func_name))) {
+            return false;
+        }
+
+        return wasm_runtime_call_wasm(dummy_exec_env_->get(), func, argc, argv);
+    }
+};
+
+class WAMRVaList
+{
+  private:
+    void *buffer_;
+    uint32_t current_loc_;
+    uint32_t capacity_;
+    wasm_exec_env_t exec_env_;
+
+    void _append(void *ptr, uint32_t size)
+    {
+        if (current_loc_ + size >= capacity_) {
+            capacity_ *= 2;
+            buffer_ = realloc(buffer_, capacity_);
+            ASSERT_NE(buffer_, nullptr);
+        }
+
+        memcpy((void *)((uintptr_t)buffer_ + current_loc_), ptr, size);
+        current_loc_ += size;
+    }
+
+  public:
+    explicit WAMRVaList(wasm_exec_env_t exec_env)
+      : exec_env_(exec_env)
+    {
+        capacity_ = 64;
+        buffer_ = malloc(capacity_);
+        EXPECT_NE(buffer_, nullptr);
+        current_loc_ = 0;
+    }
+
+    ~WAMRVaList()
+    {
+        current_loc_ = 0;
+        free(buffer_);
+    }
+
+    template<typename T>
+    void add(T arg)
+    {
+        if (std::is_floating_point<T>::value) {
+            /* float data should be 8 bytes aligned */
+            current_loc_ = ((current_loc_ + 7) & ~7);
+            _append(&arg, sizeof(T));
+        }
+        else if (std::is_integral<T>::value) {
+            if (sizeof(T) > 4) {
+                current_loc_ = ((current_loc_ + 7) & ~7);
+            }
+            _append(&arg, sizeof(T));
+        }
+    }
+
+    void add(std::string arg)
+    {
+        void *native_addr;
+        auto inst = wasm_runtime_get_module_inst(exec_env_);
+        uint32_t addr =
+            wasm_runtime_module_malloc(inst, arg.size() + 1, &native_addr);
+        ASSERT_NE(addr, 0);
+        memcpy(native_addr, arg.data(), arg.size());
+        *(char *)((uintptr_t)native_addr + arg.size()) = 0;
+        _append(&addr, sizeof(uint32_t));
+    }
+
+    void add(const char *arg) { add(std::string(arg)); }
+
+    char *get() const
+    {
+        auto inst = wasm_runtime_get_module_inst(exec_env_);
+        uint32_t addr = wasm_runtime_module_dup_data(
+            inst, (const char *)buffer_, current_loc_);
+        EXPECT_NE(addr, 0);
+        return (char *)wasm_runtime_addr_app_to_native(inst, addr);
+    }
+};
+
+/* Get memory space in app */
+class AppMemory
+{
+  private:
+    wasm_exec_env_t exec_env_;
+    void *native_addr_;
+    uint32_t app_addr_;
+
+  public:
+    AppMemory(wasm_exec_env_t exec_env, uint32_t size)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_malloc(get_module_inst(exec_env_), size,
+                                               &native_addr_);
+    }
+
+    ~AppMemory()
+    {
+        wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
+    }
+
+    void *get_native_addr() const
+    {
+        return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
+                                               app_addr_);
+    }
+    uint32_t get_app_addr() const { return app_addr_; }
+};
+
+/* Put the data to app */
+class AppData
+{
+  private:
+    wasm_exec_env_t exec_env_;
+    void *native_addr_;
+    uint32_t app_addr_;
+
+  public:
+    AppData(wasm_exec_env_t exec_env, void *data, uint32_t size)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
+                                                 (const char *)data, size);
+    }
+
+    AppData(wasm_exec_env_t exec_env, std::string str)
+      : exec_env_(exec_env)
+    {
+        app_addr_ = wasm_runtime_module_dup_data(get_module_inst(exec_env_),
+                                                 (const char *)str.c_str(),
+                                                 str.size() + 1);
+    }
+
+    ~AppData()
+    {
+        wasm_runtime_module_free(get_module_inst(exec_env_), app_addr_);
+    }
+
+    void *get_native_addr() const
+    {
+        return wasm_runtime_addr_app_to_native(get_module_inst(exec_env_),
+                                               app_addr_);
+    }
+    uint32_t get_app_addr() const { return app_addr_; }
+};

+ 72 - 0
tests/unit/compilation/CMakeLists.txt

@@ -0,0 +1,72 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-compilation)
+
+add_definitions (-DRUN_ON_LINUX)
+
+add_definitions (-Dattr_container_malloc=malloc)
+add_definitions (-Dattr_container_free=free)
+add_definitions (-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+set (WAMR_BUILD_THREAD_MGR 1)
+set (WAMR_BUILD_AOT 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${WAMR_RUNTIME_LIB_SOURCE}
+     ${UNCOMMON_SHARED_SOURCE}
+     ${SRC_LIST}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${LIB_HOST_AGENT_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${LIBC_BUILTIN_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (compilation_test ${unit_test_sources})
+
+target_link_libraries (compilation_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+add_custom_command(TARGET compilation_test POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/main.wasm
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy main.wasm to the directory: build/compilation."
+)
+
+gtest_discover_tests(compilation_test)

+ 203 - 0
tests/unit/compilation/aot_compiler_test.cc

@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "wasm_export.h"
+#include "aot_export.h"
+#include "bh_read_file.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+extern "C" {
+char *
+aot_generate_tempfile_name(const char *prefix, const char *extension,
+                           char *buffer, uint32 len);
+}
+
+class aot_compiler_test_suit : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+void
+test_aot_emit_object_file_with_option(AOTCompOption *option_ptr)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    char out_file_name[] = "test.aot";
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+
+    comp_ctx = aot_create_comp_context(comp_data, option_ptr);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_STREQ(aot_get_last_error(), "");
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_TRUE(aot_emit_object_file(comp_ctx, out_file_name));
+}
+
+TEST_F(aot_compiler_test_suit, aot_emit_object_file)
+{
+    AOTCompOption option = { 0 };
+    uint32_t i = 0;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    // Test opt_level in range from 0 to 3.
+    for (i = 0; i <= 3; i++) {
+        option.opt_level = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test size_level in range from 0 to 3.
+    option.opt_level = 3;
+    for (i = 0; i <= 3; i++) {
+        option.size_level = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test output_format in range from AOT_FORMAT_FILE to AOT_LLVMIR_OPT_FILE.
+    option.size_level = 3;
+    for (i = AOT_FORMAT_FILE; i <= AOT_LLVMIR_OPT_FILE; i++) {
+        option.output_format = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test bounds_checks in range 0 to 2.
+    option.output_format = AOT_FORMAT_FILE;
+    for (i = 0; i <= 2; i++) {
+        option.bounds_checks = i;
+        test_aot_emit_object_file_with_option(&option);
+    }
+
+    // Test all enable option is false.
+    option.bounds_checks = 2;
+    option.enable_simd = false;
+    option.enable_aux_stack_check = false;
+    option.enable_bulk_memory = false;
+    option.enable_ref_types = false;
+    test_aot_emit_object_file_with_option(&option);
+}
+
+TEST_F(aot_compiler_test_suit, aot_emit_llvm_file)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_STREQ(aot_get_last_error(), "");
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_EQ(true, aot_emit_llvm_file(comp_ctx, out_file_name));
+}
+
+TEST_F(aot_compiler_test_suit, aot_generate_tempfile_name)
+{
+    char obj_file_name[64];
+
+    // Test common case.
+    aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name,
+                               sizeof(obj_file_name));
+    EXPECT_NE(nullptr, strstr(obj_file_name, ".o"));
+
+    // Test abnormal cases.
+    EXPECT_EQ(nullptr,
+              aot_generate_tempfile_name("wamrc-obj", "o", obj_file_name, 0));
+    char obj_file_name_1[20];
+    EXPECT_EQ(nullptr, aot_generate_tempfile_name(
+                           "wamrc-obj", "12345678901234567890", obj_file_name_1,
+                           sizeof(obj_file_name_1)));
+}

+ 104 - 0
tests/unit/compilation/aot_emit_aot_file_test.cc

@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "wasm_export.h"
+#include "aot_export.h"
+#include "bh_read_file.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+extern "C" {
+uint8 *
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                      uint32 *p_aot_file_size);
+}
+
+class aot_emit_aot_file_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_aot_file_test_suite, aot_emit_aot_file)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+    aot_comp_data_t comp_data = nullptr;
+    aot_comp_context_t comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "test.aot";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = false;
+    option.enable_aux_stack_check = false;
+    option.enable_bulk_memory = false;
+    option.enable_ref_types = false;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data(wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    EXPECT_EQ(false, aot_emit_aot_file(comp_ctx, comp_data, nullptr));
+}

+ 112 - 0
tests/unit/compilation/aot_emit_compare_test.cc

@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "aot_emit_compare.h"
+
+class compilation_aot_emit_compare_test : public testing::Test
+{
+  protected:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+  public:
+};
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i32_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    IntCond cond = INT_EQZ;
+    IntCond cond1 = INT_EQZ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_i32_compare(&comp_ctx, &func_ctx, (IntCond)(-1)));
+
+    /* false cond = [1:10] || [11:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1)));
+        cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_i32_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_i64_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    IntCond cond = INT_EQZ;
+    IntCond cond1 = INT_EQZ;
+
+    /* false cond = 0 */
+    // EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_i64_compare(&comp_ctx, &func_ctx, (IntCond)(-1)));
+
+    /* false cond = [1:10] || [11:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (IntCond)(1 + (rand() % (INT_GE_U - 1 + 1)));
+        cond1 = (IntCond)((INT_GE_U + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_i64_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f32_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    FloatCond cond = FLOAT_EQ;
+    FloatCond cond1 = FLOAT_EQ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_f32_compare(&comp_ctx, &func_ctx, (FloatCond)(-1)));
+
+    /* false cond = [1:10] || [7:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1)));
+        cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_f32_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}
+
+TEST_F(compilation_aot_emit_compare_test, aot_compile_op_f64_compare)
+{
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+    FloatCond cond = FLOAT_EQ;
+    FloatCond cond1 = FLOAT_EQ;
+
+    /* false cond = 0 */
+    EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond));
+
+    /* false cond = -1 */
+    EXPECT_FALSE(
+        aot_compile_op_f64_compare(&comp_ctx, &func_ctx, (FloatCond)(-1)));
+
+    /* false cond = [1:10] || [7:100] */
+    for (int i = 0; i < 0xFFFF; i++) {
+        /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+        cond = (FloatCond)(1 + (rand() % (FLOAT_UNO - 1 + 1)));
+        cond1 = (FloatCond)((FLOAT_UNO + 1) + (rand() % (100 - 1 + 1)));
+        EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond));
+        EXPECT_FALSE(aot_compile_op_f64_compare(&comp_ctx, &func_ctx, cond1));
+    }
+}

+ 196 - 0
tests/unit/compilation/aot_emit_control_test.cc

@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot.h"
+#include "aot_llvm.h"
+#include "aot_emit_control.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_control_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_control_test_suite, check_suspend_flags)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    EXPECT_EQ(true, check_suspend_flags(comp_ctx, func_ctx, false));
+}
+
+TEST_F(aot_emit_control_test_suite, aot_compile_op_block)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+    EXPECT_EQ(false, aot_compile_op_block(comp_ctx, func_ctx, nullptr, nullptr,
+                                          0, 0, nullptr, 0, nullptr));
+}
+
+TEST_F(aot_emit_control_test_suite, aot_compile_op_else)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+
+    AOTBlock block_list_end_test;
+    block_list_end_test.label_type = LABEL_TYPE_FUNCTION;
+    func_ctx->block_stack.block_list_end = &block_list_end_test;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+
+    block_list_end_test.label_type = LABEL_TYPE_IF;
+    block_list_end_test.llvm_else_block = nullptr;
+    EXPECT_EQ(false, aot_compile_op_else(comp_ctx, func_ctx, nullptr));
+}

+ 101 - 0
tests/unit/compilation/aot_emit_function_test.cc

@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_emit_control.h"
+#include "aot_emit_function.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_function_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_function_test_suite, aot_compile_op_call)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    char out_file_name[] = "out_file_name_test";
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    func_ctx = comp_ctx->func_ctxes[1];
+    EXPECT_EQ(false, aot_compile_op_call(comp_ctx, func_ctx, 9999, true));
+}

+ 335 - 0
tests/unit/compilation/aot_emit_memory_test.cc

@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "bh_read_file.h"
+#include "aot_emit_memory.h"
+#include "test_helper.h"
+
+#define DEFAULT_CYCLE_TIMES 0xFFFF
+#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class compilation_aot_emit_memory_test : public testing::Test
+{
+  protected:
+    void SetUp() override
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+        AOTCompOption option = { 0 };
+
+        option.opt_level = 3;
+        option.size_level = 3;
+        option.output_format = AOT_FORMAT_FILE;
+        /* default value, enable or disable depends on the platform */
+        option.bounds_checks = 2;
+        /* default value, enable or disable depends on the platform */
+        option.stack_bounds_checks = 2;
+        option.enable_simd = true;
+        option.enable_aux_stack_check = true;
+        option.enable_bulk_memory = true;
+        option.enable_ref_types = true;
+
+        const char *wasm_file = WASM_FILE;
+        unsigned int wasm_file_size = 0;
+        unsigned char *wasm_file_buf = nullptr;
+        char error_buf[128] = { 0 };
+
+        wasm_file_buf =
+            (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+        EXPECT_NE(wasm_file_buf, nullptr);
+        wasm_module = reinterpret_cast<WASMModule *>(wasm_runtime_load(
+            wasm_file_buf, wasm_file_size, error_buf, sizeof(error_buf)));
+        EXPECT_NE(wasm_module, nullptr);
+        comp_data = aot_create_comp_data(wasm_module, NULL, false);
+        EXPECT_NE(comp_data, nullptr);
+
+        // properly init compilation and function context, to do that,
+        // use as a dummy module(instead of compile the function in it, simply
+        // test the APIs)
+        comp_ctx = aot_create_comp_context(comp_data, &option);
+        EXPECT_NE(comp_ctx, nullptr);
+        func_ctx = comp_ctx->func_ctxes[0];
+        EXPECT_NE(func_ctx, nullptr);
+    }
+
+    void TearDown() override
+    {
+        aot_destroy_comp_context(comp_ctx);
+        aot_destroy_comp_data(comp_data);
+        wasm_runtime_unload(reinterpret_cast<WASMModuleCommon *>(wasm_module));
+    }
+
+  public:
+    WASMModule *wasm_module = nullptr;
+    AOTCompData *comp_data = nullptr;
+    AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(compilation_aot_emit_memory_test, aot_check_memory_overflow)
+{
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes, false);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_load)
+{
+    uint32 align = 0;
+    uint32 offset = 1024;
+    uint32 bytes = 0;
+    bool sign = false;
+    bool atomic = false;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        printf("---%d", aot_compile_op_i32_load(comp_ctx, func_ctx, align,
+                                                offset, bytes, sign, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_load)
+{
+    uint32 align = 0;
+    uint32 offset = 1024;
+    uint32 bytes = 0;
+    bool sign = false;
+    bool atomic = false;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        sign = !sign;
+        atomic = !atomic;
+        aot_compile_op_i64_load(comp_ctx, func_ctx, align, offset, bytes, sign,
+                                atomic);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_load)
+{
+    uint32 align = 10;
+    uint32 offset = 10;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_compile_op_f32_load(comp_ctx, func_ctx, align, offset);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_load)
+{
+    uint32 align = 10;
+    uint32 offset = 10;
+
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        align = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        offset = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+        aot_compile_op_f64_load(comp_ctx, func_ctx, align, offset);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i32_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+    uint32 bytes = 0;
+    bool atomic = false;
+
+    EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset,
+                                          bytes, atomic));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        bytes = (1 + (rand() % (4 - 1 + 1)));
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        atomic = !atomic;
+
+        EXPECT_FALSE(aot_compile_op_i32_store(comp_ctx, func_ctx, align, offset,
+                                              bytes, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_i64_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+    uint32 bytes = 0;
+    bool atomic = false;
+
+    EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset,
+                                          bytes, atomic));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        bytes = (1 + (rand() % (8 - 1 + 1)));
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        atomic = !atomic;
+
+        EXPECT_FALSE(aot_compile_op_i64_store(comp_ctx, func_ctx, align, offset,
+                                              bytes, atomic));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f32_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+
+    EXPECT_FALSE(aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+
+        EXPECT_FALSE(
+            aot_compile_op_f32_store(comp_ctx, func_ctx, align, offset));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_f64_store)
+{
+    uint32 align = 0;
+    uint32 offset = 0;
+
+    EXPECT_FALSE(aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset));
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        offset = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        align = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+
+        EXPECT_FALSE(
+            aot_compile_op_f64_store(comp_ctx, func_ctx, align, offset));
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_size)
+{
+    aot_compile_op_memory_size(comp_ctx, func_ctx);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_grow)
+{
+    aot_compile_op_memory_grow(comp_ctx, func_ctx);
+}
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_init)
+{
+    uint32 seg_index = 0;
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        aot_compile_op_memory_init(comp_ctx, func_ctx, seg_index);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_data_drop)
+{
+    uint32 seg_index = 0;
+
+    /* Generate random number range:[m,n] int a=m+rand()%(n-m+1); */
+    for (uint32 i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+        seg_index = (1 + (rand() % (0xFFFFFFFF - 1 + 1)));
+        aot_compile_op_data_drop(comp_ctx, func_ctx, seg_index);
+    }
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_copy)
+{
+    aot_compile_op_memory_copy(comp_ctx, func_ctx);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_memory_fill)
+{
+    aot_compile_op_memory_fill(comp_ctx, func_ctx);
+}
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_rmw)
+{
+    uint8 atomic_op = LLVMAtomicRMWBinOpAdd;
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_rmw(comp_ctx, func_ctx, atomic_op, op_type, align,
+                              offset, bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_cmpxchg)
+{
+
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_cmpxchg(comp_ctx, func_ctx, op_type, align, offset,
+                                  bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compile_op_atomic_wait)
+{
+
+    uint8 op_type = VALUE_TYPE_I32;
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compile_op_atomic_wait(comp_ctx, func_ctx, op_type, align, offset,
+                               bytes);
+}
+
+TEST_F(compilation_aot_emit_memory_test, aot_compiler_op_atomic_notify)
+{
+
+    uint32 align = 4;
+    uint32 offset = 64;
+    uint32 bytes = 4;
+
+    aot_compiler_op_atomic_notify(comp_ctx, func_ctx, align, offset, bytes);
+}
+#endif

+ 119 - 0
tests/unit/compilation/aot_emit_numberic_test.cc

@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_numberic.h"
+#include "aot_compiler.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_numberic_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_numberic_test_suite, aot_compile_op_functions)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_EQ(false,
+              aot_compile_op_f32_arithmetic(comp_ctx, func_ctx, FLOAT_SUB));
+    EXPECT_EQ(false, aot_compile_op_f32_copysign(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_f32_math(comp_ctx, func_ctx, FLOAT_NEG));
+    EXPECT_EQ(false,
+              aot_compile_op_f64_arithmetic(comp_ctx, func_ctx, FLOAT_SUB));
+    EXPECT_EQ(false, aot_compile_op_f64_copysign(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_f64_math(comp_ctx, func_ctx, FLOAT_NEG));
+    EXPECT_EQ(false, aot_compile_op_i32_clz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_ctz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_popcnt(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i32_shift(comp_ctx, func_ctx, INT_SHR_S));
+    EXPECT_EQ(false, aot_compile_op_i64_arithmetic(comp_ctx, func_ctx, INT_SUB,
+                                                   nullptr));
+    EXPECT_EQ(false, aot_compile_op_i64_bitwise(comp_ctx, func_ctx, INT_OR));
+    EXPECT_EQ(false, aot_compile_op_i64_clz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_ctz(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_popcnt(comp_ctx, func_ctx));
+    EXPECT_EQ(false, aot_compile_op_i64_shift(comp_ctx, func_ctx, INT_SHR_S));
+}

+ 143 - 0
tests/unit/compilation/aot_emit_parametric_test.cc

@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_parametric.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_parametric_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_parametric_test_suite, aot_compile_op_select)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, true));
+    EXPECT_FALSE(aot_compile_op_select(comp_ctx, func_ctx, false));
+}
+
+TEST_F(aot_emit_parametric_test_suite, aot_compile_op_drop)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+    func_ctx->block_stack.block_list_end = nullptr;
+
+    EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, true));
+    EXPECT_FALSE(aot_compile_op_drop(comp_ctx, func_ctx, false));
+}

+ 105 - 0
tests/unit/compilation/aot_emit_table_test.cc

@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_emit_table.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_emit_table_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_emit_table_test_suite, get_tbl_inst_offset)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTFuncContext *func_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6));
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 1));
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 0));
+    ((AOTCompData *)comp_ctx->comp_data)->import_table_count = 1;
+    AOTImportTable import_tables_test;
+    ((AOTCompData *)comp_ctx->comp_data)->import_tables = &import_tables_test;
+    EXPECT_NE(0, get_tbl_inst_offset(comp_ctx, func_ctx, 6));
+}

+ 97 - 0
tests/unit/compilation/aot_emit_variable_test.cc

@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "aot_emit_variable.h"
+
+#define DEFAULT_CYCLE_TIMES 0xFFFF
+#define DEFAULT_MAX_RAND_NUM 0xFFFFFFFF
+
+class compilation_aot_emit_variable_test : public testing::Test
+{
+  protected:
+    virtual void SetUp() {}
+    virtual void TearDown() {}
+
+  public:
+    AOTCompContext comp_ctx = { 0 };
+    AOTFuncContext func_ctx = { 0 };
+};
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_local)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_get_local(NULL, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_get_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_local)
+{
+
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_set_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_tee_local)
+{
+
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 local_idx = 0;
+
+    // aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_tee_local(pcomp_ctx, pfunc_ctx, local_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_get_global)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 global_idx = 0;
+
+    // aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_get_global(pcomp_ctx, pfunc_ctx, global_idx);
+    // }
+}
+
+TEST_F(compilation_aot_emit_variable_test, aot_compile_op_set_global)
+{
+    AOTCompContext *pcomp_ctx = &comp_ctx;
+    AOTFuncContext *pfunc_ctx = &func_ctx;
+    uint32 global_idx = 0;
+    bool is_aux_stack = false;
+
+    // aot_compile_op_set_global(pcomp_ctx, pfunc_ctx, global_idx,
+    // is_aux_stack);
+
+    // for (uint32_t i = 0; i < DEFAULT_CYCLE_TIMES; i++) {
+    //     is_aux_stack = is_aux_stack ? false : ture;
+    //     local_idx = (1 + (rand() % (DEFAULT_MAX_RAND_NUM - 1 + 1)));
+    //     aot_compile_op_set_global(pcomp_ctx, pfunc_ctx,
+    //     global_idx,is_aux_stack);
+    // }
+}

+ 305 - 0
tests/unit/compilation/aot_llvm_test.cc

@@ -0,0 +1,305 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "test_helper.h"
+#include "gtest/gtest.h"
+
+#include "bh_read_file.h"
+#include "aot_llvm.h"
+#include "aot_compiler.h"
+
+static std::string CWD;
+static std::string MAIN_WASM = "/main.wasm";
+static char *WASM_FILE;
+
+static std::string
+get_binary_path()
+{
+    char cwd[1024];
+    memset(cwd, 0, 1024);
+
+    if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+    }
+
+    char *path_end = strrchr(cwd, '/');
+    if (path_end != NULL) {
+        *path_end = '\0';
+    }
+
+    return std::string(cwd);
+}
+
+class aot_llvm_test_suite : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    static void SetUpTestCase()
+    {
+        CWD = get_binary_path();
+        WASM_FILE = strdup((CWD + MAIN_WASM).c_str());
+    }
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+    static void TearDownTestCase() { free(WASM_FILE); }
+
+    WAMRRuntimeRAII<512 * 1024> runtime;
+};
+
+TEST_F(aot_llvm_test_suite, aot_functions)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    WASMValue wasm_value;
+    LLVMTypeRef param_types[1];
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    param_types[0] = F64_TYPE;
+    EXPECT_TRUE(aot_call_llvm_intrinsic(comp_ctx, func_ctx, "f32_demote_f64",
+                                        F32_TYPE, param_types, 0));
+
+    /* Test function aot_get_native_symbol_index. */
+    AOTNativeSymbol elem_insert_1;
+    elem_insert_1.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1);
+
+    AOTNativeSymbol elem_insert_2;
+    strcpy(elem_insert_2.symbol, "f64#_test");
+    elem_insert_2.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_2);
+    comp_ctx->pointer_size = sizeof(uint32);
+    strcpy(comp_ctx->target_arch, "i386");
+    EXPECT_NE(-1, aot_get_native_symbol_index(comp_ctx, "f64#_test"));
+}
+
+TEST_F(aot_llvm_test_suite, wasm_type_to_llvm_type) {}
+
+TEST_F(aot_llvm_test_suite, aot_build_zero_function_ret)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    AOTFuncType func_type;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = false;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+    func_ctx = comp_ctx->func_ctxes[1];
+
+    func_type.result_count = 1;
+    func_type.param_count = 0;
+    func_type.types[func_type.param_count] = VALUE_TYPE_I32;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_I64;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_F32;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_F64;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    func_type.types[func_type.param_count] = VALUE_TYPE_V128;
+    EXPECT_NE(0, aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type));
+    /* THe current optimization, if not actually use ref_types in wasm module,
+     * it will set to false, so test false condition */
+    func_type.types[func_type.param_count] = VALUE_TYPE_FUNCREF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+    func_type.types[func_type.param_count] = VALUE_TYPE_EXTERNREF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+    func_type.types[func_type.param_count] = 0xFF;
+    EXPECT_DEATH(aot_build_zero_function_ret(comp_ctx, func_ctx, &func_type),
+                 ".*");
+}
+
+TEST_F(aot_llvm_test_suite, aot_destroy_comp_context)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+    AOTFuncContext *func_ctx = nullptr;
+    AOTFuncType func_type;
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+    AOTNativeSymbol elem_insert_1;
+    elem_insert_1.index = -1;
+    bh_list_insert(&comp_ctx->native_symbols, &elem_insert_1);
+    aot_destroy_comp_context(comp_ctx);
+
+    aot_destroy_comp_context(nullptr);
+}
+
+TEST_F(aot_llvm_test_suite, aot_create_comp_context)
+{
+    const char *wasm_file = WASM_FILE;
+    unsigned int wasm_file_size = 0;
+    unsigned char *wasm_file_buf = nullptr;
+    char error_buf[128] = { 0 };
+    wasm_module_t wasm_module = nullptr;
+
+    struct AOTCompData *comp_data = nullptr;
+    struct AOTCompContext *comp_ctx = nullptr;
+    AOTCompOption option = { 0 };
+
+    option.opt_level = 3;
+    option.size_level = 3;
+    option.output_format = AOT_FORMAT_FILE;
+    /* default value, enable or disable depends on the platform */
+    option.bounds_checks = 2;
+    option.enable_simd = true;
+    option.enable_aux_stack_check = true;
+    option.enable_bulk_memory = true;
+    option.enable_ref_types = true;
+
+    wasm_file_buf =
+        (unsigned char *)bh_read_file_to_buffer(wasm_file, &wasm_file_size);
+    EXPECT_NE(wasm_file_buf, nullptr);
+    wasm_module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                    sizeof(error_buf));
+    EXPECT_NE(wasm_module, nullptr);
+    comp_data = aot_create_comp_data((WASMModule *)wasm_module, NULL, false);
+    EXPECT_NE(nullptr, comp_data);
+
+    option.enable_thread_mgr = true;
+    option.enable_tail_call = true;
+    option.is_indirect_mode = true;
+    option.disable_llvm_intrinsics = true;
+    option.disable_llvm_lto = true;
+    option.is_jit_mode = true;
+
+    option.target_arch = (char *)"arm";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    EXPECT_NE(comp_ctx, nullptr);
+    option.output_format = 100;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    // Test every target_arch.
+    option.is_jit_mode = false;
+    option.target_arch = (char *)"arm";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"armeb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"thumb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"thumbeb";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"aarch64";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"aarch64_be";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_arch = (char *)"help";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    // Test every target_abi.
+    option.target_arch = (char *)"arm";
+    option.target_abi = (char *)"test";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_abi = (char *)"help";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.target_abi = (char *)"msvc";
+    option.target_arch = (char *)"i386";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+
+    option.cpu_features = (char *)"test";
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    option.is_sgx_platform = true;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+    comp_data->func_count = 0;
+    comp_ctx = aot_create_comp_context(comp_data, &option);
+}

BIN
tests/unit/compilation/wasm-apps/main.wasm


+ 65 - 0
tests/unit/custom-section/CMakeLists.txt

@@ -0,0 +1,65 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-custom-section)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_LIBC_WASI 0)
+set (WAMR_BUILD_LIBC_BUILTIN 0)
+set (WAMR_BUILD_JIT 0)
+set (WAMR_BUILD_LAZY_JIT 0)
+set (WAMR_BUILD_AOT 1)
+
+add_definitions(-DWASM_ENABLE_WAMR_COMPILER=1)
+add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+add_definitions (-DWASM_ENABLE_AOT_STACK_FRAME=1)
+
+# Feature to test
+set (WAMR_BUILD_LOAD_CUSTOM_SECTION 1)
+
+include (../unit_common.cmake)
+
+set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
+  message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+endif ()
+set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
+find_package(LLVM REQUIRED CONFIG)
+include_directories(${LLVM_INCLUDE_DIRS})
+add_definitions(${LLVM_DEFINITIONS})
+message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
+message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
+
+include (${IWASM_DIR}/compilation/iwasm_compl.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+     ${UNIT_SOURCE}
+     ${PLATFORM_SHARED_SOURCE}
+     ${UTILS_SHARED_SOURCE}
+     ${MEM_ALLOC_SHARED_SOURCE}
+     ${NATIVE_INTERFACE_SOURCE}
+     ${IWASM_COMMON_SOURCE}
+     ${IWASM_INTERP_SOURCE}
+     ${IWASM_AOT_SOURCE}
+     ${IWASM_COMPL_SOURCE}
+     ${WASM_APP_LIB_SOURCE_ALL}
+    )
+
+# Automatically build wasm-apps for this test
+add_subdirectory(wasm-apps)
+
+# Now simply link against gtest or gtest_main as needed. Eg
+add_executable (custom_section_test ${unit_test_sources})
+
+target_link_libraries (custom_section_test ${LLVM_AVAILABLE_LIBS} gtest_main )
+
+gtest_discover_tests(custom_section_test)

+ 161 - 0
tests/unit/custom-section/custom_section_test.cc

@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include <fstream>
+#include "test_helper.h"
+#include "aot_export.h"
+
+class CustomSectionTest : public testing::Test
+{
+  protected:
+    // You should make the members protected s.t. they can be
+    // accessed from sub-classes.
+
+    // virtual void SetUp() will be called before each test is run.  You
+    // should define it if you need to initialize the varaibles.
+    // Otherwise, this can be skipped.
+    virtual void SetUp() {}
+
+    // virtual void TearDown() will be called after each test is run.
+    // You should define it if there is cleanup work to do.  Otherwise,
+    // you don't have to provide it.
+    //
+    virtual void TearDown() {}
+
+  public:
+    WAMRRuntimeRAII<1 * 1024 * 1024> runtime;
+};
+
+TEST_F(CustomSectionTest, get_custom_section_from_wasm_module_t)
+{
+    uint32_t length, len_from_aot;
+    const uint8_t *content, *content_from_aot;
+    std::ifstream wasm_file("wasm-apps/app.wasm", std::ios::binary);
+    std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(wasm_file),
+                                      {});
+    {
+        WAMRModule module(buffer.data(), buffer.size());
+        aot_comp_data_t comp_data = NULL;
+        aot_comp_context_t comp_ctx = NULL;
+        std::vector<const char *> sections_to_emit{
+            "name",
+            ".debug_info",
+            ".debug_abbrev",
+            /* skip ".debug_line" section in AoT module */
+            ".debug_str",
+            "producers",
+        };
+
+        AOTCompOption option = { 0 };
+        option.custom_sections = (char **)sections_to_emit.data();
+        option.custom_sections_count = 5;
+
+        {
+            /* Compile an AoT module */
+            comp_data = aot_create_comp_data(module.get(), NULL, false);
+            EXPECT_NE(comp_data, nullptr);
+
+            comp_ctx = aot_create_comp_context(comp_data, &option);
+            EXPECT_NE(comp_ctx, nullptr);
+
+            EXPECT_TRUE(aot_compile_wasm(comp_ctx));
+
+            EXPECT_TRUE(aot_emit_aot_file(comp_ctx, comp_data, "temp.aot"));
+        }
+
+        std::ifstream aot_file("temp.aot", std::ios::binary);
+        std::vector<unsigned char> aot_buffer(
+            std::istreambuf_iterator<char>(aot_file), {});
+        WAMRModule aot_module(aot_buffer.data(), aot_buffer.size());
+
+        /* name */
+        content =
+            wasm_runtime_get_custom_section(module.get(), "name", &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        /* TODO: aot_emit_name_section don't 
+           EMIT_U32(AOT_CUSTOM_SECTION_RAW);*
+           EMIT_STR("name");
+           but instead
+           EMIT_U32(AOT_CUSTOM_SECTION_NAME);
+           can't use get_custom_section to get it
+        */
+        // content_from_aot = wasm_runtime_get_custom_section(
+        //     aot_module.get(), "name", &len_from_aot);
+        // EXPECT_NE(content_from_aot, nullptr);
+        // EXPECT_EQ(len_from_aot, length);
+        // EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_info */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_info",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_info", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_abbrev */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_abbrev",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_abbrev", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* .debug_line */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_line",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_line", &len_from_aot);
+        EXPECT_EQ(content_from_aot, nullptr);
+
+        /* .debug_str */
+        content = wasm_runtime_get_custom_section(module.get(), ".debug_str",
+                                                  &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), ".debug_str", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* producers */
+        content =
+            wasm_runtime_get_custom_section(module.get(), "producers", &length);
+        EXPECT_NE(content, nullptr);
+        EXPECT_GT(length, 0);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), "producers", &len_from_aot);
+        EXPECT_NE(content_from_aot, nullptr);
+        EXPECT_EQ(len_from_aot, length);
+        EXPECT_EQ(memcmp(content_from_aot, content, length), 0);
+
+        /* Not exist */
+        content = wasm_runtime_get_custom_section(module.get(), "producers1",
+                                                  &length);
+        EXPECT_EQ(content, nullptr);
+
+        content_from_aot = wasm_runtime_get_custom_section(
+            aot_module.get(), "producers1", &len_from_aot);
+        EXPECT_EQ(content_from_aot, nullptr);
+    }
+}

+ 14 - 0
tests/unit/custom-section/wasm-apps/CMakeLists.txt

@@ -0,0 +1,14 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project(wasm-apps-custom-section)
+
+# Add -g option so there will be debugger related custom sections
+add_custom_target(app.wasm ALL
+    COMMAND /opt/wasi-sdk/bin/clang -g -nostdlib
+            -Wl,--no-entry,--export-all
+            -o ${CMAKE_CURRENT_BINARY_DIR}/app.wasm
+            ${CMAKE_CURRENT_LIST_DIR}/app.c
+)

+ 10 - 0
tests/unit/custom-section/wasm-apps/app.c

@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+int
+main(int argc, char const *argv[])
+{
+    return 0;
+}

+ 51 - 0
tests/unit/gc/CMakeLists.txt

@@ -0,0 +1,51 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required(VERSION 2.9)
+
+project (test-wamr-gc)
+
+add_definitions (-DRUN_ON_LINUX)
+
+set (WAMR_BUILD_GC 1)
+set (WAMR_BUILD_INTERP 1)
+set (WAMR_BUILD_AOT 0)
+set (WAMR_BUILD_APP_FRAMEWORK 0)
+
+include (../unit_common.cmake)
+
+include_directories (${CMAKE_CURRENT_SOURCE_DIR})
+
+file (GLOB_RECURSE source_all ${CMAKE_CURRENT_SOURCE_DIR}/*.cc)
+
+set (UNIT_SOURCE ${source_all})
+
+set (unit_test_sources
+    ${UNIT_SOURCE}
+    ${WAMR_RUNTIME_LIB_SOURCE}
+    ${UNCOMMON_SHARED_SOURCE}
+    ${SRC_LIST}
+    ${PLATFORM_SHARED_SOURCE}
+    ${UTILS_SHARED_SOURCE}
+    ${MEM_ALLOC_SHARED_SOURCE}
+    ${LIB_HOST_AGENT_SOURCE}
+    ${NATIVE_INTERFACE_SOURCE}
+    ${LIBC_BUILTIN_SOURCE}
+    ${IWASM_COMMON_SOURCE}
+    ${IWASM_INTERP_SOURCE}
+    ${IWASM_AOT_SOURCE}
+    ${IWASM_COMPL_SOURCE}
+    ${WASM_APP_LIB_SOURCE_ALL}
+)
+
+add_executable (gc_test ${unit_test_sources})
+target_link_libraries (gc_test gtest_main)
+
+add_custom_command(TARGET gc_test POST_BUILD
+  COMMAND ${CMAKE_COMMAND} -E copy
+  ${CMAKE_CURRENT_LIST_DIR}/wasm-apps/*.was*
+  ${CMAKE_CURRENT_BINARY_DIR}
+  COMMENT "Copy wasm files to directory ${CMAKE_CURRENT_BINARY_DIR}"
+)
+
+#gtest_discover_tests(gc_test)

+ 102 - 0
tests/unit/gc/gc_test.cc

@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "gtest/gtest.h"
+#include "bh_platform.h"
+#include "bh_read_file.h"
+#include "wasm_export.h"
+
+class WasmGCTest : public testing::Test
+{
+  private:
+    std::string get_binary_path()
+    {
+        char cwd[1024] = { 0 };
+
+        if (readlink("/proc/self/exe", cwd, 1024) <= 0) {
+            return NULL;
+        }
+
+        char *path_end = strrchr(cwd, '/');
+        if (path_end != NULL) {
+            *path_end = '\0';
+        }
+
+        return std::string(cwd);
+    }
+
+  protected:
+    void SetUp()
+    {
+        CWD = get_binary_path();
+
+        memset(&init_args, 0, sizeof(RuntimeInitArgs));
+
+        init_args.mem_alloc_type = Alloc_With_Pool;
+        init_args.mem_alloc_option.pool.heap_buf = global_heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = sizeof(global_heap_buf);
+
+        ASSERT_EQ(wasm_runtime_full_init(&init_args), true);
+
+        cleanup = true;
+    }
+
+    void TearDown()
+    {
+        if (cleanup) {
+            wasm_runtime_destroy();
+        }
+    }
+
+  public:
+    bool load_wasm_file(const char *wasm_file)
+    {
+        const char *file;
+        unsigned char *wasm_file_buf;
+        uint32 wasm_file_size;
+
+        file = strdup((CWD + "/" + wasm_file).c_str());
+
+        wasm_file_buf =
+            (unsigned char *)bh_read_file_to_buffer(file, &wasm_file_size);
+        if (!wasm_file_buf)
+            return false;
+
+        module = wasm_runtime_load(wasm_file_buf, wasm_file_size, error_buf,
+                                   sizeof(error_buf));
+        if (!module)
+            return false;
+
+        return true;
+    }
+
+  public:
+    std::string CWD;
+    RuntimeInitArgs init_args;
+    wasm_module_t module = NULL;
+    wasm_module_inst_t module_inst = NULL;
+    wasm_function_inst_t func_inst = NULL;
+    wasm_exec_env_t exec_env = NULL;
+    char error_buf[128];
+    char global_heap_buf[512 * 1024];
+    bool cleanup = true;
+};
+
+TEST_F(WasmGCTest, Test_app1)
+{
+    ASSERT_TRUE(load_wasm_file("test1.wasm"));
+    ASSERT_TRUE(load_wasm_file("test2.wasm"));
+    ASSERT_TRUE(load_wasm_file("test3.wasm"));
+    ASSERT_TRUE(load_wasm_file("test4.wasm"));
+    ASSERT_TRUE(load_wasm_file("test5.wasm"));
+    ASSERT_TRUE(load_wasm_file("test6.wasm"));
+
+    ASSERT_TRUE(load_wasm_file("struct1.wasm"));
+    ASSERT_TRUE(load_wasm_file("struct2.wasm"));
+    ASSERT_TRUE(load_wasm_file("struct3.wasm"));
+
+    ASSERT_TRUE(load_wasm_file("func1.wasm"));
+    ASSERT_TRUE(load_wasm_file("func2.wasm"));
+}

BIN
tests/unit/gc/wasm-apps/func1.wasm


+ 35 - 0
tests/unit/gc/wasm-apps/func1.wast

@@ -0,0 +1,35 @@
+(module
+  (type $t (func))
+
+  (func (export "test") (param structref i31ref)
+    (local funcref)
+    (local funcref)
+    (local funcref)
+    (local externref)
+    (local externref)
+    (local externref)
+    (local anyref)
+    (local eqref)
+    (local structref)
+    (local arrayref)
+    (local i31ref)
+    (local (ref null 0))
+    (local (ref null 0))
+    (local (ref null 0))
+    (local (ref null 1))
+    (local (ref null func))
+    (local (ref null 0))
+    (local (ref null extern))
+    (local (ref null any))
+    (local (ref null eq))
+    (local (ref null i31))
+    (local (ref null struct))
+
+    local.get 0
+    ref.test null array
+    drop
+    local.get 1
+    ref.cast i31
+    drop
+  )
+)

BIN
tests/unit/gc/wasm-apps/func2.wasm


+ 78 - 0
tests/unit/gc/wasm-apps/func2.wast

@@ -0,0 +1,78 @@
+(module
+  (type $t0 (func))
+  (type $t1 (func (param (ref null 1))))
+  (type $t2 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref structref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 1) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 2) (ref null $t0))
+                  (result (ref null func))))
+  (type $t3 (func (param i32 i32) (result (ref null 3))))
+
+  (type $t4 (func))
+  (type $t5 (func (param (ref null 3))))
+  (type $t6 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref structref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 5) (ref null $t0))
+                  (result (ref null func))))
+  (type $t7 (func (param i32 i32) (result (ref null 4))))
+
+  (type $t11 (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type $t12 (struct))
+  (type $t13 (struct (field)))
+  (type $t14 (struct (field i8)))
+  (type $t15 (struct (field i8 i8 i8 i8)))
+  (type $t16 (struct (field $x1 i32) (field $y1 i32)))
+  (type $t17 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type $t18 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type $t19 (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  (type $t20 (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref structref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type $t21 (struct))
+  (type $t22 (struct (field)))
+  (type $t23 (struct (field i8)))
+  (type $t24 (struct (field i8 i8 i8 i8)))
+  (type $t25 (struct (field $x3 i32) (field $y3 i32)))
+  (type $t26 (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type $t27 (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type $t28 (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type $t31 (array i8))
+  (type $t32 (array i16))
+  (type $t33 (array i32))
+  (type $t34 (array i64))
+  (type $t35 (array f32))
+  (type $t36 (array f64))
+  (type $t37 (array anyref))
+  (type $t38 (array (ref i31)))
+  (type $t39 (array (ref 0)))
+  (type $t40 (array (ref null 1)))
+  (type $t43 (array (mut i8)))
+  (type $t44 (array (mut i16)))
+  (type $t45 (array (mut i32)))
+  (type $t46 (array (mut i64)))
+  (type $t47 (array (mut i32)))
+  (type $t48 (array (mut i64)))
+  (type $t49 (array (mut anyref)))
+  (type $t50 (array (mut (ref struct))))
+  (type $t51 (array (mut (ref 0))))
+  (type $t52 (array (mut (ref null i31))))
+)

BIN
tests/unit/gc/wasm-apps/global1.wasm


+ 91 - 0
tests/unit/gc/wasm-apps/global1.wast

@@ -0,0 +1,91 @@
+(module
+  (type $ftype0 (func (param i32)))
+  (type $ftype1 (func (param i32 i64) (result i32)))
+  (type $ftype2 (func (param f32 f64) (result f64)))
+  (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t1 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t2 (func (param i32 i32) (result (ref null 4))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t5 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t6 (func (param i32 i32) (result (ref null 4))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  (global $g0 funcref (ref.func $f0))
+  (global $g1 externref (ref.null extern))
+  (global $g2 anyref (ref.null any))
+  (global $g3 eqref (ref.null array))
+  (global $g4 arrayref (ref.null array))
+  (global $g5 i31ref (ref.null i31))
+
+  (func $f0)
+)

BIN
tests/unit/gc/wasm-apps/struct1.wasm


+ 10 - 0
tests/unit/gc/wasm-apps/struct1.wast

@@ -0,0 +1,10 @@
+(module
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+)

BIN
tests/unit/gc/wasm-apps/struct2.wasm


+ 33 - 0
tests/unit/gc/wasm-apps/struct2.wast

@@ -0,0 +1,33 @@
+(module
+  (type $vec (struct (field f32) (field $y (mut f32)) (field $z f32)))
+
+  ;;(global (ref $vec) (struct.new_canon $vec (f32.const 1) (f32.const 2) (f32.const 3)))
+  (global (ref $vec) (struct.new_canon_default $vec))
+
+  (func (export "new") (result anyref)
+    (struct.new_canon_default $vec)
+  )
+
+  (func $get_0 (param $v (ref $vec)) (result f32)
+    (struct.get $vec 0 (local.get $v))
+  )
+  (func (export "get_0") (result f32)
+    (call $get_0 (struct.new_canon_default $vec))
+  )
+
+  (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32)
+    (struct.set $vec $y (local.get $v) (local.get $y))
+    (struct.get $vec $y (local.get $v))
+  )
+  (func (export "set_get_y") (param $y f32) (result f32)
+    (call $set_get_y (struct.new_canon_default $vec) (local.get $y))
+  )
+
+  (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32)
+    (struct.set $vec 1 (local.get $v) (local.get $y))
+    (struct.get $vec $y (local.get $v))
+  )
+  (func (export "set_get_1") (param $y f32) (result f32)
+    (call $set_get_1 (struct.new_canon_default $vec) (local.get $y))
+  )
+)

BIN
tests/unit/gc/wasm-apps/struct3.wasm


+ 9 - 0
tests/unit/gc/wasm-apps/struct3.wast

@@ -0,0 +1,9 @@
+(module
+  (type $t (struct (field i32 (mut i32))))
+  (func (export "struct.get-null")
+    (local (ref null $t)) (drop (struct.get $t 1 (local.get 0)))
+  )
+  (func (export "struct.set-null")
+    (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0))
+  )
+)

BIN
tests/unit/gc/wasm-apps/table1.wasm


+ 108 - 0
tests/unit/gc/wasm-apps/table1.wast

@@ -0,0 +1,108 @@
+(module
+  (type $ftype0 (func (param i32)))
+  (type $ftype1 (func (param i32 i64) (result i32)))
+  (type $ftype2 (func (param f32 f64) (result f64)))
+  (type $t0 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t1 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t2 (func (param i32 i32) (result (ref null 4))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref 1) (ref 2) (ref null 1) (ref null 2))))
+  (type $t5 (func (param funcref externref (ref func)(ref extern)
+                         anyref eqref arrayref i31ref
+                         (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                         (ref null any) (ref null eq) (ref null i31) (ref null array)
+                         (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                         (ref null extern) (ref null 3) (ref null $t0))
+                  (result (ref null func))))
+  (type $t6 (func (param i32 i32) (result (ref null 4))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func)(ref extern)
+                       anyref eqref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  (table 10 funcref)
+  (table 20 externref)
+  ;; non-defaultable element type
+  ;; (table 30 (ref func))
+  ;; (table 40 (ref extern))
+  (table 50 anyref)
+  (table 60 eqref)
+  (table 100 arrayref)
+  (table 100 i31ref)
+  (table 100 (ref null 0))
+  (table 100 (ref null 2))
+  (table 100 (ref null func))
+  (table 100 (ref null extern))
+  (table 100 (ref null any))
+  (table 100 (ref null eq))
+  (table 100 (ref null i31))
+  (table 100 (ref null array))
+  ;; non-defaultable element type
+  ;; (table 100 (ref 0))
+  ;; (table 100 (ref $t0))
+  ;; (table 100 (ref 3))
+  ;; (table 100 (ref $t0))
+  (table 100 (ref null func))
+  (table 100 (ref null extern))
+  (table 100 (ref null 5))
+  (table 100 (ref null $t0))
+)

BIN
tests/unit/gc/wasm-apps/test1.wasm


+ 117 - 0
tests/unit/gc/wasm-apps/test1.wast

@@ -0,0 +1,117 @@
+(module
+  (type $t (func))
+  (type $t0 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1))))
+  (type $t1 (func (param funcref externref anyref eqref
+                         i31ref structref arrayref
+                         nullref nullfuncref nullexternref
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref null none) (ref null nofunc) (ref null noextern)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array)
+                         (ref none) (ref nofunc) (ref noextern)
+
+                         (ref null 0) (ref null $t0) (ref null $t1)
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref $t) (ref $t0) (ref $t1)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array))
+                  (result (ref null func) (ref null extern) (ref $t0))))
+  (type $t2 (func (param i32 i32) (result (ref null $t1))))
+
+  ;; Duplicated types
+  (type $t3 (func))
+  (type $t4 (func (param (ref null $t) (ref $t) (ref null 0) (ref 0) (ref null 1) (ref 1))))
+  (type $t5 (func (param funcref externref anyref eqref
+                         i31ref structref arrayref
+                         nullref nullfuncref nullexternref
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref null none) (ref null nofunc) (ref null noextern)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array)
+                         (ref none) (ref nofunc) (ref noextern)
+
+                         (ref null 0) (ref null $t0) (ref null $t1)
+                         (ref null func) (ref null extern) (ref null any) (ref null eq)
+                         (ref null i31) (ref null struct) (ref null array)
+                         (ref $t) (ref $t0) (ref $t1)
+                         (ref func) (ref extern) (ref any) (ref eq)
+                         (ref i31) (ref struct) (ref array))
+                  (result (ref null func) (ref null extern) (ref $t0))))
+  (type $t6 (func (param i32 i32) (result (ref null $t1))))
+
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func) (ref extern)
+                       anyref eqref structref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x1 i32) (field $y1 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32)))
+
+  ;; Duplicated types
+  (type (struct (field i8 (mut i16) (mut i32) i64 f32 f64
+                       funcref externref (ref func) (ref extern)
+                       anyref eqref structref arrayref i31ref
+                       (ref null 0) (ref null 2) (ref null func) (ref null extern)
+                       (ref null any) (ref null eq) (ref null i31) (ref null struct) (ref null array)
+                       (ref 0) (ref $t0) (ref 3) (ref $t0) (ref null func)
+                       (ref null extern) (ref null 5) (ref null $t0))))
+  (type (struct))
+  (type (struct (field)))
+  (type (struct (field i8)))
+  (type (struct (field i8 i8 i8 i8)))
+  (type (struct (field $x3 i32) (field $y3 i32)))
+  (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1))))
+  (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref)))
+  (type (struct (field $x4 i32) (field f32 f64) (field $y4 i32)))
+
+  (type (array i8))
+  (type (array i16))
+  (type (array i32))
+  (type (array i64))
+  (type (array f32))
+  (type (array f64))
+  (type (array anyref))
+  (type (array (ref struct)))
+  (type (array (ref array)))
+  (type (array (ref null struct)))
+  (type (array (ref null array)))
+  (type (array (ref 0)))
+  (type (array (ref null 1)))
+  (type (array (mut i8)))
+  (type (array (mut i16)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut i32)))
+  (type (array (mut i64)))
+  (type (array (mut anyref)))
+  (type (array (mut (ref struct))))
+  (type (array (mut (ref array))))
+  (type (array (mut (ref null struct))))
+  (type (array (mut (ref null array))))
+  (type (array (mut (ref 0))))
+  (type (array (mut (ref null i31))))
+
+  ;; sub types
+  (type $e0 (sub (array i32)))
+  (type $e1 (sub $e0 (array i32)))
+
+  (type $e2 (sub (array anyref)))
+  (type $e3 (sub (array (ref null $e0))))
+  (type $e4 (sub (array (ref $e1))))
+  (type $e5 (sub $e1 (array i32)))
+
+  (type $m1 (sub (array (mut i32))))
+  (type $m2 (sub $m1 (array (mut i32))))
+)

BIN
tests/unit/gc/wasm-apps/test2.wasm


+ 104 - 0
tests/unit/gc/wasm-apps/test2.wast

@@ -0,0 +1,104 @@
+(module
+  (type $ft (func))
+  (type $st (struct))
+  (type $at (array i8))
+
+  (table $ta 10 anyref)
+  (table $tf 10 funcref)
+  (table $te 10 externref)
+
+  (elem declare func $f)
+  (func $f)
+
+  (func (export "init") (param $x externref)
+    (table.set $ta (i32.const 0) (ref.null any))
+    (table.set $ta (i32.const 1) (ref.null struct))
+    (table.set $ta (i32.const 2) (ref.null none))
+    (table.set $ta (i32.const 3) (i31.new (i32.const 7)))
+    (table.set $ta (i32.const 4) (struct.new_canon_default $st))
+    (table.set $ta (i32.const 5) (array.new_canon_default $at (i32.const 0)))
+    (table.set $ta (i32.const 6) (extern.internalize (local.get $x)))
+    (table.set $ta (i32.const 7) (extern.internalize (ref.null extern)))
+
+    (table.set $tf (i32.const 0) (ref.null nofunc))
+    (table.set $tf (i32.const 1) (ref.null func))
+    (table.set $tf (i32.const 2) (ref.func $f))
+
+    (table.set $te (i32.const 0) (ref.null noextern))
+    (table.set $te (i32.const 1) (ref.null extern))
+    (table.set $te (i32.const 2) (local.get $x))
+    (table.set $te (i32.const 3) (extern.externalize (i31.new (i32.const 8))))
+    (table.set $te (i32.const 4) (extern.externalize (struct.new_canon_default $st)))
+    (table.set $te (i32.const 5) (extern.externalize (ref.null any)))
+  )
+
+  (func (export "ref_test_null_data") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $ta (local.get $i)))
+      (ref.test null none (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_any") (param $i i32) (result i32)
+    (i32.add
+      (ref.test any (table.get $ta (local.get $i)))
+      (ref.test null any (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_eq") (param $i i32) (result i32)
+    (i32.add
+      (ref.test eq (table.get $ta (local.get $i)))
+      (ref.test null eq (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_i31") (param $i i32) (result i32)
+    (i32.add
+      (ref.test i31 (table.get $ta (local.get $i)))
+      (ref.test null i31 (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_struct") (param $i i32) (result i32)
+    (i32.add
+      (ref.test struct (table.get $ta (local.get $i)))
+      (ref.test null struct (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_array") (param $i i32) (result i32)
+    (i32.add
+      (ref.test array (table.get $ta (local.get $i)))
+      (ref.test null array (table.get $ta (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_null_func") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $tf (local.get $i)))
+      (ref.test null nofunc (table.get $tf (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_func") (param $i i32) (result i32)
+    (i32.add
+      (ref.test func (table.get $tf (local.get $i)))
+      (ref.test null func (table.get $tf (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_null_extern") (param $i i32) (result i32)
+    (i32.add
+      (ref.is_null (table.get $te (local.get $i)))
+      (ref.test null noextern (table.get $te (local.get $i)))
+    )
+  )
+
+  (func (export "ref_test_extern") (param $i i32) (result i32)
+    (i32.add
+      (ref.test extern (table.get $te (local.get $i)))
+      (ref.test null extern (table.get $te (local.get $i)))
+    )
+  )
+)

Some files were not shown because too many files changed in this diff