Sfoglia il codice sorgente

Merge pull request #4049 from bytecodealliance/main

Sync with main
TianlongLiang 11 mesi fa
parent
commit
85dabad252
100 ha cambiato i file con 3230 aggiunte e 896 eliminazioni
  1. 1 1
      .github/scripts/codeql_buildscript.sh
  2. 5 0
      .github/workflows/build_docker_images.yml
  3. 87 33
      .github/workflows/build_iwasm_release.yml
  4. 29 4
      .github/workflows/build_llvm_libraries.yml
  5. 8 0
      .github/workflows/build_wamr_lldb.yml
  6. 6 0
      .github/workflows/build_wamr_sdk.yml
  7. 6 0
      .github/workflows/build_wamr_vscode_ext.yml
  8. 16 2
      .github/workflows/build_wamrc.yml
  9. 12 8
      .github/workflows/codeql.yml
  10. 3 0
      .github/workflows/coding_guidelines.yml
  11. 12 2
      .github/workflows/compilation_on_android_ubuntu.yml
  12. 9 0
      .github/workflows/compilation_on_macos.yml
  13. 3 0
      .github/workflows/compilation_on_nuttx.yml
  14. 6 0
      .github/workflows/compilation_on_sgx.yml
  15. 3 0
      .github/workflows/compilation_on_windows.yml
  16. 5 0
      .github/workflows/create_tag.yml
  17. 3 0
      .github/workflows/hadolint_dockerfiles.yml
  18. 10 0
      .github/workflows/nightly_run.yml
  19. 78 0
      .github/workflows/release_process.yml
  20. 6 0
      .github/workflows/reuse_latest_release_binaries.yml
  21. 13 3
      .github/workflows/spec_test_on_nuttx.yml
  22. 65 0
      .github/workflows/supply_chain.yml
  23. 1 1
      ATTRIBUTIONS.md
  24. 6 4
      CMakeLists.txt
  25. 29 0
      CODEOWNERS
  26. 2 2
      README.md
  27. 82 0
      RELEASE_NOTES.md
  28. 50 6
      build-scripts/build_llvm.py
  29. 12 3
      build-scripts/config_common.cmake
  30. 10 1
      build-scripts/runtime_lib.cmake
  31. 1 0
      ci/coding_guidelines_check.py
  32. 5 1
      core/config.h
  33. 201 19
      core/iwasm/aot/aot_loader.c
  34. 120 28
      core/iwasm/aot/aot_runtime.c
  35. 23 2
      core/iwasm/aot/aot_runtime.h
  36. 13 0
      core/iwasm/aot/arch/aot_reloc_riscv.c
  37. 4 7
      core/iwasm/common/SConscript
  38. 2 1
      core/iwasm/common/wasm_application.c
  39. 5 16
      core/iwasm/common/wasm_c_api.c
  40. 7 2
      core/iwasm/common/wasm_exec_env.c
  41. 4 0
      core/iwasm/common/wasm_exec_env.h
  42. 62 0
      core/iwasm/common/wasm_loader_common.c
  43. 12 0
      core/iwasm/common/wasm_loader_common.h
  44. 24 7
      core/iwasm/common/wasm_memory.c
  45. 155 69
      core/iwasm/common/wasm_runtime_common.c
  46. 5 0
      core/iwasm/common/wasm_runtime_common.h
  47. 240 84
      core/iwasm/compilation/aot.c
  48. 1 1
      core/iwasm/compilation/aot.h
  49. 18 42
      core/iwasm/compilation/aot_compiler.c
  50. 11 0
      core/iwasm/compilation/aot_compiler.h
  51. 3 17
      core/iwasm/compilation/aot_emit_aot_file.c
  52. 1 1
      core/iwasm/compilation/aot_emit_control.c
  53. 43 2
      core/iwasm/compilation/aot_emit_function.c
  54. 33 5
      core/iwasm/compilation/aot_emit_memory.c
  55. 141 12
      core/iwasm/compilation/aot_emit_table.c
  56. 0 10
      core/iwasm/compilation/aot_llvm.c
  57. 12 0
      core/iwasm/compilation/aot_llvm.h
  58. 1 1
      core/iwasm/compilation/aot_orc_extra.cpp
  59. 1 0
      core/iwasm/compilation/iwasm_compl.cmake
  60. 1 0
      core/iwasm/fast-jit/iwasm_fast_jit.cmake
  61. 2 0
      core/iwasm/include/aot_comp_option.h
  62. 24 2
      core/iwasm/include/wasm_export.h
  63. 12 2
      core/iwasm/interpreter/wasm.h
  64. 114 42
      core/iwasm/interpreter/wasm_interp_classic.c
  65. 11 8
      core/iwasm/interpreter/wasm_interp_fast.c
  66. 435 191
      core/iwasm/interpreter/wasm_loader.c
  67. 449 154
      core/iwasm/interpreter/wasm_mini_loader.c
  68. 42 12
      core/iwasm/interpreter/wasm_runtime.c
  69. 2 1
      core/iwasm/interpreter/wasm_runtime.h
  70. 1 1
      core/iwasm/libraries/lib-pthread/lib_pthread.cmake
  71. 19 5
      core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c
  72. 5 4
      core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
  73. 1 1
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
  74. 29 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
  75. 18 4
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
  76. 2 6
      core/iwasm/libraries/wasi-nn/README.md
  77. 15 7
      core/iwasm/libraries/wasi-nn/cmake/Findcjson.cmake
  78. 15 7
      core/iwasm/libraries/wasi-nn/cmake/Findllamacpp.cmake
  79. 21 9
      core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake
  80. 12 0
      core/iwasm/libraries/wasi-nn/cmake/add_telemetry.patch
  81. 1 0
      core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake
  82. 17 4
      core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu
  83. 17 5
      core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu
  84. 18 5
      core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu
  85. 15 2
      core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate
  86. 4 4
      core/iwasm/libraries/wasi-nn/test/build.sh
  87. 1 1
      core/iwasm/libraries/wasi-nn/test/requirements.txt
  88. 2 1
      core/iwasm/libraries/wasi-nn/test/utils.c
  89. 7 0
      core/shared/platform/common/posix/posix_thread.c
  90. 13 2
      core/shared/platform/windows/platform_internal.h
  91. 4 0
      core/shared/platform/windows/shared_platform.cmake
  92. 18 2
      core/shared/platform/windows/win_clock.c
  93. 1 1
      core/shared/platform/windows/win_file.c
  94. 2 2
      core/shared/platform/windows/win_socket.c
  95. 66 6
      core/shared/platform/windows/win_thread.c
  96. 8 2
      core/shared/platform/windows/win_util.h
  97. 10 4
      core/shared/platform/zephyr/zephyr_thread.c
  98. 18 1
      core/shared/platform/zephyr/zephyr_time.c
  99. 2 1
      core/shared/utils/bh_atomic.h
  100. 50 0
      core/shared/utils/bh_common.c

+ 1 - 1
.github/scripts/codeql_buildscript.sh

@@ -306,7 +306,7 @@ cd ${WAMR_DIR}/product-mini/platforms/linux
 rm -rf build && mkdir build && cd build
 cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_DYNAMIC_AOT_DEBUG=1
 make -j
-if [[ $? != 0 ]];
+if [[ $? != 0 ]]; then
     echo "Failed to build iwasm dynamic aot debug enabled!"
     exit 1;
 fi

+ 5 - 0
.github/workflows/build_docker_images.yml

@@ -15,9 +15,14 @@ on:
         type: string
         required: true
 
+permissions:
+  contents: read
+
 jobs:
   build-and-push-images:
     runs-on: ubuntu-22.04
+    permissions:
+      contents: write # for uploading release artifacts
 
     steps:
       - name: Checkout repository

+ 87 - 33
.github/workflows/build_iwasm_release.yml

@@ -31,9 +31,78 @@ on:
         type: string
         required: false
 
+env:
+  DEFAULT_BUILD_OPTIONS: 
+    "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
+     -DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \
+     -DWAMR_BUILD_DEBUG_INTERP=0 \
+     -DWAMR_BUILD_DEBUG_AOT=0 \
+     -DWAMR_BUILD_DUMP_CALL_STACK=0 \
+     -DWAMR_BUILD_LIBC_UVWASI=0 \
+     -DWAMR_BUILD_LIBC_EMCC=0 \
+     -DWAMR_BUILD_LIB_RATS=0 \
+     -DWAMR_BUILD_LOAD_CUSTOM_SECTION=0 \
+     -DWAMR_BUILD_MEMORY_PROFILING=0 \
+     -DWAMR_BUILD_MINI_LOADER=0 \
+     -DWAMR_BUILD_MULTI_MODULE=0 \
+     -DWAMR_BUILD_PERF_PROFILING=0 \
+     -DWAMR_BUILD_SPEC_TEST=0 \
+     -DWAMR_BUILD_BULK_MEMORY=1 \
+     -DWAMR_BUILD_LIB_PTHREAD=1 \
+     -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \
+     -DWAMR_BUILD_LIB_WASI_THREADS=1 \
+     -DWAMR_BUILD_LIBC_BUILTIN=1 \
+     -DWAMR_BUILD_LIBC_WASI=1 \
+     -DWAMR_BUILD_REF_TYPES=1 \
+     -DWAMR_BUILD_SIMD=1 \
+     -DWAMR_BUILD_SHARED_MEMORY=1 \
+     -DWAMR_BUILD_TAIL_CALL=1 \
+     -DWAMR_BUILD_THREAD_MGR=1"
+  GC_EH_BUILD_OPTIONS:
+    "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=0 \
+     -DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \
+     -DWAMR_BUILD_DEBUG_INTERP=0 \
+     -DWAMR_BUILD_DEBUG_AOT=0 \
+     -DWAMR_BUILD_DUMP_CALL_STACK=0 \
+     -DWAMR_BUILD_LIBC_UVWASI=0 \
+     -DWAMR_BUILD_LIBC_EMCC=0 \
+     -DWAMR_BUILD_LIB_RATS=0 \
+     -DWAMR_BUILD_LOAD_CUSTOM_SECTION=0 \
+     -DWAMR_BUILD_MEMORY_PROFILING=0 \
+     -DWAMR_BUILD_MINI_LOADER=0 \
+     -DWAMR_BUILD_MULTI_MODULE=0 \
+     -DWAMR_BUILD_PERF_PROFILING=0 \
+     -DWAMR_BUILD_SPEC_TEST=0 \
+     -DWAMR_BUILD_BULK_MEMORY=1 \
+     -DWAMR_BUILD_LIB_PTHREAD=1 \
+     -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \
+     -DWAMR_BUILD_LIB_WASI_THREADS=1 \
+     -DWAMR_BUILD_LIBC_BUILTIN=1 \
+     -DWAMR_BUILD_LIBC_WASI=1 \
+     -DWAMR_BUILD_REF_TYPES=1 \
+     -DWAMR_BUILD_SIMD=1 \
+     -DWAMR_BUILD_SHARED_MEMORY=1 \
+     -DWAMR_BUILD_TAIL_CALL=1 \
+     -DWAMR_BUILD_THREAD_MGR=1 \
+     -DWAMR_BUILD_EXCE_HANDLING=1 \
+     -DWAMR_BUILD_GC=1"
+
+permissions:
+  contents: read
+
 jobs:
   build:
     runs-on: ${{ inputs.runner }}
+    strategy:
+      matrix:
+        include:
+          - build_options: $DEFAULT_BUILD_OPTIONS
+            suffix: ''
+          - build_options: $GC_EH_BUILD_OPTIONS
+            suffix: '-gc-eh'
+    permissions:
+      contents: write # for uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
 
@@ -51,40 +120,25 @@ jobs:
           fail-on-cache-miss: true
 
       - name: generate iwasm binary release
+        shell: bash
         run: |
-          cmake -S . -B build \
-            -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 \
-            -DWAMR_BUILD_CUSTOM_NAME_SECTION=0 \
-            -DWAMR_BUILD_DEBUG_INTERP=0 \
-            -DWAMR_BUILD_DEBUG_AOT=0 \
-            -DWAMR_BUILD_DUMP_CALL_STACK=0 \
-            -DWAMR_BUILD_LIBC_UVWASI=0 \
-            -DWAMR_BUILD_LIBC_EMCC=0 \
-            -DWAMR_BUILD_LIB_RATS=0 \
-            -DWAMR_BUILD_LOAD_CUSTOM_SECTION=0 \
-            -DWAMR_BUILD_MEMORY_PROFILING=0 \
-            -DWAMR_BUILD_MINI_LOADER=0 \
-            -DWAMR_BUILD_MULTI_MODULE=0 \
-            -DWAMR_BUILD_PERF_PROFILING=0 \
-            -DWAMR_BUILD_SPEC_TEST=0 \
-            -DWAMR_BUILD_BULK_MEMORY=1 \
-            -DWAMR_BUILD_LIB_PTHREAD=1 \
-            -DWAMR_BUILD_LIB_PTHREAD_SEMAPHORE=1 \
-            -DWAMR_BUILD_LIB_WASI_THREADS=1 \
-            -DWAMR_BUILD_LIBC_BUILTIN=1 \
-            -DWAMR_BUILD_LIBC_WASI=1 \
-            -DWAMR_BUILD_REF_TYPES=1 \
-            -DWAMR_BUILD_SIMD=1 \
-            -DWAMR_BUILD_SHARED_MEMORY=1 \
-            -DWAMR_BUILD_TAIL_CALL=1 \
-            -DWAMR_BUILD_THREAD_MGR=1
+          cmake -S . -B build ${{ matrix.build_options }}
           cmake --build build --config Release --parallel 4
         working-directory: ${{ inputs.cwd }}
 
-      - name: compress the binary
+      - name: Compress the binary on Windows
+        if: inputs.runner == 'windows-latest'
+        run: |
+          tar -czf iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz iwasm.exe
+          Compress-Archive -Path iwasm.exe -DestinationPath iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
+          mv iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.* ../
+        working-directory: ${{ inputs.cwd }}/build/Release
+
+      - name: compress the binary on non-Windows
+        if: inputs.runner != 'windows-latest'
         run: |
-          tar czf iwasm-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz iwasm
-          zip iwasm-${{ inputs.ver_num }}-${{ inputs.runner }}.zip iwasm
+          tar czf iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz iwasm
+          zip iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.zip iwasm
         working-directory: ${{ inputs.cwd }}/build
 
       - name: upload release tar.gz
@@ -93,8 +147,8 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
           upload_url: ${{ inputs.upload_url }}
-          asset_path: ${{ inputs.cwd }}/build/iwasm-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz
-          asset_name: iwasm-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.tar.gz
+          asset_path: ${{ inputs.cwd }}/build/iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz
+          asset_name: iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.tar.gz
           asset_content_type: application/x-gzip
 
       - name: upload release zip
@@ -103,6 +157,6 @@ jobs:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         with:
           upload_url: ${{ inputs.upload_url }}
-          asset_path: ${{ inputs.cwd }}/build/iwasm-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
-          asset_name: iwasm-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.zip
+          asset_path: ${{ inputs.cwd }}/build/iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
+          asset_name: iwasm${{ matrix.suffix }}-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}.zip
           asset_content_type: application/zip

+ 29 - 4
.github/workflows/build_llvm_libraries.yml

@@ -27,6 +27,9 @@ on:
         description: "A cached key of LLVM libraries"
         value: ${{ jobs.build_llvm_libraries.outputs.key}}
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries:
     runs-on: ${{ inputs.os }}
@@ -36,6 +39,9 @@ jobs:
       image: ${{ inputs.container_image }}
     outputs:
       key: ${{ steps.create_lib_cache_key.outputs.key}}
+    permissions:
+      contents: read
+      actions: write # for uploading cached artifact
 
     steps:
       - name: checkout
@@ -43,6 +49,7 @@ jobs:
 
       - name: install dependencies for non macos-14
         if: inputs.os != 'macos-14'
+        shell: bash
         run: /usr/bin/env python3 -m pip install -r requirements.txt
         working-directory: build-scripts
 
@@ -51,10 +58,13 @@ jobs:
         run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages
         working-directory: build-scripts
 
-      - name: retrieve the last commit ID
+      - name: Retrieve the last commit ID
         id: get_last_commit
-        run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py ${{ inputs.extra_build_llvm_options }} --llvm-ver)" >> $GITHUB_OUTPUT
-        working-directory: build-scripts
+        env:
+          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        shell: bash
+        run: |
+          echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py ${{ inputs.extra_build_llvm_options }} --llvm-ver)" >> $GITHUB_OUTPUT
 
       # Bump the prefix number to evict all previous caches and
       # enforce a clean build, in the unlikely case that some
@@ -62,7 +72,9 @@ jobs:
       # suspect.
       - name: form the cache key of libraries
         id: create_lib_cache_key
-        run: echo "key=0-llvm-libraries-${{ inputs.os }}-${{ inputs.arch }}-${{ steps.get_last_commit.outputs.last_commit }}${{ inputs.cache_key_suffix }}" >> $GITHUB_OUTPUT
+        shell: bash
+        run: |
+          echo "key=0-llvm-libraries-${{ inputs.os }}-${{ inputs.arch }}-${{ steps.get_last_commit.outputs.last_commit }}${{ inputs.cache_key_suffix }}" >> $GITHUB_OUTPUT
 
       - name: Cache LLVM libraries
         id: retrieve_llvm_libs
@@ -107,7 +119,20 @@ jobs:
       - run: brew install ccache ninja
         if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos')
 
+      - uses: actions/cache@v4
+        with:
+          path: ~/.cache/ccache
+          key: 0-ccache-${{ inputs.os }}-${{ steps.get_last_commit.outputs.last_commit }}
+          restore-keys: |
+            0-ccache-${{ inputs.os }}
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'windows-latest'
+
+      # Install tools on Windows
+      - run: choco install -y ccache ninja
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && inputs.os == 'windows-latest'
+
       - name: Build LLVM libraries
         if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
+        shell: bash
         run: /usr/bin/env python3 ./build_llvm.py ${{ inputs.extra_build_llvm_options }} --arch ${{ inputs.arch }}
         working-directory: build-scripts

+ 8 - 0
.github/workflows/build_wamr_lldb.yml

@@ -28,8 +28,13 @@ on:
         required: false
         default: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-20/wasi-sdk-20.0-linux.tar.gz"
 
+permissions:
+  contents: read
+
 jobs:
   try_reuse:
+    permissions:
+      contents: write # for uploading release artifacts
     uses: ./.github/workflows/reuse_latest_release_binaries.yml
     with:
       binary_name_stem: "wamr-lldb-${{ inputs.ver_num }}-${{ inputs.arch }}-${{ inputs.runner }}"
@@ -46,6 +51,9 @@ jobs:
       PYTHON_VERSION: '3.10'
       PYTHON_UBUNTU_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-unknown-linux-gnu-install_only.tar.gz
       PYTHON_MACOS_STANDALONE_BUILD: https://github.com/indygreg/python-build-standalone/releases/download/20230507/cpython-3.10.11+20230507-x86_64-apple-darwin-install_only.tar.gz
+    permissions:
+      contents: write # for uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
 

+ 6 - 0
.github/workflows/build_wamr_sdk.yml

@@ -35,9 +35,15 @@ on:
         type: string
         required: true
 
+permissions:
+  contents: read
+
 jobs:
   build:
     runs-on: ${{ inputs.runner }}
+    permissions:
+      contents: write # for uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
 

+ 6 - 0
.github/workflows/build_wamr_vscode_ext.yml

@@ -14,9 +14,15 @@ on:
         type: string
         required: true
 
+permissions:
+  contents: read
+
 jobs:
   build:
     runs-on: ubuntu-22.04
+    permissions:
+      contents: write # for uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
 

+ 16 - 2
.github/workflows/build_wamrc.yml

@@ -31,9 +31,15 @@ on:
         type: string
         required: false
 
+permissions:
+  contents: read
+
 jobs:
   build:
     runs-on: ${{ inputs.runner }}
+    permissions:
+      contents: write # for uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
 
@@ -56,8 +62,16 @@ jobs:
           cmake --build build --config Release --parallel 4
         working-directory: wamr-compiler
 
-      - name: compress the binary
-        if: inputs.release
+      - name: Compress the binary on Windows
+        if: inputs.runner == 'windows-latest' && inputs.release
+        run: |
+          tar -czf wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamrc.exe
+          Compress-Archive -Path wamrc.exe -DestinationPath wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.zip
+          mv wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.* ../
+        working-directory: wamr-compiler/build/Release
+
+      - name: compress the binary on non-Windows
+        if: inputs.runner != 'windows-latest' && inputs.release
         run: |
           tar czf wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.tar.gz wamrc
           zip wamrc-${{ inputs.ver_num }}-${{ inputs.runner }}.zip wamrc

+ 12 - 8
.github/workflows/codeql.yml

@@ -19,6 +19,9 @@ on:
   # allow to be triggered manually
   workflow_dispatch:
 
+permissions:
+  contents: read
+
 jobs:
   analyze:
     if: github.repository == 'bytecodealliance/wasm-micro-runtime'
@@ -30,10 +33,6 @@ jobs:
     # Consider using larger runners for possible analysis time improvements.
     runs-on: ${{ (matrix.language == 'swift' && 'macos-13') || 'ubuntu-22.04' }}
     timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
-    permissions:
-      actions: read
-      contents: read
-      security-events: write
 
     strategy:
       fail-fast: false
@@ -41,6 +40,11 @@ jobs:
         language: [ 'cpp' ]
         # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
 
+    permissions:
+      contents: read
+      actions: read
+      security-events: write
+
     steps:
     - name: Checkout repository
       uses: actions/checkout@v3
@@ -49,7 +53,7 @@ jobs:
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v3
+      uses: github/codeql-action/init@v3.28.8
       with:
         languages: ${{ matrix.language }}
 
@@ -66,7 +70,7 @@ jobs:
     - run: |
         ./.github/scripts/codeql_buildscript.sh
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v3
+      uses: github/codeql-action/analyze@v3.28.8
       with:
         category: "/language:${{matrix.language}}"
         upload: false
@@ -95,14 +99,14 @@ jobs:
         output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
 
     - name: Upload CodeQL results to code scanning
-      uses: github/codeql-action/upload-sarif@v3
+      uses: github/codeql-action/upload-sarif@v3.28.8
       with:
         sarif_file: ${{ steps.step1.outputs.sarif-output }}
         category: "/language:${{matrix.language}}"
 
     - name: Upload CodeQL results as an artifact
       if: success() || failure()
-      uses: actions/upload-artifact@v4
+      uses: actions/upload-artifact@v4.6.0
       with:
         name: codeql-results
         path: ${{ steps.step1.outputs.sarif-output }}

+ 3 - 0
.github/workflows/coding_guidelines.yml

@@ -14,6 +14,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
+permissions:
+  contents: read
+
 jobs:
   compliance_job:
     runs-on: ubuntu-20.04

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

@@ -70,8 +70,14 @@ env:
   MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
   MULTI_MEMORY_TEST_OPTIONS: "-s spec -E -b -P"
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries_on_ubuntu_2204:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-22.04"
@@ -150,6 +156,7 @@ jobs:
             "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
             "-DWAMR_BUILD_MEMORY64=1",
             "-DWAMR_BUILD_MULTI_MEMORY=1",
+            "-DWAMR_BUILD_SHARED=1",
           ]
         os: [ubuntu-22.04]
         platform: [android, linux]
@@ -247,6 +254,9 @@ jobs:
             platform: android
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             platform: android
+          # android does not support WAMR_BUILD_SHARED in its CMakeLists.txt.
+          - make_options_feature: "-DWAMR_BUILD_SHARED=1"
+            platform: android
         include:
           - os: ubuntu-22.04
             llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
@@ -807,7 +817,7 @@ jobs:
 
       - name: install dependencies
         run: |
-          rustup target add wasm32-wasi
+          rustup target add wasm32-wasip1
           sudo apt update && sudo apt-get install -y lld ninja-build
           npm install
         working-directory: test-tools/wamr-ide/VSCode-Extension
@@ -822,7 +832,7 @@ jobs:
         run: |
           mkdir build
           cd build
-          cmake .. -DWAMR_BUILD_DEBUG_INTERP=1
+          cmake .. -DWAMR_BUILD_DEBUG_INTERP=1 -DWAMR_BUILD_REF_TYPES=1
           make
         working-directory: product-mini/platforms/linux
 

+ 9 - 0
.github/workflows/compilation_on_macos.yml

@@ -52,13 +52,22 @@ env:
   LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
   LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries_on_intel_macos:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "macos-13"
       arch: "X86"
   build_llvm_libraries_on_arm_macos:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "macos-14"

+ 3 - 0
.github/workflows/compilation_on_nuttx.yml

@@ -46,6 +46,9 @@ concurrency:
 env:
   WASI_SDK_PATH: "/opt/wasi-sdk"
 
+permissions:
+  contents: read
+
 jobs:
   build_iwasm_on_nuttx:
     runs-on: ubuntu-latest

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

@@ -54,8 +54,14 @@ env:
   LLVM_LAZY_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
   LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-20.04"

+ 3 - 0
.github/workflows/compilation_on_windows.yml

@@ -53,6 +53,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
+permissions:
+  contents: read
+
 jobs:
   build:
     runs-on: windows-latest

+ 5 - 0
.github/workflows/create_tag.yml

@@ -15,6 +15,9 @@ on:
         description: "the new tag just created"
         value: ${{ jobs.create_tag.outputs.new_tag}}
 
+permissions:
+  contents: read
+
 jobs:
   create_tag:
     runs-on: ubuntu-latest
@@ -22,6 +25,8 @@ jobs:
       minor_version: ${{ steps.preparation.outputs.minor_version }}
       new_ver: ${{ steps.preparation.outputs.new_ver }}
       new_tag: ${{ steps.preparation.outputs.new_tag }}
+    permissions:
+      contents: write # create and push tags
 
     steps:
       - uses: actions/checkout@v4

+ 3 - 0
.github/workflows/hadolint_dockerfiles.yml

@@ -28,6 +28,9 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
+permissions:
+  contents: read
+
 jobs:
   run-hadolint-on-dockerfiles:
     runs-on: ubuntu-22.04

+ 10 - 0
.github/workflows/nightly_run.yml

@@ -44,13 +44,22 @@ env:
   X86_32_TARGET_TEST_OPTIONS: "-m x86_32 -P"
   WASI_TEST_OPTIONS: "-s wasi_certification -w"
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries_on_ubuntu_2004:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-20.04"
       arch: "X86"
   build_llvm_libraries_on_ubuntu_2204:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-22.04"
@@ -133,6 +142,7 @@ jobs:
             "-DWAMR_DISABLE_HW_BOUND_CHECK=1",
             "-DWAMR_BUILD_MEMORY64=1",
             "-DWAMR_BUILD_MULTI_MEMORY=1",
+            "-DWAMR_BUILD_SHARED=1",
           ]
         os: [ubuntu-20.04]
         platform: [android, linux]

+ 78 - 0
.github/workflows/release_process.yml

@@ -18,11 +18,18 @@ concurrency:
   group: ${{ github.workflow }}-${{ github.ref }}
   cancel-in-progress: true
 
+permissions:
+  contents: read
+
 jobs:
   create_tag:
+    permissions:
+      contents: write # create and push tags
     uses: ./.github/workflows/create_tag.yml
 
   create_release:
+    permissions:
+      contents: write # create release
     needs: [create_tag]
     runs-on: ubuntu-latest
     outputs:
@@ -52,6 +59,9 @@ jobs:
   #
   # LLVM_LIBRARIES
   build_llvm_libraries_on_ubuntu_2004:
+    permissions:
+      contents: read
+      actions: write
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
@@ -59,6 +69,9 @@ jobs:
       arch: "AArch64 ARM Mips RISCV X86"
 
   build_llvm_libraries_on_ubuntu_2204:
+    permissions:
+      contents: read
+      actions: write
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
@@ -66,15 +79,30 @@ jobs:
       arch: "AArch64 ARM Mips RISCV X86"
 
   build_llvm_libraries_on_macos:
+    permissions:
+      contents: read
+      actions: write
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "macos-13"
       arch: "AArch64 ARM Mips RISCV X86"
 
+  build_llvm_libraries_on_windows:
+    permissions:
+      contents: read
+      actions: write
+    needs: [create_tag, create_release]
+    uses: ./.github/workflows/build_llvm_libraries.yml
+    with:
+      os: "windows-latest"
+      arch: "AArch64 ARM Mips RISCV X86"
+
   #
   # WAMRC
   release_wamrc_on_ubuntu_2004:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_ubuntu_2004]
     uses: ./.github/workflows/build_wamrc.yml
     with:
@@ -85,6 +113,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
   release_wamrc_on_ubuntu_2204:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_ubuntu_2204 ]
     uses: ./.github/workflows/build_wamrc.yml
     with:
@@ -95,6 +125,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver }}
 
   release_wamrc_on_ubuntu_macos:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_macos]
     uses: ./.github/workflows/build_wamrc.yml
     with:
@@ -103,10 +135,24 @@ jobs:
       runner: macos-13
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       ver_num: ${{ needs.create_tag.outputs.new_ver }}
+  
+  release_wamrc_on_windows:
+    permissions:
+      contents: write # upload release artifact
+    needs: [create_tag, create_release, build_llvm_libraries_on_windows]
+    uses: ./.github/workflows/build_wamrc.yml
+    with:
+      llvm_cache_key: ${{ needs.build_llvm_libraries_on_windows.outputs.cache_key }}
+      release: true
+      runner: windows-latest
+      upload_url: ${{ needs.create_release.outputs.upload_url }}
+      ver_num: ${{ needs.create_tag.outputs.new_ver }}
 
   #
   # IWASM
   release_iwasm_on_ubuntu_2004:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_ubuntu_2004]
     uses: ./.github/workflows/build_iwasm_release.yml
     with:
@@ -117,6 +163,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
   release_iwasm_on_ubuntu_2204:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_ubuntu_2204]
     uses: ./.github/workflows/build_iwasm_release.yml
     with:
@@ -127,6 +175,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
   release_iwasm_on_macos:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release, build_llvm_libraries_on_macos]
     uses: ./.github/workflows/build_iwasm_release.yml
     with:
@@ -136,9 +186,23 @@ jobs:
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
+  release_iwasm_on_windows:
+    permissions:
+      contents: write # upload release artifact
+    needs: [create_tag, create_release, build_llvm_libraries_on_windows]
+    uses: ./.github/workflows/build_iwasm_release.yml
+    with:
+      cwd: product-mini/platforms/windows
+      llvm_cache_key: ${{ needs.build_llvm_libraries_on_windows.outputs.cache_key }}
+      runner: windows-latest
+      upload_url: ${{ needs.create_release.outputs.upload_url }}
+      ver_num: ${{ needs.create_tag.outputs.new_ver}}
+
   #
   # WAMR_SDK
   release_wamr_sdk_on_ubuntu_2004:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_sdk.yml
     with:
@@ -150,6 +214,8 @@ jobs:
       wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git
 
   release_wamr_sdk_on_ubuntu_2204:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_sdk.yml
     with:
@@ -161,6 +227,8 @@ jobs:
       wamr_app_framework_url: https://github.com/bytecodealliance/wamr-app-framework.git
 
   release_wamr_sdk_on_macos:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_sdk.yml
     with:
@@ -174,6 +242,8 @@ jobs:
   #
   # vscode extension cross-platform
   release_wamr_ide_vscode_ext:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_vscode_ext.yml
     secrets: inherit
@@ -184,6 +254,8 @@ jobs:
   #
   # vscode extension docker images package
   release_wamr_ide_docker_images_package:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_docker_images.yml
     with:
@@ -193,6 +265,8 @@ jobs:
   #
   # WAMR_LLDB
   release_wamr_lldb_on_ubuntu_2004:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_lldb.yml
     with:
@@ -201,6 +275,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
   release_wamr_lldb_on_ubuntu_2204:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_lldb.yml
     with:
@@ -209,6 +285,8 @@ jobs:
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
 
   release_wamr_lldb_on_macos_universal:
+    permissions:
+      contents: write # upload release artifact
     needs: [create_tag, create_release]
     uses: ./.github/workflows/build_wamr_lldb.yml
     with:

+ 6 - 0
.github/workflows/reuse_latest_release_binaries.yml

@@ -22,11 +22,17 @@ on:
       result:
         value: ${{ jobs.build.outputs.result }}
 
+permissions:
+  contents: read
+
 jobs:
   reuse:
     runs-on: ubuntu-latest
     outputs:
       result: ${{ steps.try_reuse.outputs.result }}
+    permissions:
+      contents: write # for creating realease and uploading release artifacts
+
     steps:
       - uses: actions/checkout@v4
         # Full git history is needed to get a proper list of commits and tags

+ 13 - 3
.github/workflows/spec_test_on_nuttx.yml

@@ -29,8 +29,14 @@ env:
   LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
   WASI_SDK_PATH: "/opt/wasi-sdk"
 
+permissions:
+  contents: read
+
 jobs:
   build_llvm_libraries:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-22.04"
@@ -38,6 +44,9 @@ jobs:
       container_image: ghcr.io/no1wudi/nuttx/apache-nuttx-ci-linux@sha256:8c4e00b607d4d6d66ba8f51c4544819a616eac69d3a2ac669e2af2150e2eb0f9
 
   build_llvm_libraries_xtensa:
+    permissions:
+      contents: read
+      actions: write
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
       os: "ubuntu-22.04"
@@ -118,7 +127,8 @@ jobs:
         wamr_feature_option:
           # Empty option for default
           - { option: "", mode: "" }
-          - { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" }
+          # need to install menhir
+          # - { option: "CONFIG_INTERPRETERS_WAMR_GC CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME", mode: "-G" }
 
         exclude:
           # XIP is not fully supported yet on RISCV64, some relocations can not be resolved
@@ -199,7 +209,7 @@ jobs:
         if: contains(matrix.wamr_test_option.mode, 'aot')
         working-directory: apps/interpreters/wamr/wamr/wamr-compiler
         run: |
-          cmake -Bbuild .
+          cmake -B build -DWAMR_BUILD_SHRUNK_MEMORY=0 -S .
           cmake --build build
 
       # the nuttx version we use for xtensa requires esptool.py newer than
@@ -341,7 +351,7 @@ jobs:
 
       - name: upload the log
         if: always()
-        uses: actions/upload-artifact@v4
+        uses: actions/upload-artifact@v4.6.0
         with:
           name: spec-test-log-${{ github.run_id }}-${{ strategy.job-index }}-${{ matrix.target_config.target }}
           path: log

+ 65 - 0
.github/workflows/supply_chain.yml

@@ -0,0 +1,65 @@
+# This workflow uses actions that are not certified by GitHub. They are provided
+# by a third-party and are governed by separate terms of service, privacy
+# policy, and support documentation.
+
+# Check current WASM Micro Runtime results here: https://securityscorecards.dev/viewer/?uri=github.com/bytecodealliance/wasm-micro-runtime
+
+name: Scorecard supply-chain security
+on:
+  # For Branch-Protection check. Only the default branch is supported. See
+  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+  branch_protection_rule:
+  # To guarantee Maintained check is occasionally updated. See
+  # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+  # midnight UTC
+  schedule:
+    - cron: "0 0 * * *"
+  # allow to be triggered manually
+  workflow_dispatch:
+
+# Declare default permissions as read only.
+permissions:
+  contents: read
+
+jobs:
+  analysis:
+    name: Scorecard analysis
+    runs-on: ubuntu-latest
+    if: github.repository == 'bytecodealliance/wasm-micro-runtime'
+    permissions:
+      # Needed to upload the results to code-scanning dashboard.
+      security-events: write
+      # Needed to publish results and get a badge (see publish_results below).
+      id-token: write      
+
+    steps:
+      - name: "Checkout code"
+        uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
+        with:
+          persist-credentials: false
+
+      - name: "Run analysis"
+        uses: ossf/scorecard-action@62b2cac7ed8198b15735ed49ab1e5cf35480ba46 # v2.4.0
+        with:
+          results_file: results.sarif
+          results_format: sarif
+
+          #   - Publish results to OpenSSF REST API for easy access by consumers
+          #   - Allows the repository to include the Scorecard badge.
+          #   - See https://github.com/ossf/scorecard-action#publishing-results.      
+          publish_results: true
+
+      # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
+      # format to the repository Actions tab.
+      - name: "Upload artifact"
+        uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v3.1.0
+        with:
+          name: SARIF file
+          path: results.sarif
+          retention-days: 5
+
+      # Upload the results to GitHub's code scanning dashboard.
+      - name: "Upload to code-scanning"
+        uses: github/codeql-action/upload-sarif@0701025a8b1600e416be4f3bb5a830b1aa6af01e # v2.2.4
+        with:
+          sarif_file: results.sarif

+ 1 - 1
ATTRIBUTIONS.md

@@ -60,7 +60,7 @@ The WAMR fast interpreter is a clean room development. We would acknowledge the
 
 ### llvm
 
-[LICENSE](./LICENCE.txt)
+[LICENSE](./LICENSE)
 
 ### wasm-c-api
 

+ 6 - 4
CMakeLists.txt

@@ -8,7 +8,9 @@ if(ESP_PLATFORM)
   return()
 endif()
 
-project (iwasm)
+project (iwasm LANGUAGES C)
+
+set(CMAKE_CXX_STANDARD 17)
 
 set (CMAKE_VERBOSE_MAKEFILE OFF)
 
@@ -113,8 +115,8 @@ if (NOT DEFINED WAMR_BUILD_SIMD)
 endif ()
 
 if (NOT DEFINED WAMR_BUILD_REF_TYPES)
-  # Disable reference types by default
-  set (WAMR_BUILD_REF_TYPES 0)
+  # Enable reference types by default
+  set (WAMR_BUILD_REF_TYPES 1)
 endif ()
 
 set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
@@ -180,7 +182,7 @@ if (WAMR_BUILD_SHARED)
     add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
     set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm)
     target_include_directories(iwasm_shared INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
-    target_link_libraries (iwasm_shared INTERFACE ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT})
+    target_link_libraries (iwasm_shared PUBLIC ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl ${CMAKE_THREAD_LIBS_INIT})
     if (WAMR_BUILD_WASM_CACHE EQUAL 1)
       target_link_libraries(iwasm_shared INTERFACE boringssl_crypto)
     endif ()

+ 29 - 0
CODEOWNERS

@@ -0,0 +1,29 @@
+# In this project, we use CODEOWNERS to identify people who are likely to know
+# who should review a pull request.
+#
+# People listed in this file are committing to respond in a timely fashion to
+# PRs in the selected areas. However, that response doesn't have to be a full
+# code review; it could also take any of these forms:
+#
+# - "I intend to review this but I can't yet. Please leave me a message if I
+#   haven't responded by (a specific date in the near future)."
+#
+# - "I think (a specific other contributor) should review this." (Note that the
+#   best reviewer for a PR may not necessarily be listed in this file.)
+#
+# People must only be added to this file if they've agreed to provide one of
+# the above responses in a reasonable amount of time for every PR to which
+# they're assigned.
+#
+# We only ask for this commitment from people who are employed full-time to
+# work on this project. We gratefully welcome reviews from other contributors,
+# but we don't believe it's fair to ask volunteers to respond quickly.
+
+# If none of the later patterns match, assign to anyone. This team is the
+# parent of all the other teams and automatically includes everyone on those
+# teams.
+* @loganek @lum1n0us @no1wudi @TianlongLiang @wenyongh @xujuntwt95329 @yamt
+
+# Some parts of the project require more specialized knowledge. In those areas
+# we designate smaller groups who are more likely to be aware of who's working
+# in specific areas.

+ 2 - 2
README.md

@@ -58,8 +58,8 @@ The WAMR VMcore supports the following architectures:
 - XTENSA, MIPS, ARC
 
 The following platforms are supported, click each link below for how to build iwasm on that platform. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform.
-- [Linux](./product-mini/README.md#linux),  [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md),  [MacOS](./product-mini/README.md#macos),  [Android](./product-mini/README.md#android), [Windows](./product-mini/README.md#windows), [Windows (MinGW)](./product-mini/README.md#mingw)
-- [Zephyr](./product-mini/README.md#zephyr),  [AliOS-Things](./product-mini/README.md#alios-things),  [VxWorks](./product-mini/README.md#vxworks), [NuttX](./product-mini/README.md#nuttx), [RT-Thread](./product-mini/README.md#RT-Thread), [ESP-IDF](./product-mini/README.md#esp-idf)
+- [Linux](./product-mini/README.md#linux),  [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md),  [MacOS](./product-mini/README.md#macos),  [Android](./product-mini/README.md#android), [Windows](./product-mini/README.md#windows), [Windows (MinGW, MSVC)](./product-mini/README.md#mingw)
+- [Zephyr](./product-mini/README.md#zephyr),  [AliOS-Things](./product-mini/README.md#alios-things),  [VxWorks](./product-mini/README.md#vxworks), [NuttX](./product-mini/README.md#nuttx), [RT-Thread](./product-mini/README.md#RT-Thread), [ESP-IDF(FreeRTOS)](./product-mini/README.md#esp-idf)
 
 
 ## Getting started

+ 82 - 0
RELEASE_NOTES.md

@@ -1,3 +1,85 @@
+## WAMR-2.2.0
+
+### Breaking changes 
+
+### New features 
+- Add support for multi-memory proposal in classic interpreter (#3742) 
+- wasi-nn: Add a new target for llama.cpp as a wasi-nn backend (#3709)
+- Add memory instance support apis (#3786) 
+- Implement a first version of shared heap feature (#3789) 
+- Support dynamic aot debug (#3788) 
+- Implement shared heap for AOT (#3815)
+- Support table64 extension in classic-interp and AOT running modes (#3811)
+  
+
+### Bug fixes
+- Enable merged os_mmap for aot data sections (#3681) 
+- Fix arm64 issues on mac (#3688) 
+- aot loader: Call os_mmap with MMAP_MAP_32BIT only when target is x86-64 or riscv64 (#3755)
+- Fix building iwasm_shared and iwasm_static libs on win32 (#3762) 
+- Fix compile error when multi-module and tags are enabled (#3781)
+- Fix aot multi export memory support (#3791)
+- Fix Windows compile error when uvwasi is enabled (#3810)
+- Fix missing symbols when using aot mode on riscv platforms (#3812)
+- Fix mac build of libc_emcc_wrapper.c (#3836)
+- aot_comp_option.h: Add missing stdint.h header (#3834)
+- Fix compilation error found in tflite test (#3820) 
+- Fix exec_env_tls assertion in module instantiation (#3844) 
+- Fix issues of destroy_shared_heaps (#3847)
+
+### Enhancements
+- aot loader: Refine os_mmap related code (#3711)
+- Enable merged os_mmap for aot data sections and aot text (#3743)
+- Improve posix mmap retry logic (#3714)
+- Remove unnecessary code duplication in aot runtime (#3767)
+- Add wamrc parameter to configure stack frame features (#3763) 
+- refactoring: Re-use commit IP functionality between exception handling and other cases (#3768)
+- AOT call stack optimizations (#3773) 
+- Appease GCC strict prototypes warning (#3775)
+- Appease GCC -Wformat (#3783)
+- Fix compiler warnings (#3784)
+- Implement option for skipping function index in the callstack (#3785)
+- Fix a compile warning in aot_emit_function.c (#3793) 
+- Restore cmake hidden compile symbol visibility (#3796)
+- Refactor shared heap feature for interpreter mode (#3794)
+- Add no_resolve to LoadArgs and wasm_runtime_resolve_symbols (#3790)
+- shared heap: Fix some issues and add basic unit test case (#3801)
+- Add shared heap sample (#3806)
+- Fix unused param warning when GC is enabled (#3814)
+- Add scoreboard CI for supply-chain security (#3819)
+- Emit load_addr and load_size if WAMR_ENABLE_COMPILER is set (#3835)
+- libc-emcc: Use alternate method to check getrandom support (#3848)
+- Enable libc-wasi for windows msvc build (#3852) 
+- Remove unused folder samples/gui and samples/littlevgl (#3853) 
+- Fix some compile warnings and typos (#3854)
+- Allow to set native stack boundary to exec_env (#3862)
+- Refine wasm/aot function instance lookup (#3865)
+- Fix quadratic runtime for duplicate export name detection (#3861)
+
+  
+### Others
+- Add a comment on AOT_SECTION_TYPE_SIGNATURE (#3746) 
+- CI: Freeze version of bloaty for NuttX compilation (#3756)
+- aot compiler: Allow to control stack boundary check when boundary check is enabled (#3754)
+- Update ref to the multi-memory tests (#3764)
+- compilation_on_nuttx.yml: Update checkout action to suppress warnings (#3765)
+- CI: Disable parallel test in spectest for NuttX (#3780)
+- spec_test_on_nuttx.yml: Disable riscv32_ilp32f for now (#3777) 
+- Ignore temporary file from aider (#3787)
+- Add CODEOWNERS (#3822)
+- build(deps): bump github/codeql-action from 2.2.4 to 3.26.9 (#3826)
+- build(deps): bump actions/upload-artifact from 3.1.0 to 4.4.0 (#3827)
+- build(deps): bump ossf/scorecard-action from 2.3.1 to 2.4.0 (#3828)
+- build(deps): bump github/codeql-action from 3.26.9 to 3.26.11 (#3843) 
+- build(deps): bump actions/upload-artifact from 4.4.0 to 4.4.3 (#3855)
+- build(deps): bump github/codeql-action from 3.26.11 to 3.26.12 (#3856)
+- Add Windows wamrc and iwasm build in release CI (#3857)
+- Fix syntax error in codeql_buildscript.sh (#3864)
+- release CI: Add another iwasm binary that supports Garbage Collection and Exception Handling (#3866)
+- Fix lookup function issue reported in nightly run (#3868)
+ 
+---
+
 ## WAMR-2.1.2
 
 ### Breaking Changes

+ 50 - 6
build-scripts/build_llvm.py

@@ -102,12 +102,27 @@ def build_llvm(llvm_dir, platform, backends, projects, use_clang=False, extra_fl
         "default": [],
     }
 
+    experimental_backends = ["ARC", "Xtensa"]
+    normal_backends = [s for s in backends if s not in experimental_backends]
+
     LLVM_TARGETS_TO_BUILD = [
-        '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(backends) + '"'
-        if backends
+        '-DLLVM_TARGETS_TO_BUILD:STRING="' + ";".join(normal_backends) + '"'
+        if normal_backends
         else '-DLLVM_TARGETS_TO_BUILD:STRING="AArch64;ARM;Mips;RISCV;X86"'
     ]
 
+    # if not on ARC platform, but want to add expeirmental backend ARC as target
+    if platform != "ARC" and "ARC" in backends: 
+        LLVM_TARGETS_TO_BUILD.extend(
+            LLVM_EXTRA_COMPILE_OPTIONS["arc"]
+        )
+
+    if platform != "Xtensa" and "Xtensa" in backends:
+        print(
+            "Currently it's not supported to build Xtensa backend on non-Xtensa platform"
+        )
+        return None
+
     LLVM_PROJECTS_TO_BUILD = [
         '-DLLVM_ENABLE_PROJECTS:STRING="' + ";".join(projects) + '"' if projects else ""
     ]
@@ -125,9 +140,7 @@ def build_llvm(llvm_dir, platform, backends, projects, use_clang=False, extra_fl
     if not llvm_dir.exists():
         raise Exception(f"{llvm_dir} doesn't exist")
 
-    build_dir = llvm_dir.joinpath(
-        "win32build" if "windows" == platform else "build"
-    ).resolve()
+    build_dir = llvm_dir.joinpath("build").resolve()
     build_dir.mkdir(exist_ok=True)
 
     lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve()
@@ -178,6 +191,7 @@ def repackage_llvm(llvm_dir):
         raise Exception("Find more than one LLVM-*.tar.gz")
 
     if not packs:
+        raise Exception("Didn't find any LLVM-* package")
         return
 
     llvm_package = packs[0].name
@@ -193,6 +207,31 @@ def repackage_llvm(llvm_dir):
     # rm ./LLVM-1*.gz
     os.remove(llvm_dir.joinpath(llvm_package).resolve())
 
+def repackage_llvm_windows(llvm_dir):
+    build_dir = llvm_dir.joinpath("./build").resolve()
+
+    packs_path = [f for f in build_dir.glob("./_CPack_Packages/win64/NSIS/LLVM-*-win64")]
+    if len(packs_path) > 1:
+        raise Exception("Find more than one LLVM-* package")
+
+    if not packs_path:
+        raise Exception("Didn't find any LLVM-* package")
+        return
+    
+    llvm_package_path = f"_CPack_Packages/win64/NSIS/{packs_path[0].name}"
+    windows_package_dir = build_dir.joinpath(llvm_package_path).resolve()
+
+    # mv package dir outside of build 
+    shutil.move(str(windows_package_dir), str(llvm_dir))
+    # rm -r build
+    shutil.rmtree(str(build_dir))
+    # mkdir build
+    build_dir.mkdir()
+    # move back all the subdiretories under cpack directory(bin/include/lib) to build dir
+    moved_package_dir = llvm_dir.joinpath(packs_path[0].name)
+    for sub_dir in moved_package_dir.iterdir():
+        shutil.move(str(sub_dir), str(build_dir))
+    moved_package_dir.rmdir()  
 
 def main():
     parser = argparse.ArgumentParser(description="build necessary LLVM libraries")
@@ -216,6 +255,7 @@ def main():
             "X86",
             "Xtensa",
         ],
+        default=[],
         help="identify LLVM supported backends, separate by space, like '--arch ARM Mips X86'",
     )
     parser.add_argument(
@@ -304,7 +344,11 @@ def main():
             )
             is not None
         ):
-            repackage_llvm(llvm_dir)
+            # TODO: repackage process may change in the future, this work for LLVM 15.x
+            if "windows" == platform:
+                repackage_llvm_windows(llvm_dir)
+            else:
+                repackage_llvm(llvm_dir)
 
         return True
     except subprocess.CalledProcessError:

+ 12 - 3
build-scripts/config_common.cmake

@@ -102,9 +102,6 @@ if (WAMR_BUILD_JIT EQUAL 1)
   if (NOT DEFINED LLVM_DIR)
     set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
     set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
-    if (WAMR_BUILD_PLATFORM STREQUAL "windows")
-      set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/win32build")
-    endif ()
     if (NOT EXISTS "${LLVM_BUILD_ROOT}")
         message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}")
     endif ()
@@ -165,6 +162,11 @@ if (WAMR_BUILD_LINUX_PERF EQUAL 1)
   endif ()
 endif ()
 
+if (NOT DEFINED WAMR_BUILD_SHRUNK_MEMORY)
+  # Enable shrunk memory by default
+  set (WAMR_BUILD_SHRUNK_MEMORY 1)
+endif ()
+
 ########################################
 
 message ("-- Build Configurations:")
@@ -602,3 +604,10 @@ endif()
 if (NOT WAMR_BUILD_SANITIZER STREQUAL "")
   message ("     Sanitizer ${WAMR_BUILD_SANITIZER} enabled")
 endif ()
+if (WAMR_BUILD_SHRUNK_MEMORY EQUAL 1)
+  add_definitions (-DWASM_ENABLE_SHRUNK_MEMORY=1)
+  message ("     Shrunk memory enabled")
+else ()
+  add_definitions (-DWASM_ENABLE_SHRUNK_MEMORY=0)
+  message ("     Shrunk memory disabled")
+endif ()

+ 10 - 1
build-scripts/runtime_lib.cmake

@@ -59,7 +59,12 @@ if (WAMR_BUILD_INTERP EQUAL 1)
 endif ()
 
 if (WAMR_BUILD_FAST_JIT EQUAL 1)
-    include (${IWASM_DIR}/fast-jit/iwasm_fast_jit.cmake)
+    if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+        message ("Fast JIT currently not supported on Windows")
+        set (WAMR_BUILD_FAST_JIT 0)
+    else ()
+        include (${IWASM_DIR}/fast-jit/iwasm_fast_jit.cmake)
+    endif ()
 endif ()
 
 if (WAMR_BUILD_JIT EQUAL 1)
@@ -104,6 +109,10 @@ if (WAMR_BUILD_WASI_NN EQUAL 1)
 endif ()
 
 if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
+    if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+        set (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE 0)
+        message ("Lib pthread semaphore currently not supported on Windows")
+    endif ()
     include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
     # Enable the dependent feature if lib pthread is enabled
     set (WAMR_BUILD_THREAD_MGR 1)

+ 1 - 0
ci/coding_guidelines_check.py

@@ -180,6 +180,7 @@ def check_file_name(path: Path) -> bool:
         "docker-compose",
         "package-lock",
         "vite-env.d",
+        "osv-scanner",
     ]:
         return True
 

+ 5 - 1
core/config.h

@@ -84,7 +84,7 @@
 #endif
 
 #define AOT_MAGIC_NUMBER 0x746f6100
-#define AOT_CURRENT_VERSION 3
+#define AOT_CURRENT_VERSION 4
 
 #ifndef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0
@@ -698,4 +698,8 @@
 #define WASM_ENABLE_SHARED_HEAP 0
 #endif
 
+#ifndef WASM_ENABLE_SHRUNK_MEMORY
+#define WASM_ENABLE_SHRUNK_MEMORY 1
+#endif
+
 #endif /* end of _CONFIG_H_ */

+ 201 - 19
core/iwasm/aot/aot_loader.c

@@ -4,9 +4,8 @@
  */
 
 #include "aot_runtime.h"
-#include "bh_common.h"
-#include "bh_log.h"
 #include "aot_reloc.h"
+#include "bh_platform.h"
 #include "../common/wasm_runtime_common.h"
 #include "../common/wasm_native.h"
 #include "../common/wasm_loader_common.h"
@@ -305,12 +304,13 @@ loader_mmap(uint32 size, bool prot_exec, char *error_buf, uint32 error_buf_size)
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
     || defined(BUILD_TARGET_RISCV64_LP64D)                       \
     || defined(BUILD_TARGET_RISCV64_LP64)
-#ifndef __APPLE__
+#if !defined(__APPLE__) && !defined(BH_PLATFORM_LINUX_SGX)
     /* The mmapped AOT data and code in 64-bit targets had better be in
        range 0 to 2G, or aot loader may fail to apply some relocations,
        e.g., R_X86_64_32/R_X86_64_32S/R_X86_64_PC32/R_RISCV_32.
        We try to mmap with MMAP_MAP_32BIT flag first, and if fails, mmap
        again without the flag. */
+    /* sgx_tprotect_rsrv_mem() and sgx_alloc_rsrv_mem() will ignore flags */
     map_flags = MMAP_MAP_32BIT;
     if ((mem = os_mmap(NULL, size, map_prot, map_flags,
                        os_get_invalid_handle()))) {
@@ -967,13 +967,29 @@ destroy_import_memories(AOTImportMemory *import_memories)
     wasm_runtime_free(import_memories);
 }
 
+/**
+ * Free memory initialization data segments.
+ *
+ * @param module the AOT module containing the data
+ * @param data_list array of memory initialization data segments to free
+ * @param count number of segments in the data_list array
+ */
+
 static void
-destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
+destroy_mem_init_data_list(AOTModule *module, AOTMemInitData **data_list,
+                           uint32 count)
 {
     uint32 i;
+    /* Free each memory initialization data segment */
     for (i = 0; i < count; i++)
-        if (data_list[i])
+        if (data_list[i]) {
+            /* If the module owns the binary data, free the bytes buffer */
+            if (module->is_binary_freeable && data_list[i]->bytes)
+                wasm_runtime_free(data_list[i]->bytes);
+            /* Free the data segment structure itself */
             wasm_runtime_free(data_list[i]);
+        }
+    /* Free the array of data segment pointers */
     wasm_runtime_free(data_list);
 }
 
@@ -982,6 +998,22 @@ load_init_expr(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                InitializerExpression *expr, char *error_buf,
                uint32 error_buf_size);
 
+/**
+ * Load memory initialization data segments from the AOT module.
+ *
+ * This function reads memory initialization data segments from the buffer and
+ * creates AOTMemInitData structures for each segment. The data can either be
+ * cloned into new memory or referenced directly from the buffer.
+ *
+ * @param p_buf pointer to buffer containing memory init data
+ * @param buf_end end of buffer
+ * @param module the AOT module being loaded
+ * @param error_buf buffer for error messages
+ * @param error_buf_size size of error buffer
+ *
+ * @return true if successful, false if error occurred
+ */
+
 static bool
 load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
                         AOTModule *module, char *error_buf,
@@ -1013,8 +1045,8 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
             return false;
         }
         read_uint32(buf, buf_end, byte_count);
-        size = offsetof(AOTMemInitData, bytes) + (uint64)byte_count;
-        if (!(data_list[i] = loader_malloc(size, error_buf, error_buf_size))) {
+        if (!(data_list[i] = loader_malloc(sizeof(AOTMemInitData), error_buf,
+                                           error_buf_size))) {
             return false;
         }
 
@@ -1026,8 +1058,22 @@ load_mem_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
         data_list[i]->offset.init_expr_type = init_value.init_expr_type;
         data_list[i]->offset.u = init_value.u;
         data_list[i]->byte_count = byte_count;
-        read_byte_array(buf, buf_end, data_list[i]->bytes,
-                        data_list[i]->byte_count);
+        data_list[i]->bytes = NULL;
+        /* If the module owns the binary data, clone the bytes buffer */
+        if (module->is_binary_freeable) {
+            if (byte_count > 0) {
+                if (!(data_list[i]->bytes = loader_malloc(byte_count, error_buf,
+                                                          error_buf_size))) {
+                    return false;
+                }
+                read_byte_array(buf, buf_end, data_list[i]->bytes,
+                                data_list[i]->byte_count);
+            }
+        }
+        else {
+            data_list[i]->bytes = (uint8 *)buf;
+            buf += byte_count;
+        }
     }
 
     *p_buf = buf;
@@ -1036,6 +1082,21 @@ fail:
     return false;
 }
 
+/**
+ * Load memory information from the AOT module.
+ *
+ * This function reads memory-related data including import memory count,
+ * memory count, memory flags, page sizes, and memory initialization data.
+ *
+ * @param p_buf pointer to buffer containing memory info
+ * @param buf_end end of buffer
+ * @param module the AOT module being loaded
+ * @param error_buf buffer for error messages
+ * @param error_buf_size size of error buffer
+ *
+ * @return true if successful, false if error occurred
+ */
+
 static bool
 load_memory_info(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
                  char *error_buf, uint32 error_buf_size)
@@ -1333,7 +1394,12 @@ load_import_table_list(const uint8 **p_buf, const uint8 *buf_end,
         if (wasm_is_type_multi_byte_type(import_table->table_type.elem_type)) {
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
         }
+        else
 #endif
+        {
+            /* Skip 1 byte */
+            buf += 1;
+        }
         read_uint32(buf, buf_end, import_table->table_type.init_size);
         read_uint32(buf, buf_end, import_table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
@@ -1382,12 +1448,23 @@ load_table_list(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
     for (i = 0; i < module->table_count; i++, table++) {
         read_uint8(buf, buf_end, table->table_type.elem_type);
         read_uint8(buf, buf_end, table->table_type.flags);
+
+        if (!wasm_table_check_flags(table->table_type.flags, error_buf,
+                                    error_buf_size, true)) {
+            return false;
+        }
+
         read_uint8(buf, buf_end, table->table_type.possible_grow);
 #if WASM_ENABLE_GC != 0
         if (wasm_is_type_multi_byte_type(table->table_type.elem_type)) {
             read_uint8(buf, buf_end, ref_type.ref_ht_common.nullable);
         }
+        else
 #endif
+        {
+            /* Skip 1 byte */
+            buf += 1;
+        }
         read_uint32(buf, buf_end, table->table_type.init_size);
         read_uint32(buf, buf_end, table->table_type.max_size);
 #if WASM_ENABLE_GC != 0
@@ -1475,7 +1552,7 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
         else
 #endif
         {
-            /* Skip 8 byte for ref type info */
+            /* Skip 8 byte(2+2+4) for ref type info */
             buf += 8;
         }
 
@@ -2506,6 +2583,15 @@ try_merge_data_and_text(const uint8 **buf, const uint8 **buf_end,
         /* merge failed but may be not critical for some targets */
         return false;
     }
+
+#ifdef BH_PLATFORM_WINDOWS
+    if (!os_mem_commit(sections, code_size,
+                       MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC)) {
+        os_munmap(sections, (uint32)total_size);
+        return false;
+    }
+#endif
+
     /* change the code part to be executable */
     if (os_mprotect(sections, code_size,
                     MMAP_PROT_READ | MMAP_PROT_WRITE | MMAP_PROT_EXEC)
@@ -2520,7 +2606,7 @@ try_merge_data_and_text(const uint8 **buf, const uint8 **buf_end,
     /* order not essential just as compiler does: .text section first */
     *buf = sections;
     *buf_end = sections + code_size;
-    bh_memcpy_s(sections, code_size, old_buf, code_size);
+    bh_memcpy_s(sections, (uint32)code_size, old_buf, (uint32)code_size);
     os_munmap(old_buf, code_size);
     sections += align_uint((uint32)code_size, page_size);
 
@@ -2738,6 +2824,48 @@ destroy_exports(AOTExport *exports)
     wasm_runtime_free(exports);
 }
 
+static int
+cmp_export_name(const void *a, const void *b)
+{
+    return strcmp(*(char **)a, *(char **)b);
+}
+
+static bool
+check_duplicate_exports(AOTModule *module, char *error_buf,
+                        uint32 error_buf_size)
+{
+    uint32 i;
+    bool result = false;
+    char *names_buf[32], **names = names_buf;
+    if (module->export_count > 32) {
+        names = loader_malloc(module->export_count * sizeof(char *), error_buf,
+                              error_buf_size);
+        if (!names) {
+            return result;
+        }
+    }
+
+    for (i = 0; i < module->export_count; i++) {
+        names[i] = module->exports[i].name;
+    }
+
+    qsort(names, module->export_count, sizeof(char *), cmp_export_name);
+
+    for (i = 1; i < module->export_count; i++) {
+        if (!strcmp(names[i], names[i - 1])) {
+            set_error_buf(error_buf, error_buf_size, "duplicate export name");
+            goto cleanup;
+        }
+    }
+
+    result = true;
+cleanup:
+    if (module->export_count > 32) {
+        wasm_runtime_free(names);
+    }
+    return result;
+}
+
 static bool
 load_exports(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
              bool is_load_from_file_buf, char *error_buf, uint32 error_buf_size)
@@ -2759,14 +2887,58 @@ load_exports(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
         read_uint32(buf, buf_end, exports[i].index);
         read_uint8(buf, buf_end, exports[i].kind);
         read_string(buf, buf_end, exports[i].name);
-#if 0 /* TODO: check kind and index */
-        if (export_funcs[i].index >=
-              module->func_count + module->import_func_count) {
-            set_error_buf(error_buf, error_buf_size,
-                          "function index is out of range");
+
+        /* Check export kind and index */
+        switch (exports[i].kind) {
+            case EXPORT_KIND_FUNC:
+                if (exports[i].index
+                    >= module->import_func_count + module->func_count) {
+                    set_error_buf(error_buf, error_buf_size,
+                                  "unknown function");
+                    return false;
+                }
+                break;
+            case EXPORT_KIND_TABLE:
+                if (exports[i].index
+                    >= module->import_table_count + module->table_count) {
+                    set_error_buf(error_buf, error_buf_size, "unknown table");
+                    return false;
+                }
+                break;
+            case EXPORT_KIND_MEMORY:
+                if (exports[i].index
+                    >= module->import_memory_count + module->memory_count) {
+                    set_error_buf(error_buf, error_buf_size, "unknown memory");
+                    return false;
+                }
+                break;
+            case EXPORT_KIND_GLOBAL:
+                if (exports[i].index
+                    >= module->import_global_count + module->global_count) {
+                    set_error_buf(error_buf, error_buf_size, "unknown global");
+                    return false;
+                }
+                break;
+#if WASM_ENABLE_TAGS != 0
+                /* TODO
+                case EXPORT_KIND_TAG:
+                    if (index >= module->import_tag_count + module->tag_count) {
+                        set_error_buf(error_buf, error_buf_size, "unknown tag");
+                        return false;
+                    }
+                    break;
+                */
+#endif
+            default:
+                set_error_buf(error_buf, error_buf_size, "invalid export kind");
+                return false;
+        }
+    }
+
+    if (module->export_count > 0) {
+        if (!check_duplicate_exports(module, error_buf, error_buf_size)) {
             return false;
         }
-#endif
     }
 
     *p_buf = buf;
@@ -4135,6 +4307,16 @@ fail:
     return false;
 }
 
+static bool
+aot_compatible_version(uint32 version)
+{
+    /*
+     * refer to "AoT-compiled module compatibility among WAMR versions" in
+     * ./doc/biuld_wasm_app.md
+     */
+    return version == 4 || version == 3;
+}
+
 static bool
 load(const uint8 *buf, uint32 size, AOTModule *module,
      bool wasm_binary_freeable, bool no_resolve, char *error_buf,
@@ -4153,7 +4335,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module,
     }
 
     read_uint32(p, p_end, version);
-    if (version != AOT_CURRENT_VERSION) {
+    if (!aot_compatible_version(version)) {
         set_error_buf(error_buf, error_buf_size, "unknown binary version");
         return false;
     }
@@ -4235,7 +4417,7 @@ aot_unload(AOTModule *module)
         wasm_runtime_free(module->memories);
 
     if (module->mem_init_data_list)
-        destroy_mem_init_data_list(module->mem_init_data_list,
+        destroy_mem_init_data_list(module, module->mem_init_data_list,
                                    module->mem_init_data_count);
 
     if (module->native_symbol_list)

+ 120 - 28
core/iwasm/aot/aot_runtime.c

@@ -137,6 +137,7 @@ is_frame_per_function(WASMExecEnv *exec_env)
     return module->feature_flags & WASM_FEATURE_FRAME_PER_FUNCTION;
 }
 
+#if WASM_ENABLE_DUMP_CALL_STACK != 0
 static bool
 is_frame_func_idx_disabled(WASMExecEnv *exec_env)
 {
@@ -145,6 +146,7 @@ is_frame_func_idx_disabled(WASMExecEnv *exec_env)
 
     return module->feature_flags & WASM_FEATURE_FRAME_NO_FUNC_IDX;
 }
+#endif
 
 static void *
 get_top_frame(WASMExecEnv *exec_env)
@@ -687,20 +689,23 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
             tbl_inst->cur_size = import_table->table_type.init_size;
             tbl_inst->max_size =
                 aot_get_imp_tbl_data_slots(import_table, false);
-            tbl_inst->elem_type = module->tables[i].table_type.elem_type;
+            tbl_inst->elem_type = import_table->table_type.elem_type;
+            tbl_inst->is_table64 =
+                import_table->table_type.flags & TABLE64_FLAG;
 #if WASM_ENABLE_GC != 0
             tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].table_type.elem_ref_type;
+                import_table->table_type.elem_ref_type;
 #endif
         }
         else {
             AOTTable *table = module->tables + (i - module->import_table_count);
             tbl_inst->cur_size = table->table_type.init_size;
             tbl_inst->max_size = aot_get_tbl_data_slots(table, false);
-            tbl_inst->elem_type = module->tables[i].table_type.elem_type;
+            tbl_inst->elem_type = table->table_type.elem_type;
+            tbl_inst->is_table64 = table->table_type.flags & TABLE64_FLAG;
 #if WASM_ENABLE_GC != 0
             tbl_inst->elem_ref_type.elem_ref_type =
-                module->tables[i].table_type.elem_ref_type;
+                table->table_type.elem_ref_type;
 #endif
         }
 
@@ -740,18 +745,24 @@ tables_instantiate(AOTModuleInstance *module_inst, AOTModule *module,
 
 #if WASM_ENABLE_REF_TYPES != 0
         bh_assert(
-            table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+            table_seg->offset.init_expr_type
+                == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
+                                         : INIT_EXPR_TYPE_I32_CONST)
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
             || table_seg->offset.init_expr_type == INIT_EXPR_TYPE_FUNCREF_CONST
             || table_seg->offset.init_expr_type
                    == INIT_EXPR_TYPE_REFNULL_CONST);
 #else
-        bh_assert(table_seg->offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
+        bh_assert(table_seg->offset.init_expr_type
+                      == (tbl_inst->is_table64 ? INIT_EXPR_TYPE_I64_CONST
+                                               : INIT_EXPR_TYPE_I32_CONST)
                   || table_seg->offset.init_expr_type
                          == INIT_EXPR_TYPE_GET_GLOBAL);
 #endif
 
         /* Resolve table data base offset */
+        /* TODO: The table64 current implementation assumes table max size
+         * UINT32_MAX, so the offset conversion here is safe */
         if (table_seg->offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
             global_index = table_seg->offset.u.global_index;
 
@@ -1088,11 +1099,11 @@ aot_get_default_memory(AOTModuleInstance *module_inst)
 }
 
 AOTMemoryInstance *
-aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index)
+aot_get_memory_with_idx(AOTModuleInstance *module_inst, uint32 mem_idx)
 {
-    if ((index >= module_inst->memory_count) || !module_inst->memories)
+    if ((mem_idx >= module_inst->memory_count) || !module_inst->memories)
         return NULL;
-    return module_inst->memories[index];
+    return module_inst->memories[mem_idx];
 }
 
 static bool
@@ -1274,21 +1285,78 @@ init_func_ptrs(AOTModuleInstance *module_inst, AOTModule *module,
     return true;
 }
 
+static int
+cmp_export_func_map(const void *a, const void *b)
+{
+    uint32 func_idx1 = ((const ExportFuncMap *)a)->func_idx;
+    uint32 func_idx2 = ((const ExportFuncMap *)b)->func_idx;
+    return func_idx1 < func_idx2 ? -1 : (func_idx1 > func_idx2 ? 1 : 0);
+}
+
 AOTFunctionInstance *
-aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx)
+aot_lookup_function_with_idx(AOTModuleInstance *module_inst, uint32 func_idx)
 {
-    AOTModule *module = (AOTModule *)module_inst->module;
     AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
     AOTFunctionInstance *export_funcs =
         (AOTFunctionInstance *)module_inst->export_functions;
+    AOTFunctionInstance *func_inst = NULL;
+    ExportFuncMap *export_func_maps, *export_func_map, key;
+    uint64 size;
     uint32 i;
 
-    /* export functions are pre-instantiated */
-    for (i = 0; i < module_inst->export_func_count; i++) {
-        if (export_funcs[i].func_index == func_idx)
-            return &export_funcs[i];
+    if (module_inst->export_func_count == 0)
+        return NULL;
+
+    exception_lock(module_inst);
+
+    /* create the func_idx to export_idx maps if it hasn't been created */
+    if (!extra->export_func_maps) {
+        size = sizeof(ExportFuncMap) * (uint64)module_inst->export_func_count;
+        if (!(export_func_maps = extra->export_func_maps =
+                  runtime_malloc(size, NULL, 0))) {
+            /* allocate memory failed, lookup the export function one by one */
+            for (i = 0; i < module_inst->export_func_count; i++) {
+                if (export_funcs[i].func_index == func_idx) {
+                    func_inst = &export_funcs[i];
+                    break;
+                }
+            }
+            goto unlock_and_return;
+        }
+
+        for (i = 0; i < module_inst->export_func_count; i++) {
+            export_func_maps[i].func_idx = export_funcs[i].func_index;
+            export_func_maps[i].export_idx = i;
+        }
+
+        qsort(export_func_maps, module_inst->export_func_count,
+              sizeof(ExportFuncMap), cmp_export_func_map);
     }
 
+    /* lookup the map to get the export_idx of the func_idx */
+    key.func_idx = func_idx;
+    export_func_map =
+        bsearch(&key, extra->export_func_maps, module_inst->export_func_count,
+                sizeof(ExportFuncMap), cmp_export_func_map);
+    if (export_func_map)
+        func_inst = &export_funcs[export_func_map->export_idx];
+
+unlock_and_return:
+    exception_unlock(module_inst);
+    return func_inst;
+}
+
+AOTFunctionInstance *
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx)
+{
+    AOTModule *module = (AOTModule *)module_inst->module;
+    AOTModuleInstanceExtra *extra = (AOTModuleInstanceExtra *)module_inst->e;
+    AOTFunctionInstance *func_inst;
+
+    /* lookup from export functions first */
+    if ((func_inst = aot_lookup_function_with_idx(module_inst, func_idx)))
+        return func_inst;
+
     exception_lock(module_inst);
 
     /* allocate functions array if needed */
@@ -1371,6 +1439,15 @@ init_func_type_indexes(AOTModuleInstance *module_inst, AOTModule *module,
     return true;
 }
 
+static int
+cmp_func_inst(const void *a, const void *b)
+{
+    const AOTFunctionInstance *func_inst1 = (const AOTFunctionInstance *)a;
+    const AOTFunctionInstance *func_inst2 = (const AOTFunctionInstance *)b;
+
+    return strcmp(func_inst1->func_name, func_inst2->func_name);
+}
+
 static bool
 create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module,
                     char *error_buf, uint32 error_buf_size)
@@ -1411,6 +1488,9 @@ create_export_funcs(AOTModuleInstance *module_inst, AOTModule *module,
                 export_func++;
             }
         }
+
+        qsort(module_inst->export_functions, module_inst->export_func_count,
+              sizeof(AOTFunctionInstance), cmp_func_inst);
     }
 
     return true;
@@ -1472,9 +1552,7 @@ create_exports(AOTModuleInstance *module_inst, AOTModule *module,
         }
     }
 
-#if WASM_ENABLE_MULTI_MEMORY == 0
-    bh_assert(module_inst->export_memory_count <= 1);
-#else
+#if WASM_ENABLE_MULTI_MEMORY != 0
     if (module_inst->export_memory_count) {
         module_inst->export_memories = export_memories_instantiate(
             module, module_inst, module_inst->export_memory_count, error_buf,
@@ -1563,8 +1641,12 @@ execute_post_instantiate_functions(AOTModuleInstance *module_inst,
     if (is_sub_inst) {
         bh_assert(exec_env_main);
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-        bh_assert(exec_env_tls == exec_env_main);
-        (void)exec_env_tls;
+        /* May come from pthread_create_wrapper, thread_spawn_wrapper and
+           wasm_cluster_spawn_exec_env. If it comes from the former two,
+           the exec_env_tls must be not NULL and equal to exec_env_main,
+           else if it comes from the last one, it may be NULL. */
+        if (exec_env_tls)
+            bh_assert(exec_env_tls == exec_env_main);
 #endif
         exec_env = exec_env_main;
 
@@ -1706,7 +1788,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
     bool ret = false;
 #endif
 
-    /* Check heap size */
+    /* Align and validate heap size */
     heap_size = align_uint(heap_size, 8);
     if (heap_size > APP_HEAP_SIZE_MAX)
         heap_size = APP_HEAP_SIZE_MAX;
@@ -1826,7 +1908,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
             goto fail;
         }
         for (i = 0; i < module->table_init_data_count; i++) {
-            if (wasm_elem_is_active(module->table_init_data_list[i]->mode))
+            if (wasm_elem_is_active(module->table_init_data_list[i]->mode)
+                || wasm_elem_is_declarative(
+                    module->table_init_data_list[i]->mode))
                 bh_bitmap_set_bit(common->elem_dropped, i);
         }
     }
@@ -1922,7 +2006,11 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
         AOTTableInstance *table_inst;
         table_elem_type_t *table_data;
 
-        table = &module->tables[i];
+        /* bypass imported table since AOTImportTable doesn't have init_expr */
+        if (i < module->import_table_count)
+            continue;
+
+        table = &module->tables[i - module->import_table_count];
         bh_assert(table);
 
         if (table->init_expr.init_expr_type == INIT_EXPR_NONE) {
@@ -2146,6 +2234,9 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
     if (module_inst->export_functions)
         wasm_runtime_free(module_inst->export_functions);
 
+    if (extra->export_func_maps)
+        wasm_runtime_free(extra->export_func_maps);
+
 #if WASM_ENABLE_MULTI_MEMORY != 0
     if (module_inst->export_memories)
         wasm_runtime_free(module_inst->export_memories);
@@ -2196,14 +2287,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
 AOTFunctionInstance *
 aot_lookup_function(const AOTModuleInstance *module_inst, const char *name)
 {
-    uint32 i;
     AOTFunctionInstance *export_funcs =
         (AOTFunctionInstance *)module_inst->export_functions;
+    AOTFunctionInstance key = { .func_name = (char *)name };
 
-    for (i = 0; i < module_inst->export_func_count; i++)
-        if (!strcmp(export_funcs[i].func_name, name))
-            return &export_funcs[i];
-    return NULL;
+    if (!export_funcs)
+        return NULL;
+
+    return bsearch(&key, export_funcs, module_inst->export_func_count,
+                   sizeof(AOTFunctionInstance), cmp_func_inst);
 }
 
 #ifdef OS_ENABLE_HW_BOUND_CHECK

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

@@ -109,6 +109,13 @@ typedef struct AOTFunctionInstance {
     } u;
 } AOTFunctionInstance;
 
+/* Map of a function index to the element ith in
+   the export functions array */
+typedef struct ExportFuncMap {
+    uint32 func_idx;
+    uint32 export_idx;
+} ExportFuncMap;
+
 typedef struct AOTModuleInstanceExtra {
     DefPointer(const uint32 *, stack_sizes);
     /*
@@ -120,6 +127,13 @@ typedef struct AOTModuleInstanceExtra {
     MemBound shared_heap_start_off;
 
     WASMModuleInstanceExtraCommon common;
+
+    /**
+     * maps of func indexes to export func indexes, which
+     * is sorted by func index for a quick lookup and is
+     * created only when first time used.
+     */
+    ExportFuncMap *export_func_maps;
     AOTFunctionInstance **functions;
     uint32 function_count;
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -556,6 +570,13 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
 AOTFunctionInstance *
 aot_lookup_function(const AOTModuleInstance *module_inst, const char *name);
 
+/**
+ * Lookup an exported function in the AOT module instance with
+ * the function index.
+ */
+AOTFunctionInstance *
+aot_lookup_function_with_idx(AOTModuleInstance *module_inst, uint32 func_idx);
+
 AOTMemoryInstance *
 aot_lookup_memory(AOTModuleInstance *module_inst, char const *name);
 
@@ -563,7 +584,7 @@ AOTMemoryInstance *
 aot_get_default_memory(AOTModuleInstance *module_inst);
 
 AOTMemoryInstance *
-aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index);
+aot_get_memory_with_idx(AOTModuleInstance *module_inst, uint32 mem_idx);
 
 /**
  * Get a function in the AOT module instance.
@@ -574,7 +595,7 @@ aot_get_memory_with_index(AOTModuleInstance *module_inst, uint32 index);
  * @return the function instance found
  */
 AOTFunctionInstance *
-aot_get_function_instance(AOTModuleInstance *module_inst, uint32_t func_idx);
+aot_get_function_instance(AOTModuleInstance *module_inst, uint32 func_idx);
 
 /**
  * Call the given AOT function of a AOT module instance with

+ 13 - 0
core/iwasm/aot/arch/aot_reloc_riscv.c

@@ -24,6 +24,7 @@
 #undef NEED_SOFT_I32_DIV
 #undef NEED_SOFT_I64_MUL
 #undef NEED_SOFT_I64_DIV
+#undef NEED_SOFT_ATOMIC
 
 #ifdef __riscv_flen
 #if __riscv_flen == 32
@@ -48,6 +49,10 @@
 #define NEED_SOFT_I64_DIV
 #endif
 
+#ifndef __riscv_atomic
+#define NEED_SOFT_ATOMIC
+#endif
+
 /* clang-format off */
 void __adddf3(void);
 void __addsf3(void);
@@ -101,6 +106,9 @@ void __umoddi3(void);
 void __umodsi3(void);
 void __unorddf2(void);
 void __unordsf2(void);
+bool __atomic_compare_exchange_4(volatile void *, void *, unsigned int,
+                                 bool, int, int);
+void __atomic_store_4(volatile void *, unsigned int, int);
 /* clang-format on */
 
 static SymbolMap target_sym_map[] = {
@@ -127,6 +135,7 @@ static SymbolMap target_sym_map[] = {
      * to convert float and long long
      */
     REG_SYM(__floatundisf),
+    REG_SYM(__floatdisf),
 #endif
 #ifdef NEED_SOFT_DP
     REG_SYM(__adddf3),
@@ -175,6 +184,10 @@ static SymbolMap target_sym_map[] = {
     REG_SYM(__moddi3),
     REG_SYM(__udivdi3),
     REG_SYM(__umoddi3),
+#endif
+#ifdef NEED_SOFT_ATOMIC
+    REG_SYM(__atomic_compare_exchange_4),
+    REG_SYM(__atomic_store_4),
 #endif
     /* clang-format on */
 };

+ 4 - 7
core/iwasm/common/SConscript

@@ -13,13 +13,10 @@ cwd     = GetCurrentDir()
 
 src = Glob('*.c')
 
-if rtconfig.ARCH == 'arm':
-    if re.match('^cortex-m.*', rtconfig.CPU):
-        src += ['arch/invokeNative_thumb.s']
-    elif re.match('^cortex-a.*', rtconfig.CPU):
-        src += ['arch/invokeNative_arm.s']
-elif rtconfig.ARCH == 'ia32':
-    src += ['arch/invokeNative_ia32.s']
+if rtconfig.ARCH == 'arm' and re.match('^cortex-m.*', rtconfig.CPU):
+    src += ['arch/invokeNative_thumb.s']
+else:
+    src.append(f"arch/invokeNative_{rtconfig.ARCH}.s")
 
 CPPPATH = [cwd, cwd + '/../include']
 

+ 2 - 1
core/iwasm/common/wasm_application.c

@@ -105,7 +105,8 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
     bool ret, is_import_func = true, is_memory64 = false;
 #if WASM_ENABLE_MEMORY64 != 0
     WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst;
-    is_memory64 = wasm_module_inst->memories[0]->is_memory64;
+    if (wasm_module_inst->memory_count > 0)
+        is_memory64 = wasm_module_inst->memories[0]->is_memory64;
 #endif
 
     exec_env = wasm_runtime_get_exec_env_singleton(module_inst);

+ 5 - 16
core/iwasm/common/wasm_c_api.c

@@ -3330,6 +3330,7 @@ argv_to_results(const uint32 *argv, const wasm_valtype_vec_t *result_defs,
                 break;
 #if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
             case WASM_EXTERNREF:
+            case WASM_FUNCREF:
                 result->of.ref = (struct wasm_ref_t *)(*(uintptr_t *)argv);
                 argv += sizeof(uintptr_t) / sizeof(uint32);
                 break;
@@ -3383,22 +3384,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
         if (!(func_comm_rt = func->func_comm_rt)) {
             AOTModuleInstance *inst_aot =
                 (AOTModuleInstance *)func->inst_comm_rt;
-            AOTModule *module_aot = (AOTModule *)inst_aot->module;
-            uint32 export_i = 0, export_func_j = 0;
-
-            for (; export_i < module_aot->export_count; ++export_i) {
-                AOTExport *export = module_aot->exports + export_i;
-                if (export->kind == EXPORT_KIND_FUNC) {
-                    if (export->index == func->func_idx_rt) {
-                        func_comm_rt =
-                            (AOTFunctionInstance *)inst_aot->export_functions
-                            + export_func_j;
-                        ((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
-                        break;
-                    }
-                    export_func_j++;
-                }
-            }
+            func_comm_rt = ((wasm_func_t *)func)->func_comm_rt =
+                aot_lookup_function_with_idx(inst_aot, func->func_idx_rt);
         }
 #endif
     }
@@ -3455,6 +3442,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
     if (result_count) {
         if (!argv_to_results(argv, wasm_functype_results(func->type),
                              results)) {
+            wasm_runtime_set_exception(func->inst_comm_rt,
+                                       "argv_to_results failed");
             goto failed;
         }
         results->num_elems = result_count;

+ 7 - 2
core/iwasm/common/wasm_exec_env.c

@@ -282,8 +282,13 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
     os_mutex_lock(&exec_env->wait_lock);
 #endif
     exec_env->handle = os_self_thread();
-    exec_env->native_stack_boundary =
-        stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
+    if (exec_env->user_native_stack_boundary)
+        /* WASM_STACK_GUARD_SIZE isn't added for flexibility to developer,
+           he must ensure that enough guard bytes are kept. */
+        exec_env->native_stack_boundary = exec_env->user_native_stack_boundary;
+    else
+        exec_env->native_stack_boundary =
+            stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
     exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
 #if WASM_ENABLE_THREAD_MGR != 0
     os_mutex_unlock(&exec_env->wait_lock);

+ 4 - 0
core/iwasm/common/wasm_exec_env.h

@@ -136,6 +136,10 @@ typedef struct WASMExecEnv {
 
     void *user_data;
 
+    /* The boundary of native stack set by host embedder. It is used
+       if it is not NULL when calling wasm functions. */
+    uint8 *user_native_stack_boundary;
+
     /* The native thread handle of current thread */
     korp_tid handle;
 

+ 62 - 0
core/iwasm/common/wasm_loader_common.c

@@ -19,6 +19,37 @@ wasm_loader_set_error_buf(char *error_buf, uint32 error_buf_size,
     }
 }
 
+#if WASM_ENABLE_MEMORY64 != 0
+bool
+check_memory64_flags_consistency(WASMModule *module, char *error_buf,
+                                 uint32 error_buf_size, bool is_aot)
+{
+    uint32 i;
+    bool wasm64_flag, all_wasm64 = true, none_wasm64 = true;
+
+    for (i = 0; i < module->import_memory_count; ++i) {
+        wasm64_flag =
+            module->import_memories[i].u.memory.mem_type.flags & MEMORY64_FLAG;
+        all_wasm64 &= wasm64_flag;
+        none_wasm64 &= !wasm64_flag;
+    }
+
+    for (i = 0; i < module->memory_count; ++i) {
+        wasm64_flag = module->memories[i].flags & MEMORY64_FLAG;
+        all_wasm64 &= wasm64_flag;
+        none_wasm64 &= !wasm64_flag;
+    }
+
+    if (!(all_wasm64 || none_wasm64)) {
+        wasm_loader_set_error_buf(
+            error_buf, error_buf_size,
+            "inconsistent limits wasm64 flags for memory sections", is_aot);
+        return false;
+    }
+    return true;
+}
+#endif
+
 bool
 wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
                         uint32 error_buf_size, bool is_aot)
@@ -60,6 +91,37 @@ wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
     return true;
 }
 
+bool
+wasm_table_check_flags(const uint8 table_flag, char *error_buf,
+                       uint32 error_buf_size, bool is_aot)
+{
+    /* Check whether certain features indicated by mem_flag are enabled in
+     * runtime */
+    if (table_flag > MAX_TABLE_SIZE_FLAG) {
+        if (table_flag & SHARED_TABLE_FLAG) {
+            wasm_loader_set_error_buf(error_buf, error_buf_size,
+                                      "tables cannot be shared", is_aot);
+        }
+#if WASM_ENABLE_MEMORY64 == 0
+        if (table_flag & TABLE64_FLAG) {
+            wasm_loader_set_error_buf(error_buf, error_buf_size,
+                                      "invalid limits flags(table64 flag was "
+                                      "found, please enable memory64)",
+                                      is_aot);
+            return false;
+        }
+#endif
+    }
+
+    if (table_flag > MAX_TABLE_SIZE_FLAG + TABLE64_FLAG) {
+        wasm_loader_set_error_buf(error_buf, error_buf_size,
+                                  "invalid limits flags", is_aot);
+        return false;
+    }
+
+    return true;
+}
+
 /*
  * compare with a bigger type set in `wasm_value_type_size_internal()`,
  * this function will only cover global value type, function's param

+ 12 - 0
core/iwasm/common/wasm_loader_common.h

@@ -13,10 +13,22 @@
 extern "C" {
 #endif
 
+#if WASM_ENABLE_MEMORY64 != 0
+/* check consistency of memory64 flags across all memories,
+ * they must be either all wasm64 or all wasm32 */
+bool
+check_memory64_flags_consistency(WASMModule *module, char *error_buf,
+                                 uint32 error_buf_size, bool is_aot);
+#endif
+
 bool
 wasm_memory_check_flags(const uint8 mem_flag, char *error_buf,
                         uint32 error_buf_size, bool is_aot);
 
+bool
+wasm_table_check_flags(const uint8 table_flag, char *error_buf,
+                       uint32 error_buf_size, bool is_aot);
+
 bool
 is_valid_value_type(uint8 value_tpye);
 

+ 24 - 7
core/iwasm/common/wasm_memory.c

@@ -420,13 +420,31 @@ is_native_addr_in_shared_heap(WASMModuleInstanceCommon *module_inst,
                               uint8 *addr, uint32 bytes)
 {
     WASMSharedHeap *heap = get_shared_heap(module_inst);
+    uintptr_t base_addr;
+    uintptr_t addr_int;
+    uintptr_t end_addr;
 
-    if (heap && addr >= heap->base_addr
-        && addr + bytes <= heap->base_addr + heap->size
-        && addr + bytes > addr) {
-        return true;
+    if (!heap) {
+        return false;
     }
-    return false;
+
+    base_addr = (uintptr_t)heap->base_addr;
+    addr_int = (uintptr_t)addr;
+    if (addr_int < base_addr) {
+        return false;
+    }
+
+    end_addr = addr_int + bytes;
+    /* Check for overflow */
+    if (end_addr <= addr_int) {
+        return false;
+    }
+
+    if (end_addr > base_addr + heap->size) {
+        return false;
+    }
+
+    return true;
 }
 
 uint64
@@ -1579,8 +1597,7 @@ wasm_runtime_get_memory(WASMModuleInstanceCommon *module_inst, uint32 index)
 
 #if WASM_ENABLE_AOT != 0
     if (module_inst->module_type == Wasm_Module_AoT)
-        return aot_get_memory_with_index((AOTModuleInstance *)module_inst,
-                                         index);
+        return aot_get_memory_with_idx((AOTModuleInstance *)module_inst, index);
 #endif
 
     return NULL;

+ 155 - 69
core/iwasm/common/wasm_runtime_common.c

@@ -358,7 +358,6 @@ runtime_exception_handler(EXCEPTION_POINTERS *exce_info)
     PEXCEPTION_RECORD ExceptionRecord = exce_info->ExceptionRecord;
     uint8 *sig_addr = (uint8 *)ExceptionRecord->ExceptionInformation[1];
     WASMModuleInstance *module_inst;
-    WASMMemoryInstance *memory_inst;
     WASMJmpBuf *jmpbuf_node;
     uint8 *mapped_mem_start_addr = NULL;
     uint8 *mapped_mem_end_addr = NULL;
@@ -2226,6 +2225,13 @@ wasm_runtime_get_user_data(WASMExecEnv *exec_env)
     return exec_env->user_data;
 }
 
+void
+wasm_runtime_set_native_stack_boundary(WASMExecEnv *exec_env,
+                                       uint8 *native_stack_boundary)
+{
+    exec_env->user_native_stack_boundary = native_stack_boundary;
+}
+
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 void
 wasm_runtime_access_exce_check_guard_page()
@@ -3008,9 +3014,9 @@ static const char *exception_msgs[] = {
     "wasm operand stack overflow",    /* EXCE_OPERAND_STACK_OVERFLOW */
     "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
     /* GC related exceptions */
-    "null function object",           /* EXCE_NULL_FUNC_OBJ */
-    "null structure object",          /* EXCE_NULL_STRUCT_OBJ */
-    "null array reference",              /* EXCE_NULL_ARRAY_OBJ */
+    "null function reference",        /* EXCE_NULL_FUNC_OBJ */
+    "null structure reference",       /* EXCE_NULL_STRUCT_OBJ */
+    "null array reference",           /* EXCE_NULL_ARRAY_OBJ */
     "null i31 reference",             /* EXCE_NULL_I31_OBJ */
     "null reference",                 /* EXCE_NULL_REFERENCE */
     "create rtt type failed",         /* EXCE_FAILED_TO_CREATE_RTT_TYPE */
@@ -3018,7 +3024,7 @@ static const char *exception_msgs[] = {
     "create array object failed",     /* EXCE_FAILED_TO_CREATE_ARRAY_OBJ */
     "create externref object failed", /* EXCE_FAILED_TO_CREATE_EXTERNREF_OBJ */
     "cast failure",                   /* EXCE_CAST_FAILURE */
-    "out of bounds array access",      /* EXCE_ARRAY_IDX_OOB */
+    "out of bounds array access",     /* EXCE_ARRAY_IDX_OOB */
     /* stringref related exceptions */
     "create string object failed",    /* EXCE_FAILED_TO_CREATE_STRING */
     "create stringref failed",        /* EXCE_FAILED_TO_CREATE_STRINGREF */
@@ -3611,7 +3617,8 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
         char mapping_copy_buf[256];
         char *mapping_copy = mapping_copy_buf;
         char *map_mapped = NULL, *map_host = NULL;
-        const unsigned long max_len = strlen(map_dir_list[i]) * 2 + 3;
+        const unsigned long max_len =
+            (unsigned long)strlen(map_dir_list[i]) * 2 + 3;
 
         /* Allocation limit for runtime environments with reduced stack size */
         if (max_len > 256) {
@@ -3624,8 +3631,14 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
 
         bh_memcpy_s(mapping_copy, max_len, map_dir_list[i],
                     (uint32)(strlen(map_dir_list[i]) + 1));
-        map_mapped = strtok(mapping_copy, "::");
-        map_host = strtok(NULL, "::");
+
+        const char *delim = "::";
+        char *delim_pos = strstr(mapping_copy, delim);
+        if (delim_pos) {
+            *delim_pos = '\0';
+            map_mapped = mapping_copy;
+            map_host = delim_pos + strlen(delim);
+        }
 
         if (!map_mapped || !map_host) {
             if (error_buf)
@@ -3901,23 +3914,18 @@ wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst)
 WASMFunctionInstanceCommon *
 wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst)
 {
-    uint32 i;
-
 #if WASM_ENABLE_INTERP != 0
     if (module_inst->module_type == Wasm_Module_Bytecode) {
         WASMModuleInstance *wasm_inst = (WASMModuleInstance *)module_inst;
-        WASMFunctionInstance *func;
-        for (i = 0; i < wasm_inst->export_func_count; i++) {
-            if (!strcmp(wasm_inst->export_functions[i].name, "_start")) {
-                func = wasm_inst->export_functions[i].function;
-                if (func->u.func->func_type->param_count != 0
-                    || func->u.func->func_type->result_count != 0) {
-                    LOG_ERROR("Lookup wasi _start function failed: "
-                              "invalid function type.\n");
-                    return NULL;
-                }
-                return (WASMFunctionInstanceCommon *)func;
+        WASMFunctionInstance *func = wasm_lookup_function(wasm_inst, "_start");
+        if (func) {
+            if (func->u.func->func_type->param_count != 0
+                || func->u.func->func_type->result_count != 0) {
+                LOG_ERROR("Lookup wasi _start function failed: "
+                          "invalid function type.\n");
+                return NULL;
             }
+            return (WASMFunctionInstanceCommon *)func;
         }
         return NULL;
     }
@@ -3926,19 +3934,15 @@ wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst)
 #if WASM_ENABLE_AOT != 0
     if (module_inst->module_type == Wasm_Module_AoT) {
         AOTModuleInstance *aot_inst = (AOTModuleInstance *)module_inst;
-        AOTFunctionInstance *export_funcs =
-            (AOTFunctionInstance *)aot_inst->export_functions;
-        for (i = 0; i < aot_inst->export_func_count; i++) {
-            if (!strcmp(export_funcs[i].func_name, "_start")) {
-                AOTFuncType *func_type = export_funcs[i].u.func.func_type;
-                if (func_type->param_count != 0
-                    || func_type->result_count != 0) {
-                    LOG_ERROR("Lookup wasi _start function failed: "
-                              "invalid function type.\n");
-                    return NULL;
-                }
-                return (WASMFunctionInstanceCommon *)&export_funcs[i];
+        AOTFunctionInstance *func = aot_lookup_function(aot_inst, "_start");
+        if (func) {
+            AOTFuncType *func_type = func->u.func.func_type;
+            if (func_type->param_count != 0 || func_type->result_count != 0) {
+                LOG_ERROR("Lookup wasi _start function failed: "
+                          "invalid function type.\n");
+                return NULL;
             }
+            return func;
         }
         return NULL;
     }
@@ -4262,31 +4266,68 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
         export_type->kind = aot_export->kind;
         switch (export_type->kind) {
             case WASM_IMPORT_EXPORT_KIND_FUNC:
-                export_type->u.func_type =
-                    (AOTFuncType *)aot_module
-                        ->types[aot_module->func_type_indexes
-                                    [aot_export->index
-                                     - aot_module->import_func_count]];
+            {
+                if (aot_export->index < aot_module->import_func_count) {
+                    export_type->u.func_type =
+                        (AOTFuncType *)aot_module
+                            ->import_funcs[aot_export->index]
+                            .func_type;
+                }
+                else {
+                    export_type->u.func_type =
+                        (AOTFuncType *)aot_module
+                            ->types[aot_module->func_type_indexes
+                                        [aot_export->index
+                                         - aot_module->import_func_count]];
+                }
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_GLOBAL:
-                export_type->u.global_type =
-                    &aot_module
-                         ->globals[aot_export->index
-                                   - aot_module->import_global_count]
-                         .type;
+            {
+                if (aot_export->index < aot_module->import_global_count) {
+                    export_type->u.global_type =
+                        &aot_module->import_globals[aot_export->index].type;
+                }
+                else {
+                    export_type->u.global_type =
+                        &aot_module
+                             ->globals[aot_export->index
+                                       - aot_module->import_global_count]
+                             .type;
+                }
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                export_type->u.table_type =
-                    &aot_module
-                         ->tables[aot_export->index
-                                  - aot_module->import_table_count]
-                         .table_type;
+            {
+                if (aot_export->index < aot_module->import_table_count) {
+                    export_type->u.table_type =
+                        &aot_module->import_tables[aot_export->index]
+                             .table_type;
+                }
+                else {
+                    export_type->u.table_type =
+                        &aot_module
+                             ->tables[aot_export->index
+                                      - aot_module->import_table_count]
+                             .table_type;
+                }
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
-                export_type->u.memory_type =
-                    &aot_module->memories[aot_export->index
-                                          - aot_module->import_memory_count];
+            {
+                if (aot_export->index < aot_module->import_memory_count) {
+                    export_type->u.memory_type =
+                        &aot_module->import_memories[aot_export->index]
+                             .mem_type;
+                }
+                else {
+                    export_type->u.memory_type =
+                        &aot_module
+                             ->memories[aot_export->index
+                                        - aot_module->import_memory_count];
+                }
                 break;
+            }
             default:
                 bh_assert(0);
                 break;
@@ -4308,31 +4349,76 @@ wasm_runtime_get_export_type(WASMModuleCommon *const module, int32 export_index,
         export_type->kind = wasm_export->kind;
         switch (export_type->kind) {
             case WASM_IMPORT_EXPORT_KIND_FUNC:
-                export_type->u.func_type =
-                    wasm_module
-                        ->functions[wasm_export->index
-                                    - wasm_module->import_function_count]
-                        ->func_type;
+            {
+                if (wasm_export->index < wasm_module->import_function_count) {
+                    export_type->u.func_type =
+                        (WASMFuncType *)wasm_module
+                            ->import_functions[wasm_export->index]
+                            .u.function.func_type;
+                }
+                else {
+                    export_type->u.func_type =
+                        wasm_module
+                            ->functions[wasm_export->index
+                                        - wasm_module->import_function_count]
+                            ->func_type;
+                }
+
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_GLOBAL:
-                export_type->u.global_type =
-                    &wasm_module
-                         ->globals[wasm_export->index
-                                   - wasm_module->import_global_count]
-                         .type;
+            {
+                if (wasm_export->index < wasm_module->import_global_count) {
+                    export_type->u.global_type =
+                        (WASMGlobalType *)&wasm_module
+                            ->import_globals[wasm_export->index]
+                            .u.global.type;
+                }
+                else {
+                    export_type->u.global_type =
+                        &wasm_module
+                             ->globals[wasm_export->index
+                                       - wasm_module->import_global_count]
+                             .type;
+                }
+
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_TABLE:
-                export_type->u.table_type =
-                    &wasm_module
-                         ->tables[wasm_export->index
-                                  - wasm_module->import_table_count]
-                         .table_type;
+            {
+                if (wasm_export->index < wasm_module->import_table_count) {
+                    export_type->u.table_type =
+                        (WASMTableType *)&wasm_module
+                            ->import_tables[wasm_export->index]
+                            .u.table.table_type;
+                }
+                else {
+                    export_type->u.table_type =
+                        &wasm_module
+                             ->tables[wasm_export->index
+                                      - wasm_module->import_table_count]
+                             .table_type;
+                }
+
                 break;
+            }
             case WASM_IMPORT_EXPORT_KIND_MEMORY:
-                export_type->u.memory_type =
-                    &wasm_module->memories[wasm_export->index
-                                           - wasm_module->import_memory_count];
+            {
+                if (wasm_export->index < wasm_module->import_memory_count) {
+                    export_type->u.memory_type =
+                        (WASMMemoryType *)&wasm_module
+                            ->import_memories[wasm_export->index]
+                            .u.memory.mem_type;
+                }
+                else {
+                    export_type->u.memory_type =
+                        &wasm_module
+                             ->memories[wasm_export->index
+                                        - wasm_module->import_memory_count];
+                }
+
                 break;
+            }
             default:
                 bh_assert(0);
                 break;

+ 5 - 0
core/iwasm/common/wasm_runtime_common.h

@@ -673,6 +673,11 @@ wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
 WASM_RUNTIME_API_EXTERN void *
 wasm_runtime_get_user_data(WASMExecEnv *exec_env);
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_native_stack_boundary(WASMExecEnv *exec_env,
+                                       uint8 *native_stack_boundary);
+
 #if WASM_CONFIGURABLE_BOUNDS_CHECKS != 0
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN void

+ 240 - 84
core/iwasm/compilation/aot.c

@@ -36,8 +36,11 @@ aot_destroy_mem_init_data_list(AOTMemInitData **data_list, uint32 count)
 {
     uint32 i;
     for (i = 0; i < count; i++)
-        if (data_list[i])
+        if (data_list[i]) {
+            if (data_list[i]->bytes)
+                wasm_runtime_free(data_list[i]->bytes);
             wasm_runtime_free(data_list[i]);
+        }
     wasm_runtime_free(data_list);
 }
 
@@ -60,8 +63,7 @@ aot_create_mem_init_data_list(const WASMModule *module)
 
     /* Create each memory data segment */
     for (i = 0; i < module->data_seg_count; i++) {
-        size = offsetof(AOTMemInitData, bytes)
-               + (uint64)module->data_segments[i]->data_length;
+        size = sizeof(AOTMemInitData);
         if (size >= UINT32_MAX
             || !(data_list[i] = wasm_runtime_malloc((uint32)size))) {
             aot_set_last_error("allocate memory failed.");
@@ -69,18 +71,31 @@ aot_create_mem_init_data_list(const WASMModule *module)
         }
 
 #if WASM_ENABLE_BULK_MEMORY != 0
+        /* Set bulk memory specific properties if enabled */
         data_list[i]->is_passive = module->data_segments[i]->is_passive;
         data_list[i]->memory_index = module->data_segments[i]->memory_index;
 #endif
         data_list[i]->offset = module->data_segments[i]->base_offset;
         data_list[i]->byte_count = module->data_segments[i]->data_length;
-        memcpy(data_list[i]->bytes, module->data_segments[i]->data,
-               module->data_segments[i]->data_length);
+        data_list[i]->bytes = NULL;
+        /* Allocate memory for AOT compiler is OK, because the data segment
+         * is small and the host memory is enough */
+        if (data_list[i]->byte_count > 0) {
+            data_list[i]->bytes = wasm_runtime_malloc(data_list[i]->byte_count);
+            if (!data_list[i]->bytes) {
+                aot_set_last_error("allocate memory failed.");
+                goto fail;
+            }
+            /* Copy the actual data bytes from the WASM module */
+            memcpy(data_list[i]->bytes, module->data_segments[i]->data,
+                   module->data_segments[i]->data_length);
+        }
     }
 
     return data_list;
 
 fail:
+    /* Clean up allocated memory in case of failure */
     aot_destroy_mem_init_data_list(data_list, module->data_seg_count);
     return NULL;
 }
@@ -487,60 +502,70 @@ calculate_struct_field_sizes_offsets(AOTCompData *comp_data, bool is_target_x86,
 }
 #endif
 
-AOTCompData *
-aot_create_comp_data(WASMModule *module, const char *target_arch,
-                     bool gc_enabled)
+/**
+ * Checks if target architecture is 64-bit based on target_arch string.
+ *
+ * @param target_arch The target architecture string (e.g. "x86_64", "aarch64")
+ * @return true if target is 64-bit architecture, false otherwise
+ *
+ * If target_arch is NULL, detection is based on UINTPTR_MAX.
+ * Otherwise looks for "64" in target_arch string.
+ */
+static bool
+arch_is_64bit(const char *target_arch)
 {
-    AOTCompData *comp_data;
-    uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0, i, j;
-    uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
-    uint64 size;
-    bool is_64bit_target = false;
-#if WASM_ENABLE_GC != 0
-    bool is_target_x86 = false;
-#endif
-
-#if WASM_ENABLE_GC != 0
     if (!target_arch) {
-#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
-    || defined(BUILD_TARGET_X86_32)
-        is_target_x86 = true;
+#if UINTPTR_MAX == UINT64_MAX
+        return true;
+#else
+        return false;
 #endif
     }
-    else {
-        if (!strncmp(target_arch, "x86_64", 6)
-            || !strncmp(target_arch, "i386", 4))
-            is_target_x86 = true;
-    }
-#endif
+    /* All 64bit targets contains "64" string in their target name */
+    return strstr(target_arch, "64") != NULL;
+}
 
+/**
+ * Checks if target architecture is x86/x64 based on target_arch string.
+ *
+ * @param target_arch The target architecture string (e.g. "x86_64", "i386")
+ * @return true if target is x86/x64 architecture, false otherwise
+ *
+ * If target_arch is NULL, detection is based on build-time definitions.
+ * Otherwise checks for x86_64 or i386 in target_arch string.
+ */
+static bool
+arch_is_x86(const char *target_arch)
+{
     if (!target_arch) {
-#if UINTPTR_MAX == UINT64_MAX
-        is_64bit_target = true;
+#if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64) \
+    || defined(BUILD_TARGET_X86_32)
+        return true;
+#else
+        return false;
 #endif
     }
-    else {
-        /* All 64bit targets contains "64" string in their target name */
-        if (strstr(target_arch, "64") != NULL) {
-            is_64bit_target = true;
-        }
-    }
-
-    /* Allocate memory */
-    if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
-        aot_set_last_error("create compile data failed.\n");
-        return NULL;
-    }
+    return !strncmp(target_arch, "x86_64", 6)
+           || !strncmp(target_arch, "i386", 4);
+}
 
-    memset(comp_data, 0, sizeof(AOTCompData));
+/**
+ * Initialize memory information in AOT compilation data from WASM module.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing memory information
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_memories(AOTCompData *comp_data, WASMModule *module)
+{
+    uint32 i, j;
+    uint64 size;
 
     comp_data->memory_count =
         module->import_memory_count + module->memory_count;
 
-    /* TODO: create import memories */
-
     /* Allocate memory for memory array, reserve one AOTMemory space at least */
-    /* TODO: multi-memory */
     if (!comp_data->memory_count)
         comp_data->memory_count = 1;
 
@@ -548,7 +573,7 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     if (size >= UINT32_MAX
         || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
         aot_set_last_error("create memories array failed.\n");
-        goto fail;
+        return false;
     }
     memset(comp_data->memories, 0, size);
 
@@ -580,22 +605,30 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
         }
     }
 
-    /* Create memory data segments */
-    comp_data->mem_init_data_count = module->data_seg_count;
-    if (comp_data->mem_init_data_count > 0
-        && !(comp_data->mem_init_data_list =
-                 aot_create_mem_init_data_list(module)))
-        goto fail;
+    return true;
+}
+
+/**
+ * Initialize table information in AOT compilation data from WASM module.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing table information
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_tables(AOTCompData *comp_data, WASMModule *module)
+{
+    uint32 i, j;
+    uint64 size;
 
-    /* Create tables */
     comp_data->table_count = module->import_table_count + module->table_count;
 
     if (comp_data->table_count > 0) {
         size = sizeof(AOTTable) * (uint64)comp_data->table_count;
         if (size >= UINT32_MAX
             || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
-            aot_set_last_error("create memories array failed.\n");
-            goto fail;
+            aot_set_last_error("create tables array failed.\n");
+            return false;
         }
         memset(comp_data->tables, 0, size);
         for (i = 0; i < comp_data->table_count; i++) {
@@ -641,64 +674,150 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
         }
     }
 
-    /* Create table data segments */
+    return true;
+}
+
+/**
+ * Initialize memory segment information in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing memory segments
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_memory_segments(AOTCompData *comp_data, WASMModule *module)
+{
+    comp_data->mem_init_data_count = module->data_seg_count;
+    if (comp_data->mem_init_data_count > 0
+        && !(comp_data->mem_init_data_list =
+                 aot_create_mem_init_data_list(module))) {
+        return false;
+    }
+    return true;
+}
+
+/**
+ * Initialize table segment information in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing table segments
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_table_segments(AOTCompData *comp_data, WASMModule *module)
+{
     comp_data->table_init_data_count = module->table_seg_count;
     if (comp_data->table_init_data_count > 0
         && !(comp_data->table_init_data_list =
-                 aot_create_table_init_data_list(module)))
-        goto fail;
+                 aot_create_table_init_data_list(module))) {
+        return false;
+    }
+    return true;
+}
 
-    /* Create import globals */
+/**
+ * Initialize global variable information in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing global information
+ * @param gc_enabled whether garbage collection is enabled
+ * @param import_global_data_size_64bit [out] size of imported global data for
+ * 64-bit
+ * @param import_global_data_size_32bit [out] size of imported global data for
+ * 32-bit
+ * @param global_data_size_64bit [out] size of global data for 64-bit
+ * @param global_data_size_32bit [out] size of global data for 32-bit
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_globals(AOTCompData *comp_data, WASMModule *module, bool gc_enabled,
+                 uint32 *import_global_data_size_64bit,
+                 uint32 *import_global_data_size_32bit,
+                 uint32 *global_data_size_64bit, uint32 *global_data_size_32bit)
+{
     comp_data->import_global_count = module->import_global_count;
     if (comp_data->import_global_count > 0
         && !(comp_data->import_globals = aot_create_import_globals(
-                 module, gc_enabled, &import_global_data_size_64bit,
-                 &import_global_data_size_32bit)))
-        goto fail;
+                 module, gc_enabled, import_global_data_size_64bit,
+                 import_global_data_size_32bit))) {
+        return false;
+    }
 
-    /* Create globals */
     comp_data->global_count = module->global_count;
     if (comp_data->global_count
         && !(comp_data->globals = aot_create_globals(
-                 module, gc_enabled, import_global_data_size_64bit,
-                 import_global_data_size_32bit, &global_data_size_64bit,
-                 &global_data_size_32bit)))
-        goto fail;
+                 module, gc_enabled, *import_global_data_size_64bit,
+                 *import_global_data_size_32bit, global_data_size_64bit,
+                 global_data_size_32bit))) {
+        return false;
+    }
 
     comp_data->global_data_size_64bit =
-        import_global_data_size_64bit + global_data_size_64bit;
+        *import_global_data_size_64bit + *global_data_size_64bit;
     comp_data->global_data_size_32bit =
-        import_global_data_size_32bit + global_data_size_32bit;
+        *import_global_data_size_32bit + *global_data_size_32bit;
+
+    return true;
+}
 
-    /* Create types, they are checked by wasm loader */
+/**
+ * Initialize type information in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing type information
+ * @param is_target_x86 whether the target architecture is x86
+ * @param gc_enabled whether garbage collection is enabled
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_types(AOTCompData *comp_data, WASMModule *module, bool is_target_x86,
+               bool gc_enabled)
+{
     comp_data->type_count = module->type_count;
     comp_data->types = module->types;
 #if WASM_ENABLE_GC != 0
-    /* Calculate the field sizes and field offsets for 64-bit and 32-bit
-       targets since they may vary in 32-bit target and 64-bit target */
     calculate_struct_field_sizes_offsets(comp_data, is_target_x86, gc_enabled);
 #endif
+    return true;
+}
 
-    /* Create import functions */
+/**
+ * Initialize function information in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing function information
+ * @param is_64bit_target whether the target architecture is 64-bit
+ * @return true if initialization succeeded, false otherwise
+ */
+static bool
+aot_init_functions(AOTCompData *comp_data, WASMModule *module,
+                   bool is_64bit_target)
+{
     comp_data->import_func_count = module->import_function_count;
     if (comp_data->import_func_count
-        && !(comp_data->import_funcs = aot_create_import_funcs(module)))
-        goto fail;
+        && !(comp_data->import_funcs = aot_create_import_funcs(module))) {
+        return false;
+    }
 
-    /* Create functions */
     comp_data->func_count = module->function_count;
     if (comp_data->func_count
         && !(comp_data->funcs =
-                 aot_create_funcs(module, is_64bit_target ? 8 : 4)))
-        goto fail;
+                 aot_create_funcs(module, is_64bit_target ? 8 : 4))) {
+        return false;
+    }
 
-#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
-    /* Create custom name section */
-    comp_data->name_section_buf = module->name_section_buf;
-    comp_data->name_section_buf_end = module->name_section_buf_end;
-#endif
+    return true;
+}
 
-    /* Create aux data/heap/stack information */
+/**
+ * Initialize auxiliary data in AOT compilation data.
+ *
+ * @param comp_data the AOT compilation data structure to initialize
+ * @param module the source WASM module containing auxiliary data
+ */
+static void
+aot_init_aux_data(AOTCompData *comp_data, WASMModule *module)
+{
     comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
     comp_data->aux_data_end = module->aux_data_end;
     comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
@@ -717,6 +836,43 @@ aot_create_comp_data(WASMModule *module, const char *target_arch,
     comp_data->string_literal_ptrs_wp = module->string_literal_ptrs;
     comp_data->string_literal_lengths_wp = module->string_literal_lengths;
 #endif
+}
+
+AOTCompData *
+aot_create_comp_data(WASMModule *module, const char *target_arch,
+                     bool gc_enabled)
+{
+    AOTCompData *comp_data;
+    uint32 import_global_data_size_64bit = 0, global_data_size_64bit = 0;
+    uint32 import_global_data_size_32bit = 0, global_data_size_32bit = 0;
+    bool is_64bit_target = arch_is_64bit(target_arch);
+    bool is_target_x86 = arch_is_x86(target_arch);
+
+    if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
+        aot_set_last_error("create compile data failed.\n");
+        return NULL;
+    }
+    memset(comp_data, 0, sizeof(AOTCompData));
+
+    if (!aot_init_memories(comp_data, module)
+        || !aot_init_memory_segments(comp_data, module)
+        || !aot_init_tables(comp_data, module)
+        || !aot_init_table_segments(comp_data, module)
+        || !aot_init_globals(comp_data, module, gc_enabled,
+                             &import_global_data_size_64bit,
+                             &import_global_data_size_32bit,
+                             &global_data_size_64bit, &global_data_size_32bit)
+        || !aot_init_types(comp_data, module, is_target_x86, gc_enabled)
+        || !aot_init_functions(comp_data, module, is_64bit_target)) {
+        goto fail;
+    }
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+    comp_data->name_section_buf = module->name_section_buf;
+    comp_data->name_section_buf_end = module->name_section_buf_end;
+#endif
+
+    aot_init_aux_data(comp_data, module);
 
     comp_data->wasm_module = module;
 

+ 1 - 1
core/iwasm/compilation/aot.h

@@ -103,7 +103,7 @@ typedef struct AOTMemInitData {
     /* Byte count */
     uint32 byte_count;
     /* Byte array */
-    uint8 bytes[1];
+    uint8 *bytes;
 } AOTMemInitData;
 
 /**

+ 18 - 42
core/iwasm/compilation/aot_compiler.c

@@ -146,9 +146,20 @@ aot_validate_wasm(AOTCompContext *comp_ctx)
     }
 
 #if WASM_ENABLE_MEMORY64 != 0
-    if (comp_ctx->pointer_size < sizeof(uint64) && IS_MEMORY64) {
-        aot_set_last_error("Compiling wasm64 to 32bit platform is not allowed");
-        return false;
+    if (comp_ctx->pointer_size < sizeof(uint64)) {
+        if (IS_MEMORY64) {
+            aot_set_last_error("Compiling wasm64(contains i64 memory section) "
+                               "to 32bit platform is not allowed");
+            return false;
+        }
+
+        for (uint32 i = 0; i < comp_ctx->comp_data->table_count; ++i) {
+            if (IS_TABLE64(i)) {
+                aot_set_last_error("Compiling wasm64(contains i64 table "
+                                   "section) to 32bit platform is not allowed");
+                return false;
+            }
+        }
     }
 #endif
 
@@ -4082,39 +4093,6 @@ aot_compile_wasm(AOTCompContext *comp_ctx)
     return true;
 }
 
-#if !(defined(_WIN32) || defined(_WIN32_))
-char *
-aot_generate_tempfile_name(const char *prefix, const char *extension,
-                           char *buffer, uint32 len)
-{
-    int fd, name_len;
-
-    name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
-
-    if ((fd = mkstemp(buffer)) <= 0) {
-        aot_set_last_error("make temp file failed.");
-        return NULL;
-    }
-
-    /* close and remove temp file */
-    close(fd);
-    unlink(buffer);
-
-    /* Check if buffer length is enough */
-    /* name_len + '.' + extension + '\0' */
-    if (name_len + 1 + strlen(extension) + 1 > len) {
-        aot_set_last_error("temp file name too long.");
-        return NULL;
-    }
-
-    snprintf(buffer + name_len, len - name_len, ".%s", extension);
-    return buffer;
-}
-#else
-
-errno_t
-_mktemp_s(char *nameTemplate, size_t sizeInChars);
-
 char *
 aot_generate_tempfile_name(const char *prefix, const char *extension,
                            char *buffer, uint32 len)
@@ -4123,7 +4101,8 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
 
     name_len = snprintf(buffer, len, "%s-XXXXXX", prefix);
 
-    if (_mktemp_s(buffer, name_len + 1) != 0) {
+    if (!bh_mkstemp(buffer, name_len + 1)) {
+        aot_set_last_error("make temp file failed.");
         return NULL;
     }
 
@@ -4137,7 +4116,6 @@ aot_generate_tempfile_name(const char *prefix, const char *extension,
     snprintf(buffer + name_len, len - name_len, ".%s", extension);
     return buffer;
 }
-#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
 
 bool
 aot_emit_llvm_file(AOTCompContext *comp_ctx, const char *file_name)
@@ -4216,7 +4194,6 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
 
     bh_print_time("Begin to emit object file");
 
-#if !(defined(_WIN32) || defined(_WIN32_))
     if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
         char cmd[1024];
         int ret;
@@ -4259,7 +4236,7 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
                      file_name, bc_file_name);
             LOG_VERBOSE("invoking external LLC compiler:\n\t%s", cmd);
 
-            ret = system(cmd);
+            ret = bh_system(cmd);
             /* remove temp bitcode file */
             unlink(bc_file_name);
 
@@ -4312,7 +4289,7 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
                      file_name, asm_file_name);
             LOG_VERBOSE("invoking external ASM compiler:\n\t%s", cmd);
 
-            ret = system(cmd);
+            ret = bh_system(cmd);
             /* remove temp assembly file */
             unlink(asm_file_name);
 
@@ -4325,7 +4302,6 @@ aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name)
 
         return true;
     }
-#endif /* end of !(defined(_WIN32) || defined(_WIN32_)) */
 
     if (!strncmp(LLVMGetTargetName(target), "arc", 3))
         /* Emit to assembly file instead for arc target

+ 11 - 0
core/iwasm/compilation/aot_compiler.h

@@ -532,8 +532,13 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define IS_MEMORY64 (comp_ctx->comp_data->memories[0].flags & MEMORY64_FLAG)
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) \
     (IS_MEMORY64 ? VAL_IF_ENABLED : VAL_IF_DISABLED)
+#define IS_TABLE64(i) \
+    (comp_ctx->comp_data->tables[i].table_type.flags & TABLE64_FLAG)
+#define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) \
+    (IS_TABLE64(i) ? VAL_IF_ENABLED : VAL_IF_DISABLED)
 #else
 #define MEMORY64_COND_VALUE(VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
+#define TABLE64_COND_VALUE(i, VAL_IF_ENABLED, VAL_IF_DISABLED) (VAL_IF_DISABLED)
 #endif
 
 #define POP_I32(v) POP(v, VALUE_TYPE_I32)
@@ -548,6 +553,9 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
     POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
 #define POP_PAGE_COUNT(v) \
     POP(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
+#define POP_TBL_ELEM_IDX(v) \
+    POP(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
+#define POP_TBL_ELEM_LEN(v) POP_TBL_ELEM_IDX(v)
 
 #define POP_COND(llvm_value)                                                   \
     do {                                                                       \
@@ -613,6 +621,9 @@ set_local_gc_ref(AOTCompFrame *frame, int n, LLVMValueRef value, uint8 ref_type)
 #define PUSH_GC_REF(v) PUSH(v, VALUE_TYPE_GC_REF)
 #define PUSH_PAGE_COUNT(v) \
     PUSH(v, MEMORY64_COND_VALUE(VALUE_TYPE_I64, VALUE_TYPE_I32))
+#define PUSH_TBL_ELEM_IDX(v) \
+    PUSH(v, TABLE64_COND_VALUE(tbl_idx, VALUE_TYPE_I64, VALUE_TYPE_I32))
+#define PUSH_TBL_ELEM_LEN(v) PUSH_TBL_ELEM_IDX(v)
 
 #define SET_CONST(v)                                                          \
     do {                                                                      \

+ 3 - 17
core/iwasm/compilation/aot_emit_aot_file.c

@@ -4292,10 +4292,6 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
 
     bh_print_time("Begin to emit object file");
     if (comp_ctx->external_llc_compiler || comp_ctx->external_asm_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-        aot_set_last_error("external toolchain not supported on Windows");
-        goto fail;
-#else
         /* Generate a temp file name */
         int ret;
         char obj_file_name[64];
@@ -4323,27 +4319,18 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
             aot_set_last_error("create mem buffer with file failed.");
             goto fail;
         }
-#endif /* end of defined(_WIN32) || defined(_WIN32_) */
     }
     else if (!strncmp(LLVMGetTargetName(target), "arc", 3)) {
-#if defined(_WIN32) || defined(_WIN32_)
-        aot_set_last_error("emit object file on Windows is unsupported.");
-        goto fail;
-#else
         /* Emit to assembly file instead for arc target
            as it cannot emit to object file */
         char file_name[] = "wasm-XXXXXX", buf[128];
-        int fd, ret;
+        int ret;
 
-        if ((fd = mkstemp(file_name)) <= 0) {
+        if (!bh_mkstemp(file_name, sizeof(file_name))) {
             aot_set_last_error("make temp file failed.");
             goto fail;
         }
 
-        /* close and remove temp file */
-        close(fd);
-        unlink(file_name);
-
         snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
         if (LLVMTargetMachineEmitToFile(comp_ctx->target_machine,
                                         comp_ctx->module, buf, LLVMAssemblyFile,
@@ -4364,7 +4351,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
                  "/opt/zephyr-sdk/arc-zephyr-elf/bin/arc-zephyr-elf-gcc ",
                  "-mcpu=arcem -o ", file_name, ".o -c ", file_name, ".s");
         /* TODO: use try..catch to handle possible exceptions */
-        ret = system(buf);
+        ret = bh_system(buf);
         /* remove temp assembly file */
         snprintf(buf, sizeof(buf), "%s%s", file_name, ".s");
         unlink(buf);
@@ -4391,7 +4378,6 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
             aot_set_last_error("create mem buffer with file failed.");
             goto fail;
         }
-#endif /* end of defined(_WIN32) || defined(_WIN32_) */
     }
     else {
         if (LLVMTargetMachineEmitToMemoryBuffer(

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

@@ -912,7 +912,7 @@ check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         aot_set_last_error("llvm build LOAD failed");
         return false;
     }
-    /* Set terminate_flags memory accecc to volatile, so that the value
+    /* Set terminate_flags memory access to volatile, so that the value
         will always be loaded from memory rather than register */
     LLVMSetVolatile(terminate_flags, true);
 

+ 43 - 2
core/iwasm/compilation/aot_emit_function.c

@@ -1832,6 +1832,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 aot_set_last_error("llvm build load failed.");
                 goto fail;
             }
+            LLVMSetAlignment(ext_ret, 4);
             PUSH(ext_ret, ext_ret_types[i]);
         }
     }
@@ -2068,6 +2069,7 @@ call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             aot_set_last_error("llvm build load failed.");
             return false;
         }
+        LLVMSetAlignment(value_rets[i], 4);
         cell_num += wasm_value_type_cell_num_internal(wasm_ret_types[i],
                                                       comp_ctx->pointer_size);
     }
@@ -2089,6 +2091,9 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef ext_ret_offset, ext_ret_ptr, ext_ret, res;
     LLVMValueRef *param_values = NULL, *value_rets = NULL;
     LLVMValueRef *result_phis = NULL, value_ret, import_func_count;
+#if WASM_ENABLE_MEMORY64 != 0
+    LLVMValueRef u32_max, u32_cmp_result = NULL;
+#endif
     LLVMTypeRef *param_types = NULL, ret_type;
     LLVMTypeRef llvm_func_type, llvm_func_ptr_type;
     LLVMTypeRef ext_ret_ptr_type;
@@ -2153,7 +2158,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     func_param_count = func_type->param_count;
     func_result_count = func_type->result_count;
 
-    POP_I32(elem_idx);
+    POP_TBL_ELEM_IDX(elem_idx);
 
     /* get the cur size of the table instance */
     if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
@@ -2182,6 +2187,27 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
+#if WASM_ENABLE_MEMORY64 != 0
+    /* Check if elem index >= UINT32_MAX */
+    if (IS_TABLE64(tbl_idx)) {
+        if (!(u32_max = I64_CONST(UINT32_MAX))) {
+            aot_set_last_error("llvm build const failed");
+            goto fail;
+        }
+        if (!(u32_cmp_result =
+                  LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
+                                u32_max, "cmp_elem_idx_u32_max"))) {
+            aot_set_last_error("llvm build icmp failed.");
+            goto fail;
+        }
+        if (!(elem_idx = LLVMBuildTrunc(comp_ctx->builder, elem_idx, I32_TYPE,
+                                        "elem_idx_i32"))) {
+            aot_set_last_error("llvm build trunc failed.");
+            goto fail;
+        }
+    }
+#endif
+
     /* Check if (uint32)elem index >= table size */
     if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
                                        table_size_const, "cmp_elem_idx"))) {
@@ -2189,7 +2215,19 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
-    /* Throw exception if elem index >= table size */
+#if WASM_ENABLE_MEMORY64 != 0
+    if (IS_TABLE64(tbl_idx)) {
+        if (!(cmp_elem_idx =
+                  LLVMBuildOr(comp_ctx->builder, cmp_elem_idx, u32_cmp_result,
+                              "larger_than_u32_max_or_cur_size"))) {
+            aot_set_last_error("llvm build or failed.");
+            goto fail;
+        }
+    }
+#endif
+
+    /* Throw exception if elem index >= table size or elem index >= UINT32_MAX
+     */
     if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
               comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
         aot_set_last_error("llvm add basic block failed.");
@@ -2663,6 +2701,7 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 aot_set_last_error("llvm build load failed.");
                 goto fail;
             }
+            LLVMSetAlignment(ext_ret, 4);
             LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1);
         }
     }
@@ -3094,6 +3133,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 aot_set_last_error("llvm build load failed.");
                 goto fail;
             }
+            LLVMSetAlignment(ext_ret, 4);
             LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1);
         }
     }
@@ -3169,6 +3209,7 @@ aot_compile_op_call_ref(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 aot_set_last_error("llvm build load failed.");
                 goto fail;
             }
+            LLVMSetAlignment(ext_ret, 4);
             LLVMAddIncoming(result_phis[i], &ext_ret, &block_curr, 1);
         }
     }

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

@@ -273,10 +273,24 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     /* offset1 = offset + addr; */
-    /* TODO: check whether integer overflow occurs when memory is 64-bit
-             and boundary check is enabled */
     BUILD_OP(Add, offset_const, addr, offset1, "offset1");
 
+    if (is_memory64 && comp_ctx->enable_bound_check) {
+        /* Check whether integer overflow occurs in offset + addr */
+        LLVMBasicBlockRef check_integer_overflow_end;
+        ADD_BASIC_BLOCK(check_integer_overflow_end,
+                        "check_integer_overflow_end");
+        LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
+
+        BUILD_ICMP(LLVMIntULT, offset1, offset_const, cmp1, "cmp1");
+        if (!aot_emit_exception(comp_ctx, func_ctx,
+                                EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp1,
+                                check_integer_overflow_end)) {
+            goto fail;
+        }
+        SET_BUILD_POS(check_integer_overflow_end);
+    }
+
     if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
         LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
         LLVMValueRef is_in_shared_heap, shared_heap_check_bound = NULL;
@@ -303,7 +317,7 @@ aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
 
         if (!is_target_64bit) {
-            /* Check whether interger overflow occurs in addr + offset */
+            /* Check whether integer overflow occurs in addr + offset */
             LLVMBasicBlockRef check_integer_overflow_end;
             ADD_BASIC_BLOCK(check_integer_overflow_end,
                             "check_integer_overflow_end");
@@ -1215,10 +1229,24 @@ check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
-    /* TODO: check whether integer overflow occurs when memory is 64-bit
-             and boundary check is enabled */
     BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
 
+    if (is_memory64 && comp_ctx->enable_bound_check) {
+        /* Check whether integer overflow occurs in offset + addr */
+        LLVMBasicBlockRef check_integer_overflow_end;
+        ADD_BASIC_BLOCK(check_integer_overflow_end,
+                        "check_integer_overflow_end");
+        LLVMMoveBasicBlockAfter(check_integer_overflow_end, block_curr);
+
+        BUILD_ICMP(LLVMIntULT, max_addr, offset, cmp, "cmp");
+        if (!aot_emit_exception(comp_ctx, func_ctx,
+                                EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS, true, cmp,
+                                check_integer_overflow_end)) {
+            goto fail;
+        }
+        SET_BUILD_POS(check_integer_overflow_end);
+    }
+
     if (comp_ctx->enable_shared_heap /* TODO: && mem_idx == 0 */) {
         LLVMBasicBlockRef app_addr_in_shared_heap, app_addr_in_linear_mem;
         LLVMValueRef shared_heap_start_off, shared_heap_check_bound;

+ 141 - 12
core/iwasm/compilation/aot_emit_table.c

@@ -10,6 +10,78 @@
 #include "aot_emit_gc.h"
 #endif
 
+#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
+#if WASM_ENABLE_MEMORY64 != 0
+static bool
+zero_extend_u64(AOTCompContext *comp_ctx, LLVMValueRef *value, const char *name)
+{
+    if (comp_ctx->pointer_size == sizeof(uint64)) {
+        /* zero extend to uint64 if the target is 64-bit */
+        *value = LLVMBuildZExt(comp_ctx->builder, *value, I64_TYPE, name);
+        if (!*value) {
+            aot_set_last_error("llvm build zero extend failed.");
+            return false;
+        }
+    }
+    return true;
+}
+#endif
+
+/* check whether a table64 elem idx is greater than UINT32_MAX, if so, throw
+ * exception, otherwise trunc it to uint32 */
+static bool
+check_tbl_elem_idx_and_trunc(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                             LLVMValueRef *elem_idx, uint32 tbl_idx)
+{
+#if WASM_ENABLE_MEMORY64 != 0
+    LLVMValueRef u32_max, u32_cmp_result;
+    LLVMBasicBlockRef check_elem_idx_succ;
+
+    if (!IS_TABLE64(tbl_idx)) {
+        return true;
+    }
+
+    /* Check if elem index >= UINT32_MAX */
+    if (!(u32_max = I64_CONST(UINT32_MAX))) {
+        aot_set_last_error("llvm build const failed");
+        goto fail;
+    }
+    if (!(u32_cmp_result =
+              LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, *elem_idx, u32_max,
+                            "cmp_elem_idx_u32_max"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        goto fail;
+    }
+    if (!(*elem_idx = LLVMBuildTrunc(comp_ctx->builder, *elem_idx, I32_TYPE,
+                                     "elem_idx_i32"))) {
+        aot_set_last_error("llvm build trunc failed.");
+        goto fail;
+    }
+
+    /* Throw exception if elem index >= UINT32_MAX*/
+    if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
+              comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        goto fail;
+    }
+
+    LLVMMoveBasicBlockAfter(check_elem_idx_succ,
+                            LLVMGetInsertBlock(comp_ctx->builder));
+
+    if (!(aot_emit_exception(comp_ctx, func_ctx,
+                             EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
+                             u32_cmp_result, check_elem_idx_succ)))
+        goto fail;
+
+    return true;
+fail:
+    return false;
+#else
+    return true;
+#endif
+}
+#endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */
+
 uint64
 get_tbl_inst_offset(const AOTCompContext *comp_ctx,
                     const AOTFuncContext *func_ctx, uint32 tbl_idx)
@@ -158,6 +230,10 @@ aot_check_table_access(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &elem_idx, tbl_idx)) {
+        goto fail;
+    }
+
     /* Check if (uint32)elem index >= table size */
     if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
                                        tbl_sz, "cmp_elem_idx"))) {
@@ -192,7 +268,7 @@ aot_compile_op_table_get(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef elem_idx, offset, func_idx;
     LLVMValueRef table_elem_base, table_elem_addr, table_elem;
 
-    POP_I32(elem_idx);
+    POP_TBL_ELEM_IDX(elem_idx);
 
     if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
         goto fail;
@@ -289,7 +365,7 @@ aot_compile_op_table_set(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    POP_I32(elem_idx);
+    POP_TBL_ELEM_IDX(elem_idx);
 
     if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
         goto fail;
@@ -388,7 +464,11 @@ aot_compile_op_table_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* s */
     POP_I32(param_values[4]);
     /* d */
-    POP_I32(param_values[5]);
+    POP_TBL_ELEM_IDX(param_values[5]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[5],
+                                      tbl_idx)) {
+        goto fail;
+    }
 
     /* "" means return void */
     if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
@@ -408,6 +488,7 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 {
     LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
     LLVMValueRef func, param_values[6], value;
+    uint32 tbl_idx;
 
     param_types[0] = INT8_PTR_TYPE;
     param_types[1] = I32_TYPE;
@@ -434,12 +515,34 @@ aot_compile_op_table_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
+    /* In table64, the length should be i32 type if any one of src/dst table
+     * is i32 type, set the table index to the lesser-or-equal table when
+     * popping length n */
+    if (!(comp_ctx->comp_data->tables[src_tbl_idx].table_type.flags
+          & TABLE64_FLAG))
+        tbl_idx = src_tbl_idx;
+    else
+        tbl_idx = dst_tbl_idx;
     /* n */
-    POP_I32(param_values[3]);
+    POP_TBL_ELEM_LEN(param_values[3]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[3],
+                                      tbl_idx)) {
+        goto fail;
+    }
     /* s */
-    POP_I32(param_values[4]);
+    tbl_idx = src_tbl_idx;
+    POP_TBL_ELEM_IDX(param_values[4]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[4],
+                                      tbl_idx)) {
+        goto fail;
+    }
     /* d */
-    POP_I32(param_values[5]);
+    tbl_idx = dst_tbl_idx;
+    POP_TBL_ELEM_IDX(param_values[5]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[5],
+                                      tbl_idx)) {
+        goto fail;
+    }
 
     /* "" means return void */
     if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 6,
@@ -484,7 +587,14 @@ aot_compile_op_table_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
-    PUSH_I32(tbl_sz);
+#if WASM_ENABLE_MEMORY64 != 0
+    if (IS_TABLE64(tbl_idx)) {
+        if (!zero_extend_u64(comp_ctx, &tbl_sz, "length64")) {
+            goto fail;
+        }
+    }
+#endif
+    PUSH_TBL_ELEM_IDX(tbl_sz);
 
     return true;
 fail:
@@ -517,7 +627,11 @@ aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     /* n */
-    POP_I32(param_values[2]);
+    POP_TBL_ELEM_LEN(param_values[2]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[2],
+                                      tbl_idx)) {
+        goto fail;
+    }
     /* v */
 
     if (comp_ctx->enable_gc) {
@@ -545,7 +659,14 @@ aot_compile_op_table_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         goto fail;
     }
 
-    PUSH_I32(ret);
+#if WASM_ENABLE_MEMORY64 != 0
+    if (IS_TABLE64(tbl_idx)) {
+        if (!zero_extend_u64(comp_ctx, &ret, "table_size64")) {
+            goto fail;
+        }
+    }
+#endif
+    PUSH_TBL_ELEM_LEN(ret);
 
     return true;
 fail:
@@ -579,7 +700,11 @@ aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     /* n */
-    POP_I32(param_values[2]);
+    POP_TBL_ELEM_LEN(param_values[2]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[2],
+                                      tbl_idx)) {
+        goto fail;
+    }
     /* v */
 
     if (comp_ctx->enable_gc) {
@@ -601,7 +726,11 @@ aot_compile_op_table_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
     /* i */
-    POP_I32(param_values[4]);
+    POP_TBL_ELEM_IDX(param_values[4]);
+    if (!check_tbl_elem_idx_and_trunc(comp_ctx, func_ctx, &param_values[4],
+                                      tbl_idx)) {
+        goto fail;
+    }
 
     /* "" means return void */
     if (!(LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values, 5,
@@ -615,4 +744,4 @@ fail:
     return false;
 }
 
-#endif /*  WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */
+#endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC !=0 */

+ 0 - 10
core/iwasm/compilation/aot_llvm.c

@@ -2746,10 +2746,6 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
         /* verify external llc compiler */
         comp_ctx->external_llc_compiler = getenv("WAMRC_LLC_COMPILER");
         if (comp_ctx->external_llc_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-            comp_ctx->external_llc_compiler = NULL;
-            LOG_WARNING("External LLC compiler not supported on Windows.");
-#else
             if (access(comp_ctx->external_llc_compiler, X_OK) != 0) {
                 LOG_WARNING("WAMRC_LLC_COMPILER [%s] not found, fallback to "
                             "default pipeline",
@@ -2761,17 +2757,12 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
                 LOG_VERBOSE("Using external LLC compiler [%s]",
                             comp_ctx->external_llc_compiler);
             }
-#endif
         }
 
         /* verify external asm compiler */
         if (!comp_ctx->external_llc_compiler) {
             comp_ctx->external_asm_compiler = getenv("WAMRC_ASM_COMPILER");
             if (comp_ctx->external_asm_compiler) {
-#if defined(_WIN32) || defined(_WIN32_)
-                comp_ctx->external_asm_compiler = NULL;
-                LOG_WARNING("External ASM compiler not supported on Windows.");
-#else
                 if (access(comp_ctx->external_asm_compiler, X_OK) != 0) {
                     LOG_WARNING(
                         "WAMRC_ASM_COMPILER [%s] not found, fallback to "
@@ -2784,7 +2775,6 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
                     LOG_VERBOSE("Using external ASM compiler [%s]",
                                 comp_ctx->external_asm_compiler);
                 }
-#endif
             }
         }
 

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

@@ -37,6 +37,18 @@
 #include "aot_orc_extra.h"
 #include "aot_comp_option.h"
 
+#if defined(_WIN32) || defined(_WIN32_)
+#include <io.h>
+#define access _access
+/* On windows there is no X_OK flag to check for executablity, only check for
+ * existence */
+#ifdef X_OK
+#undef X_OK
+#endif
+#define X_OK 00
+#define unlink _unlink
+#endif
+
 #ifdef __cplusplus
 extern "C" {
 #endif

+ 1 - 1
core/iwasm/compilation/aot_orc_extra.cpp

@@ -177,7 +177,7 @@ LLVMOrcLLLazyJITBuilderSetJITTargetMachineBuilder(
     LLVMOrcDisposeJITTargetMachineBuilder(JTMP);
 }
 
-static Optional<CompileOnDemandLayer::GlobalValueSet>
+static Optional<GlobalValueSet>
 PartitionFunction(GlobalValueSet Requested)
 {
     std::vector<const GlobalValue *> GVsToAdd;

+ 1 - 0
core/iwasm/compilation/iwasm_compl.cmake

@@ -1,6 +1,7 @@
 set (IWASM_COMPL_DIR ${CMAKE_CURRENT_LIST_DIR})
 
 include_directories(${IWASM_COMPL_DIR})
+enable_language(CXX)
 
 if (WAMR_BUILD_DEBUG_AOT EQUAL 1)
     file (GLOB_RECURSE source_all

+ 1 - 0
core/iwasm/fast-jit/iwasm_fast_jit.cmake

@@ -9,6 +9,7 @@ if (WAMR_BUILD_FAST_JIT_DUMP EQUAL 1)
 endif ()
 
 include_directories (${IWASM_FAST_JIT_DIR})
+enable_language(CXX)
 
 if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
     include(FetchContent)

+ 2 - 0
core/iwasm/include/aot_comp_option.h

@@ -6,6 +6,8 @@
 #ifndef __AOT_COMP_OPTION_H__
 #define __AOT_COMP_OPTION_H__
 
+#include <stdint.h>
+
 typedef struct {
     /* Enables or disables bounds checks for stack frames. When enabled, the AOT
      * compiler generates code to check if the stack pointer is within the

+ 24 - 2
core/iwasm/include/wasm_export.h

@@ -23,6 +23,8 @@
 #else
 #define WASM_RUNTIME_API_EXTERN __declspec(dllimport)
 #endif
+#elif defined(__GNUC__) || defined(__clang__)
+#define WASM_RUNTIME_API_EXTERN __attribute__((visibility("default")))
 #else
 #define WASM_RUNTIME_API_EXTERN
 #endif
@@ -1166,8 +1168,8 @@ wasm_application_execute_main(wasm_module_inst_t module_inst, int32_t argc,
                               char *argv[]);
 
 /**
- * Find the specified function in argv[0] from a WASM module instance
- * and execute that function.
+ * Find the specified function from a WASM module instance and execute
+ * that function.
  *
  * @param module_inst the WASM module instance
  * @param name the name of the function to execute.
@@ -1755,6 +1757,26 @@ wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
 WASM_RUNTIME_API_EXTERN void *
 wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
 
+/**
+ * Set native stack boundary to execution environment, if it is set,
+ * it will be used instead of getting the boundary with the platform
+ * layer API when calling wasm functions. This is useful for some
+ * fiber cases.
+ *
+ * Note: unlike setting the boundary by runtime, this API doesn't add
+ * the WASM_STACK_GUARD_SIZE(see comments in core/config.h) to the
+ * exec_env's native_stack_boundary to reserve bytes to the native
+ * thread stack boundary, which is used to throw native stack overflow
+ * exception if the guard boundary is reached. Developer should ensure
+ * that enough guard bytes are kept.
+ *
+ * @param exec_env the execution environment
+ * @param native_stack_boundary the user data to be set
+ */
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_native_stack_boundary(wasm_exec_env_t exec_env,
+                                       uint8_t *native_stack_boundary);
+
 /**
  * Dump runtime memory consumption, including:
  *     Exec env memory consumption

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

@@ -93,6 +93,10 @@ extern "C" {
 #define MAX_PAGE_COUNT_FLAG 0x01
 #define SHARED_MEMORY_FLAG 0x02
 #define MEMORY64_FLAG 0x04
+#define MAX_TABLE_SIZE_FLAG 0x01
+/* the shared flag for table is not actual used now */
+#define SHARED_TABLE_FLAG 0x02
+#define TABLE64_FLAG 0x04
 
 /**
  * In the multi-memory proposal, the memarg in loads and stores are
@@ -494,6 +498,7 @@ typedef struct WASMTableType {
      * 0: no max size and not shared
      * 1: has max size
      * 2: shared
+     * 4: table64
      */
     uint8 flags;
     bool possible_grow;
@@ -520,6 +525,7 @@ typedef uint64 mem_offset_t;
 typedef uint32 mem_offset_t;
 #define PR_MEM_OFFSET PRIu32
 #endif
+typedef mem_offset_t tbl_elem_idx_t;
 
 typedef struct WASMMemory {
     uint32 flags;
@@ -976,8 +982,9 @@ struct WASMModule {
     uint64 buf_code_size;
 #endif
 
-#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_FAST_JIT != 0 \
-    || WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_JIT != 0
+#if WASM_ENABLE_DEBUG_INTERP != 0 || WASM_ENABLE_FAST_JIT != 0  \
+    || WASM_ENABLE_DUMP_CALL_STACK != 0 || WASM_ENABLE_JIT != 0 \
+    || WASM_ENABLE_WAMR_COMPILER != 0
     uint8 *load_addr;
     uint64 load_size;
 #endif
@@ -1238,6 +1245,9 @@ wasm_value_type_size_internal(uint8 value_type, uint8 pointer_size)
     else {
         bh_assert(0);
     }
+#if WASM_ENABLE_GC == 0
+    (void)pointer_size;
+#endif
     return 0;
 }
 

+ 114 - 42
core/iwasm/interpreter/wasm_interp_classic.c

@@ -544,9 +544,9 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
 #endif
 
 #if WASM_ENABLE_MEMORY64 != 0
-#define PUSH_MEM_OFFSET(value)                     \
+#define COND_PUSH_TEMPLATE(cond, value)            \
     do {                                           \
-        if (is_memory64) {                         \
+        if (cond) {                                \
             PUT_I64_TO_ADDR(frame_sp, value);      \
             frame_sp += 2;                         \
         }                                          \
@@ -554,8 +554,11 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
             *(int32 *)frame_sp++ = (int32)(value); \
         }                                          \
     } while (0)
+#define PUSH_MEM_OFFSET(value) COND_PUSH_TEMPLATE(is_memory64, value)
+#define PUSH_TBL_ELEM_IDX(value) COND_PUSH_TEMPLATE(is_table64, value)
 #else
 #define PUSH_MEM_OFFSET(value) PUSH_I32(value)
+#define PUSH_TBL_ELEM_IDX(value) PUSH_I32(value)
 #endif
 
 #define PUSH_PAGE_COUNT(value) PUSH_MEM_OFFSET(value)
@@ -590,9 +593,11 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
 #endif
 
 #if WASM_ENABLE_MEMORY64 != 0
-#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32())
+#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : (uint32)POP_I32())
+#define POP_TBL_ELEM_IDX() (is_table64 ? POP_I64() : (uint32)POP_I32())
 #else
 #define POP_MEM_OFFSET() POP_I32()
+#define POP_TBL_ELEM_IDX() POP_I32()
 #endif
 
 #define POP_PAGE_COUNT() POP_MEM_OFFSET()
@@ -1595,7 +1600,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     uint8 opcode;
     uint32 i, depth, cond, count, fidx, tidx, lidx, frame_size = 0;
     uint32 all_cell_num = 0;
-    int32 val;
+    tbl_elem_idx_t val;
     uint8 *else_addr, *end_addr, *maddr = NULL;
     uint32 local_idx, local_offset, global_idx;
     uint8 local_type, *global_addr;
@@ -1635,6 +1640,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     /* TODO: multi-memories for now assuming the memory idx type is consistent
      * across multi-memories */
     bool is_memory64 = false;
+    bool is_table64 = false;
     if (memory)
         is_memory64 = memory->is_memory64;
 #endif
@@ -2364,7 +2370,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                 /**
                  * type check. compiler will make sure all like
-                 * (call_indirect (type $x) (i32.const 1))
+                 * (call_indirect (type $x) (it.const 1))
                  * the function type has to be defined in the module also
                  * no matter it is used or not
                  */
@@ -2383,9 +2389,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 /* clang-format on */
 
                 tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                is_table64 = tbl_inst->is_table64;
+#endif
 
-                val = POP_I32();
-                if ((uint32)val >= tbl_inst->cur_size) {
+                val = POP_TBL_ELEM_IDX();
+                if (val >= tbl_inst->cur_size) {
                     wasm_set_exception(module, "undefined element");
                     goto got_exception;
                 }
@@ -2531,15 +2540,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
             HANDLE_OP(WASM_OP_TABLE_GET)
             {
-                uint32 tbl_idx, elem_idx;
+                uint32 tbl_idx;
+                tbl_elem_idx_t elem_idx;
                 WASMTableInstance *tbl_inst;
 
                 read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
                 bh_assert(tbl_idx < module->table_count);
 
                 tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                is_table64 = tbl_inst->is_table64;
+#endif
 
-                elem_idx = POP_I32();
+                elem_idx = POP_TBL_ELEM_IDX();
                 if (elem_idx >= tbl_inst->cur_size) {
                     wasm_set_exception(module, "out of bounds table access");
                     goto got_exception;
@@ -2556,20 +2569,24 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
             HANDLE_OP(WASM_OP_TABLE_SET)
             {
                 WASMTableInstance *tbl_inst;
-                uint32 tbl_idx, elem_idx;
+                uint32 tbl_idx;
+                tbl_elem_idx_t elem_idx;
                 table_elem_type_t elem_val;
 
                 read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
                 bh_assert(tbl_idx < module->table_count);
 
                 tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                is_table64 = tbl_inst->is_table64;
+#endif
 
 #if WASM_ENABLE_GC == 0
                 elem_val = POP_I32();
 #else
                 elem_val = POP_REF();
 #endif
-                elem_idx = POP_I32();
+                elem_idx = POP_TBL_ELEM_IDX();
                 if (elem_idx >= tbl_inst->cur_size) {
                     wasm_set_exception(module, "out of bounds table access");
                     goto got_exception;
@@ -2632,7 +2649,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 read_leb_uint32(frame_ip, frame_ip_end, type_index);
                 func_obj = POP_REF();
                 if (!func_obj) {
-                    wasm_set_exception(module, "null function object");
+                    wasm_set_exception(module, "null function reference");
                     goto got_exception;
                 }
 
@@ -2649,7 +2666,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 read_leb_uint32(frame_ip, frame_ip_end, type_index);
                 func_obj = POP_REF();
                 if (!func_obj) {
-                    wasm_set_exception(module, "null function object");
+                    wasm_set_exception(module, "null function reference");
                     goto got_exception;
                 }
 
@@ -2796,7 +2813,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         struct_obj = POP_REF();
 
                         if (!struct_obj) {
-                            wasm_set_exception(module, "null structure object");
+                            wasm_set_exception(module,
+                                               "null structure reference");
                             goto got_exception;
                         }
 
@@ -2852,7 +2870,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         struct_obj = POP_REF();
                         if (!struct_obj) {
-                            wasm_set_exception(module, "null structure object");
+                            wasm_set_exception(module,
+                                               "null structure reference");
                             goto got_exception;
                         }
 
@@ -4679,13 +4698,19 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
             HANDLE_OP(WASM_OP_MEMORY_GROW)
             {
-                uint32 mem_idx, delta, prev_page_count;
+                uint32 mem_idx, prev_page_count;
+                mem_offset_t delta;
 
                 read_leb_memidx(frame_ip, frame_ip_end, mem_idx);
                 prev_page_count = memory->cur_page_count;
-                delta = (uint32)POP_PAGE_COUNT();
+                delta = POP_PAGE_COUNT();
 
-                if (!wasm_enlarge_memory_with_idx(module, delta, mem_idx)) {
+                if (
+#if WASM_ENABLE_MEMORY64 != 0
+                    delta > UINT32_MAX ||
+#endif
+                    !wasm_enlarge_memory_with_idx(module, (uint32)delta,
+                                                  mem_idx)) {
                     /* failed to memory.grow, return -1 */
                     PUSH_PAGE_COUNT(-1);
                 }
@@ -5880,8 +5905,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 #if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
                     case WASM_OP_TABLE_INIT:
                     {
-                        uint32 tbl_idx, elem_idx;
-                        uint32 n, s, d;
+                        uint32 tbl_idx;
+                        tbl_elem_idx_t elem_idx, d;
+                        uint32 n, s;
                         WASMTableInstance *tbl_inst;
                         table_elem_type_t *table_elems;
                         InitializerExpression *tbl_seg_init_values = NULL,
@@ -5895,10 +5921,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         bh_assert(tbl_idx < module->module->table_count);
 
                         tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = tbl_inst->is_table64;
+#endif
 
                         n = (uint32)POP_I32();
                         s = (uint32)POP_I32();
-                        d = (uint32)POP_I32();
+                        d = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
 
                         if (!bh_bitmap_get_bit(module->e->common.elem_dropped,
                                                elem_idx)) {
@@ -5911,8 +5940,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                                     .value_count;
                         }
 
-                        if (offset_len_out_of_bounds(s, n, tbl_seg_len)
-                            || offset_len_out_of_bounds(d, n,
+                        /* TODO: memory64 current implementation of table64
+                         * still assumes the max table size UINT32_MAX
+                         */
+                        if (
+#if WASM_ENABLE_MEMORY64 != 0
+                            d > UINT32_MAX ||
+#endif
+                            offset_len_out_of_bounds(s, n, tbl_seg_len)
+                            || offset_len_out_of_bounds((uint32)d, n,
                                                         tbl_inst->cur_size)) {
                             wasm_set_exception(module,
                                                "out of bounds table access");
@@ -5966,7 +6002,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     case WASM_OP_TABLE_COPY:
                     {
                         uint32 src_tbl_idx, dst_tbl_idx;
-                        uint32 n, s, d;
+                        tbl_elem_idx_t n, s, d;
                         WASMTableInstance *src_tbl_inst, *dst_tbl_inst;
 
                         read_leb_uint32(frame_ip, frame_ip_end, dst_tbl_idx);
@@ -5979,14 +6015,29 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         src_tbl_inst = wasm_get_table_inst(module, src_tbl_idx);
 
-                        n = (uint32)POP_I32();
-                        s = (uint32)POP_I32();
-                        d = (uint32)POP_I32();
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = src_tbl_inst->is_table64
+                                     && dst_tbl_inst->is_table64;
+#endif
+                        n = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = src_tbl_inst->is_table64;
+#endif
+                        s = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = dst_tbl_inst->is_table64;
+#endif
+                        d = (tbl_elem_idx_t)POP_TBL_ELEM_IDX();
 
-                        if (offset_len_out_of_bounds(d, n,
+                        if (
+#if WASM_ENABLE_MEMORY64 != 0
+                            n > UINT32_MAX || s > UINT32_MAX || d > UINT32_MAX
+                            ||
+#endif
+                            offset_len_out_of_bounds((uint32)d, (uint32)n,
                                                      dst_tbl_inst->cur_size)
                             || offset_len_out_of_bounds(
-                                s, n, src_tbl_inst->cur_size)) {
+                                (uint32)s, (uint32)n, src_tbl_inst->cur_size)) {
                             wasm_set_exception(module,
                                                "out of bounds table access");
                             goto got_exception;
@@ -6009,28 +6060,37 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                     case WASM_OP_TABLE_GROW:
                     {
                         WASMTableInstance *tbl_inst;
-                        uint32 tbl_idx, n, orig_tbl_sz;
+                        uint32 tbl_idx, orig_tbl_sz;
+                        tbl_elem_idx_t n;
                         table_elem_type_t init_val;
 
                         read_leb_uint32(frame_ip, frame_ip_end, tbl_idx);
                         bh_assert(tbl_idx < module->table_count);
 
                         tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = tbl_inst->is_table64;
+#endif
 
                         orig_tbl_sz = tbl_inst->cur_size;
 
-                        n = POP_I32();
+                        n = POP_TBL_ELEM_IDX();
 #if WASM_ENABLE_GC == 0
                         init_val = POP_I32();
 #else
                         init_val = POP_REF();
 #endif
 
-                        if (!wasm_enlarge_table(module, tbl_idx, n, init_val)) {
-                            PUSH_I32(-1);
+                        if (
+#if WASM_ENABLE_MEMORY64 != 0
+                            n > UINT32_MAX ||
+#endif
+                            !wasm_enlarge_table(module, tbl_idx, (uint32)n,
+                                                init_val)) {
+                            PUSH_TBL_ELEM_IDX(-1);
                         }
                         else {
-                            PUSH_I32(orig_tbl_sz);
+                            PUSH_TBL_ELEM_IDX(orig_tbl_sz);
                         }
                         break;
                     }
@@ -6043,13 +6103,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         bh_assert(tbl_idx < module->table_count);
 
                         tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = tbl_inst->is_table64;
+#endif
 
-                        PUSH_I32(tbl_inst->cur_size);
+                        PUSH_TBL_ELEM_IDX(tbl_inst->cur_size);
                         break;
                     }
                     case WASM_OP_TABLE_FILL:
                     {
-                        uint32 tbl_idx, n;
+                        uint32 tbl_idx;
+                        tbl_elem_idx_t n, elem_idx;
                         WASMTableInstance *tbl_inst;
                         table_elem_type_t fill_val;
 
@@ -6057,24 +6121,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         bh_assert(tbl_idx < module->table_count);
 
                         tbl_inst = wasm_get_table_inst(module, tbl_idx);
+#if WASM_ENABLE_MEMORY64 != 0
+                        is_table64 = tbl_inst->is_table64;
+#endif
 
-                        n = POP_I32();
+                        n = POP_TBL_ELEM_IDX();
 #if WASM_ENABLE_GC == 0
                         fill_val = POP_I32();
 #else
                         fill_val = POP_REF();
 #endif
-                        i = POP_I32();
+                        elem_idx = POP_TBL_ELEM_IDX();
 
-                        if (offset_len_out_of_bounds(i, n,
+                        if (
+#if WASM_ENABLE_MEMORY64 != 0
+                            n > UINT32_MAX || elem_idx > UINT32_MAX ||
+#endif
+                            offset_len_out_of_bounds((uint32)elem_idx,
+                                                     (uint32)n,
                                                      tbl_inst->cur_size)) {
                             wasm_set_exception(module,
                                                "out of bounds table access");
                             goto got_exception;
                         }
 
-                        for (; n != 0; i++, n--) {
-                            tbl_inst->elems[i] = fill_val;
+                        for (; n != 0; elem_idx++, n--) {
+                            tbl_inst->elems[elem_idx] = fill_val;
                         }
                         break;
                     }
@@ -6657,7 +6729,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
             if (memory)
-                linear_mem_size = get_linear_mem_size();
+                linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
 #endif
             if (wasm_copy_exception(module, NULL)) {
 #if WASM_ENABLE_EXCE_HANDLING != 0

+ 11 - 8
core/iwasm/interpreter/wasm_interp_fast.c

@@ -1670,7 +1670,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
             {
                 uint32 ret_idx;
                 WASMFuncType *func_type;
-                uint32 off, ret_offset;
+                int32 off;
+                uint32 ret_offset;
                 uint8 *ret_types;
                 if (cur_func->is_import_func)
                     func_type = cur_func->u.func_import->func_type;
@@ -1682,9 +1683,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                 ret_offset = prev_frame->ret_offset;
 
                 for (ret_idx = 0,
-                    off = sizeof(int16) * (func_type->result_count - 1);
+                    off = (int32)sizeof(int16) * (func_type->result_count - 1);
                      ret_idx < func_type->result_count;
-                     ret_idx++, off -= sizeof(int16)) {
+                     ret_idx++, off -= (int32)sizeof(int16)) {
                     if (ret_types[ret_idx] == VALUE_TYPE_I64
                         || ret_types[ret_idx] == VALUE_TYPE_F64) {
                         PUT_I64_TO_ADDR(prev_frame->lp + ret_offset,
@@ -1991,7 +1992,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 #endif
                 func_obj = POP_REF();
                 if (!func_obj) {
-                    wasm_set_exception(module, "null function object");
+                    wasm_set_exception(module, "null function reference");
                     goto got_exception;
                 }
 
@@ -2006,7 +2007,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 #endif
                 func_obj = POP_REF();
                 if (!func_obj) {
-                    wasm_set_exception(module, "null function object");
+                    wasm_set_exception(module, "null function reference");
                     goto got_exception;
                 }
 
@@ -2147,7 +2148,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         struct_obj = POP_REF();
 
                         if (!struct_obj) {
-                            wasm_set_exception(module, "null structure object");
+                            wasm_set_exception(module,
+                                               "null structure reference");
                             goto got_exception;
                         }
 
@@ -2203,7 +2205,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
 
                         struct_obj = POP_REF();
                         if (!struct_obj) {
-                            wasm_set_exception(module, "null structure object");
+                            wasm_set_exception(module,
+                                               "null structure reference");
                             goto got_exception;
                         }
 
@@ -5994,7 +5997,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     || WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 \
     || WASM_ENABLE_BULK_MEMORY != 0
             if (memory)
-                linear_mem_size = get_linear_mem_size();
+                linear_mem_size = GET_LINEAR_MEMORY_SIZE(memory);
 #endif
             if (wasm_copy_exception(module, NULL))
                 goto got_exception;

File diff suppressed because it is too large
+ 435 - 191
core/iwasm/interpreter/wasm_loader.c


File diff suppressed because it is too large
+ 449 - 154
core/iwasm/interpreter/wasm_mini_loader.c


+ 42 - 12
core/iwasm/interpreter/wasm_runtime.c

@@ -678,6 +678,8 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
            uninitialized elements */
 #endif
 
+        table->is_table64 = import->u.table.table_type.flags & TABLE64_FLAG;
+
 #if WASM_ENABLE_MULTI_MODULE != 0
         *table_linked = table_inst_linked;
         if (table_inst_linked != NULL) {
@@ -736,6 +738,7 @@ tables_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
         /* For GC, all elements have already been set to NULL_REF (0) as
            uninitialized elements */
 #endif
+        table->is_table64 = module->tables[i].table_type.flags & TABLE64_FLAG;
         table->elem_type = module->tables[i].table_type.elem_type;
 #if WASM_ENABLE_GC != 0
         table->elem_ref_type.elem_ref_type =
@@ -1205,9 +1208,8 @@ globals_instantiate(WASMModule *module, WASMModuleInstance *module_inst,
 
             /* The linked global instance has been initialized, we
                just need to copy the value. */
-            bh_memcpy_s(&(global->initial_value), sizeof(WASMValue),
-                        &(global_import->import_global_linked->init_expr),
-                        sizeof(WASMValue));
+            global->initial_value =
+                global_import->import_global_linked->init_expr.u;
         }
         else
 #endif
@@ -1364,6 +1366,17 @@ export_functions_deinstantiate(WASMExportFuncInstance *functions)
         wasm_runtime_free(functions);
 }
 
+static int
+cmp_export_func_inst(const void *a, const void *b)
+{
+    const WASMExportFuncInstance *export_func1 =
+        (const WASMExportFuncInstance *)a;
+    const WASMExportFuncInstance *export_func2 =
+        (const WASMExportFuncInstance *)b;
+
+    return strcmp(export_func1->name, export_func2->name);
+}
+
 /**
  * Instantiate export functions in a module.
  */
@@ -1392,6 +1405,9 @@ export_functions_instantiate(const WASMModule *module,
         }
 
     bh_assert((uint32)(export_func - export_funcs) == export_func_count);
+
+    qsort(export_funcs, export_func_count, sizeof(WASMExportFuncInstance),
+          cmp_export_func_inst);
     return export_funcs;
 }
 
@@ -1594,8 +1610,12 @@ execute_post_instantiate_functions(WASMModuleInstance *module_inst,
     if (is_sub_inst) {
         bh_assert(exec_env_main);
 #ifdef OS_ENABLE_HW_BOUND_CHECK
-        bh_assert(exec_env_tls == exec_env_main);
-        (void)exec_env_tls;
+        /* May come from pthread_create_wrapper, thread_spawn_wrapper and
+           wasm_cluster_spawn_exec_env. If it comes from the former two,
+           the exec_env_tls must be not NULL and equal to exec_env_main,
+           else if it comes from the last one, it may be NULL. */
+        if (exec_env_tls)
+            bh_assert(exec_env_tls == exec_env_main);
 #endif
         exec_env = exec_env_main;
 
@@ -2446,7 +2466,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
             goto fail;
         }
         for (i = 0; i < module->table_seg_count; i++) {
-            if (wasm_elem_is_active(module->table_segments[i].mode))
+            if (wasm_elem_is_active(module->table_segments[i].mode)
+                || wasm_elem_is_declarative(module->table_segments[i].mode))
                 bh_bitmap_set_bit(module_inst->e->common.elem_dropped, i);
         }
     }
@@ -3413,11 +3434,20 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
 WASMFunctionInstance *
 wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name)
 {
-    uint32 i;
-    for (i = 0; i < module_inst->export_func_count; i++)
-        if (!strcmp(module_inst->export_functions[i].name, name))
-            return module_inst->export_functions[i].function;
-    return NULL;
+    WASMExportFuncInstance key = { .name = (char *)name };
+    WASMExportFuncInstance *export_func_inst;
+
+    if (!module_inst->export_functions)
+        return NULL;
+
+    export_func_inst = bsearch(
+        &key, module_inst->export_functions, module_inst->export_func_count,
+        sizeof(WASMExportFuncInstance), cmp_export_func_inst);
+
+    if (!export_func_inst)
+        return NULL;
+
+    return export_func_inst->function;
 }
 
 WASMMemoryInstance *
@@ -4630,7 +4660,7 @@ llvm_jit_table_init(WASMModuleInstance *module_inst, uint32 tbl_idx,
             if (!(func_obj = wasm_create_func_obj(module_inst,
                                                   init_values[i].u.ref_index,
                                                   true, NULL, 0))) {
-                wasm_set_exception(module_inst, "null function object");
+                wasm_set_exception(module_inst, "null function reference");
                 return;
             }
             table_elems[i] = func_obj;

+ 2 - 1
core/iwasm/interpreter/wasm_runtime.h

@@ -166,7 +166,8 @@ struct WASMMemoryInstance {
 struct WASMTableInstance {
     /* The element type */
     uint8 elem_type;
-    uint8 __padding__[7];
+    uint8 is_table64;
+    uint8 __padding__[6];
     union {
 #if WASM_ENABLE_GC != 0
         WASMRefType *elem_ref_type;

+ 1 - 1
core/iwasm/libraries/lib-pthread/lib_pthread.cmake

@@ -6,7 +6,7 @@ set (LIB_PTHREAD_DIR ${CMAKE_CURRENT_LIST_DIR})
 add_definitions (-DWASM_ENABLE_LIB_PTHREAD=1)
 
 if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
-add_definitions (-DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=1)
+    add_definitions (-DWASM_ENABLE_LIB_PTHREAD_SEMAPHORE=1)
 endif()
 
 include_directories(${LIB_PTHREAD_DIR})

+ 19 - 5
core/iwasm/libraries/libc-emcc/libc_emcc_wrapper.c

@@ -7,8 +7,13 @@
 #include "bh_log.h"
 #include "wasm_export.h"
 #include "../interpreter/wasm.h"
-#if !defined(_DEFAULT_SOURCE) && !defined(BH_PLATFORM_LINUX_SGX)
-#include "sys/syscall.h"
+
+#if defined(__linux__)
+#include <linux/version.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
+#define HAVE_SYSCALL_GETRANDOM
+#include <sys/syscall.h>
+#endif
 #endif
 
 /* clang-format off */
@@ -168,12 +173,21 @@ statbuf_native2app(const struct stat *statbuf_native,
     statbuf_app->st_blksize = (unsigned)statbuf_native->st_blksize;
     statbuf_app->st_blocks = (unsigned)statbuf_native->st_blocks;
     statbuf_app->st_ino = (int64)statbuf_native->st_ino;
+#if defined(__APPLE__)
+    statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atimespec.tv_sec;
+    statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atimespec.tv_nsec;
+    statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtimespec.tv_sec;
+    statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtimespec.tv_nsec;
+    statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctimespec.tv_sec;
+    statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctimespec.tv_nsec;
+#else
     statbuf_app->st_atim.tv_sec = (int)statbuf_native->st_atim.tv_sec;
     statbuf_app->st_atim.tv_nsec = (int)statbuf_native->st_atim.tv_nsec;
     statbuf_app->st_mtim.tv_sec = (int)statbuf_native->st_mtim.tv_sec;
     statbuf_app->st_mtim.tv_nsec = (int)statbuf_native->st_mtim.tv_nsec;
     statbuf_app->st_ctim.tv_sec = (int)statbuf_native->st_ctim.tv_sec;
     statbuf_app->st_ctim.tv_nsec = (int)statbuf_native->st_ctim.tv_nsec;
+#endif
 }
 
 static int
@@ -261,10 +275,10 @@ getentropy_wrapper(wasm_exec_env_t exec_env, void *buffer, uint32 length)
 {
     if (buffer == NULL)
         return -1;
-#if defined(_DEFAULT_SOURCE) || defined(BH_PLATFORM_LINUX_SGX)
-    return getentropy(buffer, length);
-#else
+#if defined(HAVE_SYSCALL_GETRANDOM)
     return syscall(SYS_getrandom, buffer, length, 0);
+#else
+    return getentropy(buffer, length);
 #endif
 }
 

+ 5 - 4
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -1022,8 +1022,8 @@ execute_interruptible_poll_oneoff(
     uint32 i;
 
     const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff(
-                                 in, nsubscriptions),
-                             time_quant = 1e9;
+                                 in, (uint32)nsubscriptions),
+                             time_quant = (__wasi_timestamp_t)1e9;
     const uint64 size_to_copy =
         nsubscriptions * (uint64)sizeof(wasi_subscription_t);
     __wasi_subscription_t *in_copy = NULL;
@@ -1034,12 +1034,13 @@ execute_interruptible_poll_oneoff(
         return __WASI_ENOMEM;
     }
 
-    bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy);
+    bh_memcpy_s(in_copy, (uint32)size_to_copy, in, (uint32)size_to_copy);
 
     while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) {
         /* update timeout for clock subscription events */
         update_clock_subscription_data(
-            in_copy, nsubscriptions, min_uint64(time_quant, timeout - elapsed));
+            in_copy, (uint32)nsubscriptions,
+            min_uint64(time_quant, timeout - elapsed));
         err = wasmtime_ssp_poll_oneoff(exec_env, curfds, in_copy, out,
                                        nsubscriptions, nevents);
         elapsed += time_quant;

+ 1 - 1
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c

@@ -3130,7 +3130,7 @@ compare_address(const struct addr_pool *addr_pool_entry,
         }
         addr_size = 16;
     }
-    max_addr_mask = addr_size * 8;
+    max_addr_mask = (uint8)(addr_size * 8);
 
     /* IPv4 0.0.0.0 or IPv6 :: means any address */
     if (basebuf[0] == 0 && !memcmp(basebuf, basebuf + 1, addr_size - 1)) {

+ 29 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h

@@ -132,6 +132,35 @@ refcount_release(struct refcount *r)
 #error "Reference counter isn't implemented"
 #endif /* end of __GNUC_PREREQ (4.7) */
 
+#elif defined(_MSC_VER)
+
+/* Simple reference counter. */
+struct LOCKABLE refcount {
+    LONG count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+    InterlockedExchange(&r->count, (LONG)count);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+    InterlockedIncrement(&r->count);
+}
+
+/* Decrement the reference counter, returning whether the reference
+   dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+    return InterlockedDecrement(&r->count) == 0 ? true : false;
+}
+
 #else /* else of CONFIG_HAS_STD_ATOMIC */
 #error "Reference counter isn't implemented"
 #endif /* end of CONFIG_HAS_STD_ATOMIC */

+ 18 - 4
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h

@@ -70,9 +70,11 @@
 #endif
 
 #if !defined(BH_PLATFORM_LINUX_SGX)
+
 /* Clang's __GNUC_PREREQ macro has a different meaning than GCC one,
 so we have to handle this case specially */
 #if defined(__clang__)
+
 /* Clang provides stdatomic.h since 3.6.0
 See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */
 #if __clang_major__ > 3 || (__clang_major__ == 3 && __clang_minor__ >= 6)
@@ -80,7 +82,9 @@ See https://releases.llvm.org/3.6.0/tools/clang/docs/ReleaseNotes.html */
 #else
 #define CONFIG_HAS_STD_ATOMIC 0
 #endif
+
 #elif defined(__GNUC_PREREQ)
+
 /* Even though older versions of GCC support C11, atomics were
 not implemented until 4.9. See
 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */
@@ -89,11 +93,21 @@ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58016 */
 #else /* else of __GNUC_PREREQ(4, 9) */
 #define CONFIG_HAS_STD_ATOMIC 0
 #endif /* end of __GNUC_PREREQ(4, 9) */
-#else  /* else of defined(__GNUC_PREREQ) */
+
+#elif defined(_MSC_VER)
+
+#define CONFIG_HAS_STD_ATOMIC 0
+
+#else
+
 #define CONFIG_HAS_STD_ATOMIC 1
-#endif /* end of defined(__GNUC_PREREQ) */
-#else  /* else of !defined(BH_PLATFORM_LINUX_SGX) */
+
+#endif /* end of defined(__clang__) */
+
+#else /* else of !defined(BH_PLATFORM_LINUX_SGX) */
+
 #define CONFIG_HAS_STD_ATOMIC 0
+
 #endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */
 
-#endif
+#endif /* end of SSP_CONFIG_H */

+ 2 - 6
core/iwasm/libraries/wasi-nn/README.md

@@ -103,7 +103,6 @@ docker run \
     wasi-nn-cpu \
     --dir=/ \
     --env="TARGET=cpu" \
-    --native-lib=/lib/libwasi-nn-tflite.so \
     /assets/test_tensorflow.wasm
 ```
 
@@ -119,7 +118,6 @@ docker run \
     wasi-nn-nvidia-gpu \
     --dir=/ \
     --env="TARGET=gpu" \
-    --native-lib=/lib/libwasi-nn-tflite.so \
     /assets/test_tensorflow.wasm
 ```
 
@@ -131,7 +129,6 @@ docker run \
     wasi-nn-vx-delegate \
     --dir=/ \
     --env="TARGET=gpu" \
-    --native-lib=/lib/libwasi-nn-tflite.so \
     /assets/test_tensorflow_quantized.wasm
 ```
 
@@ -147,7 +144,6 @@ docker run \
     wasi-nn-tpu \
     --dir=/ \
     --env="TARGET=tpu" \
-    --native-lib=/lib/libwasi-nn-tflite.so \
     /assets/test_tensorflow_quantized.wasm
 ```
 
@@ -155,8 +151,8 @@ docker run \
 
 Supported:
 
-- Graph encoding: `tensorflowlite`.
-- Execution target: `cpu`, `gpu` and `tpu`.
+- Graph encoding: `tensorflowlite`, `openvino` and `ggml`
+- Execution target: `cpu` for all. `gpu` and `tpu` for `tensorflowlite`.
 - Tensor type: `fp32`.
 
 ## Smoke test

+ 15 - 7
core/iwasm/libraries/wasi-nn/cmake/Findcjson.cmake

@@ -4,13 +4,21 @@
 include(FetchContent)
 
 set(CJSON_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/cjson")
-
-FetchContent_Declare(
-  cjson
-  GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git
-  GIT_TAG        v1.7.18
-  SOURCE_DIR     ${CJSON_SOURCE_DIR}
-)
+if(EXISTS ${CJSON_SOURCE_DIR})
+  message("Use existed source code under ${CJSON_SOURCE_DIR}")
+  FetchContent_Declare(
+    cjson
+    SOURCE_DIR     ${CJSON_SOURCE_DIR}
+  )
+else()
+  message("download source code and store it at ${CJSON_SOURCE_DIR}")
+  FetchContent_Declare(
+    cjson
+    GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git
+    GIT_TAG        v1.7.18
+    SOURCE_DIR     ${CJSON_SOURCE_DIR}
+  )
+endif()
 
 set(ENABLE_CJSON_TEST OFF CACHE INTERNAL "Turn off tests")
 set(ENABLE_CJSON_UNINSTALL OFF CACHE INTERNAL "Turn off uninstall to avoid targets conflict")

+ 15 - 7
core/iwasm/libraries/wasi-nn/cmake/Findllamacpp.cmake

@@ -4,13 +4,21 @@
 include(FetchContent)
 
 set(LLAMA_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/llama.cpp")
-
-FetchContent_Declare(
-  llamacpp
-  GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git
-  GIT_TAG        b3573
-  SOURCE_DIR     ${LLAMA_SOURCE_DIR}
-)
+if(EXISTS ${LLAMA_SOURCE_DIR})
+  message("Use existed source code under ${LLAMA_SOURCE_DIR}")
+  FetchContent_Declare(
+    llamacpp
+    SOURCE_DIR     ${LLAMA_SOURCE_DIR}
+  )
+else()
+  message("download source code and store it at ${LLAMA_SOURCE_DIR}")
+  FetchContent_Declare(
+    llamacpp
+    GIT_REPOSITORY https://github.com/ggerganov/llama.cpp.git
+    GIT_TAG        b3573
+    SOURCE_DIR     ${LLAMA_SOURCE_DIR}
+  )
+endif()
 
 set(LLAMA_BUILD_TESTS OFF)
 set(LLAMA_BUILD_EXAMPLES OFF)

+ 21 - 9
core/iwasm/libraries/wasi-nn/cmake/Findtensorflow_lite.cmake

@@ -4,20 +4,32 @@
 include(FetchContent)
 
 set(TFLITE_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+if(EXISTS ${TFLITE_SOURCE_DIR})
+  message("Use existed source code under ${TFLITE_SOURCE_DIR}")
+  FetchContent_Declare(
+    tensorflow_lite
+    SOURCE_DIR     ${TFLITE_SOURCE_DIR}
+    SOURCE_SUBDIR  tensorflow/lite
+  )
+else()
+  message("download source code and store it at ${TFLITE_SOURCE_DIR}")
+  FetchContent_Declare(
+    tensorflow_lite
+    GIT_REPOSITORY https://github.com/tensorflow/tensorflow.git
+    GIT_TAG        v2.12.0
+    GIT_SHALLOW    ON
+    GIT_PROGRESS   ON
+    SOURCE_DIR     ${TFLITE_SOURCE_DIR}
+    SOURCE_SUBDIR  tensorflow/lite
+    PATCH_COMMAND  git apply ${CMAKE_CURRENT_LIST_DIR}/add_telemetry.patch
+  )
+endif()
 
-FetchContent_Declare(
-  tensorflow_lite
-  GIT_REPOSITORY https://github.com/tensorflow/tensorflow.git 
-  GIT_TAG        v2.12.0 
-  GIT_SHALLOW    ON
-  GIT_PROGRESS   ON
-  SOURCE_DIR     ${TFLITE_SOURCE_DIR}
-  SOURCE_SUBDIR  tensorflow/lite
-)
 
 if(WAMR_BUILD_WASI_NN_ENABLE_GPU EQUAL 1)
   set(TFLITE_ENABLE_GPU ON)
 endif()
+
 if (CMAKE_SIZEOF_VOID_P EQUAL 4)
   set(TFLITE_ENABLE_XNNPACK OFF)
 endif()

+ 12 - 0
core/iwasm/libraries/wasi-nn/cmake/add_telemetry.patch

@@ -0,0 +1,12 @@
+diff --git a/tensorflow/lite/CMakeLists.txt b/tensorflow/lite/CMakeLists.txt
+index c71a3925ac..39591a3bd7 100644
+--- a/tensorflow/lite/CMakeLists.txt
++++ b/tensorflow/lite/CMakeLists.txt
+@@ -493,6 +493,7 @@ set(TFLITE_PROFILER_SRCS
+   ${TFLITE_SOURCE_DIR}/profiling/root_profiler.h
+   ${TFLITE_SOURCE_DIR}/profiling/root_profiler.cc
+   ${TFLITE_SOURCE_DIR}/profiling/telemetry/profiler.cc
++  ${TFLITE_SOURCE_DIR}/profiling/telemetry/telemetry.cc
+ )
+ if(CMAKE_SYSTEM_NAME MATCHES "Android")
+   list(APPEND TFLITE_PROFILER_SRCS

+ 1 - 0
core/iwasm/libraries/wasi-nn/cmake/wasi_nn.cmake

@@ -22,6 +22,7 @@ add_compile_definitions(
 # - tflite
 if(WAMR_BUILD_WASI_NN_TFLITE EQUAL 1)
   find_package(tensorflow_lite REQUIRED)
+  enable_language(CXX)
 
   add_library(
     wasi_nn_tflite

+ 17 - 4
core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu

@@ -14,19 +14,32 @@ WORKDIR /usr/local/share/ca-certificates/cacert.org
 RUN wget -qP /usr/local/share/ca-certificates/cacert.org http://www.cacert.org/certs/root.crt http://www.cacert.org/certs/class3.crt \
   && update-ca-certificates
 
+# need a newer cmake
+RUN apt-get purge -y cmake
+
+ARG CMAKE_VER=3.27.0
+RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \
+  -q -O /tmp/cmake-install.sh \
+  && chmod u+x /tmp/cmake-install.sh \
+  && mkdir /opt/cmake-${CMAKE_VER} \
+  && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \
+  && rm /tmp/cmake-install.sh \
+  && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin
+
 WORKDIR /home/wamr
 COPY . .
 RUN git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
 
 WORKDIR /home/wamr/product-mini/platforms/linux
 RUN rm -rf build \
-  && cmake -S . -B build -DWAMR_BUILD_WASI_NN=1 \
+  && cmake -S . -B build\
+       -DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_NN_TFLITE=1\
   && cmake --build build -j "$(grep -c ^processor /proc/cpuinfo)"
 
 FROM ubuntu:22.04
 
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /usr/bin/iwasm
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/libiwasm.so /lib/libiwasm.so
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/libwasi-nn-*.so /lib/
+COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /usr/bin
+COPY --from=base /home/wamr/product-mini/platforms/linux/build/lib*.so /usr/lib
+ENV LD_LIBRARY_PATH=/usr/lib
 
 ENTRYPOINT [ "iwasm" ]

+ 17 - 5
core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu

@@ -14,14 +14,26 @@ WORKDIR /usr/local/share/ca-certificates/cacert.org
 RUN wget -qP /usr/local/share/ca-certificates/cacert.org http://www.cacert.org/certs/root.crt http://www.cacert.org/certs/class3.crt \
   && update-ca-certificates
 
+# need a newer cmake
+RUN apt-get purge -y cmake
+
+ARG CMAKE_VER=3.27.0
+RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \
+  -q -O /tmp/cmake-install.sh \
+  && chmod u+x /tmp/cmake-install.sh \
+  && mkdir /opt/cmake-${CMAKE_VER} \
+  && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \
+  && rm /tmp/cmake-install.sh \
+  && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin
+
 WORKDIR /home/wamr
 COPY . .
 RUN git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
 
-WORKDIR /home/wamr/product-mini/platforms/linux/build
+WORKDIR /home/wamr/product-mini/platforms/linux
 RUN rm -rf build \
   && cmake -S . -B build \
-       -DWAMR_BUILD_WASI_NN=1 \
+       -DWAMR_BUILD_WASI_NN=1 -DWAMR_BUILD_WASI_NN_TFLITE=1\
        -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \
   && cmake --build build -j "$(grep -c ^processor /proc/cpuinfo)"
 
@@ -40,8 +52,8 @@ RUN mkdir -p /etc/OpenCL/vendors && \
 ENV NVIDIA_VISIBLE_DEVICES=all
 ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility
 
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /usr/bin/iwasm
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/libiwasm.so /lib/libiwasm.so
-COPY --from=base /home/wamr/product-mini/platforms/linux/build/libwasi-nn-*.so /lib/
+COPY --from=base /home/wamr/product-mini/platforms/linux/build/iwasm /usr/bin
+COPY --from=base /home/wamr/product-mini/platforms/linux/build/lib*.so /usr/lib
+ENV LD_LIBRARY_PATH=/usr/lib
 
 ENTRYPOINT [ "iwasm" ]

+ 18 - 5
core/iwasm/libraries/wasi-nn/test/Dockerfile.tpu

@@ -14,22 +14,35 @@ WORKDIR /usr/local/share/ca-certificates/cacert.org
 RUN wget -qP /usr/local/share/ca-certificates/cacert.org http://www.cacert.org/certs/root.crt http://www.cacert.org/certs/class3.crt \
   && update-ca-certificates
 
+# need a newer cmake
+RUN apt-get purge -y cmake
+
+ARG CMAKE_VER=3.27.0
+RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \
+  -q -O /tmp/cmake-install.sh \
+  && chmod u+x /tmp/cmake-install.sh \
+  && mkdir /opt/cmake-${CMAKE_VER} \
+  && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \
+  && rm /tmp/cmake-install.sh \
+  && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin
+
 WORKDIR /home/wamr
 COPY . .
 RUN git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
 
 WORKDIR /home/wamr/product-mini/platforms/linux
 RUN rm -rf build \
-  && cmake -S . -B build -DWAMR_BUILD_WASI_NN=1 \
-    -DWAMR_BUILD_WASI_NN=1 \
+  && cmake -S . -B build\
+    -DWAMR_BUILD_WASI_NN=1\
+    -DWAMR_BUILD_WASI_NN_TFLITE=1\
     -DWAMR_BUILD_WASI_NN_ENABLE_EXTERNAL_DELEGATE=1 \
     -DWAMR_BUILD_WASI_NN_EXTERNAL_DELEGATE_PATH="libedgetpu.so.1.0" \
     -DWAMR_BUILD_WASI_NN_ENABLE_GPU=1 \
   && cmake --build build -j "$(grep -c ^processor /proc/cpuinfo)"
 
-RUN cp /home/wamr/product-mini/platforms/linux/build/iwasm /usr/bin/iwasm \
-  && cp /home/wamr/product-mini/platforms/linux/build/libiwasm.so /lib/libiwasm.so \
-  && cp /home/wamr/product-mini/platforms/linux/build/libwasi-nn-*.so /lib/
+RUN cp /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm \
+  && cp /home/wamr/product-mini/platforms/linux/build/lib*.so /usr/lib
+ENV LD_LIBRARY_PATH=/usr/lib
 
 WORKDIR /assets
 ENTRYPOINT [ "iwasm" ]

+ 15 - 2
core/iwasm/libraries/wasi-nn/test/Dockerfile.vx-delegate

@@ -21,6 +21,18 @@ RUN apt-get update && apt-get install -y wget ca-certificates --no-install-recom
     && update-ca-certificates \
     && git config --global http.sslCAinfo /etc/ssl/certs/ca-certificates.crt
 
+# need a newer cmake
+RUN apt-get purge -y cmake
+
+ARG CMAKE_VER=3.27.0
+RUN wget https://github.com/Kitware/CMake/releases/download/v${CMAKE_VER}/cmake-${CMAKE_VER}-Linux-x86_64.sh \
+  -q -O /tmp/cmake-install.sh \
+  && chmod u+x /tmp/cmake-install.sh \
+  && mkdir /opt/cmake-${CMAKE_VER} \
+  && /tmp/cmake-install.sh --skip-license --prefix=/opt/cmake-${CMAKE_VER} \
+  && rm /tmp/cmake-install.sh \
+  && ln -s /opt/cmake-${CMAKE_VER}/bin/* /usr/local/bin
+
 # Build TensorFlow Lite VX delegate default built for x86-64 simulator
 WORKDIR /tmp
 RUN git clone https://github.com/VeriSilicon/TIM-VX.git tim-vx \
@@ -89,7 +101,6 @@ ENV VSIMULATOR_CONFIG=czl
 
 ENV LD_LIBRARY_PATH=/tmp/tim-vx/prebuilt-sdk/x86_64_linux/lib:/usr/local/lib:/lib/x86_64-linux-gnu/:/lib64/:/usr/lib:$LD_LIBRARY_PATH 
 
-
 # Build WASI-NN
 WORKDIR /home/wamr
 
@@ -102,12 +113,14 @@ RUN cmake \
     -DCMAKE_LIBRARY_PATH=${CMAKE_LIBRARY_PATH}:/usr/local/lib/ \
     -DCMAKE_INCLUDE_PATH=${CMAKE_INCLUDE_PATH}:/usr/local/include/ \
     -DWAMR_BUILD_WASI_NN=1 \
+    -DWAMR_BUILD_WASI_NN_TFLITE=1\
     -DWAMR_BUILD_WASI_NN_ENABLE_EXT=1 \
     -DWASI_NN_EXT_DELEGATE_PATH="/usr/lib/libvx_delegate.so" \
     ..
 
 RUN make -j "$(grep -c ^processor /proc/cpuinfo)"
 
-RUN cp /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm
+RUN cp /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm \
+  && cp /home/wamr/product-mini/platforms/linux/build/lib*.so /usr/lib
 
 ENTRYPOINT [ "/run/iwasm" ]

+ 4 - 4
core/iwasm/libraries/wasi-nn/test/build.sh

@@ -8,9 +8,9 @@ CURR_PATH=$(cd $(dirname $0) && pwd -P)
 # WASM application that uses WASI-NN
 
 /opt/wasi-sdk/bin/clang \
+    --target=wasm32-wasi \
+    -DNN_LOG_LEVEL=1 \
     -Wl,--allow-undefined \
-    -Wl,--strip-all,--no-entry \
-    --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
     -I../include -I../src/utils \
     -o test_tensorflow.wasm \
     test_tensorflow.c utils.c
@@ -28,9 +28,9 @@ python3 sum.py
 
 cd ${CURR_PATH}
 /opt/wasi-sdk/bin/clang \
+    --target=wasm32-wasi \
+    -DNN_LOG_LEVEL=1 \
     -Wl,--allow-undefined \
-    -Wl,--strip-all,--no-entry \
-    --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
     -I../include -I../src/utils \
     -o test_tensorflow_quantized.wasm \
     test_tensorflow_quantized.c utils.c

+ 1 - 1
core/iwasm/libraries/wasi-nn/test/requirements.txt

@@ -1,2 +1,2 @@
 tensorflow==2.12.1
-numpy==1.26.4
+numpy==1.24.4

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

@@ -5,6 +5,7 @@
 
 #include "utils.h"
 #include "logger.h"
+#include "wasi_nn.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -57,7 +58,7 @@ wasm_load(char *model_name, graph *g, execution_target target)
 wasi_nn_error
 wasm_load_by_name(const char *model_name, graph *g)
 {
-    wasm_nn_error res = load_by_name(model_name, g);
+    wasi_nn_error res = load_by_name(model_name, g);
     return res;
 }
 

+ 7 - 0
core/shared/platform/common/posix/posix_thread.c

@@ -712,6 +712,13 @@ os_thread_signal_init(os_signal_handler handler)
 #if WASM_DISABLE_STACK_HW_BOUND_CHECK == 0
     sigalt_stack_base_addr = map_addr;
 #endif
+
+#if defined(os_thread_local_attribute)
+    // calculate and cache the new stack boundary.
+    // see https://github.com/bytecodealliance/wasm-micro-runtime/issues/3966
+    (void)os_thread_get_stack_boundary();
+#endif
+
     signal_handler = handler;
     thread_signal_inited = true;
     return 0;

+ 13 - 2
core/shared/platform/windows/platform_internal.h

@@ -6,6 +6,12 @@
 #ifndef _PLATFORM_INTERNAL_H
 #define _PLATFORM_INTERNAL_H
 
+/*
+ * Suppress the noisy warnings:
+ * winbase.h: warning C5105: macro expansion producing 'defined' has
+ * undefined behavior
+ */
+#pragma warning(disable : 5105)
 #include <inttypes.h>
 #include <stdbool.h>
 #include <assert.h>
@@ -168,12 +174,13 @@ typedef struct windows_dir_stream {
     windows_handle *handle;
 } windows_dir_stream;
 
-typedef windows_handle *os_file_handle;
 typedef windows_dir_stream *os_dir_stream;
 
-#if WASM_ENABLE_UVWASI != 1
+#if WASM_ENABLE_UVWASI == 0
+typedef windows_handle *os_file_handle;
 typedef HANDLE os_raw_file_handle;
 #else
+typedef uint32_t os_file_handle;
 typedef uint32_t os_raw_file_handle;
 #endif
 
@@ -190,7 +197,11 @@ typedef uint32_t os_raw_file_handle;
 static inline os_file_handle
 os_get_invalid_handle(void)
 {
+#if WASM_ENABLE_UVWASI == 0
     return NULL;
+#else
+    return -1;
+#endif
 }
 
 #ifdef __cplusplus

+ 4 - 0
core/shared/platform/windows/shared_platform.cmake

@@ -6,6 +6,7 @@ set (PLATFORM_SHARED_DIR ${CMAKE_CURRENT_LIST_DIR})
 add_definitions(-DBH_PLATFORM_WINDOWS)
 add_definitions(-DHAVE_STRUCT_TIMESPEC)
 add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
+enable_language(CXX)
 
 include_directories(${PLATFORM_SHARED_DIR})
 include_directories(${PLATFORM_SHARED_DIR}/../include)
@@ -15,6 +16,9 @@ file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c
 
 if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
     list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/win_file.c)
+elseif (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
+    # uvwasi doesn't need to compile win_file.c
+    list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/win_file.c)
 else()
     include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake)
     set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE})

+ 18 - 2
core/shared/platform/windows/win_clock.c

@@ -10,6 +10,22 @@
 #define NANOSECONDS_PER_SECOND 1000000000ULL
 #define NANOSECONDS_PER_TICK 100
 
+#if WINAPI_PARTITION_DESKTOP
+#ifndef __kernel_entry
+#define __kernel_entry
+#endif
+#ifndef NTAPI
+#define NTAPI
+#endif
+#ifndef _Out_
+#define _Out_
+#endif
+extern __kernel_entry NTSTATUS NTAPI
+NtQueryTimerResolution(_Out_ PULONG MinimumResolution,
+                       _Out_ PULONG MaximumResolution,
+                       _Out_ PULONG CurrentResolution);
+#endif
+
 static __wasi_errno_t
 calculate_monotonic_clock_frequency(uint64 *out_frequency)
 {
@@ -54,7 +70,7 @@ os_clock_res_get(__wasi_clockid_t clock_id, __wasi_timestamp_t *resolution)
         case __WASI_CLOCK_PROCESS_CPUTIME_ID:
         case __WASI_CLOCK_THREAD_CPUTIME_ID:
         {
-#if WINAPI_PARTITION_DESKTOP
+#if WINAPI_PARTITION_DESKTOP && WASM_ENABLE_WAMR_COMPILER == 0
             ULONG maximum_time;
             ULONG minimum_time;
             ULONG current_time;
@@ -140,4 +156,4 @@ os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
         default:
             return __WASI_EINVAL;
     }
-}
+}

+ 1 - 1
core/shared/platform/windows/win_file.c

@@ -1758,7 +1758,7 @@ os_closedir(os_dir_stream dir_stream)
     if (!success) {
         DWORD win_error = GetLastError();
 
-        if (win_error = ERROR_INVALID_HANDLE)
+        if (win_error == ERROR_INVALID_HANDLE)
             BH_FREE(dir_stream);
         return convert_windows_error_code(win_error);
     }

+ 2 - 2
core/shared/platform/windows/win_socket.c

@@ -182,8 +182,8 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
     (*sock)->type = windows_handle_type_socket;
     (*sock)->access_mode = windows_access_mode_read | windows_access_mode_write;
     (*sock)->fdflags = 0;
-    (*sock)->raw.socket =
-        accept(server_sock->raw.socket, (struct sockaddr *)&addr_tmp, &len);
+    (*sock)->raw.socket = accept(server_sock->raw.socket,
+                                 (struct sockaddr *)&addr_tmp, (int *)&len);
 
     if ((*sock)->raw.socket == INVALID_SOCKET) {
         BH_FREE(*sock);

+ 66 - 6
core/shared/platform/windows/win_thread.c

@@ -71,6 +71,63 @@ os_sem_reltimed_wait(korp_sem *sem, uint64 useconds);
 int
 os_sem_signal(korp_sem *sem);
 
+static void
+thread_data_list_add(os_thread_data *thread_data)
+{
+    os_mutex_lock(&thread_data_list_lock);
+    /* If already in list, just return */
+    os_thread_data *p = &supervisor_thread_data;
+    while (p) {
+        if (p == thread_data) {
+            os_mutex_unlock(&thread_data_list_lock);
+            return;
+        }
+        p = p->next;
+    }
+    thread_data->next = supervisor_thread_data.next;
+    supervisor_thread_data.next = thread_data;
+    os_mutex_unlock(&thread_data_list_lock);
+}
+
+static void
+thread_data_list_remove(os_thread_data *thread_data)
+{
+    os_mutex_lock(&thread_data_list_lock);
+    /* Search and remove it from list */
+    os_thread_data *p = &supervisor_thread_data;
+    while (p && p->next != thread_data)
+        p = p->next;
+
+    if (p && p->next) {
+        bh_assert(p->next == thread_data);
+        p->next = p->next->next;
+        /* Release the resources in thread_data */
+        os_cond_destroy(&thread_data->wait_cond);
+        os_mutex_destroy(&thread_data->wait_lock);
+        os_sem_destroy(&thread_data->wait_node.sem);
+        BH_FREE(thread_data);
+    }
+    os_mutex_unlock(&thread_data_list_lock);
+}
+
+static os_thread_data *
+thread_data_list_lookup(korp_tid tid)
+{
+    os_thread_data *thread_data = (os_thread_data *)tid;
+    os_mutex_lock(&thread_data_list_lock);
+    os_thread_data *p = supervisor_thread_data.next;
+    while (p) {
+        if (p == thread_data) {
+            /* Found */
+            os_mutex_unlock(&thread_data_list_lock);
+            return p;
+        }
+        p = p->next;
+    }
+    os_mutex_unlock(&thread_data_list_lock);
+    return NULL;
+}
+
 int
 os_thread_sys_init()
 {
@@ -254,10 +311,7 @@ os_thread_create_with_prio(korp_tid *p_tid, thread_start_routine_t start,
     }
 
     /* Add thread data into thread data list */
-    os_mutex_lock(&thread_data_list_lock);
-    thread_data->next = supervisor_thread_data.next;
-    supervisor_thread_data.next = thread_data;
-    os_mutex_unlock(&thread_data_list_lock);
+    thread_data_list_add(thread_data);
 
     /* Wait for the thread routine to set thread_data's tid
        and add thread_data to thread data list */
@@ -302,8 +356,12 @@ os_thread_join(korp_tid thread, void **p_retval)
     curr_thread_data->wait_node.next = NULL;
 
     /* Get thread data of thread to join */
-    thread_data = (os_thread_data *)thread;
-    bh_assert(thread_data);
+    thread_data = thread_data_list_lookup(thread);
+
+    if (thread_data == NULL) {
+        os_printf("Can't join thread %p, it does not exist", thread);
+        return BHT_ERROR;
+    }
 
     os_mutex_lock(&thread_data->wait_lock);
 
@@ -312,6 +370,7 @@ os_thread_join(korp_tid thread, void **p_retval)
         if (p_retval)
             *p_retval = thread_data->thread_retval;
         os_mutex_unlock(&thread_data->wait_lock);
+        thread_data_list_remove(thread_data);
         return BHT_OK;
     }
 
@@ -332,6 +391,7 @@ os_thread_join(korp_tid thread, void **p_retval)
     os_sem_wait(&curr_thread_data->wait_node.sem);
     if (p_retval)
         *p_retval = curr_thread_data->wait_node.retval;
+    thread_data_list_remove(thread_data);
     return BHT_OK;
 }
 

+ 8 - 2
core/shared/platform/windows/win_util.h

@@ -7,7 +7,13 @@
 #define _WIN_UTIL_H
 
 #include "platform_wasi_types.h"
-#include "windows.h"
+/*
+ * Suppress the noisy warnings:
+ * winbase.h: warning C5105: macro expansion producing 'defined' has
+ * undefined behavior
+ */
+#pragma warning(disable : 5105)
+#include <windows.h>
 
 __wasi_timestamp_t
 convert_filetime_to_wasi_timestamp(LPFILETIME filetime);
@@ -23,4 +29,4 @@ convert_windows_error_code(DWORD windows_error_code);
 __wasi_errno_t
 convert_winsock_error_code(int error_code);
 
-#endif /* end of _WIN_UTIL_H */
+#endif /* end of _WIN_UTIL_H */

+ 10 - 4
core/shared/platform/zephyr/zephyr_thread.c

@@ -393,6 +393,16 @@ os_thread_join(korp_tid thread, void **value_ptr)
     os_thread_data *thread_data;
     os_thread_wait_node *node;
 
+    /* Get thread data */
+    thread_data = thread_data_list_lookup(thread);
+
+    if (thread_data == NULL) {
+        os_printf(
+            "Can't join thread %p, probably already exited or does not exist",
+            thread);
+        return BHT_OK;
+    }
+
     /* Create wait node and append it to wait list */
     if (!(node = BH_MALLOC(sizeof(os_thread_wait_node))))
         return BHT_ERROR;
@@ -400,10 +410,6 @@ os_thread_join(korp_tid thread, void **value_ptr)
     sem_init(&node->sem, 0, 1);
     node->next = NULL;
 
-    /* Get thread data */
-    thread_data = thread_data_list_lookup(thread);
-    bh_assert(thread_data != NULL);
-
     mutex_lock(&thread_data->wait_list_lock, K_FOREVER);
     if (!thread_data->thread_wait_list)
         thread_data->thread_wait_list = node;

+ 18 - 1
core/shared/platform/zephyr/zephyr_time.c

@@ -14,6 +14,23 @@ os_time_get_boot_us()
 uint64
 os_time_thread_cputime_us(void)
 {
-    /* FIXME if u know the right api */
+    /* On certain boards, enabling userspace could impact the collection of
+     * thread runtime statistics */
+#ifdef CONFIG_THREAD_RUNTIME_STATS
+    k_tid_t tid;
+    struct k_thread_runtime_stats stats;
+    uint32 clock_freq;
+    uint64 cpu_cycles, time_in_us = 0;
+
+    tid = k_current_get();
+    if (k_thread_runtime_stats_get(tid, &stats) == 0) {
+        cpu_cycles = stats.execution_cycles;
+        clock_freq = CONFIG_SYS_CLOCK_HW_CYCLES_PER_SEC;
+        time_in_us = (cpu_cycles * 1000000) / clock_freq;
+    }
+
+    return time_in_us;
+#else
     return os_time_get_boot_us();
+#endif
 }

+ 2 - 1
core/shared/utils/bh_atomic.h

@@ -114,7 +114,8 @@ typedef uint16 bh_atomic_16_t;
 #endif
 
 /* On some 32-bit platform, disable 64-bit atomic operations, otherwise
- * undefined reference to `__atomic_load_8' */
+ * undefined reference to `__atomic_load_8', if on Zephyr, can add board related
+ * macro in autoconf.h to control */
 #ifndef WASM_UINT64_IS_ATOMIC
 #if !defined(__linux__) && !defined(__FreeBSD__) && !defined(__NetBSD__) \
     && !defined(__OpenBSD__) && (defined(__riscv) || defined(__arm__))   \

+ 50 - 0
core/shared/utils/bh_common.c

@@ -165,3 +165,53 @@ wa_strdup(const char *s)
     }
     return s1;
 }
+
+#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
+int
+bh_system(const char *cmd)
+{
+    int ret;
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+    ret = system(cmd);
+#else
+    ret = _spawnlp(_P_WAIT, "cmd.exe", "/c", cmd, NULL);
+#endif
+
+    return ret;
+}
+
+#if defined(_WIN32) || defined(_WIN32_)
+errno_t
+_mktemp_s(char *nameTemplate, size_t sizeInChars);
+#endif
+
+bool
+bh_mkstemp(char *file_name, size_t name_len)
+{
+    int fd;
+
+#if !(defined(_WIN32) || defined(_WIN32_))
+    (void)name_len;
+    /* On Linux, it generates a unique temporary filename from template, creates
+     * and opens the file, and returns an open file descriptor for the file. */
+    if ((fd = mkstemp(file_name)) <= 0) {
+        goto fail;
+    }
+
+    /* close and remove temp file */
+    close(fd);
+    unlink(file_name);
+#else
+    /* On Windows, it generates a unique temporary file name but does not create
+     * or open the file */
+    if (_mktemp_s(file_name, name_len) != 0) {
+        goto fail;
+    }
+#endif
+
+    return true;
+fail:
+    return false;
+}
+#endif /* End of WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0 */

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