Explorar o código

Merge pull request #3511 from bytecodealliance/main

Merge branch main into dev/checkpoint_and_restore
Wenyong Huang hai 1 ano
pai
achega
ac308c4fa9
Modificáronse 100 ficheiros con 5900 adicións e 415 borrados
  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=BIN
      tests/regression/ba-issues/issues/issue-3467/tt_unreachable.wasm
  52. BIN=BIN
      tests/regression/ba-issues/issues/issue-3468/i64.add.wasm
  53. BIN=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=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=BIN
      tests/unit/gc/wasm-apps/func1.wasm
  84. 35 0
      tests/unit/gc/wasm-apps/func1.wast
  85. BIN=BIN
      tests/unit/gc/wasm-apps/func2.wasm
  86. 78 0
      tests/unit/gc/wasm-apps/func2.wast
  87. BIN=BIN
      tests/unit/gc/wasm-apps/global1.wasm
  88. 91 0
      tests/unit/gc/wasm-apps/global1.wast
  89. BIN=BIN
      tests/unit/gc/wasm-apps/struct1.wasm
  90. 10 0
      tests/unit/gc/wasm-apps/struct1.wast
  91. BIN=BIN
      tests/unit/gc/wasm-apps/struct2.wasm
  92. 33 0
      tests/unit/gc/wasm-apps/struct2.wast
  93. BIN=BIN
      tests/unit/gc/wasm-apps/struct3.wasm
  94. 9 0
      tests/unit/gc/wasm-apps/struct3.wast
  95. BIN=BIN
      tests/unit/gc/wasm-apps/table1.wasm
  96. 108 0
      tests/unit/gc/wasm-apps/table1.wast
  97. BIN=BIN
      tests/unit/gc/wasm-apps/test1.wasm
  98. 117 0
      tests/unit/gc/wasm-apps/test1.wast
  99. BIN=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/**"
       - "!samples/workload/**"
       - "!samples/workload/**"
       - "tests/wamr-test-suites/**"
       - "tests/wamr-test-suites/**"
+      - "tests/unit/**"
       - "wamr-compiler/**"
       - "wamr-compiler/**"
       - "test-tools/wamr-ide/**"
       - "test-tools/wamr-ide/**"
   # will be triggered on push events
   # will be triggered on push events
@@ -36,6 +37,7 @@ on:
       - "samples/**"
       - "samples/**"
       - "!samples/workload/**"
       - "!samples/workload/**"
       - "tests/wamr-test-suites/**"
       - "tests/wamr-test-suites/**"
+      - "tests/unit/**"
       - "wamr-compiler/**"
       - "wamr-compiler/**"
       - "test-tools/wamr-ide/**"
       - "test-tools/wamr-ide/**"
   # allow to be triggered manually
   # allow to be triggered manually
@@ -272,10 +274,73 @@ jobs:
           cmake --build . --config Release --parallel 4
           cmake --build . --config Release --parallel 4
         working-directory: product-mini/platforms/${{ matrix.platform }}
         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
       - name: Build and run unit tests
         run: |
         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
           cmake --build . --config Release --parallel 4
           ctest
           ctest
         working-directory: tests/unit
         working-directory: tests/unit

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

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

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

@@ -112,14 +112,14 @@ jobs:
       - name: Checkout NuttX
       - name: Checkout NuttX
         uses: actions/checkout@v4
         uses: actions/checkout@v4
         with:
         with:
-          repository: apache/incubator-nuttx
+          repository: apache/nuttx
           ref: releases/12.4
           ref: releases/12.4
           path: nuttx
           path: nuttx
 
 
       - name: Checkout NuttX Apps
       - name: Checkout NuttX Apps
         uses: actions/checkout@v4
         uses: actions/checkout@v4
         with:
         with:
-          repository: apache/incubator-nuttx-apps
+          repository: apache/nuttx-apps
           ref: releases/12.4
           ref: releases/12.4
           path: apps
           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 | |
 | uvwasi | unspecified | v0.0.12 | https://github.com/nodejs/uvwasi | |
 | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | |
 | asmjit | unspecified | unspecified | https://github.com/asmjit/asmjit | |
 | zydis | unspecified | e14a07895136182a5b53e181eec3b1c6e0b434de | https://github.com/zyantific/zydis | |
 | 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/ | |
 | Dhrystone | 2.1 | 2.1 | https://fossies.org/linux/privat/old/ | |
 
 
 ## Licenses
 ## 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
 ## WAMR-2.0.0
 
 
 ### Breaking Changes
 ### 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
 #define WASM_MEM_ALLOC_WITH_USAGE 0
 #endif
 #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_ */
 #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++) {
     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;
             return false;
         }
         }
 
 
         read_uint32(buf, buf_end, module->memories[i].num_bytes_per_page);
         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);
     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
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
      * across multi-memories */
     if (module->import_memory_count > 0)
     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)
     else if (module->memory_count > 0)
-        return !!(module->memories[0].memory_flags & MEMORY64_FLAG);
+        return !!(module->memories[0].flags & MEMORY64_FLAG);
 
 
     return false;
     return false;
 }
 }

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

@@ -789,10 +789,9 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
 {
 {
     void *heap_handle;
     void *heap_handle;
     uint32 num_bytes_per_page = memory->num_bytes_per_page;
     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 default_max_pages;
     uint32 inc_page_count, global_idx;
     uint32 inc_page_count, global_idx;
     uint32 bytes_of_last_page, bytes_to_page_end;
     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;
         heap_offset = (uint64)num_bytes_per_page * init_page_count;
     uint64 memory_data_size, max_memory_data_size;
     uint64 memory_data_size, max_memory_data_size;
     uint8 *p = NULL, *global_addr;
     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;
     bool is_shared_memory = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #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 */
     /* Shared memory */
     if (is_shared_memory && parent != NULL) {
     if (is_shared_memory && parent != NULL) {
         AOTMemoryInstance *shared_memory_instance;
         AOTMemoryInstance *shared_memory_instance;
@@ -1946,7 +1945,7 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 
 
     if (!is_sub_inst) {
     if (!is_sub_inst) {
 #if WASM_ENABLE_WASI_NN != 0
 #if WASM_ENABLE_WASI_NN != 0
-        wasi_nn_destroy(module_inst);
+        wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst);
 #endif
 #endif
         wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
         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;
     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
 #if WASM_ENABLE_STRINGREF != 0
 inline static bool
 inline static bool
 wasm_is_reftype_supers_of_string(uint8 type)
 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) {
     if (func_type->param_count) {
         for (i = 0; i < argc; i++)
         for (i = 0; i < argc; i++)
             total_argv_size += (uint32)(strlen(argv[i]) + 1);
             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
         if (total_size >= UINT32_MAX
             || !(argv_buf_offset = wasm_runtime_module_malloc(
             || !(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++) {
         for (i = 0; i < argc; i++) {
             bh_memcpy_s(p, (uint32)(p_end - p), argv[i],
             bh_memcpy_s(p, (uint32)(p_end - p), argv[i],
                         (uint32)(strlen(argv[i]) + 1));
                         (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;
             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);
                     + (i - import_func_count - import_global_count);
                 module_name_rt = import->u.names.module_name;
                 module_name_rt = import->u.names.module_name;
                 field_name_rt = import->u.names.field_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
 #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);
                     + (i - import_func_count - import_global_count);
                 module_name_rt = import->module_name;
                 module_name_rt = import->module_name;
                 field_name_rt = import->memory_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
 #endif
 
 
@@ -4308,12 +4308,12 @@ wasm_memory_new_internal(wasm_store_t *store, uint16 memory_idx_rt,
         AOTModule *module_aot = (AOTModule *)inst_aot->module;
         AOTModule *module_aot = (AOTModule *)inst_aot->module;
 
 
         if (memory_idx_rt < module_aot->import_memory_count) {
         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 {
         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;
         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;
                 return ret;
         }
         }
 #endif
 #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;
     return EXCEPTION_CONTINUE_SEARCH;
 }
 }
 #endif /* end of BH_PLATFORM_WINDOWS */
 #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->kind = WASM_IMPORT_EXPORT_KIND_FUNC;
             import_type->linked =
             import_type->linked =
                 aot_import_func->func_ptr_linked ? true : false;
                 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;
             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->name = aot_import_memory->memory_name;
             import_type->kind = WASM_IMPORT_EXPORT_KIND_MEMORY;
             import_type->kind = WASM_IMPORT_EXPORT_KIND_MEMORY;
             import_type->linked = false;
             import_type->linked = false;
+            import_type->u.memory_type =
+                (WASMMemoryType *)&aot_import_memory->mem_type;
             return;
             return;
         }
         }
 
 
@@ -3931,7 +3936,8 @@ wasm_runtime_get_import_type(WASMModuleCommon *const module, int32 import_index,
         switch (import_type->kind) {
         switch (import_type->kind) {
             case WASM_IMPORT_EXPORT_KIND_FUNC:
             case WASM_IMPORT_EXPORT_KIND_FUNC:
                 import_type->linked = wasm_import->u.function.func_ptr_linked;
                 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;
                 break;
             case WASM_IMPORT_EXPORT_KIND_GLOBAL:
             case WASM_IMPORT_EXPORT_KIND_GLOBAL:
                 import_type->linked = wasm_import->u.global.is_linked;
                 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;
                     (WASMGlobalType *)&wasm_import->u.global.type;
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                import_type->linked = false;
+                import_type->linked = false; /* not supported */
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
             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;
                 break;
             default:
             default:
                 bh_assert(0);
                 bh_assert(0);
@@ -4024,12 +4030,11 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                          .type;
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                // export_type->linked = false;
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
             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;
                 break;
             default:
             default:
                 bh_assert(0);
                 bh_assert(0);
@@ -4066,13 +4071,13 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
                          .type;
                          .type;
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_TABLE:
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                /* not supported */
-                // export_type->linked = false;
                 break;
                 break;
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
             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;
                 break;
+            default:
                 bh_assert(0);
                 bh_assert(0);
                 break;
                 break;
         }
         }
@@ -4168,7 +4173,7 @@ wasm_func_type_get_result_valkind(WASMFuncType *const func_type,
 }
 }
 
 
 wasm_valkind_t
 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);
     bh_assert(global_type);
 
 
@@ -4176,13 +4181,37 @@ wasm_global_type_get_valkind(const wasm_global_type_t global_type)
 }
 }
 
 
 bool
 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);
     bh_assert(global_type);
 
 
     return global_type->is_mutable;
     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
 bool
 wasm_runtime_register_natives(const char *module_name,
 wasm_runtime_register_natives(const char *module_name,
                               NativeSymbol *native_symbols,
                               NativeSymbol *native_symbols,
@@ -6517,8 +6546,8 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
         if (export->index < module->import_memory_count) {
         if (export->index < module->import_memory_count) {
             WASMMemoryImport *import_memory =
             WASMMemoryImport *import_memory =
                 &((module->import_memories + export->index)->u.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 {
         else {
             WASMMemory *memory =
             WASMMemory *memory =
@@ -6538,14 +6567,14 @@ wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
         if (export->index < module->import_memory_count) {
         if (export->index < module->import_memory_count) {
             AOTImportMemory *import_memory =
             AOTImportMemory *import_memory =
                 module->import_memories + export->index;
                 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 {
         else {
             AOTMemory *memory = module->memories
             AOTMemory *memory = module->memories
                                 + (export->index - module->import_memory_count);
                                 + (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;
         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 */
     /* Set memory page count */
     for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
     for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
         if (i < module->import_memory_count) {
         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 =
             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 {
         else {
             j = i - module->import_memory_count;
             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 =
             comp_data->memories[i].num_bytes_per_page =
                 module->memories[j].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;
                 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;
                 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;
 typedef WASMArrayType AOTArrayType;
 #endif
 #endif
 typedef WASMExport AOTExport;
 typedef WASMExport AOTExport;
+typedef WASMMemory AOTMemory;
+typedef WASMMemoryType AOTMemoryType;
 
 
 #if WASM_ENABLE_DEBUG_AOT != 0
 #if WASM_ENABLE_DEBUG_AOT != 0
 typedef void *dwarf_extractor_handle_t;
 typedef void *dwarf_extractor_handle_t;
@@ -81,23 +83,9 @@ typedef enum AOTFloatCond {
 typedef struct AOTImportMemory {
 typedef struct AOTImportMemory {
     char *module_name;
     char *module_name;
     char *memory_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;
 } 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
  * 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 {
                 else {
                     frame_ip--;
                     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 =
                     func_type =
                         (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                         (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                     param_count = func_type->param_count;
                     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_LOOP:
             case EXT_OP_IF:
             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 =
                 func_type =
                     (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                     (AOTFuncType *)comp_ctx->comp_data->types[type_index];
                 param_count = func_type->param_count;
                 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)
     } while (0)
 
 
 #if WASM_ENABLE_MEMORY64 != 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) \
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
 #else
 #else

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

@@ -189,7 +189,7 @@ get_import_memory_size(AOTCompData *comp_data)
 static uint32
 static uint32
 get_memory_size(AOTCompData *comp_data)
 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) */
                                init_page_count + max_page_count) */
     return (uint32)(sizeof(uint32)
     return (uint32)(sizeof(uint32)
                     + comp_data->memory_count * sizeof(uint32) * 4);
                     + 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_U32(comp_data->memory_count);
     /* Emit memory items */
     /* Emit memory items */
     for (i = 0; i < comp_data->memory_count; i++) {
     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].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 */
     /* 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;
     LLVMBasicBlockRef terminate_block, non_terminate_block;
     AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
     AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
     bool is_shared_memory =
     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
     /* Only need to check the suspend flags when memory is shared since
        shared memory must be enabled for multi-threading */
        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;
     bool is_target_64bit, is_local_of_aot_value = false;
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #if WASM_ENABLE_SHARED_MEMORY != 0
     bool is_shared_memory =
     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
 #endif
 
 
     is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64)) ? true : false;
     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 =
         uint32 num_bytes_per_page =
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
         uint32 init_page_count =
         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;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
 
 
         if (mem_offset + bytes <= mem_data_size) {
         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,
              && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value,
                                            offset, bytes))) {
                                            offset, bytes))) {
         uint32 init_page_count =
         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) {
         if (init_page_count == 0) {
             LLVMValueRef mem_size;
             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 */
     /* Get memory base address and memory data size */
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #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) {
     if (func_ctx->mem_space_unchanged || is_shared_memory) {
 #else
 #else
@@ -961,7 +960,7 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         uint32 num_bytes_per_page =
         uint32 num_bytes_per_page =
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
             comp_ctx->comp_data->memories[0].num_bytes_per_page;
         uint32 init_page_count =
         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;
         uint64 mem_data_size = (uint64)num_bytes_per_page * init_page_count;
         if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) {
         if (mem_data_size > 0 && mem_offset + mem_len <= mem_data_size) {
             /* inside memory space */
             /* 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 */
     /* Load memory base address */
 #if WASM_ENABLE_SHARED_MEMORY != 0
 #if WASM_ENABLE_SHARED_MEMORY != 0
     is_shared_memory =
     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) {
     if (is_shared_memory) {
         LLVMValueRef shared_mem_addr;
         LLVMValueRef shared_mem_addr;
         offset = I32_CONST(offsetof(AOTModuleInstance, memories));
         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) {
     if (mem_idx < module->import_memory_count) {
         memory_import = &(module->import_memories[mem_idx].u.memory);
         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 {
     else {
         memory = &module->memories[mem_idx - module->import_memory_count];
         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_LOOP:
             case EXT_OP_IF:
             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];
                 func_type = cc->cur_wasm_module->types[type_idx];
                 param_count = func_type->param_count;
                 param_count = func_type->param_count;
                 param_types = func_type->types;
                 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;
 struct WASMGlobalType;
 typedef struct WASMGlobalType *wasm_global_type_t;
 typedef struct WASMGlobalType *wasm_global_type_t;
 
 
+struct WASMMemory;
+typedef struct WASMMemory WASMMemoryType;
+typedef WASMMemoryType *wasm_memory_type_t;
+
 typedef struct wasm_import_t {
 typedef struct wasm_import_t {
     const char *module_name;
     const char *module_name;
     const char *name;
     const char *name;
@@ -86,6 +90,7 @@ typedef struct wasm_import_t {
     union {
     union {
         wasm_func_type_t func_type;
         wasm_func_type_t func_type;
         wasm_global_type_t global_type;
         wasm_global_type_t global_type;
+        wasm_memory_type_t memory_type;
     } u;
     } u;
 } wasm_import_t;
 } wasm_import_t;
 
 
@@ -95,6 +100,7 @@ typedef struct wasm_export_t {
     union {
     union {
         wasm_func_type_t func_type;
         wasm_func_type_t func_type;
         wasm_global_type_t global_type;
         wasm_global_type_t global_type;
+        wasm_memory_type_t memory_type;
     } u;
     } u;
 } wasm_export_t;
 } 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_RUNTIME_API_EXTERN bool
 wasm_global_type_get_mutable(const wasm_global_type_t global_type);
 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
  * 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 num_bytes_per_page;
     uint32 init_page_count;
     uint32 init_page_count;
     uint32 max_page_count;
     uint32 max_page_count;
-} WASMMemory;
+} WASMMemory, WASMMemoryType;
 
 
 typedef struct WASMTableImport {
 typedef struct WASMTableImport {
     char *module_name;
     char *module_name;
@@ -536,10 +536,7 @@ typedef struct WASMTableImport {
 typedef struct WASMMemoryImport {
 typedef struct WASMMemoryImport {
     char *module_name;
     char *module_name;
     char *field_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
 #if WASM_ENABLE_MULTI_MODULE != 0
     WASMModule *import_module;
     WASMModule *import_module;
     WASMMemory *import_memory_linked;
     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 */
                 /* clang-format off */
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
-                    local_offset = *frame_ip++;
+                local_offset = *frame_ip++;
 #else
 #else
-                    local_offset = *frame_ip;
-                    frame_ip += 2;
+                local_offset = *frame_ip;
+                frame_ip += 2;
 #endif
 #endif
                 /* clang-format on */
                 /* clang-format on */
                 *(uint32 *)(frame_lp + local_offset) =
                 *(uint32 *)(frame_lp + local_offset) =
@@ -3463,10 +3463,10 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
             {
             {
                 /* clang-format off */
                 /* clang-format off */
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
-                    local_offset = *frame_ip++;
+                local_offset = *frame_ip++;
 #else
 #else
-                    local_offset = *frame_ip;
-                    frame_ip += 2;
+                local_offset = *frame_ip;
+                frame_ip += 2;
 #endif
 #endif
                 /* clang-format on */
                 /* clang-format on */
                 PUT_I64_TO_ADDR((uint32 *)(frame_lp + local_offset),
                 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
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
      * across multi-memories */
     if (module->import_memory_count > 0)
     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)
     else if (module->memory_count > 0)
         return !!(module->memories[0].flags & MEMORY64_FLAG);
         return !!(module->memories[0].flags & MEMORY64_FLAG);
 
 
@@ -379,7 +380,8 @@ loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
 {
 {
     void *mem;
     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");
         set_error_buf(error_buf, error_buf_size, "allocate memory failed");
         return NULL;
         return NULL;
     }
     }
@@ -2934,10 +2936,10 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
     }
     }
 
 
     /* now we believe all declaration are ok */
     /* 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;
     *p_buf = p;
 
 
@@ -3052,7 +3054,12 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
 
 
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
     CHECK_BUF(p, p_end, 2);
     CHECK_BUF(p, p_end, 2);
+    /* global type */
     declare_type = read_uint8(p);
     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);
     declare_mutable = read_uint8(p);
 #else
 #else
     if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
     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++) {
         for (i = 0; i < global_count; i++, global++) {
 #if WASM_ENABLE_GC == 0
 #if WASM_ENABLE_GC == 0
             CHECK_BUF(p, p_end, 2);
             CHECK_BUF(p, p_end, 2);
+            /* global type */
             global->type.val_type = read_uint8(p);
             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);
             mutable = read_uint8(p);
 #else
 #else
             if (!resolve_value_type(&p, p_end, module, module->type_count,
             if (!resolve_value_type(&p, p_end, module, module->type_count,
@@ -4705,8 +4717,12 @@ fail:
 
 
 static bool
 static bool
 load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
 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;
     const uint8 *p = buf, *p_end = buf_end;
     uint32 data_seg_count, i, mem_index, data_seg_len;
     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);
     read_leb_uint32(p, p_end, data_seg_count);
 
 
 #if WASM_ENABLE_BULK_MEMORY != 0
 #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,
         set_error_buf(error_buf, error_buf_size,
                       "data count and data section have inconsistent lengths");
                       "data count and data section have inconsistent lengths");
         return false;
         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 */
                 /* This memory_flag is from memory instead of data segment */
                 uint8 memory_flag;
                 uint8 memory_flag;
                 if (module->import_memory_count > 0) {
                 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 {
                 else {
                     memory_flag =
                     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 = buf;
         module->name_section_buf_end = buf_end;
         module->name_section_buf_end = buf_end;
         p += name_len;
         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.");
         LOG_VERBOSE("Load custom name section success.");
-        return true;
     }
     }
 #endif
 #endif
 
 
@@ -5778,6 +5794,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool clone_data_seg = 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 */
     /* Find code and function sections if have */
     while (section) {
     while (section) {
@@ -5870,6 +5889,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 break;
                 break;
             case SECTION_TYPE_DATA:
             case SECTION_TYPE_DATA:
                 if (!load_data_segment_section(buf, buf_end, module,
                 if (!load_data_segment_section(buf, buf_end, module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                                               has_datacount_section,
+#endif
                                                clone_data_seg, error_buf,
                                                clone_data_seg, error_buf,
                                                error_buf_size))
                                                error_buf_size))
                     return false;
                     return false;
@@ -5879,6 +5901,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                                             error_buf_size))
                                             error_buf_size))
                     return false;
                     return false;
+                has_datacount_section = true;
                 break;
                 break;
 #endif
 #endif
 #if WASM_ENABLE_STRINGREF != 0
 #if WASM_ENABLE_STRINGREF != 0
@@ -6131,13 +6154,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             if (shrunk_memory_size <= UINT32_MAX) {
             if (shrunk_memory_size <= UINT32_MAX) {
                 if (module->import_memory_count) {
                 if (module->import_memory_count) {
                     memory_import = &module->import_memories[0].u.memory;
                     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) {
                     if (shrunk_memory_size <= init_memory_size) {
                         /* Reset memory info to decrease memory usage */
                         /* 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;
                             (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,
                         LOG_VERBOSE("Shrink import memory size to %" PRIu64,
                                     shrunk_memory_size);
                                     shrunk_memory_size);
                     }
                     }
@@ -6163,16 +6187,16 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             memory_import = &module->import_memories[0].u.memory;
             memory_import = &module->import_memories[0].u.memory;
             /* Only resize the memory to one big page if num_bytes_per_page is
             /* Only resize the memory to one big page if num_bytes_per_page is
              * in valid range of uint32 */
              * 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
                 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) {
         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)
                 char *error_buf, uint32 error_buf_size)
 {
 {
     WASMSection *section_list_end = NULL, *section;
     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;
     uint8 section_type, section_index, last_section_index = (uint8)-1;
     uint32 section_size;
     uint32 section_size;
 
 
@@ -7075,7 +7099,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                 }
                 }
                 else {
                 else {
                     p--;
                     p--;
-                    skip_leb_uint32(p, p_end);
+                    /* block type */
+                    skip_leb_int32(p, p_end);
                 }
                 }
                 if (block_nested_depth
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     < 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_LOOP:
             case EXT_OP_IF:
             case EXT_OP_IF:
                 /* block type */
                 /* block type */
-                skip_leb_uint32(p, p_end);
+                skip_leb_int32(p, p_end);
                 if (block_nested_depth
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     block_stack[block_nested_depth].start_addr = p;
                     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)
 #if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0)
             case WASM_OP_SIMD_PREFIX:
             case WASM_OP_SIMD_PREFIX:
             {
             {
-                /* TODO: memory64 offset type changes */
                 uint32 opcode1;
                 uint32 opcode1;
 
 
                 read_leb_uint32(p, p_end, 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:
                     case SIMD_v128_store:
                         /* memarg align */
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         break;
                         break;
 
 
                     case SIMD_v128_const:
                     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:
                     case SIMD_v128_store64_lane:
                         /* memarg align */
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         /* ImmLaneId */
                         /* ImmLaneId */
                         CHECK_BUF(p, p_end, 1);
                         CHECK_BUF(p, p_end, 1);
                         p++;
                         p++;
@@ -7723,8 +7747,8 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
                     case SIMD_v128_load64_zero:
                     case SIMD_v128_load64_zero:
                         /* memarg align */
                         /* memarg align */
                         skip_leb_uint32(p, p_end);
                         skip_leb_uint32(p, p_end);
-                        /* memarg offset*/
-                        skip_leb_uint32(p, p_end);
+                        /* memarg offset */
+                        skip_leb_mem_offset(p, p_end);
                         break;
                         break;
 
 
                     default:
                     default:
@@ -7840,7 +7864,11 @@ typedef struct BranchBlock {
     BranchBlockPatch *patch_list;
     BranchBlockPatch *patch_list;
     /* This is used to save params frame_offset of of if block */
     /* This is used to save params frame_offset of of if block */
     int16 *param_frame_offsets;
     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;
     uint16 start_dynamic_offset;
 #endif
 #endif
 
 
@@ -7991,13 +8019,26 @@ static void
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 {
 {
     BranchBlock *tmp_csp = frame_csp;
     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);
         free_label_patch_list(tmp_csp);
         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 */
 #endif /* end of WASM_ENABLE_FAST_INTERP */
 
 
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
@@ -8116,6 +8157,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
         if (ctx->frame_csp_bottom) {
         if (ctx->frame_csp_bottom) {
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
             free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
             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
 #endif
 #if WASM_ENABLE_GC != 0
 #if WASM_ENABLE_GC != 0
             wasm_loader_clean_all_local_use_masks(ctx);
             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));
             emit_operand(ctx, *(int16 *)(frame_offset));
         }
         }
         /* Part e */
         /* 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)
         if (is_br)
             ctx->dynamic_offset = dynamic_offset;
             ctx->dynamic_offset = dynamic_offset;
         for (i = (int32)arity - 1; i >= 0; i--) {
         for (i = (int32)arity - 1; i >= 0; i--) {
@@ -10613,8 +10662,8 @@ fail:
  *   Part e: each param's dst offset
  *   Part e: each param's dst offset
  */
  */
 static bool
 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;
     bool ret = false;
     int16 *frame_offset = NULL;
     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;
     uint32 param_count = block_type->u.type->param_count;
     int16 condition_offset = 0;
     int16 condition_offset = 0;
     bool disable_emit = false;
     bool disable_emit = false;
+    bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false);
     int16 operand_offset = 0;
     int16 operand_offset = 0;
 
 
     uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
     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)
     if (is_if_block)
         emit_operand(loader_ctx, condition_offset);
         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) */
     /* Part e) */
     /* Push to dynamic space. The push will emit the dst offset. */
     /* Push to dynamic space. The push will emit the dst offset. */
     for (i = 0; i < param_count; i++)
     for (i = 0; i < param_count; i++)
@@ -11052,12 +11110,12 @@ re_scan:
 #endif /* end of WASM_ENABLE_GC != 0 */
 #endif /* end of WASM_ENABLE_GC != 0 */
                 }
                 }
                 else {
                 else {
-                    uint32 type_index;
+                    int32 type_index;
                     /* Resolve the leb128 encoded type index as block type */
                     /* Resolve the leb128 encoded type index as block type */
                     p--;
                     p--;
                     p_org = p - 1;
                     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,
                         set_error_buf(error_buf, error_buf_size,
                                       "unknown type");
                                       "unknown type");
                         goto fail;
                         goto fail;
@@ -11161,8 +11219,8 @@ re_scan:
 
 
                     if (BLOCK_HAS_PARAM(block_type)) {
                     if (BLOCK_HAS_PARAM(block_type)) {
                         /* Make sure params are in dynamic space */
                         /* 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;
                             goto fail;
                     }
                     }
 
 
@@ -11208,8 +11266,8 @@ re_scan:
                         /* skip the if label */
                         /* skip the if label */
                         skip_label();
                         skip_label();
                         /* Emit a copy instruction */
                         /* 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;
                             goto fail;
 
 
                         /* Emit the if instruction */
                         /* 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
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
      * across multi-memories */
     if (module->import_memory_count > 0)
     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)
     else if (module->memory_count > 0)
         return !!(module->memories[0].flags & MEMORY64_FLAG);
         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 */
     /* 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;
     *p_buf = p;
     return true;
     return true;
@@ -1740,8 +1740,12 @@ load_table_segment_section(const uint8 *buf, const uint8 *buf_end,
 
 
 static bool
 static bool
 load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
 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;
     const uint8 *p = buf, *p_end = buf_end;
     uint32 data_seg_count, i, mem_index, data_seg_len;
     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);
     read_leb_uint32(p, p_end, data_seg_count);
 
 
 #if WASM_ENABLE_BULK_MEMORY != 0
 #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);
               || data_seg_count == module->data_seg_count1);
 #endif
 #endif
 
 
@@ -1808,7 +1812,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
                 uint8 memory_flag;
                 uint8 memory_flag;
                 if (module->import_memory_count > 0) {
                 if (module->import_memory_count > 0) {
                     memory_flag =
                     memory_flag =
-                        module->import_memories[mem_index].u.memory.flags;
+                        module->import_memories[mem_index].u.mem_type.flags;
                 }
                 }
                 else {
                 else {
                     memory_flag =
                     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 WASM_ENABLE_CUSTOM_NAME_SECTION != 0
     if (name_len == 4 && memcmp(p, "name", 4) == 0) {
     if (name_len == 4 && memcmp(p, "name", 4) == 0) {
         p += name_len;
         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
 #endif
     LOG_VERBOSE("Load custom section success.\n");
     LOG_VERBOSE("Load custom section success.\n");
@@ -2108,7 +2114,7 @@ static bool
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
                                uint32 error_buf_size)
                                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 };
     AOTCompOption option = { 0 };
     char *aot_last_error;
     char *aot_last_error;
     uint64 size;
     uint64 size;
@@ -2579,6 +2585,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     uint8 malloc_free_io_type = VALUE_TYPE_I32;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool reuse_const_strings = is_load_from_file_buf && !wasm_binary_freeable;
     bool clone_data_seg = 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 */
     /* Find code and function sections if have */
     while (section) {
     while (section) {
@@ -2660,6 +2669,9 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 break;
                 break;
             case SECTION_TYPE_DATA:
             case SECTION_TYPE_DATA:
                 if (!load_data_segment_section(buf, buf_end, module,
                 if (!load_data_segment_section(buf, buf_end, module,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                                               has_datacount_section,
+#endif
                                                clone_data_seg, error_buf,
                                                clone_data_seg, error_buf,
                                                error_buf_size))
                                                error_buf_size))
                     return false;
                     return false;
@@ -2669,6 +2681,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                 if (!load_datacount_section(buf, buf_end, module, error_buf,
                                             error_buf_size))
                                             error_buf_size))
                     return false;
                     return false;
+                has_datacount_section = true;
                 break;
                 break;
 #endif
 #endif
             default:
             default:
@@ -2909,12 +2922,14 @@ load_from_sections(WASMModule *module, WASMSection *sections,
             if (shrunk_memory_size <= UINT32_MAX) {
             if (shrunk_memory_size <= UINT32_MAX) {
                 if (module->import_memory_count) {
                 if (module->import_memory_count) {
                     memory_import = &module->import_memories[0].u.memory;
                     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) {
                     if (shrunk_memory_size <= init_memory_size) {
                         /* Reset memory info to decrease memory usage */
                         /* 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,
                         LOG_VERBOSE("Shrink import memory size to %" PRIu64,
                                     shrunk_memory_size);
                                     shrunk_memory_size);
                     }
                     }
@@ -2937,15 +2952,15 @@ load_from_sections(WASMModule *module, WASMSection *sections,
 
 
         if (module->import_memory_count) {
         if (module->import_memory_count) {
             memory_import = &module->import_memories[0].u.memory;
             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
                 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 *
 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);
     WASMModule *module = create_module(args->name, error_buf, error_buf_size);
     if (!module) {
     if (!module) {
@@ -3239,6 +3257,10 @@ wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf,
         goto fail;
         goto fail;
     }
     }
 
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+    (void)main_module;
+#endif
+
     LOG_VERBOSE("Load module success.\n");
     LOG_VERBOSE("Load module success.\n");
     return module;
     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_LOOP:
             case EXT_OP_IF:
             case EXT_OP_IF:
                 /* block type */
                 /* block type */
-                skip_leb_uint32(p, p_end);
+                skip_leb_int32(p, p_end);
                 if (block_nested_depth
                 if (block_nested_depth
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     < sizeof(block_stack) / sizeof(BlockAddr)) {
                     block_stack[block_nested_depth].start_addr = p;
                     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
     /* 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 */
      * opcode can know how many parameters should be copied to the stack */
     uint32 available_param_num;
     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;
     uint16 start_dynamic_offset;
 #endif
 #endif
 
 
@@ -4050,13 +4076,26 @@ static void
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 free_all_label_patch_lists(BranchBlock *frame_csp, uint32 csp_num)
 {
 {
     BranchBlock *tmp_csp = frame_csp;
     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);
         free_label_patch_list(tmp_csp);
         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
 #endif
 
 
 static bool
 static bool
@@ -4120,6 +4159,8 @@ wasm_loader_ctx_destroy(WASMLoaderContext *ctx)
         if (ctx->frame_csp_bottom) {
         if (ctx->frame_csp_bottom) {
 #if WASM_ENABLE_FAST_INTERP != 0
 #if WASM_ENABLE_FAST_INTERP != 0
             free_all_label_patch_lists(ctx->frame_csp_bottom, ctx->csp_num);
             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
 #endif
             wasm_runtime_free(ctx->frame_csp_bottom);
             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));
             emit_operand(ctx, *(int16 *)(frame_offset));
         }
         }
         /* Part e */
         /* 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)
         if (is_br)
             ctx->dynamic_offset = dynamic_offset;
             ctx->dynamic_offset = dynamic_offset;
         for (i = (int32)arity - 1; i >= 0; i--) {
         for (i = (int32)arity - 1; i >= 0; i--) {
@@ -5778,8 +5825,8 @@ fail:
  *   Part e: each param's dst offset
  *   Part e: each param's dst offset
  */
  */
 static bool
 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;
     bool ret = false;
     int16 *frame_offset = NULL;
     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;
     uint32 param_count = block_type->u.type->param_count;
     int16 condition_offset = 0;
     int16 condition_offset = 0;
     bool disable_emit = false;
     bool disable_emit = false;
+    bool is_if_block = (block->label_type == LABEL_TYPE_IF ? true : false);
     int16 operand_offset = 0;
     int16 operand_offset = 0;
 
 
     uint64 size = (uint64)param_count * (sizeof(*cells) + sizeof(*src_offsets));
     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)
     if (is_if_block)
         emit_operand(loader_ctx, condition_offset);
         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) */
     /* Part e) */
     /* Push to dynamic space. The push will emit the dst offset. */
     /* Push to dynamic space. The push will emit the dst offset. */
     for (i = 0; i < param_count; i++)
     for (i = 0; i < param_count; i++)
@@ -6043,11 +6099,11 @@ re_scan:
                     block_type.u.value_type.type = value_type;
                     block_type.u.value_type.type = value_type;
                 }
                 }
                 else {
                 else {
-                    uint32 type_index;
+                    int32 type_index;
                     /* Resolve the leb128 encoded type index as block type */
                     /* Resolve the leb128 encoded type index as block type */
                     p--;
                     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.is_value_type = false;
                     block_type.u.type = module->types[type_index];
                     block_type.u.type = module->types[type_index];
 #if WASM_ENABLE_FAST_INTERP == 0
 #if WASM_ENABLE_FAST_INTERP == 0
@@ -6134,8 +6190,8 @@ re_scan:
                     skip_label();
                     skip_label();
                     if (BLOCK_HAS_PARAM(block_type)) {
                     if (BLOCK_HAS_PARAM(block_type)) {
                         /* Make sure params are in dynamic space */
                         /* 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;
                             goto fail;
                     }
                     }
                     if (opcode == WASM_OP_LOOP) {
                     if (opcode == WASM_OP_LOOP) {
@@ -6175,8 +6231,8 @@ re_scan:
                         /* skip the if label */
                         /* skip the if label */
                         skip_label();
                         skip_label();
                         /* Emit a copy instruction */
                         /* 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;
                             goto fail;
 
 
                         /* Emit the if instruction */
                         /* Emit the if instruction */
@@ -6942,7 +6998,8 @@ re_scan:
                     uint32 j;
                     uint32 j;
 
 
                     for (i = 0; i < module->global_count; i++) {
                     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
                             && module->globals[i].init_expr.init_expr_type
                                    == INIT_EXPR_TYPE_FUNCREF_CONST
                                    == INIT_EXPR_TYPE_FUNCREF_CONST
                             && module->globals[i].init_expr.u.u32 == func_idx) {
                             && 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 */
     /* instantiate memories from import section */
     import = module->import_memories;
     import = module->import_memories;
     for (i = 0; i < module->import_memory_count; i++, import++, memory++) {
     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(
         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;
         uint32 actual_heap_size = heap_size;
 
 
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -3181,7 +3182,7 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
 
 
     if (!is_sub_inst) {
     if (!is_sub_inst) {
 #if WASM_ENABLE_WASI_NN != 0
 #if WASM_ENABLE_WASI_NN != 0
-        wasi_nn_destroy(module_inst);
+        wasi_nn_destroy((WASMModuleInstanceCommon *)module_inst);
 #endif
 #endif
         wasm_native_call_context_dtors((WASMModuleInstanceCommon *)module_inst);
         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.
 To run the tests we assume that the current directory is the root of the repository.
 
 
-
 ### Build the runtime
 ### Build the runtime
 
 
 Build the runtime image for your execution target type.
 Build the runtime image for your execution target type.
 
 
 `EXECUTION_TYPE` can be:
 `EXECUTION_TYPE` can be:
-* `cpu`
-* `nvidia-gpu`
-* `vx-delegate`
-* `tpu`
+
+- `cpu`
+- `nvidia-gpu`
+- `vx-delegate`
+- `tpu`
 
 
 ```
 ```
 EXECUTION_TYPE=cpu
 EXECUTION_TYPE=cpu
 docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
 docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
 ```
 ```
 
 
-
 ### Build wasm app
 ### 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
 docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile
 ```
 ```
 
 
-
 ### Run wasm app
 ### Run wasm app
 
 
 If all the tests have run properly you will the the following message in the terminal,
 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!
 Tests: passed!
 ```
 ```
 
 
-* CPU
+- CPU
 
 
 ```
 ```
 docker run \
 docker run \
@@ -64,9 +62,9 @@ docker run \
     /assets/test_tensorflow.wasm
     /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 \
 docker run \
@@ -79,7 +77,7 @@ docker run \
     /assets/test_tensorflow.wasm
     /assets/test_tensorflow.wasm
 ```
 ```
 
 
-* vx-delegate for NPU (x86 simulator)
+- vx-delegate for NPU (x86 simulator)
 
 
 ```
 ```
 docker run \
 docker run \
@@ -90,9 +88,9 @@ docker run \
     /assets/test_tensorflow_quantized.wasm
     /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 \
 docker run \
@@ -109,6 +107,45 @@ docker run \
 
 
 Supported:
 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 encoding  Model encoding.
  * @param target    Execution target.
  * @param target    Execution target.
  * @param g         Graph.
  * @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,
 load(graph_builder_array *builder, graph_encoding encoding,
      execution_target target, graph *g)
      execution_target target, graph *g)
     __attribute__((import_module("wasi_nn")));
     __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.
  * @brief Create an execution instance of a loaded graph.
  *
  *
  * @param g         Graph.
  * @param g         Graph.
  * @param ctx       Execution context.
  * @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)
 init_execution_context(graph g, graph_execution_context *ctx)
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));
 
 
@@ -54,9 +51,9 @@ init_execution_context(graph g, graph_execution_context *ctx)
  * @param ctx       Execution context.
  * @param ctx       Execution context.
  * @param index     Input tensor index.
  * @param index     Input tensor index.
  * @param tensor    Input tensor.
  * @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)
 set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
     __attribute__((import_module("wasi_nn")));
     __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.
  * @brief Compute the inference on the given inputs.
  *
  *
  * @param ctx       Execution context.
  * @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")));
 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.
  * @param output_tensor_size    Pointer to `output_tensor` maximum size.
  *                              After the function call it is updated with the
  *                              After the function call it is updated with the
  * copied number of bytes.
  * 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,
 get_output(graph_execution_context ctx, uint32_t index,
            tensor_data output_tensor, uint32_t *output_tensor_size)
            tensor_data output_tensor, uint32_t *output_tensor_size)
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));

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

@@ -28,7 +28,7 @@ typedef enum {
     busy,
     busy,
     // Runtime Error.
     // Runtime Error.
     runtime_error,
     runtime_error,
-} error;
+} wasi_nn_error;
 
 
 /**
 /**
  * TENSOR
  * TENSOR
@@ -106,4 +106,7 @@ typedef enum {
 // Define where the graph should be executed.
 // Define where the graph should be executed.
 typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
 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
 #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"
 #include "wasi_nn_app_native.h"
 
 
-static error
+static wasi_nn_error
 graph_builder_app_native(wasm_module_inst_t instance,
 graph_builder_app_native(wasm_module_inst_t instance,
                          graph_builder_wasm *builder_wasm,
                          graph_builder_wasm *builder_wasm,
                          graph_builder *builder)
                          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}
  * builder_array_wasm is consisted of {builder_wasm, size}
  */
  */
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_wasm *builder_wasm, uint32_t size,
                                graph_builder_wasm *builder_wasm, uint32_t size,
                                graph_builder_array *builder_array)
                                graph_builder_array *builder_array)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
-error
+wasi_nn_error
 graph_builder_array_app_native(wasm_module_inst_t instance,
 graph_builder_array_app_native(wasm_module_inst_t instance,
                                graph_builder_array_wasm *builder_array_wasm,
                                graph_builder_array_wasm *builder_array_wasm,
                                graph_builder_array *builder_array)
                                graph_builder_array *builder_array)
@@ -79,7 +79,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance,
         return missing_memory;
         return missing_memory;
 
 
     for (uint32_t i = 0; i < array_size; ++i) {
     for (uint32_t i = 0; i < array_size; ++i) {
-        error res;
+        wasi_nn_error res;
         if (success
         if (success
             != (res = graph_builder_app_native(instance, &builder_wasm[i],
             != (res = graph_builder_app_native(instance, &builder_wasm[i],
                                                &builder[i]))) {
                                                &builder[i]))) {
@@ -97,7 +97,7 @@ graph_builder_array_app_native(wasm_module_inst_t instance,
 #undef array_size
 #undef array_size
 }
 }
 
 
-static error
+static wasi_nn_error
 tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
 tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
                        tensor_wasm *input_tensor_wasm, tensor_data *data)
                        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
 #undef data_size
 }
 }
 
 
-static error
+static wasi_nn_error
 tensor_dimensions_app_native(wasm_module_inst_t instance,
 tensor_dimensions_app_native(wasm_module_inst_t instance,
                              tensor_wasm *input_tensor_wasm,
                              tensor_wasm *input_tensor_wasm,
                              tensor_dimensions **dimensions)
                              tensor_dimensions **dimensions)
@@ -159,7 +159,7 @@ tensor_dimensions_app_native(wasm_module_inst_t instance,
     return success;
     return success;
 }
 }
 
 
-error
+wasi_nn_error
 tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
 tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
                   tensor *input_tensor)
                   tensor *input_tensor)
 {
 {
@@ -170,7 +170,7 @@ tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
         return invalid_argument;
         return invalid_argument;
     }
     }
 
 
-    error res;
+    wasi_nn_error res;
 
 
     tensor_dimensions *dimensions = NULL;
     tensor_dimensions *dimensions = NULL;
     if (success
     if (success

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

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

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

@@ -11,7 +11,6 @@
 #include <string.h>
 #include <string.h>
 #include <stdint.h>
 #include <stdint.h>
 
 
-#include "wasi_nn.h"
 #include "wasi_nn_private.h"
 #include "wasi_nn_private.h"
 #include "wasi_nn_app_native.h"
 #include "wasi_nn_app_native.h"
 #include "wasi_nn_tensorflowlite.hpp"
 #include "wasi_nn_tensorflowlite.hpp"
@@ -24,14 +23,15 @@
 
 
 /* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
 /* 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 {
 typedef struct {
     LOAD load;
     LOAD load;
@@ -177,7 +177,7 @@ is_encoding_implemented(graph_encoding encoding)
            && lookup[encoding].get_output;
            && lookup[encoding].get_output;
 }
 }
 
 
-static error
+static wasi_nn_error
 is_model_initialized(WASINNContext *wasi_nn_ctx)
 is_model_initialized(WASINNContext *wasi_nn_ctx)
 {
 {
     if (!wasi_nn_ctx->is_model_loaded) {
     if (!wasi_nn_ctx->is_model_loaded) {
@@ -190,12 +190,12 @@ is_model_initialized(WASINNContext *wasi_nn_ctx)
 /* WASI-NN implementation */
 /* WASI-NN implementation */
 
 
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
-error
+wasi_nn_error
 wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder,
 wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_wasm *builder,
              uint32_t builder_wasm_size, graph_encoding encoding,
              uint32_t builder_wasm_size, graph_encoding encoding,
              execution_target target, graph *g)
              execution_target target, graph *g)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
 #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,
 wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
              graph_encoding encoding, execution_target target, graph *g)
              graph_encoding encoding, execution_target target, graph *g)
 #endif /* WASM_ENABLE_WASI_EPHEMERAL_NN != 0 */
 #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);
     wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
     bh_assert(instance);
     bh_assert(instance);
 
 
-    error res;
+    wasi_nn_error res;
     graph_builder_array builder_native = { 0 };
     graph_builder_array builder_native = { 0 };
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
 #if WASM_ENABLE_WASI_EPHEMERAL_NN != 0
     if (success
     if (success
@@ -249,7 +249,7 @@ fail:
     return res;
     return res;
 }
 }
 
 
-error
+wasi_nn_error
 wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
 wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
                                graph_execution_context *ctx)
                                graph_execution_context *ctx)
 {
 {
@@ -259,7 +259,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
     bh_assert(instance);
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(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)))
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
         return res;
 
 
@@ -278,7 +278,7 @@ wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
     return res;
     return res;
 }
 }
 
 
-error
+wasi_nn_error
 wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
 wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
                   uint32_t index, tensor_wasm *input_tensor)
                   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);
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(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)))
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
         return res;
 
 
@@ -310,7 +310,7 @@ wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
     return res;
     return res;
 }
 }
 
 
-error
+wasi_nn_error
 wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
 wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
 {
 {
     NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", 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);
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(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)))
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
         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
 #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,
 wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t output_tensor_len, uint32_t *output_tensor_size)
                    uint32_t output_tensor_len, uint32_t *output_tensor_size)
 #else  /* WASM_ENABLE_WASI_EPHEMERAL_NN == 0 */
 #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,
 wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t index, tensor_data output_tensor,
                    uint32_t *output_tensor_size)
                    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);
     bh_assert(instance);
     WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(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)))
     if (success != (res = is_model_initialized(wasi_nn_ctx)))
         return res;
         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
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
  */
 
 
-#include "wasi_nn.h"
+#include "wasi_nn_types.h"
 #include "wasi_nn_tensorflowlite.hpp"
 #include "wasi_nn_tensorflowlite.hpp"
 #include "logger.h"
 #include "logger.h"
 
 
@@ -50,7 +50,7 @@ typedef struct {
 
 
 /* Utils */
 /* Utils */
 
 
-static error
+static wasi_nn_error
 initialize_g(TFLiteContext *tfl_ctx, graph *g)
 initialize_g(TFLiteContext *tfl_ctx, graph *g)
 {
 {
     os_mutex_lock(&tfl_ctx->g_lock);
     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);
     os_mutex_unlock(&tfl_ctx->g_lock);
     return success;
     return success;
 }
 }
-static error
+static wasi_nn_error
 initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
 initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
                      graph_execution_context *ctx)
                      graph_execution_context *ctx)
 {
 {
@@ -78,7 +78,7 @@ initialize_graph_ctx(TFLiteContext *tfl_ctx, graph g,
     return success;
     return success;
 }
 }
 
 
-static error
+static wasi_nn_error
 is_valid_graph(TFLiteContext *tfl_ctx, graph g)
 is_valid_graph(TFLiteContext *tfl_ctx, graph g)
 {
 {
     if (g >= MAX_GRAPHS_PER_INST) {
     if (g >= MAX_GRAPHS_PER_INST) {
@@ -96,7 +96,7 @@ is_valid_graph(TFLiteContext *tfl_ctx, graph g)
     return success;
     return success;
 }
 }
 
 
-static error
+static wasi_nn_error
 is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
 is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
                                  graph_execution_context ctx)
                                  graph_execution_context ctx)
 {
 {
@@ -114,7 +114,7 @@ is_valid_graph_execution_context(TFLiteContext *tfl_ctx,
 
 
 /* WASI-NN (tensorflow) implementation */
 /* WASI-NN (tensorflow) implementation */
 
 
-error
+wasi_nn_error
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
                     graph_encoding encoding, execution_target target, graph *g)
                     graph_encoding encoding, execution_target target, graph *g)
 {
 {
@@ -135,7 +135,7 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
         return invalid_argument;
         return invalid_argument;
     }
     }
 
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = initialize_g(tfl_ctx, g)))
     if (success != (res = initialize_g(tfl_ctx, g)))
         return res;
         return res;
 
 
@@ -168,13 +168,13 @@ tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
     return success;
     return success;
 }
 }
 
 
-error
+wasi_nn_error
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
                                       graph_execution_context *ctx)
                                       graph_execution_context *ctx)
 {
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph(tfl_ctx, g)))
     if (success != (res = is_valid_graph(tfl_ctx, g)))
         return res;
         return res;
 
 
@@ -257,13 +257,13 @@ tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
     return success;
     return success;
 }
 }
 
 
-error
+wasi_nn_error
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
                          uint32_t index, tensor *input_tensor)
                          uint32_t index, tensor *input_tensor)
 {
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
         return res;
 
 
@@ -328,12 +328,12 @@ tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
     return success;
     return success;
 }
 }
 
 
-error
+wasi_nn_error
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
 {
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
         return res;
 
 
@@ -341,14 +341,14 @@ tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx)
     return success;
     return success;
 }
 }
 
 
-error
+wasi_nn_error
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t *output_tensor_size)
                           uint32_t *output_tensor_size)
 {
 {
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
     TFLiteContext *tfl_ctx = (TFLiteContext *)tflite_ctx;
 
 
-    error res;
+    wasi_nn_error res;
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
     if (success != (res = is_valid_graph_execution_context(tfl_ctx, ctx)))
         return res;
         return res;
 
 
@@ -472,6 +472,8 @@ tensorflowlite_destroy(void *tflite_ctx)
 #endif
 #endif
                         break;
                         break;
                     }
                     }
+                    default:
+                        break;
                 }
                 }
             }
             }
             wasm_runtime_free(tfl_ctx->models[i].model_pointer);
             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
 #ifndef WASI_NN_TENSORFLOWLITE_HPP
 #define WASI_NN_TENSORFLOWLITE_HPP
 #define WASI_NN_TENSORFLOWLITE_HPP
 
 
-#include "wasi_nn.h"
+#include "wasi_nn_types.h"
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-error
+wasi_nn_error
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
 tensorflowlite_load(void *tflite_ctx, graph_builder_array *builder,
                     graph_encoding encoding, execution_target target, graph *g);
                     graph_encoding encoding, execution_target target, graph *g);
 
 
-error
+wasi_nn_error
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
 tensorflowlite_init_execution_context(void *tflite_ctx, graph g,
                                       graph_execution_context *ctx);
                                       graph_execution_context *ctx);
 
 
-error
+wasi_nn_error
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
 tensorflowlite_set_input(void *tflite_ctx, graph_execution_context ctx,
                          uint32_t index, tensor *input_tensor);
                          uint32_t index, tensor *input_tensor);
 
 
-error
+wasi_nn_error
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx);
 tensorflowlite_compute(void *tflite_ctx, graph_execution_context ctx);
 
 
-error
+wasi_nn_error
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
 tensorflowlite_get_output(void *tflite_ctx, graph_execution_context ctx,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t index, tensor_data output_tensor,
                           uint32_t *output_tensor_size);
                           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 <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 
 
-error
+wasi_nn_error
 wasm_load(char *model_name, graph *g, execution_target target)
 wasm_load(char *model_name, graph *g, execution_target target)
 {
 {
     FILE *pFile = fopen(model_name, "r");
     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].size = result;
     arr.buf[0].buf = buffer;
     arr.buf[0].buf = buffer;
 
 
-    error res = load(&arr, tensorflowlite, target, g);
+    wasi_nn_error res = load(&arr, tensorflowlite, target, g);
 
 
     fclose(pFile);
     fclose(pFile);
     free(buffer);
     free(buffer);
@@ -54,13 +54,13 @@ wasm_load(char *model_name, graph *g, execution_target target)
     return res;
     return res;
 }
 }
 
 
-error
+wasi_nn_error
 wasm_init_execution_context(graph g, graph_execution_context *ctx)
 wasm_init_execution_context(graph g, graph_execution_context *ctx)
 {
 {
     return init_execution_context(g, ctx);
     return init_execution_context(g, ctx);
 }
 }
 
 
-error
+wasi_nn_error
 wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
 wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
 {
 {
     tensor_dimensions dims;
     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.dimensions->buf[i] = dim[i];
     tensor.type = fp32;
     tensor.type = fp32;
     tensor.data = (uint8_t *)input_tensor;
     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);
     free(dims.buf);
     return err;
     return err;
 }
 }
 
 
-error
+wasi_nn_error
 wasm_compute(graph_execution_context ctx)
 wasm_compute(graph_execution_context ctx)
 {
 {
     return compute(ctx);
     return compute(ctx);
 }
 }
 
 
-error
+wasi_nn_error
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
                 uint32_t *out_size)
                 uint32_t *out_size)
 {
 {

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

@@ -23,19 +23,19 @@ typedef struct {
 
 
 /* wasi-nn wrappers */
 /* wasi-nn wrappers */
 
 
-error
+wasi_nn_error
 wasm_load(char *model_name, graph *g, execution_target target);
 wasm_load(char *model_name, graph *g, execution_target target);
 
 
-error
+wasi_nn_error
 wasm_init_execution_context(graph g, graph_execution_context *ctx);
 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);
 wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim);
 
 
-error
+wasi_nn_error
 wasm_compute(graph_execution_context ctx);
 wasm_compute(graph_execution_context ctx);
 
 
-error
+wasi_nn_error
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
 wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
                 uint32_t *out_size);
                 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
     list(REMOVE_ITEM source_all
         ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c
         ${PLATFORM_COMMON_POSIX_DIR}/posix_file.c
         ${PLATFORM_COMMON_POSIX_DIR}/posix_clock.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
         ${PLATFORM_COMMON_POSIX_DIR}/posix_socket.c
     )
     )
 else()
 else()

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

@@ -94,4 +94,12 @@ os_get_invalid_handle()
     return -1;
     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 */
 #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);
     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
 void
 os_munmap(void *addr, size_t size)
 os_munmap(void *addr, size_t size)
 {
 {

+ 1 - 1
core/version.h

@@ -6,6 +6,6 @@
 #ifndef _WAMR_VERSION_H_
 #ifndef _WAMR_VERSION_H_
 #define _WAMR_VERSION_H_
 #define _WAMR_VERSION_H_
 #define WAMR_VERSION_MAJOR 2
 #define WAMR_VERSION_MAJOR 2
-#define WAMR_VERSION_MINOR 0
+#define WAMR_VERSION_MINOR 1
 #define WAMR_VERSION_PATCH 0
 #define WAMR_VERSION_PATCH 0
 #endif
 #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)
 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_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
 
 
 set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
 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)
 timeout_thread(void *vp)
 {
 {
     const struct timeout_arg *arg = 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) {
     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);
             wasm_runtime_terminate(arg->inst);
             break;
             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;
     return NULL;
 }
 }

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

@@ -272,9 +272,9 @@ DumpDetails(AoTFile *aot)
         AOTImportMemory memory = import_memories[index];
         AOTImportMemory memory = import_memories[index];
         printf("    -[%u] num_bytes_per_page:%5u    init_page_count:%5u    "
         printf("    -[%u] num_bytes_per_page:%5u    init_page_count:%5u    "
                "max_page_count:%5u    module_name: %s    memory_name: %s\n",
                "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");
     printf("\n");
 
 
@@ -365,10 +365,10 @@ DumpDetails(AoTFile *aot)
 
 
     for (uint32_t index = 0; index < memory_count; index++) {
     for (uint32_t index = 0; index < memory_count; index++) {
         AOTMemory memory = memories[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",
                "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");
     printf("\n\n");
 
 

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

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

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

@@ -58,12 +58,12 @@ endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
 if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
   # Enable libc builtin support by default
   # Enable libc builtin support by default
-  set (WAMR_BUILD_LIBC_BUILTIN 1)
+  set (WAMR_BUILD_LIBC_BUILTIN 0)
 endif ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
 if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
   # Enable libc wasi support by default
   # Enable libc wasi support by default
-  set (WAMR_BUILD_LIBC_WASI 1)
+  set (WAMR_BUILD_LIBC_WASI 0)
 endif ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
 if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
@@ -92,8 +92,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD)
 endif ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_REF_TYPES)
 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 ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
 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_C_FLAGS "${CMAKE_C_FLAGS}")
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_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
 # Enable fuzzer
 add_compile_options(-fsanitize=fuzzer)
 add_compile_options(-fsanitize=fuzzer)

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

@@ -8,51 +8,61 @@
 # 1.check parameter
 # 1.check parameter
 if [ ! $1 ]; then
 if [ ! $1 ]; then
 	echo "Parameter is empty, please enter parameter !"
 	echo "Parameter is empty, please enter parameter !"
-    exit 
+    exit
 fi
 fi
+EXPECTED_NUM=$1
 
 
 # 2.check dir
 # 2.check dir
 buildPath="./build"
 buildPath="./build"
 corpusPath="$buildPath/CORPUS_DIR"
 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
 # 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
 # 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
 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 ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_REF_TYPES)
 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 ()
 endif ()
 
 
 if (NOT DEFINED WAMR_BUILD_DEBUG_INTERP)
 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_C_FLAGS "${CMAKE_C_FLAGS}")
 set (CMAKE_CXX_FLAGS "${CMAKE_CXX_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
 # Enable fuzzer
 add_compile_options(-fsanitize=fuzzer)
 add_compile_options(-fsanitize=fuzzer)

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


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


BIN=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": "",
             "options": "",
             "argument": "",
             "argument": "",
             "expected return": {
             "expected return": {
-                "ret code": 57,
+                "ret code": 8,
                 "stdout content": "",
                 "stdout content": "",
                 "description": "sock_shutdown on a non-socket file descriptor should fail with 57 notsock"
                 "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:",
                 "stdout content": "Hello from Kotlin via WASI\nCurrent 'realtime' timestamp is:",
                 "description": "no 'type mismatch: expect (ref null ht) but got other1 unknown type'"
                 "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
 # 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)
 include (FetchContent)
 FetchContent_Declare (
 FetchContent_Declare (
     googletest
     googletest
     URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip
     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)
 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=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=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=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=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=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=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=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=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=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=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)))
+    )
+  )
+)

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio