ソースを参照

Merge branch main into dev/wasi_threads

Wenyong Huang 3 年 前
コミット
e170c355a2
100 ファイル変更5250 行追加1365 行削除
  1. 40 19
      .devcontainer/Dockerfile
  2. 7 5
      .devcontainer/devcontainer.json
  3. 1 1
      .github/workflows/build_iwasm_release.yml
  4. 63 11
      .github/workflows/build_llvm_libraries.yml
  5. 1 1
      .github/workflows/coding_guidelines.yml
  6. 105 55
      .github/workflows/compilation_on_android_ubuntu.yml
  7. 39 32
      .github/workflows/compilation_on_macos.yml
  8. 5 2
      .github/workflows/compilation_on_nuttx.yml
  9. 25 32
      .github/workflows/compilation_on_sgx.yml
  10. 3 3
      .github/workflows/release_process.yml
  11. 6 4
      .github/workflows/spec_test_on_nuttx.yml
  12. 3 0
      .gitignore
  13. 73 30
      build-scripts/build_llvm.py
  14. 1 0
      build-scripts/requirements.txt
  15. 13 4
      build-scripts/runtime_lib.cmake
  16. 24 0
      core/iwasm/aot/aot_runtime.c
  17. 7 0
      core/iwasm/aot/aot_runtime.h
  18. 6 1
      core/iwasm/common/arch/invokeNative_ia32.s
  19. 217 206
      core/iwasm/common/wasm_c_api.c
  20. 1 0
      core/iwasm/common/wasm_exec_env.c
  21. 17 0
      core/iwasm/common/wasm_exec_env.h
  22. 8 1
      core/iwasm/common/wasm_native.c
  23. 150 2
      core/iwasm/common/wasm_runtime_common.c
  24. 45 0
      core/iwasm/common/wasm_runtime_common.h
  25. 72 0
      core/iwasm/common/wasm_shared_memory.c
  26. 5 0
      core/iwasm/common/wasm_shared_memory.h
  27. 1 0
      core/iwasm/compilation/aot_compiler.h
  28. 100 8
      core/iwasm/compilation/aot_emit_function.c
  29. 24 1
      core/iwasm/compilation/aot_llvm.c
  30. 5 0
      core/iwasm/compilation/aot_llvm.h
  31. 92 1
      core/iwasm/fast-jit/fe/jit_emit_memory.c
  32. 26 4
      core/iwasm/fast-jit/jit_codecache.c
  33. 15 3
      core/iwasm/fast-jit/jit_compiler.c
  34. 1 0
      core/iwasm/include/aot_export.h
  35. 4 0
      core/iwasm/include/wasm_c_api.h
  36. 84 3
      core/iwasm/include/wasm_export.h
  37. 40 6
      core/iwasm/interpreter/wasm.h
  38. 98 99
      core/iwasm/interpreter/wasm_interp_classic.c
  39. 62 56
      core/iwasm/interpreter/wasm_interp_fast.c
  40. 31 19
      core/iwasm/interpreter/wasm_loader.c
  41. 21 10
      core/iwasm/interpreter/wasm_mini_loader.c
  42. 234 56
      core/iwasm/interpreter/wasm_runtime.c
  43. 20 11
      core/iwasm/interpreter/wasm_runtime.h
  44. 41 0
      core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c
  45. 103 7
      core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c
  46. 14 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h
  47. 0 42
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h
  48. 2 3
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c
  49. 37 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/refcount.h
  50. 22 0
      core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h
  51. 76 20
      core/iwasm/libraries/thread-mgr/thread_manager.c
  52. 0 1
      core/iwasm/libraries/wasi-nn/.dockerignore
  53. 56 7
      core/iwasm/libraries/wasi-nn/README.md
  54. 0 55
      core/iwasm/libraries/wasi-nn/logger.h
  55. 63 0
      core/iwasm/libraries/wasi-nn/src/utils/logger.h
  56. 163 0
      core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.c
  57. 51 0
      core/iwasm/libraries/wasi-nn/src/utils/wasi_nn_app_native.h
  58. 302 0
      core/iwasm/libraries/wasi-nn/src/wasi_nn.c
  59. 30 0
      core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h
  60. 66 20
      core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp
  61. 41 0
      core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.hpp
  62. 2 2
      core/iwasm/libraries/wasi-nn/test/CMakeLists.txt
  63. 0 32
      core/iwasm/libraries/wasi-nn/test/Dockerfile
  64. 22 0
      core/iwasm/libraries/wasi-nn/test/Dockerfile.base
  65. 23 0
      core/iwasm/libraries/wasi-nn/test/Dockerfile.compile
  66. 8 0
      core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu
  67. 20 0
      core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu
  68. 1 1
      core/iwasm/libraries/wasi-nn/test/build.sh
  69. 48 30
      core/iwasm/libraries/wasi-nn/test/test_tensorflow.c
  70. 10 1
      core/iwasm/libraries/wasi-nn/wasi_nn.cmake
  71. 19 62
      core/iwasm/libraries/wasi-nn/wasi_nn.h
  72. 0 44
      core/iwasm/libraries/wasi-nn/wasi_nn_common.h
  73. 0 264
      core/iwasm/libraries/wasi-nn/wasi_nn_native.c
  74. 0 40
      core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.hpp
  75. 106 0
      core/iwasm/libraries/wasi-nn/wasi_nn_types.h
  76. 4 4
      core/shared/platform/esp-idf/espidf_socket.c
  77. 60 14
      core/shared/platform/linux-sgx/sgx_ipfs.c
  78. 2 2
      doc/build_wasm_app.md
  79. 17 8
      doc/port_wamr.md
  80. 1 0
      language-bindings/python/MANIFEST.in
  81. 18 15
      language-bindings/python/README.md
  82. 28 3
      language-bindings/python/setup.py
  83. 0 0
      language-bindings/python/src/wamr/__init__.py
  84. 0 0
      language-bindings/python/src/wamr/libs/.placeholder
  85. 0 0
      language-bindings/python/src/wamr/wamrapi/__init__.py
  86. 1779 0
      language-bindings/python/src/wamr/wamrapi/iwasm.py
  87. 123 0
      language-bindings/python/src/wamr/wamrapi/wamr.py
  88. 0 0
      language-bindings/python/src/wamr/wasmcapi/__init__.py
  89. 0 0
      language-bindings/python/src/wamr/wasmcapi/binding.py
  90. 2 2
      language-bindings/python/src/wamr/wasmcapi/ffi.py
  91. 17 0
      language-bindings/python/utils/create_lib.sh
  92. 25 0
      language-bindings/python/wamr-api/README.md
  93. 1 0
      language-bindings/python/wamr-api/requirements.txt
  94. 11 0
      language-bindings/python/wamr-api/samples/compile.sh
  95. 22 0
      language-bindings/python/wamr-api/samples/main.py
  96. 12 0
      language-bindings/python/wamr-api/samples/sum.c
  97. 7 0
      language-bindings/python/wasm-c-api/README.md
  98. 0 0
      language-bindings/python/wasm-c-api/docs/design.md
  99. 0 0
      language-bindings/python/wasm-c-api/docs/images/python_package_life_cycle.png
  100. 0 0
      language-bindings/python/wasm-c-api/docs/setup_dev_env.md

+ 40 - 19
.devcontainer/Dockerfile

@@ -12,7 +12,7 @@ ENV TZ=Asian/Shanghai
 # hadolint ignore=DL3008
 # hadolint ignore=DL3008
 RUN apt-get update \
 RUN apt-get update \
   && apt-get install -y apt-transport-https apt-utils build-essential \
   && apt-get install -y apt-transport-https apt-utils build-essential \
-  ca-certificates curl g++-multilib git gnupg \
+  ca-certificates ccache curl g++-multilib git gnupg \
   libgcc-9-dev lib32gcc-9-dev lsb-release \
   libgcc-9-dev lib32gcc-9-dev lsb-release \
   ninja-build ocaml ocamlbuild python2.7 \
   ninja-build ocaml ocamlbuild python2.7 \
   software-properties-common tree tzdata \
   software-properties-common tree tzdata \
@@ -20,6 +20,15 @@ RUN apt-get update \
   && apt-get clean -y \
   && apt-get clean -y \
   && rm -rf /var/lib/apt/lists/*
   && rm -rf /var/lib/apt/lists/*
 
 
+#
+# binaryen
+ARG BINARYEN_VER=111
+WORKDIR /opt
+RUN wget -c --progress=dot:giga https://github.com/WebAssembly/binaryen/releases/download/version_${BINARYEN_VER}/binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \
+  && tar xf binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz \
+  && ln -sf /opt/binaryen-version_111 /opt/binaryen \
+  && rm binaryen-version_${BINARYEN_VER}-x86_64-linux.tar.gz
+
 #
 #
 # CMAKE (https://apt.kitware.com/)
 # CMAKE (https://apt.kitware.com/)
 SHELL ["/bin/bash", "-o", "pipefail", "-c"]
 SHELL ["/bin/bash", "-o", "pipefail", "-c"]
@@ -31,25 +40,26 @@ RUN wget --progress=dot:giga -O - https://apt.kitware.com/keys/kitware-archive-l
   && apt-get install -y kitware-archive-keyring --no-install-recommends \
   && apt-get install -y kitware-archive-keyring --no-install-recommends \
   && apt-get install -y cmake --no-install-recommends \
   && apt-get install -y cmake --no-install-recommends \
   && apt-get clean -y \
   && apt-get clean -y \
-  && rm -rf /var/lib/apt/lists/* 
+  && rm -rf /var/lib/apt/lists/*
 
 
 #
 #
 # install emsdk
 # install emsdk
 WORKDIR /opt
 WORKDIR /opt
 RUN git clone https://github.com/emscripten-core/emsdk.git
 RUN git clone https://github.com/emscripten-core/emsdk.git
 
 
+ARG EMSDK_VER=3.0.0
 WORKDIR /opt/emsdk
 WORKDIR /opt/emsdk
 RUN  git pull \
 RUN  git pull \
-  && ./emsdk install 2.0.26 \
-  && ./emsdk activate 2.0.26 \
+  && ./emsdk install ${EMSDK_VER} \
+  && ./emsdk activate ${EMSDK_VER} \
   && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
   && echo "source /opt/emsdk/emsdk_env.sh" >> /root/.bashrc
 
 
 #
 #
 # install wasi-sdk
 # install wasi-sdk
-ARG WASI_SDK_VER=16
+ARG WASI_SDK_VER=19
 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \
 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \
   && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \
   && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \
-  && ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \
+  && ln -sf /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \
   && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz
   && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz
 
 
 #
 #
@@ -57,29 +67,29 @@ RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases
 ARG WABT_VER=1.0.29
 ARG WABT_VER=1.0.29
 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \
 RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wabt/releases/download/${WABT_VER}/wabt-${WABT_VER}-ubuntu.tar.gz -P /opt \
   && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \
   && tar xf /opt/wabt-${WABT_VER}-ubuntu.tar.gz -C /opt \
-  && ln -fs /opt/wabt-${WABT_VER} /opt/wabt \
+  && ln -sf /opt/wabt-${WABT_VER} /opt/wabt \
   && rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz
   && rm /opt/wabt-${WABT_VER}-ubuntu.tar.gz
 
 
 #
 #
 # install bazelisk
 # install bazelisk
 ARG BAZELISK_VER=1.12.0
 ARG BAZELISK_VER=1.12.0
-RUN mkdir /opt/bazelisk \ 
+RUN mkdir /opt/bazelisk \
   && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \
   && wget -c --progress=dot:giga https://github.com/bazelbuild/bazelisk/releases/download/v${BAZELISK_VER}/bazelisk-linux-amd64 -P /opt/bazelisk \
   && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \
   && chmod a+x /opt/bazelisk/bazelisk-linux-amd64 \
   && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel
   && ln -fs /opt/bazelisk/bazelisk-linux-amd64 /opt/bazelisk/bazel
 
 
 #
 #
 # install clang+llvm
 # install clang+llvm
+ARG LLVM_VER=14
+RUN apt-get purge -y clang-10 llvm-10 && apt autoremove -y
 WORKDIR /etc/apt/apt.conf.d
 WORKDIR /etc/apt/apt.conf.d
 RUN touch 99verfiy-peer.conf \
 RUN touch 99verfiy-peer.conf \
   && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
   && echo "Acquire { https::Verify-Peer false }" > 99verfiy-peer.conf
 
 
-WORKDIR /tmp 
+WORKDIR /tmp
 RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
 RUN wget --progress=dot:giga https://apt.llvm.org/llvm.sh \
   && chmod a+x ./llvm.sh \
   && chmod a+x ./llvm.sh \
-  && /tmp/llvm.sh 12 all \ 
-  && ln -sf /usr/bin/clang-format-12 /usr/bin/clang-format \
-  && rm -rf /tmp/*
+  && ./llvm.sh ${LLVM_VER} all
 
 
 #
 #
 # [Optional]
 # [Optional]
@@ -96,17 +106,28 @@ RUN apt-get update \
 # Install required python packages
 # Install required python packages
 # hadolint ignore=DL3013
 # hadolint ignore=DL3013
 RUN python3 -m pip install --no-cache-dir --upgrade pip \
 RUN python3 -m pip install --no-cache-dir --upgrade pip \
-  && pip3 install --no-cache-dir --user black nose pycparser pylint
+  && pip3 install --no-cache-dir black nose pycparser pylint
+
+#
+# Install github-cli. It doens't work as a feature of devcontainer.json
+RUN cd /tmp \
+  && wget https://github.com/cli/cli/releases/download/v2.20.2/gh_2.20.2_linux_amd64.deb \
+  && dpkg -i gh_2.20.2_linux_amd64.deb
 
 
-# set path, PS and clean up
-ENV PATH "/opt/bazelisk:/opt/clang-llvm/bin:${PATH}"
-RUN echo "export PATH=/opt/bazelisk:/opt/clang-llvm/bin:${PATH}" >> /root/.bashrc \
-  && printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \
+#
+# Install NodeJS
+RUN curl -fsSL https://deb.nodesource.com/setup_19.x | bash -
+RUN apt-get install -y nodejs
+
+# set path
+ENV PATH="/opt/bazelisk:/usr/lib/llvm-${LLVM_VER}/bin:${PATH}"
+ENV CC=/usr/lib/llvm-${LLVM_VER}/bin/clang CXX=/usr/lib/llvm-${LLVM_VER}/bin/clang++
+RUN printf "%s\n" "PS1='\n[ \u@wamr-dev-docker \W ]\n$ '" >> /root/.bashrc \
   && apt-get autoremove -y \
   && apt-get autoremove -y \
   && apt-get clean -y \
   && apt-get clean -y \
   && rm -rf /var/lib/apt/lists/* \
   && rm -rf /var/lib/apt/lists/* \
   && rm -rf /tmp/*
   && rm -rf /tmp/*
 
 
 # set workdir when container run
 # set workdir when container run
-VOLUME /workspace
-WORKDIR /workspace
+VOLUME /workspaces
+WORKDIR /workspaces

+ 7 - 5
.devcontainer/devcontainer.json

@@ -1,6 +1,5 @@
 // Copyright (C) 2019 Intel Corporation.  All rights reserved.
 // Copyright (C) 2019 Intel Corporation.  All rights reserved.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
 // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
 // For format details, see https://aka.ms/vscode-remote/devcontainer.json or this file's README at:
 // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp
 // https://github.com/microsoft/vscode-dev-containers/tree/v0.195.0/containers/cpp
 {
 {
@@ -10,7 +9,12 @@
     // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
     // Update 'VARIANT' to pick an Debian / Ubuntu OS version: debian-11, debian-10, debian-9, ubuntu-21.04, ubuntu-20.04, ubuntu-18.04
     // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
     // Use Debian 11, Debian 9, Ubuntu 18.04 or Ubuntu 21.04 on local arm64/Apple Silicon
     "args": {
     "args": {
-      "VARIANT": "ubuntu-20.04"
+      "BINARYEN_VER": "111",
+      "EMSDK_VER": "3.0.0",
+      "LLVM_VER": "15",
+      "VARIANT": "ubuntu-20.04",
+      "WASI_SDK_VER": "19",
+      "WABT_VER": "1.0.31"
     }
     }
   },
   },
   "runArgs": [
   "runArgs": [
@@ -27,12 +31,10 @@
       // Add the IDs of extensions you want installed when the container is created.
       // Add the IDs of extensions you want installed when the container is created.
       "extensions": [
       "extensions": [
         "dtsvet.vscode-wasm",
         "dtsvet.vscode-wasm",
-        "esbenp.prettier-vscode",
+        "llvm-vs-code-extensions.vscode-clangd",
         "ms-python.python",
         "ms-python.python",
         "ms-python.vscode-pylance",
         "ms-python.vscode-pylance",
         "ms-vscode.cmake-tools",
         "ms-vscode.cmake-tools",
-        "ms-vscode.cpptools",
-        "twxs.cmake"
       ]
       ]
     }
     }
   },
   },

+ 1 - 1
.github/workflows/build_iwasm_release.yml

@@ -36,7 +36,7 @@ jobs:
       - name: generate iwasm binary release
       - name: generate iwasm binary release
         run: |
         run: |
           cmake -S . -B build \
           cmake -S . -B build \
-            -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 \
+            -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_CUSTOM_NAME_SECTION=0 \
             -DWAMR_BUILD_DEBUG_INTERP=0 \
             -DWAMR_BUILD_DEBUG_INTERP=0 \
             -DWAMR_BUILD_DEBUG_AOT=0 \
             -DWAMR_BUILD_DEBUG_AOT=0 \

+ 63 - 11
.github/workflows/build_llvm_libraries.yml

@@ -5,23 +5,46 @@ name: Reusable workflow-build_llvm_libraries
 on:
 on:
   workflow_call:
   workflow_call:
     inputs:
     inputs:
-      runs-on:
+      os:
         required: true
         required: true
         type: string
         type: string
+      arch:
+        required: true
+        type: string
+    outputs:
+      cache_key:
+        description: "A cached key of LLVM libraries"
+        value: ${{ jobs.build_llvm_libraries.outputs.key}}
 
 
 jobs:
 jobs:
   build_llvm_libraries:
   build_llvm_libraries:
-    runs-on: ${{ matrix.os }}
-    strategy:
-      matrix:
-        os: ${{ fromJson(inputs.runs-on) }}
+    runs-on: ${{ inputs.os }}
+    outputs:
+      key: ${{ steps.create_lib_cache_key.outputs.key}}
 
 
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
+      - name: install dependencies
+        run: /usr/bin/env python3 -m pip install -r requirements.txt
+        working-directory: build-scripts
+
+      - name: retrive the last commit ID
+        id: get_last_commit
+        run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT
+        working-directory: build-scripts
+
+      # Bump the prefix number to evict all previous caches and
+      # enforce a clean build, in the unlikely case that some
+      # weird build error occur and llvm/build becomes a potential
+      # 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 }}" >> $GITHUB_OUTPUT
+
       - name: Cache LLVM libraries
       - name: Cache LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -30,10 +53,39 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-build-llvm_libraries_ex
+          key: ${{ steps.create_lib_cache_key.outputs.key}}
+
+      - uses: actions/cache@v3
+        with:
+          path: ~/.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 == 'ubuntu-20.04'
+
+      - uses: actions/cache@v3
+        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 == 'ubuntu-22.04'
+
+      - run: sudo apt install -y ccache ninja-build
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'ubuntu')
+
+      - uses: actions/cache@v3
+        with:
+          path: ~/Library/Caches/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' && startsWith(inputs.os, 'macos')
+
+      - run: brew install ccache ninja
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true' && startsWith(inputs.os, 'macos')
 
 
-      - name: Build llvm
-        id: build_llvm
-        if: ${{ steps.cache_llvm.outputs.cache-hit != 'true' }} 
-        run: /usr/bin/env python3 ./build_llvm.py --arch X86 WebAssembly
+      - name: Build LLVM libraries
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
+        run: /usr/bin/env python3 ./build_llvm.py --arch ${{ inputs.arch }}
         working-directory: build-scripts
         working-directory: build-scripts

+ 1 - 1
.github/workflows/codeing_guildelines.yml → .github/workflows/coding_guidelines.yml

@@ -15,7 +15,7 @@ concurrency:
   cancel-in-progress: true
   cancel-in-progress: true
 
 
 jobs:
 jobs:
-  complinace_job:
+  compliance_job:
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
       - name: checkout
       - name: checkout

+ 105 - 55
.github/workflows/compilation_on_android_ubuntu.yml

@@ -53,8 +53,7 @@ env:
   FAST_JIT_BUILD_OPTIONS: "      -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_JIT_BUILD_OPTIONS: "      -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
   LLVM_LAZY_JIT_BUILD_OPTIONS: " -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=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_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
   LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_FAST_JIT=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
-  # LLVM
-  LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
+  MULTI_TIER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_FAST_JIT=1 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=1"
   # For Spec Test
   # For Spec Test
   DEFAULT_TEST_OPTIONS: "-s spec -b -P"
   DEFAULT_TEST_OPTIONS: "-s spec -b -P"
   MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
   MULTI_MODULES_TEST_OPTIONS: "-s spec -b -M -P"
@@ -64,23 +63,37 @@ env:
   WASI_TEST_OPTIONS: "-s wasi_certification"
   WASI_TEST_OPTIONS: "-s wasi_certification"
 
 
 jobs:
 jobs:
-  build_llvm_libraries:
+  build_llvm_libraries_on_ubuntu_2004:
     uses: ./.github/workflows/build_llvm_libraries.yml
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
     with:
-      runs-on: "['ubuntu-20.04', 'ubuntu-22.04']"
+      os: "ubuntu-20.04"
+      arch: "X86"
+
+  build_llvm_libraries_on_ubuntu_2204:
+    uses: ./.github/workflows/build_llvm_libraries.yml
+    with:
+      os: "ubuntu-22.04"
+      arch: "X86"
 
 
   build_wamrc:
   build_wamrc:
-    needs: [build_llvm_libraries]
+    needs:
+      [build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     strategy:
     strategy:
       matrix:
       matrix:
-        os: [ubuntu-20.04, ubuntu-22.04]
+        include:
+          - os: ubuntu-20.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
+      # since jobs.id can't contain the dot character
+      # it is hard to use `format` to assemble the cache key
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -89,10 +102,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: steps.cache_llvm.outputs.cache-hit != 'true'
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Build wamrc
       - name: Build wamrc
@@ -103,7 +116,8 @@ jobs:
         working-directory: wamr-compiler
         working-directory: wamr-compiler
 
 
   build_iwasm:
   build_iwasm:
-    needs: [build_llvm_libraries]
+    needs:
+      [build_llvm_libraries_on_ubuntu_2004, build_llvm_libraries_on_ubuntu_2204]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     strategy:
     strategy:
       matrix:
       matrix:
@@ -115,6 +129,7 @@ jobs:
             $FAST_JIT_BUILD_OPTIONS,
             $FAST_JIT_BUILD_OPTIONS,
             $LLVM_LAZY_JIT_BUILD_OPTIONS,
             $LLVM_LAZY_JIT_BUILD_OPTIONS,
             $LLVM_EAGER_JIT_BUILD_OPTIONS,
             $LLVM_EAGER_JIT_BUILD_OPTIONS,
+            $MULTI_TIER_JIT_BUILD_OPTIONS,
           ]
           ]
         make_options_feature: [
         make_options_feature: [
             # Features
             # Features
@@ -147,6 +162,8 @@ jobs:
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
             make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
+          - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
+            make_options_feature: "-DWAMR_BUILD_MULTI_MODULE=1"
           # SIMD only on JIT/AOT mode
           # SIMD only on JIT/AOT mode
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_SIMD=1"
             make_options_feature: "-DWAMR_BUILD_SIMD=1"
@@ -163,6 +180,8 @@ jobs:
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
             make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
+          - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
+            make_options_feature: "-DWAMR_BUILD_DEBUG_INTERP=1"
           # DEBUG_AOT only on JIT/AOT mode
           # DEBUG_AOT only on JIT/AOT mode
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
           - make_options_run_mode: $CLASSIC_INTERP_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
@@ -175,6 +194,8 @@ jobs:
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
             make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
+          - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
+            make_options_feature: "-DWAMR_BUILD_DEBUG_AOT=1"
           # MINI_LOADER only on INTERP mode
           # MINI_LOADER only on INTERP mode
           - make_options_run_mode: $AOT_BUILD_OPTIONS
           - make_options_run_mode: $AOT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
@@ -184,16 +205,28 @@ jobs:
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
-          # Fast-JIT mode doesn't support android(X86-32)
+          - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
+            make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
+          # Fast-JIT and Multi-Tier-JIT mode don't support android(X86-32)
           - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
           - make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
             platform: android
             platform: android
+          - make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
+            platform: android
+          # only test andorid on ubuntu latest
+          - os: ubuntu-20.04
+            platform: android
+        include:
+          - os: ubuntu-20.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       # only download llvm cache when needed
       # only download llvm cache when needed
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
         if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
@@ -203,10 +236,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true')
+        if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Build iwasm
       - name: Build iwasm
@@ -217,7 +250,13 @@ jobs:
         working-directory: product-mini/platforms/${{ matrix.platform }}
         working-directory: product-mini/platforms/${{ matrix.platform }}
 
 
   build_samples_wasm_c_api:
   build_samples_wasm_c_api:
-    needs: [build_iwasm, build_llvm_libraries, build_wamrc]
+    needs:
+      [
+        build_iwasm,
+        build_llvm_libraries_on_ubuntu_2004,
+        build_llvm_libraries_on_ubuntu_2204,
+        build_wamrc,
+      ]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     strategy:
     strategy:
       matrix:
       matrix:
@@ -229,22 +268,28 @@ jobs:
             $FAST_JIT_BUILD_OPTIONS,
             $FAST_JIT_BUILD_OPTIONS,
             $LLVM_LAZY_JIT_BUILD_OPTIONS,
             $LLVM_LAZY_JIT_BUILD_OPTIONS,
             $LLVM_EAGER_JIT_BUILD_OPTIONS,
             $LLVM_EAGER_JIT_BUILD_OPTIONS,
+            $MULTI_TIER_JIT_BUILD_OPTIONS,
           ]
           ]
         os: [ubuntu-20.04, ubuntu-22.04]
         os: [ubuntu-20.04, ubuntu-22.04]
         wasi_sdk_release:
         wasi_sdk_release:
           [
           [
-            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz",
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
           ]
           ]
         wabt_release:
         wabt_release:
           [
           [
-            "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
           ]
           ]
+        include:
+          - os: ubuntu-20.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}
+          - os: ubuntu-22.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries_on_ubuntu_2204.outputs.cache_key }}
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
         if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
@@ -254,18 +299,18 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.cache_llvm.outputs.cache-hit != 'true')
+        if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS')) && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: download and install wabt
       - name: download and install wabt
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: Build wamrc
       - name: Build wamrc
         if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
         if: (!endsWith(matrix.make_options, '_INTERP_BUILD_OPTIONS'))
@@ -277,19 +322,9 @@ jobs:
 
 
       - name: Build Sample [wasm-c-api]
       - name: Build Sample [wasm-c-api]
         run: |
         run: |
-          mkdir build && cd build
-          cmake .. ${{ matrix.make_options }}
-          cmake --build . --config Release --parallel 4
-          ./callback
-          ./callback_chain
-          ./empty_imports
-          ./global
-          ./hello
-          ./hostref
-          ./memory
-          ./reflect
-          ./table
-          ./trap
+          cmake -S . -B build ${{ matrix.make_options }}
+          cmake --build build --config Release --parallel 4
+          ctest --test-dir build
         working-directory: samples/wasm-c-api
         working-directory: samples/wasm-c-api
 
 
   build_samples_others:
   build_samples_others:
@@ -298,14 +333,13 @@ jobs:
     strategy:
     strategy:
       matrix:
       matrix:
         os: [ubuntu-20.04, ubuntu-22.04]
         os: [ubuntu-20.04, ubuntu-22.04]
-        wasi_sdk_release:
-          [
-            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz",
-          ]
-        wabt_release:
-          [
-            "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
-          ]
+        include:
+          - os: ubuntu-20.04
+            wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz"
+            wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
+          - os: ubuntu-22.04
+            wasi_sdk_release: "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz"
+            wabt_release: "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz"
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
@@ -314,15 +348,15 @@ jobs:
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wasi_sdk_release }}
           sudo wget ${{ matrix.wasi_sdk_release }}
-          sudo tar -xzf wasi-sdk-16.0-*.tar.gz
-          sudo mv wasi-sdk-16.0 wasi-sdk
+          sudo tar -xzf wasi-sdk-*.tar.gz
+          sudo mv wasi-sdk-19.0 wasi-sdk
 
 
       - name: download and install wabt
       - name: download and install wabt
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: build wasi-libc (needed for wasi-threads)
       - name: build wasi-libc (needed for wasi-threads)
         run: |
         run: |
@@ -402,12 +436,19 @@ jobs:
           ./iwasm wasm-apps/no_pthread.wasm
           ./iwasm wasm-apps/no_pthread.wasm
 
 
   test:
   test:
-    needs: [build_iwasm, build_llvm_libraries, build_wamrc]
+    needs: [build_iwasm, build_llvm_libraries_on_ubuntu_2004, build_wamrc]
     runs-on: ubuntu-20.04
     runs-on: ubuntu-20.04
     strategy:
     strategy:
       matrix:
       matrix:
         running_mode:
         running_mode:
-          ["classic-interp", "fast-interp", "jit", "aot", "fast-jit"]
+          [
+            "classic-interp",
+            "fast-interp",
+            "jit",
+            "aot",
+            "fast-jit",
+            "multi-tier-jit",
+          ]
         test_option:
         test_option:
           [
           [
             $DEFAULT_TEST_OPTIONS,
             $DEFAULT_TEST_OPTIONS,
@@ -416,6 +457,8 @@ jobs:
             $THREADS_TEST_OPTIONS,
             $THREADS_TEST_OPTIONS,
             $WASI_TEST_OPTIONS,
             $WASI_TEST_OPTIONS,
           ]
           ]
+        llvm_cache_key:
+          ["${{ needs.build_llvm_libraries_on_ubuntu_2004.outputs.cache_key }}"]
         exclude:
         exclude:
           # uncompatiable modes and features
           # uncompatiable modes and features
           # classic-interp and fast-interp don't support simd
           # classic-interp and fast-interp don't support simd
@@ -431,32 +474,39 @@ jobs:
             test_option: $WASI_TEST_OPTIONS
             test_option: $WASI_TEST_OPTIONS
           - running_mode: "jit"
           - running_mode: "jit"
             test_option: $MULTI_MODULES_TEST_OPTIONS
             test_option: $MULTI_MODULES_TEST_OPTIONS
-          # fast-jit is only tested on default mode, exclude other three
+          # fast-jit doesn't support multi module, simd, and threads
           - running_mode: "fast-jit"
           - running_mode: "fast-jit"
             test_option: $MULTI_MODULES_TEST_OPTIONS
             test_option: $MULTI_MODULES_TEST_OPTIONS
           - running_mode: "fast-jit"
           - running_mode: "fast-jit"
             test_option: $SIMD_TEST_OPTIONS
             test_option: $SIMD_TEST_OPTIONS
           - running_mode: "fast-jit"
           - running_mode: "fast-jit"
             test_option: $THREADS_TEST_OPTIONS
             test_option: $THREADS_TEST_OPTIONS
+          # multi-tier-jit doesn't support multi module, simd, and threads
+          - running_mode: "multi-tier-jit"
+            test_option: $MULTI_MODULES_TEST_OPTIONS
+          - running_mode: "multi-tier-jit"
+            test_option: $SIMD_TEST_OPTIONS
+          - running_mode: "multi-tier-jit"
+            test_option: $THREADS_TEST_OPTIONS
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       - name: set env variable(if llvm are used)
       - name: set env variable(if llvm are used)
-        if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit'
+        if: matrix.running_mode == 'aot' || matrix.running_mode == 'jit' || matrix.running_mode == 'multi-tier-jit'
         run: echo "USE_LLVM=true" >> $GITHUB_ENV
         run: echo "USE_LLVM=true" >> $GITHUB_ENV
 
 
       - name: set env variable(if x86_32 test needed)
       - name: set env variable(if x86_32 test needed)
         if: >
         if: >
           (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
           (matrix.test_option == '$DEFAULT_TEST_OPTIONS' || matrix.test_option == '$THREADS_TEST_OPTIONS'
            || matrix.test_option == '$WASI_TEST_OPTIONS')
            || matrix.test_option == '$WASI_TEST_OPTIONS')
-          && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit'
+          && matrix.running_mode != 'fast-jit' && matrix.running_mode != 'jit' && matrix.running_mode != 'multi-tier-jit'
         run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
         run: echo "TEST_ON_X86_32=true" >> $GITHUB_ENV
 
 
       #only download llvm libraries in jit and aot mode
       #only download llvm libraries in jit and aot mode
       - name: Get LLVM libraries
       - name: Get LLVM libraries
         if: env.USE_LLVM == 'true'
         if: env.USE_LLVM == 'true'
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -465,10 +515,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: env.USE_LLVM == 'true' && steps.cache_llvm.outputs.cache-hit != 'true'
+        if: env.USE_LLVM == 'true' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: run tests
       - name: run tests

+ 39 - 32
.github/workflows/compilation_on_macos.yml

@@ -51,26 +51,28 @@ env:
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   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_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"
   LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
-  LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
 
 
 jobs:
 jobs:
   build_llvm_libraries:
   build_llvm_libraries:
     uses: ./.github/workflows/build_llvm_libraries.yml
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
     with:
-      runs-on: "['macos-latest']"
+      os: "macos-latest"
+      arch: "X86"
 
 
   build_wamrc:
   build_wamrc:
     needs: [build_llvm_libraries]
     needs: [build_llvm_libraries]
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     strategy:
     strategy:
       matrix:
       matrix:
-        os: [macos-latest]
+        include:
+          - os: macos-latest
+            llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -79,10 +81,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: steps.cache_llvm.outputs.cache-hit != 'true'
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Build wamrc
       - name: Build wamrc
@@ -166,13 +168,16 @@ jobs:
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
           - make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
             make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
+        include:
+          - os: macos-latest
+            llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       # only download llvm cache when needed
       # only download llvm cache when needed
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
         if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS')
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
@@ -182,10 +187,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.cache_llvm.outputs.cache-hit != 'true')
+        if: endsWith(matrix.make_options_run_mode, '_JIT_BUILD_OPTIONS') && (steps.retrieve_llvm_libs.outputs.cache-hit != 'true')
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Build iwasm
       - name: Build iwasm
@@ -210,8 +215,14 @@ jobs:
             #$AOT_BUILD_OPTIONS,
             #$AOT_BUILD_OPTIONS,
           ]
           ]
         os: [macos-latest]
         os: [macos-latest]
-        wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"]
-        wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
+        wasi_sdk_release:
+          [
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz",
+          ]
+        wabt_release:
+          [
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz",
+          ]
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
@@ -220,24 +231,14 @@ jobs:
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: Build Sample [wasm-c-api]
       - name: Build Sample [wasm-c-api]
         run: |
         run: |
-          mkdir build && cd build
-          cmake .. ${{ matrix.make_options }}
-          cmake --build . --config Release --parallel 4
-          ./callback
-          ./callback_chain
-          ./empty_imports
-          ./global
-          ./hello
-          ./hostref
-          ./memory
-          ./reflect
-          ./table
-          ./trap
+          cmake -S . -B build ${{ matrix.make_options }}
+          cmake --build build --config Release --parallel 4
+          ctest --test-dir build
         working-directory: samples/wasm-c-api
         working-directory: samples/wasm-c-api
 
 
   build_samples_others:
   build_samples_others:
@@ -246,8 +247,14 @@ jobs:
     strategy:
     strategy:
       matrix:
       matrix:
         os: [macos-latest]
         os: [macos-latest]
-        wasi_sdk_release: ["https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-macos.tar.gz"]
-        wabt_release: ["https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-macos.tar.gz"]
+        wasi_sdk_release:
+          [
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz",
+          ]
+        wabt_release:
+          [
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-macos-12.tar.gz",
+          ]
     steps:
     steps:
       - name: checkout
       - name: checkout
         uses: actions/checkout@v3
         uses: actions/checkout@v3
@@ -256,15 +263,15 @@ jobs:
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wasi_sdk_release }}
           sudo wget ${{ matrix.wasi_sdk_release }}
-          sudo tar -xzf wasi-sdk-16.0-*.tar.gz
-          sudo mv wasi-sdk-16.0 wasi-sdk
+          sudo tar -xzf wasi-sdk-*.tar.gz
+          sudo mv wasi-sdk-19.0 wasi-sdk
 
 
       - name: download and install wabt
       - name: download and install wabt
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: build wasi-libc (needed for wasi-threads)
       - name: build wasi-libc (needed for wasi-threads)
         run: |
         run: |

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

@@ -65,9 +65,12 @@ jobs:
           "boards/risc-v/k210/maix-bit/configs/nsh",
           "boards/risc-v/k210/maix-bit/configs/nsh",
         ]
         ]
         wamr_config_option: [
         wamr_config_option: [
-          "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
+          "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n",
+          "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\n",
+          "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_WASI=y\\n",
+          "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_CLASSIC=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\nCONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_AOT=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
           "CONFIG_INTERPRETERS_WAMR=y\\nCONFIG_INTERPRETERS_WAMR_FAST=y\\n",
@@ -112,7 +115,7 @@ jobs:
 
 
       - name: Enable WAMR for NuttX
       - name: Enable WAMR for NuttX
         run: |
         run: |
-          find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\n${{ matrix.wamr_config_option }}'
+          find nuttx/boards -name defconfig | xargs sed -i '$a\CONFIG_EOL_IS_LF=y\nCONFIG_PSEUDOFS_SOFTLINKS=y\n${{ matrix.wamr_config_option }}'
           find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n'
           find nuttx/boards/sim -name defconfig | xargs sed -i '$a\CONFIG_LIBM=y\n'
 
 
       - name: Build
       - name: Build

+ 25 - 32
.github/workflows/compilation_on_sgx.yml

@@ -51,13 +51,13 @@ env:
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   FAST_INTERP_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=0 -DWAMR_BUILD_FAST_INTERP=1 -DWAMR_BUILD_INTERP=1 -DWAMR_BUILD_JIT=0 -DWAMR_BUILD_LAZY_JIT=0"
   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_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"
   LLVM_EAGER_JIT_BUILD_OPTIONS: "-DWAMR_BUILD_AOT=1 -DWAMR_BUILD_FAST_INTERP=0 -DWAMR_BUILD_INTERP=0 -DWAMR_BUILD_JIT=1 -DWAMR_BUILD_LAZY_JIT=0"
-  LLVM_CACHE_SUFFIX: "build-llvm_libraries_ex"
 
 
 jobs:
 jobs:
   build_llvm_libraries:
   build_llvm_libraries:
     uses: ./.github/workflows/build_llvm_libraries.yml
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
     with:
-      runs-on: "['ubuntu-20.04']"
+      os: "ubuntu-20.04"
+      arch: "X86"
 
 
   build_iwasm:
   build_iwasm:
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
@@ -131,7 +131,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
     strategy:
     strategy:
       matrix:
       matrix:
-        os: [ubuntu-20.04]
+        include:
+          - os: ubuntu-20.04
+            llvm_cache_key: ${{ needs.build_llvm_libraries.outputs.cache_key }}
     steps:
     steps:
       - name: install SGX SDK and necessary libraries
       - name: install SGX SDK and necessary libraries
         run: |
         run: |
@@ -150,7 +152,7 @@ jobs:
         uses: actions/checkout@v3
         uses: actions/checkout@v3
 
 
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -159,10 +161,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: steps.cache_llvm.outputs.cache-hit != 'true'
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Build wamrc
       - name: Build wamrc
@@ -189,11 +191,11 @@ jobs:
         os: [ubuntu-20.04]
         os: [ubuntu-20.04]
         wasi_sdk_release:
         wasi_sdk_release:
           [
           [
-            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz",
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
           ]
           ]
         wabt_release:
         wabt_release:
           [
           [
-            "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
           ]
           ]
     steps:
     steps:
       - name: checkout
       - name: checkout
@@ -203,8 +205,8 @@ jobs:
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: install SGX SDK and necessary libraries
       - name: install SGX SDK and necessary libraries
         run: |
         run: |
@@ -221,19 +223,9 @@ jobs:
 
 
       - name: Build Sample [wasm-c-api]
       - name: Build Sample [wasm-c-api]
         run: |
         run: |
-          mkdir build && cd build
-          cmake .. ${{ matrix.make_options }}
-          cmake --build . --config Release --parallel 4
-          ./callback
-          ./callback_chain
-          ./empty_imports
-          ./global
-          ./hello
-          ./hostref
-          ./memory
-          ./reflect
-          ./table
-          ./trap
+          cmake -S . -B build ${{ matrix.make_options }}
+          cmake --build build --config Release --parallel 4
+          ctest --test-dir build
         working-directory: samples/wasm-c-api
         working-directory: samples/wasm-c-api
 
 
   build_samples_others:
   build_samples_others:
@@ -244,11 +236,11 @@ jobs:
         os: [ubuntu-20.04]
         os: [ubuntu-20.04]
         wasi_sdk_release:
         wasi_sdk_release:
           [
           [
-            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-16/wasi-sdk-16.0-linux.tar.gz",
+            "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz",
           ]
           ]
         wabt_release:
         wabt_release:
           [
           [
-            "https://github.com/WebAssembly/wabt/releases/download/1.0.24/wabt-1.0.24-ubuntu.tar.gz",
+            "https://github.com/WebAssembly/wabt/releases/download/1.0.31/wabt-1.0.31-ubuntu.tar.gz",
           ]
           ]
     steps:
     steps:
       - name: checkout
       - name: checkout
@@ -258,15 +250,15 @@ jobs:
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wasi_sdk_release }}
           sudo wget ${{ matrix.wasi_sdk_release }}
-          sudo tar -xzf wasi-sdk-16.0-*.tar.gz
-          sudo mv wasi-sdk-16.0 wasi-sdk
+          sudo tar -xzf wasi-sdk-*.tar.gz
+          sudo mv wasi-sdk-19.0 wasi-sdk
 
 
       - name: download and install wabt
       - name: download and install wabt
         run: |
         run: |
           cd /opt
           cd /opt
           sudo wget ${{ matrix.wabt_release }}
           sudo wget ${{ matrix.wabt_release }}
-          sudo tar -xzf wabt-1.0.24-*.tar.gz
-          sudo mv wabt-1.0.24 wabt
+          sudo tar -xzf wabt-1.0.31-*.tar.gz
+          sudo mv wabt-1.0.31 wabt
 
 
       - name: build wasi-libc (needed for wasi-threads)
       - name: build wasi-libc (needed for wasi-threads)
         run: |
         run: |
@@ -358,6 +350,7 @@ jobs:
       matrix:
       matrix:
         running_mode: ["classic-interp", "fast-interp", "aot"]
         running_mode: ["classic-interp", "fast-interp", "aot"]
         test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"]
         test_option: ["-x -p -s spec -b -P", "-x -p -s spec -S -b -P"]
+        llvm_cache_key: ["${{ needs.build_llvm_libraries.outputs.cache_key }}"]
         # classic-interp and fast-interp don't support simd
         # classic-interp and fast-interp don't support simd
         exclude:
         exclude:
           - running_mode: "classic-interp"
           - running_mode: "classic-interp"
@@ -371,7 +364,7 @@ jobs:
 
 
       - name: Get LLVM libraries
       - name: Get LLVM libraries
         if: matrix.running_mode == 'aot'
         if: matrix.running_mode == 'aot'
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -380,10 +373,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key: ubuntu-20.04-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: matrix.running_mode == 'aot' && steps.cache_llvm.outputs.cache-hit != 'true'
+        if: matrix.running_mode == 'aot' && steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: install SGX SDK and necessary libraries
       - name: install SGX SDK and necessary libraries

+ 3 - 3
.github/workflows/release_process.yml

@@ -123,7 +123,7 @@ jobs:
       runner: ubuntu-20.04
       runner: ubuntu-20.04
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
-      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
+      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
 
 
   release_wamr_sdk_on_ubuntu_2204:
   release_wamr_sdk_on_ubuntu_2204:
     needs: [create_tag, create_release]
     needs: [create_tag, create_release]
@@ -133,7 +133,7 @@ jobs:
       runner: ubuntu-22.04
       runner: ubuntu-22.04
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
-      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-linux.tar.gz
+      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-linux.tar.gz
 
 
   release_wamr_sdk_on_macos:
   release_wamr_sdk_on_macos:
     needs: [create_tag, create_release]
     needs: [create_tag, create_release]
@@ -143,7 +143,7 @@ jobs:
       runner: macos-latest
       runner: macos-latest
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       upload_url: ${{ needs.create_release.outputs.upload_url }}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
       ver_num: ${{ needs.create_tag.outputs.new_ver}}
-      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-12/wasi-sdk-12.0-macos.tar.gz
+      wasi_sdk_url: https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-19/wasi-sdk-19.0-macos.tar.gz
 
 
   #
   #
   # vscode extension cross-platform
   # vscode extension cross-platform

+ 6 - 4
.github/workflows/spec_test_on_nuttx.yml

@@ -16,7 +16,8 @@ jobs:
   build_llvm_libraries:
   build_llvm_libraries:
     uses: ./.github/workflows/build_llvm_libraries.yml
     uses: ./.github/workflows/build_llvm_libraries.yml
     with:
     with:
-      runs-on: "['ubuntu-22.04']"
+      os: "ubuntu-22.04"
+      arch: "ARM RISCV AArch64"
 
 
   spec_test_on_qemu:
   spec_test_on_qemu:
     runs-on: ${{ matrix.os }}
     runs-on: ${{ matrix.os }}
@@ -37,6 +38,7 @@ jobs:
           "-t aot",
           "-t aot",
           "-t aot -X"
           "-t aot -X"
         ]
         ]
+        llvm_cache_key: [ "${{ needs.build_llvm_libraries.outputs.cache_key }}" ]
     steps:
     steps:
       - name: Install Utilities
       - name: Install Utilities
         run: |
         run: |
@@ -72,7 +74,7 @@ jobs:
           path: apps/interpreters/wamr/wamr
           path: apps/interpreters/wamr/wamr
 
 
       - name: Get LLVM libraries
       - name: Get LLVM libraries
-        id: cache_llvm
+        id: retrieve_llvm_libs
         uses: actions/cache@v3
         uses: actions/cache@v3
         with:
         with:
           path: |
           path: |
@@ -81,10 +83,10 @@ jobs:
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/lib
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/libexec
             ./core/deps/llvm/build/share
             ./core/deps/llvm/build/share
-          key:  ${{ matrix.os }}-${{ env.LLVM_CACHE_SUFFIX }}
+          key: ${{ matrix.llvm_cache_key }}
 
 
       - name: Quit if cache miss
       - name: Quit if cache miss
-        if: steps.cache_llvm.outputs.cache-hit != 'true'
+        if: steps.retrieve_llvm_libs.outputs.cache-hit != 'true'
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
         run: echo "::error::can not get prebuilt llvm libraries" && exit 1
 
 
       - name: Copy LLVM
       - name: Copy LLVM

+ 3 - 0
.gitignore

@@ -32,3 +32,6 @@ samples/socket-api/wasm-src/inc/pthread.h
 **/__pycache__
 **/__pycache__
 
 
 tests/benchmarks/coremark/coremark*
 tests/benchmarks/coremark/coremark*
+
+samples/workload/include/**
+!samples/workload/include/.gitkeep

+ 73 - 30
build-scripts/build_llvm.py

@@ -7,6 +7,7 @@
 import argparse
 import argparse
 import os
 import os
 import pathlib
 import pathlib
+import requests
 import shlex
 import shlex
 import shutil
 import shutil
 import subprocess
 import subprocess
@@ -21,28 +22,43 @@ def clone_llvm(dst_dir, llvm_repo, llvm_branch):
     llvm_dir = dst_dir.joinpath("llvm").resolve()
     llvm_dir = dst_dir.joinpath("llvm").resolve()
 
 
     if not llvm_dir.exists():
     if not llvm_dir.exists():
-        print(f"Clone llvm to {llvm_dir} ...")
         GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm"
         GIT_CLONE_CMD = f"git clone --depth 1 --branch {llvm_branch} {llvm_repo} llvm"
         subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir)
         subprocess.check_output(shlex.split(GIT_CLONE_CMD), cwd=dst_dir)
-    else:
-        print(f"There is an LLVM local repo in {llvm_dir}, clean and keep using it")
 
 
     return llvm_dir
     return llvm_dir
 
 
 
 
-def build_llvm(llvm_dir, platform, backends, projects):
+def query_llvm_version(llvm_info):
+    github_token = os.environ['GH_TOKEN']
+    owner_project = llvm_info['repo'].replace("https://github.com/", "").replace(".git", "")
+    url = f"https://api.github.com/repos/{owner_project}/commits/{llvm_info['branch']}"
+    headers = {
+        'Authorization': f"Bearer {github_token}"
+    }
+
+    try:
+        response = requests.request("GET", url, headers=headers, data={})
+        response.raise_for_status()
+    except requests.exceptions.HTTPError as error:
+        print (error) # for debugging purpose
+        return None
+
+    response = response.json()
+    return response['sha']
+
+
+def build_llvm(llvm_dir, platform, backends, projects, use_clang=False):
     LLVM_COMPILE_OPTIONS = [
     LLVM_COMPILE_OPTIONS = [
         '-DCMAKE_BUILD_TYPE:STRING="Release"',
         '-DCMAKE_BUILD_TYPE:STRING="Release"',
         "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
         "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON",
         "-DLLVM_APPEND_VC_REV:BOOL=ON",
         "-DLLVM_APPEND_VC_REV:BOOL=ON",
-        "-DLLVM_BUILD_BENCHMARKS:BOOL=OFF",
-        "-DLLVM_BUILD_DOCS:BOOL=OFF",
         "-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
         "-DLLVM_BUILD_EXAMPLES:BOOL=OFF",
         "-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
         "-DLLVM_BUILD_LLVM_DYLIB:BOOL=OFF",
         "-DLLVM_BUILD_TESTS:BOOL=OFF",
         "-DLLVM_BUILD_TESTS:BOOL=OFF",
-        "-DLLVM_CCACHE_BUILD:BOOL=OFF",
+        "-DLLVM_CCACHE_BUILD:BOOL=ON",
         "-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
         "-DLLVM_ENABLE_BINDINGS:BOOL=OFF",
         "-DLLVM_ENABLE_IDE:BOOL=OFF",
         "-DLLVM_ENABLE_IDE:BOOL=OFF",
+        "-DLLVM_ENABLE_LIBEDIT=OFF",
         "-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
         "-DLLVM_ENABLE_TERMINFO:BOOL=OFF",
         "-DLLVM_ENABLE_ZLIB:BOOL=OFF",
         "-DLLVM_ENABLE_ZLIB:BOOL=OFF",
         "-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
         "-DLLVM_INCLUDE_BENCHMARKS:BOOL=OFF",
@@ -54,6 +70,18 @@ def build_llvm(llvm_dir, platform, backends, projects):
         "-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON",
         "-DLLVM_OPTIMIZED_TABLEGEN:BOOL=ON",
     ]
     ]
 
 
+    # use clang/clang++/lld. but macos doesn't support lld
+    if not sys.platform.startswith("darwin") and use_clang:
+        if shutil.which("clang") and shutil.which("clang++") and shutil.which("lld"):
+            os.environ["CC"] = "clang"
+            os.environ["CXX"] = "clang++"
+            LLVM_COMPILE_OPTIONS.append('-DLLVM_USE_LINKER:STRING="lld"')
+            print("Use the clang toolchain")
+        else:
+            print("Can not find clang, clang++ and lld, keep using the gcc toolchain")
+    else:
+        print("Use the gcc toolchain")
+
     LLVM_EXTRA_COMPILE_OPTIONS = {
     LLVM_EXTRA_COMPILE_OPTIONS = {
         "arc": [
         "arc": [
             '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"',
             '-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD:STRING="ARC"',
@@ -99,8 +127,10 @@ def build_llvm(llvm_dir, platform, backends, projects):
 
 
     lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve()
     lib_llvm_core_library = build_dir.joinpath("lib/libLLVMCore.a").resolve()
     if lib_llvm_core_library.exists():
     if lib_llvm_core_library.exists():
-        print(f"Please remove {build_dir} manually and try again")
-        return build_dir
+        print(
+            f"It has already been fully compiled. If want to a re-build, please remove {build_dir} manually and try again"
+        )
+        return None
 
 
     compile_options = " ".join(
     compile_options = " ".join(
         LLVM_COMPILE_OPTIONS
         LLVM_COMPILE_OPTIONS
@@ -119,10 +149,11 @@ def build_llvm(llvm_dir, platform, backends, projects):
             CONFIG_CMD += " -G'Unix Makefiles'"
             CONFIG_CMD += " -G'Unix Makefiles'"
         else:
         else:
             CONFIG_CMD += " -A x64"
             CONFIG_CMD += " -A x64"
-    print(f"{CONFIG_CMD}")
+    else:
+        CONFIG_CMD += " -G'Ninja'"
     subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir)
     subprocess.check_call(shlex.split(CONFIG_CMD), cwd=build_dir)
 
 
-    BUILD_CMD = f"cmake --build . --target package --parallel {os.cpu_count()}" + (
+    BUILD_CMD = "cmake --build . --target package" + (
         " --config Release" if "windows" == platform else ""
         " --config Release" if "windows" == platform else ""
     )
     )
     subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir)
     subprocess.check_call(shlex.split(BUILD_CMD), cwd=build_dir)
@@ -133,23 +164,25 @@ def build_llvm(llvm_dir, platform, backends, projects):
 def repackage_llvm(llvm_dir):
 def repackage_llvm(llvm_dir):
     build_dir = llvm_dir.joinpath("./build").resolve()
     build_dir = llvm_dir.joinpath("./build").resolve()
 
 
-    packs = [f for f in build_dir.glob("LLVM-13*.tar.gz")]
+    packs = [f for f in build_dir.glob("LLVM-*.tar.gz")]
     if len(packs) > 1:
     if len(packs) > 1:
-        raise Exception("Find more than one LLVM-13*.tar.gz")
+        raise Exception("Find more than one LLVM-*.tar.gz")
 
 
     if not packs:
     if not packs:
         return
         return
 
 
     llvm_package = packs[0].name
     llvm_package = packs[0].name
-    # mv build/LLVM-13.0.0*.gz .
+    # mv build/LLVM-*.gz .
     shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir))
     shutil.move(str(build_dir.joinpath(llvm_package).resolve()), str(llvm_dir))
     # rm -r build
     # rm -r build
     shutil.rmtree(str(build_dir))
     shutil.rmtree(str(build_dir))
     # mkdir build
     # mkdir build
     build_dir.mkdir()
     build_dir.mkdir()
-    # tar xf ./LLVM-13.0.0-*.tar.gz --strip-components=1 --directory=build
+    # tar xf ./LLVM-*.tar.gz --strip-components=1 --directory=build
     CMD = f"tar xf {llvm_dir.joinpath(llvm_package).resolve()} --strip-components=1 --directory={build_dir}"
     CMD = f"tar xf {llvm_dir.joinpath(llvm_package).resolve()} --strip-components=1 --directory={build_dir}"
     subprocess.check_call(shlex.split(CMD), cwd=llvm_dir)
     subprocess.check_call(shlex.split(CMD), cwd=llvm_dir)
+    # rm ./LLVM-1*.gz
+    os.remove(llvm_dir.joinpath(llvm_package).resolve())
 
 
 
 
 def main():
 def main():
@@ -184,8 +217,17 @@ def main():
         choices=["clang", "lldb"],
         choices=["clang", "lldb"],
         help="identify extra LLVM projects, separate by space, like '--project clang lldb'",
         help="identify extra LLVM projects, separate by space, like '--project clang lldb'",
     )
     )
+    parser.add_argument(
+        "--llvm-ver",
+        action="store_true",
+        help="return the version info of generated llvm libraries",
+    )
+    parser.add_argument(
+        "--use-clang",
+        action="store_true",
+        help="use clang instead of gcc",
+    )
     options = parser.parse_args()
     options = parser.parse_args()
-    print(f"options={options}")
 
 
     # if the "platform" is not identified in the command line option,
     # if the "platform" is not identified in the command line option,
     # detect it
     # detect it
@@ -199,12 +241,10 @@ def main():
     else:
     else:
         platform = options.platform
         platform = options.platform
 
 
-    print(f"========== Build LLVM for {platform} ==========\n")
-
     llvm_repo_and_branch = {
     llvm_repo_and_branch = {
         "arc": {
         "arc": {
             "repo": "https://github.com/llvm/llvm-project.git",
             "repo": "https://github.com/llvm/llvm-project.git",
-            "branch": "release/13.x",
+            "branch": "release/15.x",
         },
         },
         "xtensa": {
         "xtensa": {
             "repo": "https://github.com/espressif/llvm-project.git",
             "repo": "https://github.com/espressif/llvm-project.git",
@@ -212,7 +252,7 @@ def main():
         },
         },
         "default": {
         "default": {
             "repo": "https://github.com/llvm/llvm-project.git",
             "repo": "https://github.com/llvm/llvm-project.git",
-            "branch": "release/13.x",
+            "branch": "release/15.x",
         },
         },
     }
     }
 
 
@@ -225,19 +265,22 @@ def main():
     deps_dir = current_dir.joinpath("../core/deps").resolve()
     deps_dir = current_dir.joinpath("../core/deps").resolve()
 
 
     try:
     try:
-        print(f"==================== CLONE LLVM ====================")
         llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"])
         llvm_info = llvm_repo_and_branch.get(platform, llvm_repo_and_branch["default"])
-        llvm_dir = clone_llvm(deps_dir, llvm_info["repo"], llvm_info["branch"])
 
 
-        print()
-        print(f"==================== BUILD LLVM ====================")
-        build_llvm(llvm_dir, platform, options.arch, options.project)
-
-        print()
-        print(f"==================== PACKAGE LLVM ====================")
-        repackage_llvm(llvm_dir)
+        if options.llvm_ver:
+            commit_hash = query_llvm_version(llvm_info)
+            print(commit_hash)
+            return commit_hash is not None
+        
+        llvm_dir = clone_llvm(deps_dir, llvm_info["repo"], llvm_info["branch"])
+        if (
+            build_llvm(
+                llvm_dir, platform, options.arch, options.project, options.use_clang
+            )
+            is not None
+        ):
+            repackage_llvm(llvm_dir)
 
 
-        print()
         return True
         return True
     except subprocess.CalledProcessError:
     except subprocess.CalledProcessError:
         return False
         return False

+ 1 - 0
build-scripts/requirements.txt

@@ -0,0 +1 @@
+requests==2.28.2

+ 13 - 4
build-scripts/runtime_lib.cmake

@@ -19,6 +19,11 @@ endif ()
 if (NOT DEFINED DEPS_DIR)
 if (NOT DEFINED DEPS_DIR)
     set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
     set (DEPS_DIR ${WAMR_ROOT_DIR}/core/deps)
 endif ()
 endif ()
+if (NOT DEFINED SHARED_PLATFORM_CONFIG)
+    # CMake file for platform configuration. The PLATFORM_SHARED_SOURCE varable
+    # should point to a list of platform-specfic source files to compile.
+    set (SHARED_PLATFORM_CONFIG ${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake)
+endif ()
 
 
 if (DEFINED EXTRA_SDK_INCLUDE_PATH)
 if (DEFINED EXTRA_SDK_INCLUDE_PATH)
     message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ")
     message(STATUS, "EXTRA_SDK_INCLUDE_PATH = ${EXTRA_SDK_INCLUDE_PATH} ")
@@ -96,9 +101,13 @@ if (WAMR_BUILD_LIB_PTHREAD_SEMAPHORE EQUAL 1)
 endif ()
 endif ()
 
 
 if (WAMR_BUILD_WASI_NN EQUAL 1)
 if (WAMR_BUILD_WASI_NN EQUAL 1)
-    execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
-                    RESULT_VARIABLE TENSORFLOW_RESULT
-    )
+    if (NOT EXISTS "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
+        execute_process(COMMAND ${WAMR_ROOT_DIR}/core/deps/install_tensorflow.sh
+                        RESULT_VARIABLE TENSORFLOW_RESULT
+        )
+    else ()
+        message("Tensorflow is already downloaded.")
+    endif()
     set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
     set(TENSORFLOW_SOURCE_DIR "${WAMR_ROOT_DIR}/core/deps/tensorflow-src")
     include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
     include_directories (${CMAKE_CURRENT_BINARY_DIR}/flatbuffers/include)
     include_directories (${TENSORFLOW_SOURCE_DIR})
     include_directories (${TENSORFLOW_SOURCE_DIR})
@@ -169,7 +178,7 @@ LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
 
 
 enable_language (ASM)
 enable_language (ASM)
 
 
-include (${SHARED_DIR}/platform/${WAMR_BUILD_PLATFORM}/shared_platform.cmake)
+include (${SHARED_PLATFORM_CONFIG})
 include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
 include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
 include (${IWASM_DIR}/common/iwasm_common.cmake)
 include (${IWASM_DIR}/common/iwasm_common.cmake)
 include (${SHARED_DIR}/utils/shared_utils.cmake)
 include (${SHARED_DIR}/utils/shared_utils.cmake)

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

@@ -30,6 +30,8 @@ bh_static_assert(offsetof(WASMExecEnv, aux_stack_boundary)
 bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
 bh_static_assert(offsetof(WASMExecEnv, aux_stack_bottom)
                  == 7 * sizeof(uintptr_t));
                  == 7 * sizeof(uintptr_t));
 bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t));
 bh_static_assert(offsetof(WASMExecEnv, native_symbol) == 8 * sizeof(uintptr_t));
+bh_static_assert(offsetof(WASMExecEnv, native_stack_top_min)
+                 == 9 * sizeof(uintptr_t));
 
 
 bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64));
 bh_static_assert(offsetof(AOTModuleInstance, memories) == 1 * sizeof(uint64));
 bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64));
 bh_static_assert(offsetof(AOTModuleInstance, func_ptrs) == 5 * sizeof(uint64));
@@ -1083,6 +1085,17 @@ aot_instantiate(AOTModule *module, bool is_sub_inst, uint32 stack_size,
     }
     }
 #endif
 #endif
 
 
+#if WASM_ENABLE_WASI_NN != 0
+    if (!is_sub_inst) {
+        if (!(((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx =
+                  wasi_nn_initialize())) {
+            set_error_buf(error_buf, error_buf_size,
+                          "wasi nn initialization failed");
+            goto fail;
+        }
+    }
+#endif
+
     /* Initialize the thread related data */
     /* Initialize the thread related data */
     if (stack_size == 0)
     if (stack_size == 0)
         stack_size = DEFAULT_WASM_STACK_SIZE;
         stack_size = DEFAULT_WASM_STACK_SIZE;
@@ -1194,6 +1207,15 @@ aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst)
         wasm_runtime_free(
         wasm_runtime_free(
             ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
             ((AOTModuleInstanceExtra *)module_inst->e)->c_api_func_imports);
 
 
+#if WASM_ENABLE_WASI_NN != 0
+    if (!is_sub_inst) {
+        WASINNContext *wasi_nn_ctx =
+            ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+        if (wasi_nn_ctx)
+            wasi_nn_destroy(wasi_nn_ctx);
+    }
+#endif
+
     wasm_runtime_free(module_inst);
     wasm_runtime_free(module_inst);
 }
 }
 
 
@@ -1237,6 +1259,7 @@ invoke_native_with_hw_bound_check(WASMExecEnv *exec_env, void *func_ptr,
     /* Check native stack overflow firstly to ensure we have enough
     /* Check native stack overflow firstly to ensure we have enough
        native stack to run the following codes before actually calling
        native stack to run the following codes before actually calling
        the aot function in invokeNative function. */
        the aot function in invokeNative function. */
+    RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
     if ((uint8 *)&module_inst < exec_env->native_stack_boundary
     if ((uint8 *)&module_inst < exec_env->native_stack_boundary
                                     + page_size * (guard_page_count + 1)) {
                                     + page_size * (guard_page_count + 1)) {
         aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
         aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
@@ -1836,6 +1859,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
        exec_env->native_stack_boundary must have been set, we don't set
        exec_env->native_stack_boundary must have been set, we don't set
        it again */
        it again */
 
 
+    RECORD_STACK_USAGE(exec_env, (uint8 *)&module_inst);
     if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
     if ((uint8 *)&module_inst < exec_env->native_stack_boundary) {
         aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
         aot_set_exception_with_id(module_inst, EXCE_NATIVE_STACK_OVERFLOW);
         goto fail;
         goto fail;

+ 7 - 0
core/iwasm/aot/aot_runtime.h

@@ -11,6 +11,10 @@
 #include "../interpreter/wasm_runtime.h"
 #include "../interpreter/wasm_runtime.h"
 #include "../compilation/aot.h"
 #include "../compilation/aot.h"
 
 
+#if WASM_ENABLE_WASI_NN != 0
+#include "../libraries/wasi-nn/src/wasi_nn_private.h"
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -75,6 +79,9 @@ typedef struct AOTFunctionInstance {
 
 
 typedef struct AOTModuleInstanceExtra {
 typedef struct AOTModuleInstanceExtra {
     CApiFuncImport *c_api_func_imports;
     CApiFuncImport *c_api_func_imports;
+#if WASM_ENABLE_WASI_NN != 0
+    WASINNContext *wasi_nn_ctx;
+#endif
 } AOTModuleInstanceExtra;
 } AOTModuleInstanceExtra;
 
 
 #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
 #if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)

+ 6 - 1
core/iwasm/common/arch/invokeNative_ia32.s

@@ -16,9 +16,14 @@ _invokeNative:
     push    %ebp
     push    %ebp
     movl    %esp, %ebp
     movl    %esp, %ebp
     movl    16(%ebp), %ecx          /* ecx = argc */
     movl    16(%ebp), %ecx          /* ecx = argc */
-    movl    12(%ebp), %edx          /* edx = argv */
+    leal    2(%ecx), %edx           /* edx = ecx + 2 (count return address and saved ebp) */
+    andl    $3, %edx                /* edx = edx % 4 */
+    jz   stack_aligned              /* if edx == 0, stack is already 16 bytes aligned */
+    leal    -16(%esp, %edx, 4), %esp /* esp = esp - 16 + edx * 4 */
+stack_aligned:
     test    %ecx, %ecx
     test    %ecx, %ecx
     jz      skip_push_args          /* if ecx == 0, skip pushing arguments */
     jz      skip_push_args          /* if ecx == 0, skip pushing arguments */
+    movl    12(%ebp), %edx          /* edx = argv */
     leal    -4(%edx,%ecx,4), %edx   /* edx = edx + ecx * 4 - 4 */
     leal    -4(%edx,%ecx,4), %edx   /* edx = edx + ecx * 4 - 4 */
     subl    %esp, %edx              /* edx = edx - esp */
     subl    %esp, %edx              /* edx = edx - esp */
 1:
 1:

+ 217 - 206
core/iwasm/common/wasm_c_api.c

@@ -276,7 +276,7 @@ WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
 WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
 WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
-#if WAMR_BUILD_MEMORY_PROFILING != 0
+#if WASM_ENABLE_MEMORY_PROFILING != 0
 #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
 #define WASM_C_DUMP_PROC_MEM() LOG_PROC_MEM()
 #else
 #else
 #define WASM_C_DUMP_PROC_MEM() (void)0
 #define WASM_C_DUMP_PROC_MEM() (void)0
@@ -398,7 +398,7 @@ wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
 }
 }
 
 
 /* global engine instance */
 /* global engine instance */
-static wasm_engine_t *singleton_engine = NULL;
+static wasm_engine_t *singleton_engine;
 #ifdef os_thread_local_attribute
 #ifdef os_thread_local_attribute
 /* categorize wasm_store_t as threads*/
 /* categorize wasm_store_t as threads*/
 static os_thread_local_attribute unsigned thread_local_stores_num = 0;
 static os_thread_local_attribute unsigned thread_local_stores_num = 0;
@@ -1458,6 +1458,30 @@ wasm_importtype_type(const wasm_importtype_t *import_type)
     return import_type->extern_type;
     return import_type->extern_type;
 }
 }
 
 
+bool
+wasm_importtype_is_linked(const wasm_importtype_t *import_type)
+{
+    if (!import_type)
+        return false;
+
+    const wasm_name_t *module_name = wasm_importtype_module(import_type);
+    const wasm_name_t *field_name = wasm_importtype_name(import_type);
+
+    switch (wasm_externtype_kind(wasm_importtype_type(import_type))) {
+        case WASM_EXTERN_FUNC:
+            return wasm_runtime_is_import_func_linked(module_name->data,
+                                                      field_name->data);
+        case WASM_EXTERN_GLOBAL:
+            return wasm_runtime_is_import_global_linked(module_name->data,
+                                                        field_name->data);
+        case WASM_EXTERN_MEMORY:
+        case WASM_EXTERN_TABLE:
+        default:
+            break;
+    }
+    return false;
+}
+
 own wasm_exporttype_t *
 own wasm_exporttype_t *
 wasm_exporttype_new(own wasm_byte_vec_t *name,
 wasm_exporttype_new(own wasm_byte_vec_t *name,
                     own wasm_externtype_t *extern_type)
                     own wasm_externtype_t *extern_type)
@@ -2537,12 +2561,12 @@ wasm_module_imports(const wasm_module_t *module, own wasm_importtype_vec_t *out)
 
 
         bh_assert(extern_type);
         bh_assert(extern_type);
 
 
-        wasm_name_new_from_string(&module_name, module_name_rt);
+        wasm_name_new_from_string_nt(&module_name, module_name_rt);
         if (strlen(module_name_rt) && !module_name.data) {
         if (strlen(module_name_rt) && !module_name.data) {
             goto failed;
             goto failed;
         }
         }
 
 
-        wasm_name_new_from_string(&name, field_name_rt);
+        wasm_name_new_from_string_nt(&name, field_name_rt);
         if (strlen(field_name_rt) && !name.data) {
         if (strlen(field_name_rt) && !name.data) {
             goto failed;
             goto failed;
         }
         }
@@ -2622,7 +2646,7 @@ wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
         }
         }
 
 
         /* byte* -> wasm_byte_vec_t */
         /* byte* -> wasm_byte_vec_t */
-        wasm_name_new_from_string(&name, export->name);
+        wasm_name_new_from_string_nt(&name, export->name);
         if (strlen(export->name) && !name.data) {
         if (strlen(export->name) && !name.data) {
             goto failed;
             goto failed;
         }
         }
@@ -3008,6 +3032,20 @@ failed:
     return NULL;
     return NULL;
 }
 }
 
 
+static wasm_func_t *
+wasm_func_new_empty(wasm_store_t *store)
+{
+    wasm_func_t *func = NULL;
+
+    if (!(func = malloc_internal(sizeof(wasm_func_t))))
+        goto failed;
+
+    func->store = store;
+    func->kind = WASM_EXTERN_FUNC;
+
+    RETURN_OBJ(func, wasm_func_delete)
+}
+
 void
 void
 wasm_func_delete(wasm_func_t *func)
 wasm_func_delete(wasm_func_t *func)
 {
 {
@@ -3211,7 +3249,8 @@ wasm_func_call(const wasm_func_t *func, const wasm_val_vec_t *params,
         wasm_name_t message = { 0 };
         wasm_name_t message = { 0 };
         wasm_trap_t *trap;
         wasm_trap_t *trap;
 
 
-        wasm_name_new_from_string(&message, "failed to call unlinked function");
+        wasm_name_new_from_string_nt(&message,
+                                     "failed to call unlinked function");
         trap = wasm_trap_new(func->store, &message);
         trap = wasm_trap_new(func->store, &message);
         wasm_byte_vec_delete(&message);
         wasm_byte_vec_delete(&message);
 
 
@@ -3371,6 +3410,25 @@ failed:
     return NULL;
     return NULL;
 }
 }
 
 
+static wasm_global_t *
+wasm_global_new_empty(wasm_store_t *store)
+{
+    wasm_global_t *global = NULL;
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global)
+        goto failed;
+
+    global->store = store;
+    global->kind = WASM_EXTERN_GLOBAL;
+
+    return global;
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
 /* almost same with wasm_global_new */
 /* almost same with wasm_global_new */
 wasm_global_t *
 wasm_global_t *
 wasm_global_copy(const wasm_global_t *src)
 wasm_global_copy(const wasm_global_t *src)
@@ -4205,7 +4263,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
             (WASMModuleInstance *)module_inst_comm;
             (WASMModuleInstance *)module_inst_comm;
         WASMMemoryInstance *memory_inst =
         WASMMemoryInstance *memory_inst =
             module_inst->memories[memory->memory_idx_rt];
             module_inst->memories[memory->memory_idx_rt];
-        return memory_inst->cur_page_count * memory_inst->num_bytes_per_page;
+        return (size_t)memory_inst->cur_page_count
+               * memory_inst->num_bytes_per_page;
     }
     }
 #endif
 #endif
 
 
@@ -4215,7 +4274,8 @@ wasm_memory_data_size(const wasm_memory_t *memory)
         AOTMemoryInstance *memory_inst =
         AOTMemoryInstance *memory_inst =
             ((AOTMemoryInstance **)
             ((AOTMemoryInstance **)
                  module_inst->memories)[memory->memory_idx_rt];
                  module_inst->memories)[memory->memory_idx_rt];
-        return memory_inst->cur_page_count * memory_inst->num_bytes_per_page;
+        return (size_t)memory_inst->cur_page_count
+               * memory_inst->num_bytes_per_page;
     }
     }
 #endif
 #endif
 
 
@@ -4286,6 +4346,11 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
 
 
     imported_func_interp = module_interp->import_functions + func_idx_rt;
     imported_func_interp = module_interp->import_functions + func_idx_rt;
     bh_assert(imported_func_interp);
     bh_assert(imported_func_interp);
+    bh_assert(imported_func_interp->kind == IMPORT_KIND_FUNC);
+
+    /* it is a placeholder and let's skip it*/
+    if (!import->type)
+        return true;
 
 
     /* type comparison */
     /* type comparison */
     if (!wasm_functype_same_internal(
     if (!wasm_functype_same_internal(
@@ -4300,6 +4365,8 @@ interp_link_func(const wasm_instance_t *inst, const WASMModule *module_interp,
         imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
         imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
     else
     else
         imported_func_interp->u.function.func_ptr_linked = import->u.cb;
         imported_func_interp->u.function.func_ptr_linked = import->u.cb;
+    bh_assert(imported_func_interp->u.function.func_ptr_linked);
+
     import->func_idx_rt = func_idx_rt;
     import->func_idx_rt = func_idx_rt;
 
 
     (void)inst;
     (void)inst;
@@ -4318,12 +4385,19 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
 
 
     imported_global_interp = module_interp->import_globals + global_idx_rt;
     imported_global_interp = module_interp->import_globals + global_idx_rt;
     bh_assert(imported_global_interp);
     bh_assert(imported_global_interp);
+    bh_assert(imported_global_interp->kind == IMPORT_KIND_GLOBAL);
 
 
+    /* it is a placeholder and let's skip it*/
+    if (!import->type)
+        return true;
+
+    /* type comparison */
     if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
     if (!cmp_val_kind_with_val_type(wasm_valtype_kind(import->type->val_type),
                                     imported_global_interp->u.global.type))
                                     imported_global_interp->u.global.type))
         return false;
         return false;
 
 
     /* set init value */
     /* set init value */
+    bh_assert(import->init);
     switch (wasm_valtype_kind(import->type->val_type)) {
     switch (wasm_valtype_kind(import->type->val_type)) {
         case WASM_I32:
         case WASM_I32:
             imported_global_interp->u.global.global_data_linked.i32 =
             imported_global_interp->u.global.global_data_linked.i32 =
@@ -4350,58 +4424,6 @@ interp_link_global(const WASMModule *module_interp, uint16 global_idx_rt,
     return true;
     return true;
 }
 }
 
 
-static bool
-interp_link(const wasm_instance_t *inst, const WASMModule *module_interp,
-            wasm_extern_t *imports[])
-{
-    uint32 i = 0;
-    uint32 import_func_i = 0;
-    uint32 import_global_i = 0;
-
-    bh_assert(inst && module_interp && imports);
-
-    for (i = 0; i < module_interp->import_count; ++i) {
-        wasm_extern_t *import = imports[i];
-        WASMImport *import_rt = module_interp->imports + i;
-
-        switch (import_rt->kind) {
-            case IMPORT_KIND_FUNC:
-            {
-                if (!interp_link_func(inst, module_interp, import_func_i,
-                                      wasm_extern_as_func(import))) {
-                    LOG_WARNING("link #%d function failed", import_func_i);
-                    goto failed;
-                }
-                import_func_i++;
-                break;
-            }
-            case IMPORT_KIND_GLOBAL:
-            {
-                if (!interp_link_global(module_interp, import_global_i,
-                                        wasm_extern_as_global(import))) {
-                    LOG_WARNING("link #%d global failed", import_global_i);
-                    goto failed;
-                }
-                import_global_i++;
-                break;
-            }
-            case IMPORT_KIND_MEMORY:
-            case IMPORT_KIND_TABLE:
-            default:
-                ASSERT_NOT_IMPLEMENTED();
-                LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
-                            import_rt->kind);
-                goto failed;
-        }
-    }
-
-    return true;
-
-failed:
-    LOG_DEBUG("%s failed", __FUNCTION__);
-    return false;
-}
-
 static bool
 static bool
 interp_process_export(wasm_store_t *store,
 interp_process_export(wasm_store_t *store,
                       const WASMModuleInstance *inst_interp,
                       const WASMModuleInstance *inst_interp,
@@ -4501,6 +4523,10 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
     import_aot_func = module_aot->import_funcs + import_func_idx_rt;
     import_aot_func = module_aot->import_funcs + import_func_idx_rt;
     bh_assert(import_aot_func);
     bh_assert(import_aot_func);
 
 
+    /* it is a placeholder and let's skip it*/
+    if (!import->type)
+        return true;
+
     /* type comparison */
     /* type comparison */
     if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
     if (!wasm_functype_same_internal(import->type, import_aot_func->func_type))
         return false;
         return false;
@@ -4513,6 +4539,8 @@ aot_link_func(const wasm_instance_t *inst, const AOTModule *module_aot,
         import_aot_func->func_ptr_linked = import->u.cb_env.cb;
         import_aot_func->func_ptr_linked = import->u.cb_env.cb;
     else
     else
         import_aot_func->func_ptr_linked = import->u.cb;
         import_aot_func->func_ptr_linked = import->u.cb;
+    bh_assert(import_aot_func->func_ptr_linked);
+
     import->func_idx_rt = import_func_idx_rt;
     import->func_idx_rt = import_func_idx_rt;
 
 
     return true;
     return true;
@@ -4530,6 +4558,10 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
     import_aot_global = module_aot->import_globals + global_idx_rt;
     import_aot_global = module_aot->import_globals + global_idx_rt;
     bh_assert(import_aot_global);
     bh_assert(import_aot_global);
 
 
+    /* it is a placeholder and let's skip it*/
+    if (!import->type)
+        return true;
+
     val_type = wasm_globaltype_content(import->type);
     val_type = wasm_globaltype_content(import->type);
     bh_assert(val_type);
     bh_assert(val_type);
 
 
@@ -4537,6 +4569,7 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
                                     import_aot_global->type))
                                     import_aot_global->type))
         return false;
         return false;
 
 
+    bh_assert(import->init);
     switch (wasm_valtype_kind(val_type)) {
     switch (wasm_valtype_kind(val_type)) {
         case WASM_I32:
         case WASM_I32:
             import_aot_global->global_data_linked.i32 = import->init->of.i32;
             import_aot_global->global_data_linked.i32 = import->init->of.i32;
@@ -4557,62 +4590,6 @@ aot_link_global(const AOTModule *module_aot, uint16 global_idx_rt,
     import->global_idx_rt = global_idx_rt;
     import->global_idx_rt = global_idx_rt;
     import_aot_global->is_linked = true;
     import_aot_global->is_linked = true;
     return true;
     return true;
-
-failed:
-    LOG_DEBUG("%s failed", __FUNCTION__);
-    return false;
-}
-
-static bool
-aot_link(const wasm_instance_t *inst, const AOTModule *module_aot,
-         wasm_extern_t *imports[])
-{
-    uint32 i = 0;
-    uint32 import_func_i = 0;
-    uint32 import_global_i = 0;
-    wasm_extern_t *import = NULL;
-    wasm_func_t *func = NULL;
-    wasm_global_t *global = NULL;
-
-    bh_assert(inst && module_aot && imports);
-
-    while (import_func_i < module_aot->import_func_count
-           || import_global_i < module_aot->import_global_count) {
-        import = imports[i++];
-
-        bh_assert(import);
-
-        switch (wasm_extern_kind(import)) {
-            case WASM_EXTERN_FUNC:
-                bh_assert(import_func_i < module_aot->import_func_count);
-                func = wasm_extern_as_func((wasm_extern_t *)import);
-                if (!aot_link_func(inst, module_aot, import_func_i, func)) {
-                    LOG_WARNING("link #%d function failed", import_func_i);
-                    goto failed;
-                }
-                import_func_i++;
-
-                break;
-            case WASM_EXTERN_GLOBAL:
-                bh_assert(import_global_i < module_aot->import_global_count);
-                global = wasm_extern_as_global((wasm_extern_t *)import);
-                if (!aot_link_global(module_aot, import_global_i, global)) {
-                    LOG_WARNING("link #%d global failed", import_global_i);
-                    goto failed;
-                }
-                import_global_i++;
-
-                break;
-            case WASM_EXTERN_MEMORY:
-            case WASM_EXTERN_TABLE:
-            default:
-                ASSERT_NOT_IMPLEMENTED();
-                goto failed;
-        }
-    }
-
-    return true;
-
 failed:
 failed:
     LOG_DEBUG("%s failed", __FUNCTION__);
     LOG_DEBUG("%s failed", __FUNCTION__);
     return false;
     return false;
@@ -4693,7 +4670,7 @@ aot_process_export(wasm_store_t *store, const AOTModuleInstance *inst_aot,
             goto failed;
             goto failed;
         }
         }
 
 
-        wasm_name_new_from_string(external->name, export->name);
+        wasm_name_new_from_string_nt(external->name, export->name);
         if (strlen(export->name) && !external->name->data) {
         if (strlen(export->name) && !external->name->data) {
             goto failed;
             goto failed;
         }
         }
@@ -4711,65 +4688,103 @@ failed:
 }
 }
 #endif /* WASM_ENABLE_AOT */
 #endif /* WASM_ENABLE_AOT */
 
 
-wasm_instance_t *
-wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
-                  const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
-{
-    return wasm_instance_new_with_args(store, module, imports, trap,
-                                       KILOBYTE(32), KILOBYTE(32));
-}
-
 static bool
 static bool
-compare_imports(const wasm_module_t *module, const wasm_extern_vec_t *imports)
+do_link(const wasm_instance_t *inst, const wasm_module_t *module,
+        const wasm_extern_vec_t *imports)
 {
 {
-    unsigned import_func_count = 0;
-    unsigned import_global_count = 0;
-    unsigned import_memory_count = 0;
-    unsigned import_table_count = 0;
-    unsigned i = 0;
+    uint32 i, import_func_i, import_global_i;
 
 
-    for (i = 0; imports && i < imports->num_elems; i++) {
+    bh_assert(inst && module);
+
+    /* we have run a module_type check before. */
+
+    for (i = 0, import_func_i = 0, import_global_i = 0; i < imports->num_elems;
+         i++) {
         wasm_extern_t *import = imports->data[i];
         wasm_extern_t *import = imports->data[i];
+
+        if (!import) {
+            LOG_ERROR("imports[%d] is NULL and it is fatal\n", i);
+            goto failed;
+        }
+
         switch (wasm_extern_kind(import)) {
         switch (wasm_extern_kind(import)) {
             case WASM_EXTERN_FUNC:
             case WASM_EXTERN_FUNC:
-                import_func_count++;
+            {
+                bool ret = false;
+#if WASM_ENABLE_INTERP != 0
+                if ((*module)->module_type == Wasm_Module_Bytecode) {
+                    ret = interp_link_func(inst, MODULE_INTERP(module),
+                                           import_func_i,
+                                           wasm_extern_as_func(import));
+                }
+#endif
+#if WASM_ENABLE_AOT != 0
+                if ((*module)->module_type == Wasm_Module_AoT) {
+                    ret = aot_link_func(inst, MODULE_AOT(module), import_func_i,
+                                        wasm_extern_as_func(import));
+                }
+#endif
+                if (!ret) {
+                    LOG_WARNING("link function  #%d failed", import_func_i);
+                    goto failed;
+                }
+
+                import_func_i++;
                 break;
                 break;
+            }
             case WASM_EXTERN_GLOBAL:
             case WASM_EXTERN_GLOBAL:
-                import_global_count++;
+            {
+                bool ret = false;
+#if WASM_ENABLE_INTERP != 0
+                if ((*module)->module_type == Wasm_Module_Bytecode) {
+                    ret = interp_link_global(MODULE_INTERP(module),
+                                             import_global_i,
+                                             wasm_extern_as_global(import));
+                }
+#endif
+#if WASM_ENABLE_AOT != 0
+                if ((*module)->module_type == Wasm_Module_AoT) {
+                    ret = aot_link_global(MODULE_AOT(module), import_global_i,
+                                          wasm_extern_as_global(import));
+                }
+#endif
+                if (!ret) {
+                    LOG_WARNING("link global #%d failed", import_global_i);
+                    goto failed;
+                }
+
+                import_global_i++;
                 break;
                 break;
+            }
             case WASM_EXTERN_MEMORY:
             case WASM_EXTERN_MEMORY:
-                import_memory_count++;
-                break;
             case WASM_EXTERN_TABLE:
             case WASM_EXTERN_TABLE:
-                import_table_count++;
+            {
+                LOG_WARNING("doesn't support import memories and tables for "
+                            "now, ignore them");
                 break;
                 break;
+            }
             default:
             default:
+            {
                 UNREACHABLE();
                 UNREACHABLE();
-                return false;
+                break;
+            }
         }
         }
     }
     }
 
 
-#if WASM_ENABLE_INTERP != 0
-    if ((*module)->module_type == Wasm_Module_Bytecode)
-        return import_func_count == MODULE_INTERP(module)->import_function_count
-               && import_global_count
-                      == MODULE_INTERP(module)->import_global_count
-               && import_memory_count
-                      == MODULE_INTERP(module)->import_memory_count
-               && import_table_count
-                      == MODULE_INTERP(module)->import_table_count;
-#endif
-#if WASM_ENABLE_AOT != 0
-    if ((*module)->module_type == Wasm_Module_AoT)
-        return import_func_count == MODULE_AOT(module)->import_func_count
-               && import_global_count == MODULE_AOT(module)->import_global_count
-               && import_memory_count == MODULE_AOT(module)->import_memory_count
-               && import_table_count == MODULE_AOT(module)->import_table_count;
-#endif
-
+    return true;
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
     return false;
     return false;
 }
 }
 
 
+wasm_instance_t *
+wasm_instance_new(wasm_store_t *store, const wasm_module_t *module,
+                  const wasm_extern_vec_t *imports, own wasm_trap_t **trap)
+{
+    return wasm_instance_new_with_args(store, module, imports, trap,
+                                       KILOBYTE(32), KILOBYTE(32));
+}
+
 wasm_instance_t *
 wasm_instance_t *
 wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
 wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
                             const wasm_extern_vec_t *imports,
                             const wasm_extern_vec_t *imports,
@@ -4779,7 +4794,6 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
     char sub_error_buf[128] = { 0 };
     char sub_error_buf[128] = { 0 };
     char error_buf[256] = { 0 };
     char error_buf[256] = { 0 };
     wasm_instance_t *instance = NULL;
     wasm_instance_t *instance = NULL;
-    WASMModuleInstance *inst_rt;
     CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
     CApiFuncImport *func_import = NULL, **p_func_imports = NULL;
     uint32 i = 0, import_func_count = 0;
     uint32 i = 0, import_func_count = 0;
     uint64 total_size;
     uint64 total_size;
@@ -4790,11 +4804,9 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
     if (!module)
     if (!module)
         return NULL;
         return NULL;
 
 
-    if (!compare_imports(module, imports)) {
-        snprintf(sub_error_buf, sizeof(sub_error_buf),
-                 "Failed to match imports");
-        goto failed;
-    }
+    /*
+     * will do the check at the end of wasm_runtime_instantiate
+     */
 
 
     WASM_C_DUMP_PROC_MEM();
     WASM_C_DUMP_PROC_MEM();
 
 
@@ -4805,43 +4817,17 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
         goto failed;
         goto failed;
     }
     }
 
 
-    /* link module and imports */
-    if (imports && imports->num_elems) {
-        bool link = false;
-#if WASM_ENABLE_INTERP != 0
-        if ((*module)->module_type == Wasm_Module_Bytecode) {
-            if (!interp_link(instance, MODULE_INTERP(module),
-                             (wasm_extern_t **)imports->data)) {
-                snprintf(sub_error_buf, sizeof(sub_error_buf),
-                         "Failed to validate imports");
-                goto failed;
-            }
-            link = true;
-        }
-#endif
-
-#if WASM_ENABLE_AOT != 0
-        if ((*module)->module_type == Wasm_Module_AoT) {
-            if (!aot_link(instance, MODULE_AOT(module),
-                          (wasm_extern_t **)imports->data)) {
-                snprintf(sub_error_buf, sizeof(sub_error_buf),
-                         "Failed to validate imports");
-                goto failed;
-            }
-            link = true;
-        }
-#endif
-
-        /*
-         * a wrong combination of module filetype and compilation flags
-         * also leads to below branch
-         */
-        if (!link) {
+    /* executes the instantiate-time linking if provided */
+    if (imports) {
+        if (!do_link(instance, module, imports)) {
             snprintf(sub_error_buf, sizeof(sub_error_buf),
             snprintf(sub_error_buf, sizeof(sub_error_buf),
-                     "Failed to verify import count");
+                     "Failed to validate imports");
             goto failed;
             goto failed;
         }
         }
     }
     }
+    /*
+     * will do the linking result check at the end of wasm_runtime_instantiate
+     */
 
 
     instance->inst_comm_rt = wasm_runtime_instantiate(
     instance->inst_comm_rt = wasm_runtime_instantiate(
         *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
         *module, stack_size, heap_size, sub_error_buf, sizeof(sub_error_buf));
@@ -4856,18 +4842,22 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
     }
     }
 
 
     /* create the c-api func import list */
     /* create the c-api func import list */
-    inst_rt = (WASMModuleInstance *)instance->inst_comm_rt;
 #if WASM_ENABLE_INTERP != 0
 #if WASM_ENABLE_INTERP != 0
     if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
     if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
-        p_func_imports = &inst_rt->e->c_api_func_imports;
-        import_func_count = inst_rt->module->import_function_count;
+        WASMModuleInstanceExtra *e =
+            ((WASMModuleInstance *)instance->inst_comm_rt)->e;
+        p_func_imports = &(e->c_api_func_imports);
+        import_func_count = MODULE_INTERP(module)->import_function_count;
     }
     }
 #endif
 #endif
 #if WASM_ENABLE_AOT != 0
 #if WASM_ENABLE_AOT != 0
     if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
     if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
-        p_func_imports =
-            &((AOTModuleInstanceExtra *)inst_rt->e)->c_api_func_imports;
-        import_func_count = ((AOTModule *)inst_rt->module)->import_func_count;
+        AOTModuleInstanceExtra *e =
+            (AOTModuleInstanceExtra *)((AOTModuleInstance *)
+                                           instance->inst_comm_rt)
+                ->e;
+        p_func_imports = &(e->c_api_func_imports);
+        import_func_count = MODULE_AOT(module)->import_func_count;
     }
     }
 #endif
 #endif
     bh_assert(p_func_imports);
     bh_assert(p_func_imports);
@@ -4880,16 +4870,21 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
         goto failed;
         goto failed;
     }
     }
 
 
-    /* fill in c-api func import list */
+    /* fill in module_inst->e->c_api_func_imports */
     for (i = 0; imports && i < imports->num_elems; i++) {
     for (i = 0; imports && i < imports->num_elems; i++) {
-        wasm_func_t *func_host;
-        wasm_extern_t *in;
+        wasm_func_t *func_host = NULL;
+        wasm_extern_t *in = imports->data[i];
+        bh_assert(in);
 
 
-        in = imports->data[i];
         if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
         if (wasm_extern_kind(in) != WASM_EXTERN_FUNC)
             continue;
             continue;
 
 
         func_host = wasm_extern_as_func(in);
         func_host = wasm_extern_as_func(in);
+        /* it is a placeholder and let's skip it*/
+        if (!func_host->type) {
+            func_import++;
+            continue;
+        }
 
 
         func_import->with_env_arg = func_host->with_env;
         func_import->with_env_arg = func_host->with_env;
         if (func_host->with_env) {
         if (func_host->with_env) {
@@ -4900,6 +4895,7 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
             func_import->func_ptr_linked = func_host->u.cb;
             func_import->func_ptr_linked = func_host->u.cb;
             func_import->env_arg = NULL;
             func_import->env_arg = NULL;
         }
         }
+        bh_assert(func_import->func_ptr_linked);
 
 
         func_import++;
         func_import++;
     }
     }
@@ -4907,6 +4903,8 @@ wasm_instance_new_with_args(wasm_store_t *store, const wasm_module_t *module,
     /* fill with inst */
     /* fill with inst */
     for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
     for (i = 0; imports && imports->data && i < imports->num_elems; ++i) {
         wasm_extern_t *import = imports->data[i];
         wasm_extern_t *import = imports->data[i];
+        bh_assert(import);
+
         switch (import->kind) {
         switch (import->kind) {
             case WASM_EXTERN_FUNC:
             case WASM_EXTERN_FUNC:
                 wasm_extern_as_func(import)->inst_comm_rt =
                 wasm_extern_as_func(import)->inst_comm_rt =
@@ -5002,7 +5000,7 @@ failed:
              sub_error_buf);
              sub_error_buf);
     if (trap != NULL) {
     if (trap != NULL) {
         wasm_message_t message = { 0 };
         wasm_message_t message = { 0 };
-        wasm_name_new_from_string(&message, error_buf);
+        wasm_name_new_from_string_nt(&message, error_buf);
         *trap = wasm_trap_new(store, &message);
         *trap = wasm_trap_new(store, &message);
         wasm_byte_vec_delete(&message);
         wasm_byte_vec_delete(&message);
     }
     }
@@ -5202,3 +5200,16 @@ BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST)
 
 
 BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
 BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
 #undef WASM_OTHER_AS_EXTERN_CONST
 #undef WASM_OTHER_AS_EXTERN_CONST
+
+wasm_extern_t *
+wasm_extern_new_empty(wasm_store_t *store, wasm_externkind_t extern_kind)
+{
+    if (extern_kind == WASM_EXTERN_FUNC)
+        return wasm_func_as_extern(wasm_func_new_empty(store));
+
+    if (extern_kind == WASM_EXTERN_GLOBAL)
+        return wasm_global_as_extern(wasm_global_new_empty(store));
+
+    LOG_ERROR("Don't support linking table and memory for now");
+    return NULL;
+}

+ 1 - 0
core/iwasm/common/wasm_exec_env.c

@@ -211,6 +211,7 @@ wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
     exec_env->handle = os_self_thread();
     exec_env->handle = os_self_thread();
     exec_env->native_stack_boundary =
     exec_env->native_stack_boundary =
         stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
         stack_boundary ? stack_boundary + WASM_STACK_GUARD_SIZE : NULL;
+    exec_env->native_stack_top_min = (void *)UINTPTR_MAX;
 }
 }
 
 
 #if WASM_ENABLE_THREAD_MGR != 0
 #if WASM_ENABLE_THREAD_MGR != 0

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

@@ -84,6 +84,12 @@ typedef struct WASMExecEnv {
     void **native_symbol;
     void **native_symbol;
 #endif
 #endif
 
 
+    /*
+     * The lowest stack pointer value observed.
+     * Assumption: native stack grows to the lower address.
+     */
+    uint8 *native_stack_top_min;
+
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
     /**
     /**
      * Cache for
      * Cache for
@@ -165,6 +171,17 @@ typedef struct WASMExecEnv {
     } wasm_stack;
     } wasm_stack;
 } WASMExecEnv;
 } WASMExecEnv;
 
 
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+#define RECORD_STACK_USAGE(e, p)               \
+    do {                                       \
+        if ((e)->native_stack_top_min > (p)) { \
+            (e)->native_stack_top_min = (p);   \
+        }                                      \
+    } while (0)
+#else
+#define RECORD_STACK_USAGE(e, p) (void)0
+#endif
+
 WASMExecEnv *
 WASMExecEnv *
 wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
 wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
                               uint32 stack_size);
                               uint32 stack_size);

+ 8 - 1
core/iwasm/common/wasm_native.c

@@ -250,6 +250,10 @@ lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
     return NULL;
     return NULL;
 }
 }
 
 
+/**
+ * allow func_type and all outputs, like p_signature, p_attachment and
+ * p_call_conv_raw to be NULL
+ */
 void *
 void *
 wasm_native_resolve_symbol(const char *module_name, const char *field_name,
 wasm_native_resolve_symbol(const char *module_name, const char *field_name,
                            const WASMType *func_type, const char **p_signature,
                            const WASMType *func_type, const char **p_signature,
@@ -275,10 +279,13 @@ wasm_native_resolve_symbol(const char *module_name, const char *field_name,
         node = node_next;
         node = node_next;
     }
     }
 
 
+    if (!p_signature || !p_attachment || !p_call_conv_raw)
+        return func_ptr;
+
     if (func_ptr) {
     if (func_ptr) {
         if (signature && signature[0] != '\0') {
         if (signature && signature[0] != '\0') {
             /* signature is not empty, check its format */
             /* signature is not empty, check its format */
-            if (!check_symbol_signature(func_type, signature)) {
+            if (!func_type || !check_symbol_signature(func_type, signature)) {
 #if WASM_ENABLE_WAMR_COMPILER == 0
 #if WASM_ENABLE_WAMR_COMPILER == 0
                 /* Output warning except running aot compiler */
                 /* Output warning except running aot compiler */
                 LOG_WARNING("failed to check signature '%s' and resolve "
                 LOG_WARNING("failed to check signature '%s' and resolve "

+ 150 - 2
core/iwasm/common/wasm_runtime_common.c

@@ -7,6 +7,7 @@
 #include "bh_common.h"
 #include "bh_common.h"
 #include "bh_assert.h"
 #include "bh_assert.h"
 #include "bh_log.h"
 #include "bh_log.h"
+#include "wasm_native.h"
 #include "wasm_runtime_common.h"
 #include "wasm_runtime_common.h"
 #include "wasm_memory.h"
 #include "wasm_memory.h"
 #if WASM_ENABLE_INTERP != 0
 #if WASM_ENABLE_INTERP != 0
@@ -128,6 +129,12 @@ runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
 static JitCompOptions jit_options = { 0 };
 static JitCompOptions jit_options = { 0 };
 #endif
 #endif
 
 
+#if WASM_ENABLE_JIT != 0
+static LLVMJITOptions llvm_jit_options = { 3, 3 };
+#endif
+
+static RunningMode runtime_running_mode = Mode_Default;
+
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 /* The exec_env of thread local storage, set before calling function
 /* The exec_env of thread local storage, set before calling function
    and used in signal handler, as we cannot get it from the argument
    and used in signal handler, as we cannot get it from the argument
@@ -514,6 +521,20 @@ wasm_runtime_destroy()
     wasm_runtime_memory_destroy();
     wasm_runtime_memory_destroy();
 }
 }
 
 
+RunningMode
+wasm_runtime_get_default_running_mode(void)
+{
+    return runtime_running_mode;
+}
+
+#if WASM_ENABLE_JIT != 0
+LLVMJITOptions
+wasm_runtime_get_llvm_jit_options(void)
+{
+    return llvm_jit_options;
+}
+#endif
+
 bool
 bool
 wasm_runtime_full_init(RuntimeInitArgs *init_args)
 wasm_runtime_full_init(RuntimeInitArgs *init_args)
 {
 {
@@ -521,10 +542,20 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
                                   &init_args->mem_alloc_option))
                                   &init_args->mem_alloc_option))
         return false;
         return false;
 
 
+    if (!wasm_runtime_set_default_running_mode(init_args->running_mode)) {
+        wasm_runtime_memory_destroy();
+        return false;
+    }
+
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
     jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
     jit_options.code_cache_size = init_args->fast_jit_code_cache_size;
 #endif
 #endif
 
 
+#if WASM_ENABLE_JIT != 0
+    llvm_jit_options.size_level = init_args->llvm_jit_size_level;
+    llvm_jit_options.opt_level = init_args->llvm_jit_opt_level;
+#endif
+
     if (!wasm_runtime_env_init()) {
     if (!wasm_runtime_env_init()) {
         wasm_runtime_memory_destroy();
         wasm_runtime_memory_destroy();
         return false;
         return false;
@@ -554,6 +585,47 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
     return true;
     return true;
 }
 }
 
 
+bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode)
+{
+    if (running_mode == Mode_Default) {
+        return true;
+    }
+    else if (running_mode == Mode_Interp) {
+#if WASM_ENABLE_INTERP != 0
+        return true;
+#endif
+    }
+    else if (running_mode == Mode_Fast_JIT) {
+#if WASM_ENABLE_FAST_JIT != 0
+        return true;
+#endif
+    }
+    else if (running_mode == Mode_LLVM_JIT) {
+#if WASM_ENABLE_JIT != 0
+        return true;
+#endif
+    }
+    else if (running_mode == Mode_Multi_Tier_JIT) {
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
+        return true;
+#endif
+    }
+
+    return false;
+}
+
+bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode)
+{
+    if (wasm_runtime_is_running_mode_supported(running_mode)) {
+        runtime_running_mode = running_mode;
+        return true;
+    }
+    return false;
+}
+
 PackageType
 PackageType
 get_package_type(const uint8 *buf, uint32 size)
 get_package_type(const uint8 *buf, uint32 size)
 {
 {
@@ -1171,6 +1243,41 @@ wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
 #endif
 #endif
 }
 }
 
 
+bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+                              RunningMode running_mode)
+{
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT)
+        return true;
+#endif
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMModuleInstance *module_inst_interp =
+            (WASMModuleInstance *)module_inst;
+
+        return wasm_set_running_mode(module_inst_interp, running_mode);
+    }
+#endif
+
+    return false;
+}
+
+RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst)
+{
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMModuleInstance *module_inst_interp =
+            (WASMModuleInstance *)module_inst;
+        return module_inst_interp->e->running_mode;
+    }
+#endif
+
+    return Mode_Default;
+}
+
 void
 void
 wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
 wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst)
 {
 {
@@ -1399,6 +1506,22 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
     else
     else
         os_printf("Total aux stack used: no enough info to profile\n");
         os_printf("Total aux stack used: no enough info to profile\n");
 
 
+    /*
+     * Report the native stack usage estimation.
+     *
+     * Unlike the aux stack above, we report the amount unused
+     * because we don't know the stack "bottom".
+     *
+     * Note that this is just about what the runtime itself observed.
+     * It doesn't cover host func implementations, signal handlers, etc.
+     */
+    if (exec_env->native_stack_top_min != (void *)UINTPTR_MAX)
+        os_printf("Native stack left: %zd\n",
+                  exec_env->native_stack_top_min
+                      - exec_env->native_stack_boundary);
+    else
+        os_printf("Native stack left: no enough info to profile\n");
+
     os_printf("Total app heap used: %u\n", app_heap_peak_size);
     os_printf("Total app heap used: %u\n", app_heap_peak_size);
 }
 }
 #endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
 #endif /* end of (WASM_ENABLE_MEMORY_PROFILING != 0) \
@@ -2195,6 +2318,12 @@ wasm_set_exception(WASMModuleInstance *module_inst, const char *exception)
     if (exec_env) {
     if (exec_env) {
         wasm_cluster_spread_exception(exec_env, exception ? false : true);
         wasm_cluster_spread_exception(exec_env, exception ? false : true);
     }
     }
+#if WASM_ENABLE_SHARED_MEMORY
+    if (exception) {
+        notify_stale_threads_on_exception(
+            (WASMModuleInstanceCommon *)module_inst);
+    }
+#endif
 #else
 #else
     (void)exec_env;
     (void)exec_env;
 #endif
 #endif
@@ -2219,9 +2348,7 @@ static const char *exception_msgs[] = {
     "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
     "wasm auxiliary stack underflow", /* EXCE_AUX_STACK_UNDERFLOW */
     "out of bounds table access",     /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
     "out of bounds table access",     /* EXCE_OUT_OF_BOUNDS_TABLE_ACCESS */
     "wasm operand stack overflow",    /* EXCE_OPERAND_STACK_OVERFLOW */
     "wasm operand stack overflow",    /* EXCE_OPERAND_STACK_OVERFLOW */
-#if WASM_ENABLE_FAST_JIT != 0
     "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
     "failed to compile fast jit function", /* EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC */
-#endif
     "",                               /* EXCE_ALREADY_THROWN */
     "",                               /* EXCE_ALREADY_THROWN */
 };
 };
 /* clang-format on */
 /* clang-format on */
@@ -5205,3 +5332,24 @@ wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch)
     *minor = WAMR_VERSION_MINOR;
     *minor = WAMR_VERSION_MINOR;
     *patch = WAMR_VERSION_PATCH;
     *patch = WAMR_VERSION_PATCH;
 }
 }
+
+bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+                                   const char *func_name)
+{
+    return wasm_native_resolve_symbol(module_name, func_name, NULL, NULL, NULL,
+                                      NULL);
+}
+
+bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+                                     const char *global_name)
+{
+#if WASM_ENABLE_LIBC_BUILTIN != 0
+    WASMGlobalImport global = { 0 };
+    return wasm_native_lookup_libc_builtin_global(module_name, global_name,
+                                                  &global);
+#else
+    return false;
+#endif
+}

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

@@ -25,6 +25,9 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
+/* Internal use for setting default running mode */
+#define Mode_Default 0
+
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
 #if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
 
 
 #define PUT_I64_TO_ADDR(addr, value)       \
 #define PUT_I64_TO_ADDR(addr, value)       \
@@ -413,6 +416,13 @@ typedef struct wasm_frame_t {
     const char *func_name_wp;
     const char *func_name_wp;
 } WASMCApiFrame;
 } WASMCApiFrame;
 
 
+#ifdef WASM_ENABLE_JIT
+typedef struct LLVMJITOptions {
+    uint32 opt_level;
+    uint32 size_level;
+} LLVMJITOptions;
+#endif
+
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 #ifdef OS_ENABLE_HW_BOUND_CHECK
 /* Signal info passing to interp/aot signal handler */
 /* Signal info passing to interp/aot signal handler */
 typedef struct WASMSignalInfo {
 typedef struct WASMSignalInfo {
@@ -437,10 +447,28 @@ wasm_runtime_get_exec_env_tls(void);
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_init(void);
 wasm_runtime_init(void);
 
 
+/* Internal API */
+RunningMode
+wasm_runtime_get_default_running_mode(void);
+
+#if WASM_ENABLE_JIT != 0
+/* Internal API */
+LLVMJITOptions
+wasm_runtime_get_llvm_jit_options(void);
+#endif
+
 /* See wasm_export.h for description */
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode);
+
 /* See wasm_export.h for description */
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy(void);
 wasm_runtime_destroy(void);
@@ -484,6 +512,15 @@ wasm_runtime_instantiate(WASMModuleCommon *module, uint32 stack_size,
                          uint32 heap_size, char *error_buf,
                          uint32 heap_size, char *error_buf,
                          uint32 error_buf_size);
                          uint32 error_buf_size);
 
 
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+                              RunningMode running_mode);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
+
 /* See wasm_export.h for description */
 /* See wasm_export.h for description */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
 wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
@@ -956,6 +993,14 @@ void
 wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
 wasm_runtime_destroy_custom_sections(WASMCustomSection *section_list);
 #endif
 #endif
 
 
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+                                   const char *func_name);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+                                     const char *global_name);
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 72 - 0
core/iwasm/common/wasm_shared_memory.c

@@ -30,6 +30,11 @@ typedef struct AtomicWaitNode {
     korp_cond wait_cond;
     korp_cond wait_cond;
 } AtomicWaitNode;
 } AtomicWaitNode;
 
 
+typedef struct AtomicWaitAddressArgs {
+    uint32 index;
+    void **addr;
+} AtomicWaitAddressArgs;
+
 /* Atomic wait map */
 /* Atomic wait map */
 static HashMap *wait_map;
 static HashMap *wait_map;
 
 
@@ -87,6 +92,61 @@ search_module(WASMModuleCommon *module)
     return NULL;
     return NULL;
 }
 }
 
 
+static void
+wait_map_address_count_callback(void *key, void *value,
+                                void *p_total_elem_count)
+{
+    *(uint32 *)p_total_elem_count = *(uint32 *)p_total_elem_count + 1;
+}
+
+static void
+create_list_of_waiter_addresses(void *key, void *value, void *user_data)
+{
+    AtomicWaitAddressArgs *data = (AtomicWaitAddressArgs *)user_data;
+    data->addr[data->index++] = key;
+}
+
+void
+notify_stale_threads_on_exception(WASMModuleInstanceCommon *module_inst)
+{
+    AtomicWaitAddressArgs args = { 0 };
+    uint32 i = 0, total_elem_count = 0;
+    uint64 total_elem_count_size = 0;
+
+    os_mutex_lock(&shared_memory_list_lock);
+
+    /* count number of addresses in wait_map */
+    bh_hash_map_traverse(wait_map, wait_map_address_count_callback,
+                         (void *)&total_elem_count);
+
+    if (!total_elem_count) {
+        os_mutex_unlock(&shared_memory_list_lock);
+        return;
+    }
+
+    /* allocate memory */
+    total_elem_count_size = (uint64)sizeof(void *) * total_elem_count;
+    if (total_elem_count_size >= UINT32_MAX
+        || !(args.addr = wasm_runtime_malloc((uint32)total_elem_count_size))) {
+        LOG_ERROR(
+            "failed to allocate memory for list of atomic wait addresses");
+        os_mutex_unlock(&shared_memory_list_lock);
+        return;
+    }
+
+    /* set values in list of addresses */
+    bh_hash_map_traverse(wait_map, create_list_of_waiter_addresses, &args);
+    os_mutex_unlock(&shared_memory_list_lock);
+
+    /* notify */
+    for (i = 0; i < args.index; i++) {
+        wasm_runtime_atomic_notify(module_inst, args.addr[i], UINT32_MAX);
+    }
+
+    /* free memory allocated to args data */
+    wasm_runtime_free(args.addr);
+}
+
 WASMSharedMemNode *
 WASMSharedMemNode *
 wasm_module_get_shared_memory(WASMModuleCommon *module)
 wasm_module_get_shared_memory(WASMModuleCommon *module)
 {
 {
@@ -120,6 +180,7 @@ shared_memory_dec_reference(WASMModuleCommon *module)
             bh_list_remove(shared_memory_list, node);
             bh_list_remove(shared_memory_list, node);
             os_mutex_unlock(&shared_memory_list_lock);
             os_mutex_unlock(&shared_memory_list_lock);
 
 
+            os_mutex_destroy(&node->shared_mem_lock);
             os_mutex_destroy(&node->lock);
             os_mutex_destroy(&node->lock);
             wasm_runtime_free(node);
             wasm_runtime_free(node);
         }
         }
@@ -148,7 +209,14 @@ shared_memory_set_memory_inst(WASMModuleCommon *module,
     node->module = module;
     node->module = module;
     node->memory_inst = memory;
     node->memory_inst = memory;
     node->ref_count = 1;
     node->ref_count = 1;
+
+    if (os_mutex_init(&node->shared_mem_lock) != 0) {
+        wasm_runtime_free(node);
+        return NULL;
+    }
+
     if (os_mutex_init(&node->lock) != 0) {
     if (os_mutex_init(&node->lock) != 0) {
+        os_mutex_destroy(&node->shared_mem_lock);
         wasm_runtime_free(node);
         wasm_runtime_free(node);
         return NULL;
         return NULL;
     }
     }
@@ -322,6 +390,10 @@ wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
     bh_assert(module->module_type == Wasm_Module_Bytecode
     bh_assert(module->module_type == Wasm_Module_Bytecode
               || module->module_type == Wasm_Module_AoT);
               || module->module_type == Wasm_Module_AoT);
 
 
+    if (wasm_get_exception(module_inst)) {
+        return -1;
+    }
+
     /* Currently we have only one memory instance */
     /* Currently we have only one memory instance */
     if (!module_inst->memories[0]->is_shared) {
     if (!module_inst->memories[0]->is_shared) {
         wasm_runtime_set_exception(module, "expected shared memory");
         wasm_runtime_set_exception(module, "expected shared memory");

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

@@ -26,6 +26,8 @@ typedef struct WASMSharedMemNode {
     WASMModuleCommon *module;
     WASMModuleCommon *module;
     /* The memory information */
     /* The memory information */
     WASMMemoryInstanceCommon *memory_inst;
     WASMMemoryInstanceCommon *memory_inst;
+    /* Lock used for atomic operations */
+    korp_mutex shared_mem_lock;
 
 
     /* reference count */
     /* reference count */
     uint32 ref_count;
     uint32 ref_count;
@@ -37,6 +39,9 @@ wasm_shared_memory_init();
 void
 void
 wasm_shared_memory_destroy();
 wasm_shared_memory_destroy();
 
 
+void
+notify_stale_threads_on_exception(WASMModuleInstanceCommon *module);
+
 WASMSharedMemNode *
 WASMSharedMemNode *
 wasm_module_get_shared_memory(WASMModuleCommon *module);
 wasm_module_get_shared_memory(WASMModuleCommon *module);
 
 

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

@@ -259,6 +259,7 @@ check_type_compatible(uint8 src_type, uint8 dst_type)
 #define I32_SIX LLVM_CONST(i32_six)
 #define I32_SIX LLVM_CONST(i32_six)
 #define I32_SEVEN LLVM_CONST(i32_seven)
 #define I32_SEVEN LLVM_CONST(i32_seven)
 #define I32_EIGHT LLVM_CONST(i32_eight)
 #define I32_EIGHT LLVM_CONST(i32_eight)
+#define I32_NINE LLVM_CONST(i32_nine)
 #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
 #define I32_NEG_ONE LLVM_CONST(i32_neg_one)
 #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
 #define I64_NEG_ONE LLVM_CONST(i64_neg_one)
 #define I32_MIN LLVM_CONST(i32_min)
 #define I32_MIN LLVM_CONST(i32_min)

+ 100 - 8
core/iwasm/compilation/aot_emit_function.c

@@ -366,6 +366,87 @@ fail:
 #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
 #endif /* end of (WASM_ENABLE_DUMP_CALL_STACK != 0) \
                  || (WASM_ENABLE_PERF_PROFILING != 0) */
                  || (WASM_ENABLE_PERF_PROFILING != 0) */
 
 
+static bool
+record_stack_usage(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                   uint32 callee_cell_num)
+{
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef block_update;
+    LLVMBasicBlockRef block_after_update;
+    LLVMValueRef callee_local_size, new_sp, cmp;
+    LLVMValueRef native_stack_top_min;
+    LLVMTypeRef ptrdiff_type;
+    if (comp_ctx->pointer_size == sizeof(uint64_t)) {
+        ptrdiff_type = I64_TYPE;
+    }
+    else {
+        ptrdiff_type = I32_TYPE;
+    }
+
+    /*
+     * new_sp = last_alloca - callee_local_size;
+     * if (*native_stack_top_min_addr > new_sp) {
+     *    *native_stack_top_min_addr = new_sp;
+     * }
+     */
+
+    if (!(callee_local_size = LLVMConstInt(
+              ptrdiff_type, -(int64_t)callee_cell_num * 4, true))) {
+        aot_set_last_error("llvm build const failed.");
+        return false;
+    }
+    if (!(new_sp = LLVMBuildInBoundsGEP2(comp_ctx->builder, INT8_TYPE,
+                                         func_ctx->last_alloca,
+                                         &callee_local_size, 1, "new_sp"))) {
+        aot_set_last_error("llvm build gep failed");
+        return false;
+    }
+    if (!(native_stack_top_min = LLVMBuildLoad2(
+              comp_ctx->builder, OPQ_PTR_TYPE,
+              func_ctx->native_stack_top_min_addr, "native_stack_top_min"))) {
+        aot_set_last_error("llvm build load failed");
+        return false;
+    }
+    if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULT, new_sp,
+                              native_stack_top_min, "cmp"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        return false;
+    }
+
+    if (!(block_update = LLVMAppendBasicBlockInContext(
+              comp_ctx->context, func_ctx->func, "block_update"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+    if (!(block_after_update = LLVMAppendBasicBlockInContext(
+              comp_ctx->context, func_ctx->func, "block_after_update"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        return false;
+    }
+    LLVMMoveBasicBlockAfter(block_update, block_curr);
+    LLVMMoveBasicBlockAfter(block_after_update, block_update);
+
+    if (!LLVMBuildCondBr(comp_ctx->builder, cmp, block_update,
+                         block_after_update)) {
+        aot_set_last_error("llvm build cond br failed.");
+        return false;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_update);
+    if (!LLVMBuildStore(comp_ctx->builder, new_sp,
+                        func_ctx->native_stack_top_min_addr)) {
+        aot_set_last_error("llvm build store failed");
+        return false;
+    }
+    if (!LLVMBuildBr(comp_ctx->builder, block_after_update)) {
+        aot_set_last_error("llvm build br failed.");
+        return false;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_after_update);
+    return true;
+}
+
 static bool
 static bool
 check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                      uint32 callee_cell_num)
                      uint32 callee_cell_num)
@@ -409,6 +490,19 @@ check_stack_boundary(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     return true;
     return true;
 }
 }
 
 
+static bool
+check_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+            uint32 callee_cell_num)
+{
+    if (comp_ctx->enable_stack_estimation
+        && !record_stack_usage(comp_ctx, func_ctx, callee_cell_num))
+        return false;
+    if (comp_ctx->enable_stack_bound_check
+        && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
+        return false;
+    return true;
+}
+
 /**
 /**
  * Check whether the app address and its buffer are inside the linear memory,
  * Check whether the app address and its buffer are inside the linear memory,
  * if no, throw exception
  * if no, throw exception
@@ -852,8 +946,7 @@ aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         callee_cell_num =
         callee_cell_num =
             aot_func->param_cell_num + aot_func->local_cell_num + 1;
             aot_func->param_cell_num + aot_func->local_cell_num + 1;
 
 
-        if (comp_ctx->enable_stack_bound_check
-            && !check_stack_boundary(comp_ctx, func_ctx, callee_cell_num))
+        if (!check_stack(comp_ctx, func_ctx, callee_cell_num))
             goto fail;
             goto fail;
 
 
 #if LLVM_VERSION_MAJOR >= 14
 #if LLVM_VERSION_MAJOR >= 14
@@ -1467,12 +1560,11 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Translate call non-import block */
     /* Translate call non-import block */
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
     LLVMPositionBuilderAtEnd(comp_ctx->builder, block_call_non_import);
 
 
-    if (comp_ctx->enable_stack_bound_check
-        && !check_stack_boundary(comp_ctx, func_ctx,
-                                 param_cell_num + ext_cell_num
-                                     + 1
-                                     /* Reserve some local variables */
-                                     + 16))
+    if (!check_stack(comp_ctx, func_ctx,
+                     param_cell_num + ext_cell_num
+                         + 1
+                         /* Reserve some local variables */
+                         + 16))
         goto fail;
         goto fail;
 
 
     /* Load function pointer */
     /* Load function pointer */

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

@@ -286,6 +286,21 @@ create_native_stack_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
     return true;
     return true;
 }
 }
 
 
+static bool
+create_native_stack_top_min(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef offset = I32_NINE;
+
+    if (!(func_ctx->native_stack_top_min_addr = LLVMBuildInBoundsGEP2(
+              comp_ctx->builder, OPQ_PTR_TYPE, func_ctx->exec_env, &offset, 1,
+              "native_stack_top_min_addr"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+
+    return true;
+}
+
 static bool
 static bool
 create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 create_aux_stack_info(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
 {
@@ -434,7 +449,8 @@ create_local_variables(AOTCompData *comp_data, AOTCompContext *comp_ctx,
         }
         }
     }
     }
 
 
-    if (comp_ctx->enable_stack_bound_check) {
+    if (comp_ctx->enable_stack_bound_check
+        || comp_ctx->enable_stack_estimation) {
         if (aot_func_type->param_count + func->local_count > 0) {
         if (aot_func_type->param_count + func->local_count > 0) {
             func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
             func_ctx->last_alloca = func_ctx->locals[aot_func_type->param_count
                                                      + func->local_count - 1];
                                                      + func->local_count - 1];
@@ -963,6 +979,10 @@ aot_create_func_context(AOTCompData *comp_data, AOTCompContext *comp_ctx,
         && !create_native_stack_bound(comp_ctx, func_ctx)) {
         && !create_native_stack_bound(comp_ctx, func_ctx)) {
         goto fail;
         goto fail;
     }
     }
+    if (comp_ctx->enable_stack_estimation
+        && !create_native_stack_top_min(comp_ctx, func_ctx)) {
+        goto fail;
+    }
 
 
     /* Get auxiliary stack info */
     /* Get auxiliary stack info */
     if (wasm_func->has_op_set_global_aux_stack
     if (wasm_func->has_op_set_global_aux_stack
@@ -1622,6 +1642,9 @@ aot_create_comp_context(AOTCompData *comp_data, aot_comp_option_t option)
     if (option->disable_llvm_lto)
     if (option->disable_llvm_lto)
         comp_ctx->disable_llvm_lto = true;
         comp_ctx->disable_llvm_lto = true;
 
 
+    if (option->enable_stack_estimation)
+        comp_ctx->enable_stack_estimation = true;
+
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->opt_level = option->opt_level;
     comp_ctx->size_level = option->size_level;
     comp_ctx->size_level = option->size_level;
 
 

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

@@ -163,6 +163,7 @@ typedef struct AOTFuncContext {
     LLVMValueRef aot_inst;
     LLVMValueRef aot_inst;
     LLVMValueRef argv_buf;
     LLVMValueRef argv_buf;
     LLVMValueRef native_stack_bound;
     LLVMValueRef native_stack_bound;
+    LLVMValueRef native_stack_top_min_addr;
     LLVMValueRef aux_stack_bound;
     LLVMValueRef aux_stack_bound;
     LLVMValueRef aux_stack_bottom;
     LLVMValueRef aux_stack_bottom;
     LLVMValueRef native_symbol;
     LLVMValueRef native_symbol;
@@ -313,6 +314,9 @@ typedef struct AOTCompContext {
     /* Native stack bounday Check */
     /* Native stack bounday Check */
     bool enable_stack_bound_check;
     bool enable_stack_bound_check;
 
 
+    /* Native stack usage estimation */
+    bool enable_stack_estimation;
+
     /* 128-bit SIMD */
     /* 128-bit SIMD */
     bool enable_simd;
     bool enable_simd;
 
 
@@ -403,6 +407,7 @@ typedef struct AOTCompOption {
     bool enable_aux_stack_frame;
     bool enable_aux_stack_frame;
     bool disable_llvm_intrinsics;
     bool disable_llvm_intrinsics;
     bool disable_llvm_lto;
     bool disable_llvm_lto;
+    bool enable_stack_estimation;
     uint32 opt_level;
     uint32 opt_level;
     uint32 size_level;
     uint32 size_level;
     uint32 output_format;
     uint32 output_format;

+ 92 - 1
core/iwasm/fast-jit/fe/jit_emit_memory.c

@@ -135,7 +135,8 @@ check_and_seek(JitCompContext *cc, JitReg addr, uint32 offset, uint32 bytes)
 #ifndef OS_ENABLE_HW_BOUND_CHECK
 #ifndef OS_ENABLE_HW_BOUND_CHECK
     /* ---------- check ---------- */
     /* ---------- check ---------- */
     /* 1. shortcut if the memory size is 0 */
     /* 1. shortcut if the memory size is 0 */
-    if (0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
+    if (cc->cur_wasm_module->memories != NULL
+        && 0 == cc->cur_wasm_module->memories[mem_idx].init_page_count) {
         JitReg module_inst, cur_page_count;
         JitReg module_inst, cur_page_count;
         uint32 cur_page_count_offset =
         uint32 cur_page_count_offset =
             (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
             (uint32)offsetof(WASMModuleInstance, global_table_data.bytes)
@@ -176,6 +177,18 @@ fail:
     return 0;
     return 0;
 }
 }
 
 
+#define CHECK_ALIGNMENT(maddr, memory_data, offset1)                   \
+    do {                                                               \
+        GEN_INSN(ADD, maddr, memory_data, offset1);                    \
+        JitReg align_mask = NEW_CONST(I64, ((uint64)1 << align) - 1);  \
+        JitReg AND_res = jit_cc_new_reg_I64(cc);                       \
+        GEN_INSN(AND, AND_res, maddr, align_mask);                     \
+        GEN_INSN(CMP, cc->cmp_reg, AND_res, NEW_CONST(I64, 0));        \
+        if (!jit_emit_exception(cc, EXCE_UNALIGNED_ATOMIC, JIT_OP_BNE, \
+                                cc->cmp_reg, NULL))                    \
+            goto fail;                                                 \
+    } while (0)
+
 bool
 bool
 jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
 jit_compile_op_i32_load(JitCompContext *cc, uint32 align, uint32 offset,
                         uint32 bytes, bool sign, bool atomic)
                         uint32 bytes, bool sign, bool atomic)
@@ -779,6 +792,51 @@ bool
 jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
 jit_compile_op_atomic_wait(JitCompContext *cc, uint8 op_type, uint32 align,
                            uint32 offset, uint32 bytes)
                            uint32 offset, uint32 bytes)
 {
 {
+    bh_assert(op_type == VALUE_TYPE_I32 || op_type == VALUE_TYPE_I64);
+
+    // Pop atomic.wait arguments
+    JitReg timeout, expect, expect_64, addr;
+    POP_I64(timeout);
+    if (op_type == VALUE_TYPE_I32) {
+        POP_I32(expect);
+        expect_64 = jit_cc_new_reg_I64(cc);
+        GEN_INSN(I32TOI64, expect_64, expect);
+    }
+    else {
+        POP_I64(expect_64);
+    }
+    POP_I32(addr);
+
+    // Get referenced address and store it in `maddr`
+    JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
+    JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
+    if (!offset1)
+        goto fail;
+    JitReg maddr = jit_cc_new_reg_I64(cc);
+    CHECK_ALIGNMENT(maddr, memory_data, offset1);
+
+    // Prepare `wasm_runtime_atomic_wait` arguments
+    JitReg res = jit_cc_new_reg_I32(cc);
+    JitReg args[5] = { 0 };
+    args[0] = get_module_inst_reg(cc->jit_frame);
+    args[1] = maddr;
+    args[2] = expect_64;
+    args[3] = timeout;
+    args[4] = NEW_CONST(I32, false);
+
+    if (!jit_emit_callnative(cc, wasm_runtime_atomic_wait, res, args,
+                             sizeof(args) / sizeof(args[0])))
+        goto fail;
+
+    // Handle return code
+    GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, -1));
+    if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BEQ, cc->cmp_reg,
+                            NULL))
+        goto fail;
+
+    PUSH_I32(res);
+    return true;
+fail:
     return false;
     return false;
 }
 }
 
 
@@ -786,6 +844,39 @@ bool
 jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
 jit_compiler_op_atomic_notify(JitCompContext *cc, uint32 align, uint32 offset,
                               uint32 bytes)
                               uint32 bytes)
 {
 {
+    // Pop atomic.notify arguments
+    JitReg notify_count, addr;
+    POP_I32(notify_count);
+    POP_I32(addr);
+
+    // Get referenced address and store it in `maddr`
+    JitReg memory_data = get_memory_data_reg(cc->jit_frame, 0);
+    JitReg offset1 = check_and_seek(cc, addr, offset, bytes);
+    if (!offset1)
+        goto fail;
+    JitReg maddr = jit_cc_new_reg_I64(cc);
+    CHECK_ALIGNMENT(maddr, memory_data, offset1);
+
+    // Prepare `wasm_runtime_atomic_notify` arguments
+    JitReg res = jit_cc_new_reg_I32(cc);
+    JitReg args[3] = { 0 };
+    args[0] = get_module_inst_reg(cc->jit_frame);
+    args[1] = maddr;
+    args[2] = notify_count;
+
+    if (!jit_emit_callnative(cc, wasm_runtime_atomic_notify, res, args,
+                             sizeof(args) / sizeof(args[0])))
+        goto fail;
+
+    // Handle return code
+    GEN_INSN(CMP, cc->cmp_reg, res, NEW_CONST(I32, 0));
+    if (!jit_emit_exception(cc, EXCE_ALREADY_THROWN, JIT_OP_BLTS, cc->cmp_reg,
+                            NULL))
+        goto fail;
+
+    PUSH_I32(res);
+    return true;
+fail:
     return false;
     return false;
 }
 }
 #endif
 #endif

+ 26 - 4
core/iwasm/fast-jit/jit_codecache.c

@@ -56,9 +56,31 @@ jit_code_cache_free(void *ptr)
 bool
 bool
 jit_pass_register_jitted_code(JitCompContext *cc)
 jit_pass_register_jitted_code(JitCompContext *cc)
 {
 {
-    uint32 jit_func_idx =
-        cc->cur_wasm_func_idx - cc->cur_wasm_module->import_function_count;
-    cc->cur_wasm_module->fast_jit_func_ptrs[jit_func_idx] =
-        cc->cur_wasm_func->fast_jit_jitted_code = cc->jitted_addr_begin;
+    WASMModuleInstance *instance;
+    WASMModule *module = cc->cur_wasm_module;
+    WASMFunction *func = cc->cur_wasm_func;
+    uint32 jit_func_idx = cc->cur_wasm_func_idx - module->import_function_count;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
+    os_mutex_lock(&module->instance_list_lock);
+#endif
+
+    module->fast_jit_func_ptrs[jit_func_idx] = func->fast_jit_jitted_code =
+        cc->jitted_addr_begin;
+
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
+    instance = module->instance_list;
+    while (instance) {
+        if (instance->e->running_mode == Mode_Fast_JIT)
+            instance->fast_jit_func_ptrs[jit_func_idx] = cc->jitted_addr_begin;
+        instance = instance->e->next;
+    }
+
+    os_mutex_unlock(&module->instance_list_lock);
+#else
+    (void)instance;
+#endif
     return true;
     return true;
 }
 }

+ 15 - 3
core/iwasm/fast-jit/jit_compiler.c

@@ -157,8 +157,16 @@ jit_compiler_compile(WASMModule *module, uint32 func_idx)
     /* Apply compiler passes */
     /* Apply compiler passes */
     if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
     if (!apply_compiler_passes(cc) || jit_get_last_error(cc)) {
         last_error = jit_get_last_error(cc);
         last_error = jit_get_last_error(cc);
+
+#if WASM_ENABLE_CUSTOM_NAME_SECTION != 0
+        char *function_name = cc->cur_wasm_func->field_name;
+        os_printf("fast jit compilation failed: %s (function_name=%s)\n",
+                  last_error ? last_error : "unknown error", function_name);
+#else
         os_printf("fast jit compilation failed: %s\n",
         os_printf("fast jit compilation failed: %s\n",
                   last_error ? last_error : "unknown error");
                   last_error ? last_error : "unknown error");
+#endif
+
         goto fail;
         goto fail;
     }
     }
 
 
@@ -246,6 +254,8 @@ jit_compiler_set_call_to_fast_jit(WASMModule *module, uint32 func_idx)
 
 
     func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
     func_ptr = jit_codegen_compile_call_to_fast_jit(module, func_idx);
     if (func_ptr) {
     if (func_ptr) {
+        uint32 i = func_idx - module->import_function_count;
+        module->functions[i]->call_to_fast_jit_from_llvm_jit = func_ptr;
         jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr);
         jit_compiler_set_llvm_jit_func_ptr(module, func_idx, func_ptr);
     }
     }
 
 
@@ -259,12 +269,14 @@ jit_compiler_set_llvm_jit_func_ptr(WASMModule *module, uint32 func_idx,
     WASMModuleInstance *instance;
     WASMModuleInstance *instance;
     uint32 i = func_idx - module->import_function_count;
     uint32 i = func_idx - module->import_function_count;
 
 
-    module->functions[i]->llvm_jit_func_ptr = module->func_ptrs[i] = func_ptr;
-
     os_mutex_lock(&module->instance_list_lock);
     os_mutex_lock(&module->instance_list_lock);
+
+    module->func_ptrs[i] = func_ptr;
+
     instance = module->instance_list;
     instance = module->instance_list;
     while (instance) {
     while (instance) {
-        instance->func_ptrs[func_idx] = func_ptr;
+        if (instance->e->running_mode == Mode_Multi_Tier_JIT)
+            instance->func_ptrs[func_idx] = func_ptr;
         instance = instance->e->next;
         instance = instance->e->next;
     }
     }
     os_mutex_unlock(&module->instance_list_lock);
     os_mutex_unlock(&module->instance_list_lock);

+ 1 - 0
core/iwasm/include/aot_export.h

@@ -55,6 +55,7 @@ typedef struct AOTCompOption {
     bool enable_aux_stack_frame;
     bool enable_aux_stack_frame;
     bool disable_llvm_intrinsics;
     bool disable_llvm_intrinsics;
     bool disable_llvm_lto;
     bool disable_llvm_lto;
+    bool enable_stack_estimation;
     uint32_t opt_level;
     uint32_t opt_level;
     uint32_t size_level;
     uint32_t size_level;
     uint32_t output_format;
     uint32_t output_format;

+ 4 - 0
core/iwasm/include/wasm_c_api.h

@@ -354,6 +354,7 @@ WASM_API_EXTERN own wasm_importtype_t* wasm_importtype_new(
 WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
 WASM_API_EXTERN const wasm_name_t* wasm_importtype_module(const wasm_importtype_t*);
 WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
 WASM_API_EXTERN const wasm_name_t* wasm_importtype_name(const wasm_importtype_t*);
 WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
 WASM_API_EXTERN const wasm_externtype_t* wasm_importtype_type(const wasm_importtype_t*);
+WASM_API_EXTERN bool wasm_importtype_is_linked(const wasm_importtype_t*);
 
 
 
 
 // Export Types
 // Export Types
@@ -797,6 +798,9 @@ static inline void* wasm_val_ptr(const wasm_val_t* val) {
 
 
 #define KILOBYTE(n) ((n) * 1024)
 #define KILOBYTE(n) ((n) * 1024)
 
 
+// Create placeholders filled in `wasm_externvec_t* imports` for `wasm_instance_new()`
+WASM_API_EXTERN wasm_extern_t *wasm_extern_new_empty(wasm_store_t *,  wasm_externkind_t);
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #undef own
 #undef own

+ 84 - 3
core/iwasm/include/wasm_export.h

@@ -131,6 +131,14 @@ typedef struct mem_alloc_info_t {
     uint32_t highmark_size;
     uint32_t highmark_size;
 } mem_alloc_info_t;
 } mem_alloc_info_t;
 
 
+/* Running mode of runtime and module instance*/
+typedef enum RunningMode {
+    Mode_Interp = 1,
+    Mode_Fast_JIT,
+    Mode_LLVM_JIT,
+    Mode_Multi_Tier_JIT,
+} RunningMode;
+
 /* WASM runtime initialize arguments */
 /* WASM runtime initialize arguments */
 typedef struct RuntimeInitArgs {
 typedef struct RuntimeInitArgs {
     mem_alloc_type_t mem_alloc_type;
     mem_alloc_type_t mem_alloc_type;
@@ -152,6 +160,13 @@ typedef struct RuntimeInitArgs {
 
 
     /* Fast JIT code cache size */
     /* Fast JIT code cache size */
     uint32_t fast_jit_code_cache_size;
     uint32_t fast_jit_code_cache_size;
+
+    /* Default running mode of the runtime */
+    RunningMode running_mode;
+
+    /* LLVM JIT opt and size level */
+    uint32_t llvm_jit_opt_level;
+    uint32_t llvm_jit_size_level;
 } RuntimeInitArgs;
 } RuntimeInitArgs;
 
 
 #ifndef WASM_VALKIND_T_DEFINED
 #ifndef WASM_VALKIND_T_DEFINED
@@ -195,9 +210,9 @@ WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_init(void);
 wasm_runtime_init(void);
 
 
 /**
 /**
- * Initialize the WASM runtime environment, and also initialize
- * the memory allocator and register native symbols, which are specified
- * with init arguments
+ * Initialize the WASM runtime environment, WASM running mode,
+ * and also initialize the memory allocator and register native symbols,
+ * which are specified with init arguments
  *
  *
  * @param init_args specifies the init arguments
  * @param init_args specifies the init arguments
  *
  *
@@ -206,6 +221,28 @@ wasm_runtime_init(void);
 WASM_RUNTIME_API_EXTERN bool
 WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 
 
+/**
+ * Query whether a certain running mode is supported for the runtime
+ *
+ * @param running_mode the running mode to query
+ *
+ * @return true if this running mode is supported, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_running_mode_supported(RunningMode running_mode);
+
+/**
+ * Set the default running mode for the runtime. It is inherited
+ * to set the running mode of a module instance when it is instantiated,
+ * and can be changed by calling wasm_runtime_set_running_mode
+ *
+ * @param running_mode the running mode to set
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_default_running_mode(RunningMode running_mode);
+
 /**
 /**
  * Destroy the WASM runtime environment.
  * Destroy the WASM runtime environment.
  */
  */
@@ -450,6 +487,34 @@ wasm_runtime_instantiate(const wasm_module_t module,
                          uint32_t stack_size, uint32_t heap_size,
                          uint32_t stack_size, uint32_t heap_size,
                          char *error_buf, uint32_t error_buf_size);
                          char *error_buf, uint32_t error_buf_size);
 
 
+/**
+ * Set the running mode of a WASM module instance, override the
+ * default running mode of the runtime. Note that it only makes sense when
+ * the input is a wasm bytecode file: for the AOT file, runtime always runs
+ * it with AOT engine, and this function always returns true.
+ *
+ * @param module_inst the WASM module instance to set running mode
+ * @param running_mode the running mode to set
+ *
+ * @return true if success, false otherwise
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_set_running_mode(wasm_module_inst_t module_inst,
+                              RunningMode running_mode);
+
+/**
+ * Get the running mode of a WASM module instance, if no running mode
+ * is explicitly set the default running mode of runtime will
+ * be used and returned. Note that it only makes sense when the input is a
+ * wasm bytecode file: for the AOT file, this function always returns 0.
+ *
+ * @param module_inst the WASM module instance to query for running mode
+ *
+ * @return the running mode this module instance currently use
+ */
+WASM_RUNTIME_API_EXTERN RunningMode
+wasm_runtime_get_running_mode(wasm_module_inst_t module_inst);
+
 /**
 /**
  * Deinstantiate a WASM module instance, destroy the resources.
  * Deinstantiate a WASM module instance, destroy the resources.
  *
  *
@@ -1259,6 +1324,22 @@ wasm_runtime_get_custom_section(wasm_module_t const module_comm,
  */
  */
 WASM_RUNTIME_API_EXTERN void
 WASM_RUNTIME_API_EXTERN void
 wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
 wasm_runtime_get_version(uint32_t *major, uint32_t *minor, uint32_t *patch);
+
+/**
+ * Check whether an import func `(import <module_name> <func_name> (func ...))` is linked or not
+ * with runtime registered natvie functions
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_func_linked(const char *module_name,
+                                   const char *func_name);
+
+/**
+ * Check whether an import global `(import <module_name> <global_name> (global ...))` is linked or not
+ * with runtime registered natvie globals
+ */
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_is_import_global_linked(const char *module_name,
+                                     const char *global_name);
 /* clang-format on */
 /* clang-format on */
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus

+ 40 - 6
core/iwasm/interpreter/wasm.h

@@ -278,9 +278,14 @@ struct WASMFunction {
 #endif
 #endif
 
 
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
+    /* The compiled fast jit jitted code block of this function */
     void *fast_jit_jitted_code;
     void *fast_jit_jitted_code;
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+    /* The compiled llvm jit func ptr of this function */
     void *llvm_jit_func_ptr;
     void *llvm_jit_func_ptr;
+    /* Code block to call fast jit jitted code of this function
+       from the llvm jit jitted code */
+    void *call_to_fast_jit_from_llvm_jit;
 #endif
 #endif
 #endif
 #endif
 };
 };
@@ -505,15 +510,14 @@ struct WASMModule {
     uint64 load_size;
     uint64 load_size;
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                    \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
+#if WASM_ENABLE_DEBUG_INTERP != 0                         \
+    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
         && WASM_ENABLE_LAZY_JIT != 0)
         && WASM_ENABLE_LAZY_JIT != 0)
     /**
     /**
      * List of instances referred to this module. When source debugging
      * List of instances referred to this module. When source debugging
      * feature is enabled, the debugger may modify the code section of
      * feature is enabled, the debugger may modify the code section of
      * the module, so we need to report a warning if user create several
      * the module, so we need to report a warning if user create several
-     * instances based on the same module. Sub instances created by
-     * lib-pthread or spawn API won't be added into the list.
+     * instances based on the same module.
      *
      *
      * Also add the instance to the list for Fast JIT to LLVM JIT
      * Also add the instance to the list for Fast JIT to LLVM JIT
      * tier-up, since we need to lazily update the LLVM func pointers
      * tier-up, since we need to lazily update the LLVM func pointers
@@ -533,7 +537,22 @@ struct WASMModule {
 #endif
 #endif
 
 
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
-    /* func pointers of Fast JITed (un-imported) functions */
+    /**
+     * func pointers of Fast JITed (un-imported) functions
+     * for non Multi-Tier JIT mode:
+     *   (1) when lazy jit is disabled, each pointer is set to the compiled
+     *       fast jit jitted code
+     *   (2) when lazy jit is enabled, each pointer is firstly inited as
+     *       jit_global->compile_fast_jit_and_then_call, and then set to the
+     *       compiled fast jit jitted code when it is called (the stub will
+     *       compile the jit function and then update itself)
+     * for Multi-Tier JIT mode:
+     *   each pointer is firstly inited as compile_fast_jit_and_then_call,
+     *   and then set to the compiled fast jit jitted code when it is called,
+     *   and when the llvm jit func ptr of the same function is compiled, it
+     *   will be set to call_to_llvm_jit_from_fast_jit of this function type
+     *   (tier-up from fast-jit to llvm-jit)
+     */
     void **fast_jit_func_ptrs;
     void **fast_jit_func_ptrs;
     /* locks for Fast JIT lazy compilation */
     /* locks for Fast JIT lazy compilation */
     korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
     korp_mutex fast_jit_thread_locks[WASM_ORC_JIT_BACKEND_THREAD_NUM];
@@ -543,7 +562,16 @@ struct WASMModule {
 #if WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_JIT != 0
     struct AOTCompData *comp_data;
     struct AOTCompData *comp_data;
     struct AOTCompContext *comp_ctx;
     struct AOTCompContext *comp_ctx;
-    /* func pointers of LLVM JITed (un-imported) functions */
+    /**
+     * func pointers of LLVM JITed (un-imported) functions
+     * for non Multi-Tier JIT mode:
+     *   each pointer is set to the lookuped llvm jit func ptr, note that it
+     *   is a stub and will trigger the actual compilation when it is called
+     * for Multi-Tier JIT mode:
+     *   each pointer is inited as call_to_fast_jit code block, when the llvm
+     *   jit func ptr is actually compiled, it is set to the compiled llvm jit
+     *   func ptr
+     */
     void **func_ptrs;
     void **func_ptrs;
     /* whether the func pointers are compiled */
     /* whether the func pointers are compiled */
     bool *func_ptrs_compiled;
     bool *func_ptrs_compiled;
@@ -568,6 +596,12 @@ struct WASMModule {
     korp_tid llvm_jit_init_thread;
     korp_tid llvm_jit_init_thread;
     /* whether the llvm jit is initialized */
     /* whether the llvm jit is initialized */
     bool llvm_jit_inited;
     bool llvm_jit_inited;
+    /* Whether to enable llvm jit compilation:
+       it is set to true only when there is a module instance starts to
+       run with running mode Mode_LLVM_JIT or Mode_Multi_Tier_JIT,
+       since no need to enable llvm jit compilation for Mode_Interp and
+       Mode_Fast_JIT, so as to improve performance for them */
+    bool enable_llvm_jit_compilation;
 #endif
 #endif
 };
 };
 
 

+ 98 - 99
core/iwasm/interpreter/wasm_interp_classic.c

@@ -696,28 +696,28 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint32)(*(uint8 *)maddr);                       \
             readv = (uint32)(*(uint8 *)maddr);                       \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint32)LOAD_U16(maddr);                         \
             readv = (uint32)LOAD_U16(maddr);                         \
             STORE_U16(maddr, (uint16)(readv op sval));               \
             STORE_U16(maddr, (uint16)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else {                                                       \
         else {                                                       \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = LOAD_I32(maddr);                                 \
             readv = LOAD_I32(maddr);                                 \
             STORE_U32(maddr, readv op sval);                         \
             STORE_U32(maddr, readv op sval);                         \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         PUSH_I32(readv);                                             \
         PUSH_I32(readv);                                             \
         break;                                                       \
         break;                                                       \
@@ -736,39 +736,39 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)(*(uint8 *)maddr);                       \
             readv = (uint64)(*(uint8 *)maddr);                       \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_U16(maddr);                         \
             readv = (uint64)LOAD_U16(maddr);                         \
             STORE_U16(maddr, (uint16)(readv op sval));               \
             STORE_U16(maddr, (uint16)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_U32(maddr);                         \
             readv = (uint64)LOAD_U32(maddr);                         \
             STORE_U32(maddr, (uint32)(readv op sval));               \
             STORE_U32(maddr, (uint32)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else {                                                       \
         else {                                                       \
             uint64 op_result;                                        \
             uint64 op_result;                                        \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
             CHECK_ATOMIC_MEMORY_ACCESS();                            \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_I64(maddr);                         \
             readv = (uint64)LOAD_I64(maddr);                         \
             op_result = readv op sval;                               \
             op_result = readv op sval;                               \
             STORE_I64(maddr, op_result);                             \
             STORE_I64(maddr, op_result);                             \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         PUSH_I64(readv);                                             \
         PUSH_I64(readv);                                             \
         break;                                                       \
         break;                                                       \
@@ -1151,6 +1151,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     uint32 cache_index, type_index, param_cell_num, cell_num;
     uint32 cache_index, type_index, param_cell_num, cell_num;
     uint8 value_type;
     uint8 value_type;
 
 
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    WASMSharedMemNode *node =
+        wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
+#endif
+
 #if WASM_ENABLE_DEBUG_INTERP != 0
 #if WASM_ENABLE_DEBUG_INTERP != 0
     uint8 *frame_ip_orig = NULL;
     uint8 *frame_ip_orig = NULL;
     WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
     WASMDebugInstance *debug_instance = wasm_exec_env_get_instance(exec_env);
@@ -3458,23 +3463,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
                         if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)(*(uint8 *)maddr);
                             readv = (uint32)(*(uint8 *)maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
                         else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)LOAD_U16(maddr);
                             readv = (uint32)LOAD_U16(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I32(maddr);
                             readv = LOAD_I32(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
 
 
                         PUSH_I32(readv);
                         PUSH_I32(readv);
@@ -3493,30 +3498,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
                         if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)(*(uint8 *)maddr);
                             readv = (uint64)(*(uint8 *)maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U16(maddr);
                             readv = (uint64)LOAD_U16(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U32(maddr);
                             readv = (uint64)LOAD_U32(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I64(maddr);
                             readv = LOAD_I64(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
 
 
                         PUSH_I64(readv);
                         PUSH_I64(readv);
@@ -3535,23 +3540,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
                         if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             *(uint8 *)maddr = (uint8)sval;
                             *(uint8 *)maddr = (uint8)sval;
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
                         else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U16(maddr, (uint16)sval);
                             STORE_U16(maddr, (uint16)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U32(maddr, frame_sp[1]);
                             STORE_U32(maddr, frame_sp[1]);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         break;
                         break;
                     }
                     }
@@ -3569,31 +3574,31 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
                         if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             *(uint8 *)maddr = (uint8)sval;
                             *(uint8 *)maddr = (uint8)sval;
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U16(maddr, (uint16)sval);
                             STORE_U16(maddr, (uint16)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U32(maddr, (uint32)sval);
                             STORE_U32(maddr, (uint32)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             PUT_I64_TO_ADDR((uint32 *)maddr,
                             PUT_I64_TO_ADDR((uint32 *)maddr,
                                             GET_I64_FROM_ADDR(frame_sp + 1));
                                             GET_I64_FROM_ADDR(frame_sp + 1));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         break;
                         break;
                     }
                     }
@@ -3613,32 +3618,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
                             expect = (uint8)expect;
                             expect = (uint8)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)(*(uint8 *)maddr);
                             readv = (uint32)(*(uint8 *)maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 *(uint8 *)maddr = (uint8)(sval);
                                 *(uint8 *)maddr = (uint8)(sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
                             expect = (uint16)expect;
                             expect = (uint16)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)LOAD_U16(maddr);
                             readv = (uint32)LOAD_U16(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U16(maddr, (uint16)(sval));
                                 STORE_U16(maddr, (uint16)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I32(maddr);
                             readv = LOAD_I32(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U32(maddr, sval);
                                 STORE_U32(maddr, sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         PUSH_I32(readv);
                         PUSH_I32(readv);
                         break;
                         break;
@@ -3659,44 +3664,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
                             expect = (uint8)expect;
                             expect = (uint8)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)(*(uint8 *)maddr);
                             readv = (uint64)(*(uint8 *)maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 *(uint8 *)maddr = (uint8)(sval);
                                 *(uint8 *)maddr = (uint8)(sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
                             expect = (uint16)expect;
                             expect = (uint16)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U16(maddr);
                             readv = (uint64)LOAD_U16(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U16(maddr, (uint16)(sval));
                                 STORE_U16(maddr, (uint16)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
                             expect = (uint32)expect;
                             expect = (uint32)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U32(maddr);
                             readv = (uint64)LOAD_U32(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U32(maddr, (uint32)(sval));
                                 STORE_U32(maddr, (uint32)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS();
                             CHECK_ATOMIC_MEMORY_ACCESS();
 
 
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_I64(maddr);
                             readv = (uint64)LOAD_I64(maddr);
                             if (readv == expect) {
                             if (readv == expect) {
                                 STORE_I64(maddr, sval);
                                 STORE_I64(maddr, sval);
                             }
                             }
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         PUSH_I64(readv);
                         PUSH_I64(readv);
                         break;
                         break;
@@ -4150,6 +4155,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     }
     }
     argc = function->param_cell_num;
     argc = function->param_cell_num;
 
 
+    RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
 #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
 #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
       && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
       && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
@@ -4194,58 +4200,51 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
         }
         }
     }
     }
     else {
     else {
-#if WASM_ENABLE_LAZY_JIT != 0
+        RunningMode running_mode =
+            wasm_runtime_get_running_mode((wasm_module_inst_t)module_inst);
 
 
-        /* Fast JIT to LLVM JIT tier-up is enabled */
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0
-        /* Fast JIT and LLVM JIT are both enabled, call llvm jit function
-           if it is compiled, else call fast jit function */
-        uint32 func_idx = (uint32)(function - module_inst->e->functions);
-        if (module_inst->module->func_ptrs_compiled
-                [func_idx - module_inst->module->import_function_count]) {
+        if (running_mode == Mode_Interp) {
+            wasm_interp_call_func_bytecode(module_inst, exec_env, function,
+                                           frame);
+        }
+#if WASM_ENABLE_FAST_JIT != 0
+        else if (running_mode == Mode_Fast_JIT) {
+            fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
+        }
+#endif
+#if WASM_ENABLE_JIT != 0
+        else if (running_mode == Mode_LLVM_JIT) {
             llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
             llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
                                         argv);
                                         argv);
             /* For llvm jit, the results have been stored in argv,
             /* For llvm jit, the results have been stored in argv,
                no need to copy them from stack frame again */
                no need to copy them from stack frame again */
             copy_argv_from_frame = false;
             copy_argv_from_frame = false;
         }
         }
-        else {
-            fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
-        }
-#elif WASM_ENABLE_JIT != 0
-        /* Only LLVM JIT is enabled */
-        llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
-                                    argv);
-        /* For llvm jit, the results have been stored in argv,
-           no need to copy them from stack frame again */
-        copy_argv_from_frame = false;
-#elif WASM_ENABLE_FAST_JIT != 0
-        /* Only Fast JIT is enabled */
-        fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
-#else
-        /* Both Fast JIT and LLVM JIT are disabled */
-        wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
 #endif
 #endif
-
-#else /* else of WASM_ENABLE_LAZY_JIT != 0 */
-
-        /* Fast JIT to LLVM JIT tier-up is enabled */
-#if WASM_ENABLE_JIT != 0
-        /* LLVM JIT is enabled */
-        llvm_jit_call_func_bytecode(module_inst, exec_env, function, argc,
-                                    argv);
-        /* For llvm jit, the results have been stored in argv,
-           no need to copy them from stack frame again */
-        copy_argv_from_frame = false;
-#elif WASM_ENABLE_FAST_JIT != 0
-        /* Fast JIT is enabled */
-        fast_jit_call_func_bytecode(module_inst, exec_env, function, frame);
-#else
-        /* Both Fast JIT and LLVM JIT are disabled */
-        wasm_interp_call_func_bytecode(module_inst, exec_env, function, frame);
+#if WASM_ENABLE_LAZY_JIT != 0 && WASM_ENABLE_FAST_JIT != 0 \
+    && WASM_ENABLE_JIT != 0
+        else if (running_mode == Mode_Multi_Tier_JIT) {
+            /* Tier-up from Fast JIT to LLVM JIT, call llvm jit function
+               if it is compiled, else call fast jit function */
+            uint32 func_idx = (uint32)(function - module_inst->e->functions);
+            if (module_inst->module->func_ptrs_compiled
+                    [func_idx - module_inst->module->import_function_count]) {
+                llvm_jit_call_func_bytecode(module_inst, exec_env, function,
+                                            argc, argv);
+                /* For llvm jit, the results have been stored in argv,
+                   no need to copy them from stack frame again */
+                copy_argv_from_frame = false;
+            }
+            else {
+                fast_jit_call_func_bytecode(module_inst, exec_env, function,
+                                            frame);
+            }
+        }
 #endif
 #endif
-
-#endif /* end of WASM_ENABLE_LAZY_JIT != 0 */
+        else {
+            /* There should always be a supported running mode selected */
+            bh_assert(0);
+        }
 
 
         (void)wasm_interp_call_func_bytecode;
         (void)wasm_interp_call_func_bytecode;
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0

+ 62 - 56
core/iwasm/interpreter/wasm_interp_fast.c

@@ -469,28 +469,28 @@ LOAD_PTR(void *addr)
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(1);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(1);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint32)(*(uint8 *)maddr);                       \
             readv = (uint32)(*(uint8 *)maddr);                       \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##16_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(2);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(2);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint32)LOAD_U16(maddr);                         \
             readv = (uint32)LOAD_U16(maddr);                         \
             STORE_U16(maddr, (uint16)(readv op sval));               \
             STORE_U16(maddr, (uint16)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else {                                                       \
         else {                                                       \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(4);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(4);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = LOAD_I32(maddr);                                 \
             readv = LOAD_I32(maddr);                                 \
             STORE_U32(maddr, readv op sval);                         \
             STORE_U32(maddr, readv op sval);                         \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         PUSH_I32(readv);                                             \
         PUSH_I32(readv);                                             \
         break;                                                       \
         break;                                                       \
@@ -509,39 +509,39 @@ LOAD_PTR(void *addr)
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(1);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(1);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)(*(uint8 *)maddr);                       \
             readv = (uint64)(*(uint8 *)maddr);                       \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
             *(uint8 *)maddr = (uint8)(readv op sval);                \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##16_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(2);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(2);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_U16(maddr);                         \
             readv = (uint64)LOAD_U16(maddr);                         \
             STORE_U16(maddr, (uint16)(readv op sval));               \
             STORE_U16(maddr, (uint16)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
         else if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##32_U) { \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(4);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(4);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_U32(maddr);                         \
             readv = (uint64)LOAD_U32(maddr);                         \
             STORE_U32(maddr, (uint32)(readv op sval));               \
             STORE_U32(maddr, (uint32)(readv op sval));               \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         else {                                                       \
         else {                                                       \
             uint64 op_result;                                        \
             uint64 op_result;                                        \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);     \
             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);     \
             CHECK_ATOMIC_MEMORY_ACCESS(8);                           \
             CHECK_ATOMIC_MEMORY_ACCESS(8);                           \
                                                                      \
                                                                      \
-            os_mutex_lock(&module->e->mem_lock);                     \
+            os_mutex_lock(&node->shared_mem_lock);                   \
             readv = (uint64)LOAD_I64(maddr);                         \
             readv = (uint64)LOAD_I64(maddr);                         \
             op_result = readv op sval;                               \
             op_result = readv op sval;                               \
             STORE_I64(maddr, op_result);                             \
             STORE_I64(maddr, op_result);                             \
-            os_mutex_unlock(&module->e->mem_lock);                   \
+            os_mutex_unlock(&node->shared_mem_lock);                 \
         }                                                            \
         }                                                            \
         PUSH_I64(readv);                                             \
         PUSH_I64(readv);                                             \
         break;                                                       \
         break;                                                       \
@@ -1183,6 +1183,11 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
     uint32 local_idx, local_offset, global_idx;
     uint32 local_idx, local_offset, global_idx;
     uint8 opcode, local_type, *global_addr;
     uint8 opcode, local_type, *global_addr;
 
 
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    WASMSharedMemNode *node =
+        wasm_module_get_shared_memory((WASMModuleCommon *)module->module);
+#endif
+
 #if WASM_ENABLE_LABELS_AS_VALUES != 0
 #if WASM_ENABLE_LABELS_AS_VALUES != 0
 #define HANDLE_OPCODE(op) &&HANDLE_##op
 #define HANDLE_OPCODE(op) &&HANDLE_##op
     DEFINE_GOTO_TABLE(const void *, handle_table);
     DEFINE_GOTO_TABLE(const void *, handle_table);
@@ -3296,23 +3301,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
                         if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)(*(uint8 *)maddr);
                             readv = (uint32)(*(uint8 *)maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
                         else if (opcode == WASM_OP_ATOMIC_I32_LOAD16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)LOAD_U16(maddr);
                             readv = (uint32)LOAD_U16(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I32(maddr);
                             readv = LOAD_I32(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
 
 
                         PUSH_I32(readv);
                         PUSH_I32(readv);
@@ -3331,30 +3336,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
                         if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)(*(uint8 *)maddr);
                             readv = (uint64)(*(uint8 *)maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U16(maddr);
                             readv = (uint64)LOAD_U16(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
                         else if (opcode == WASM_OP_ATOMIC_I64_LOAD32_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U32(maddr);
                             readv = (uint64)LOAD_U32(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I64(maddr);
                             readv = LOAD_I64(maddr);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
 
 
                         PUSH_I64(readv);
                         PUSH_I64(readv);
@@ -3372,23 +3377,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
                         if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             *(uint8 *)maddr = (uint8)sval;
                             *(uint8 *)maddr = (uint8)sval;
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
                         else if (opcode == WASM_OP_ATOMIC_I32_STORE16) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U16(maddr, (uint16)sval);
                             STORE_U16(maddr, (uint16)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U32(maddr, sval);
                             STORE_U32(maddr, sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         break;
                         break;
                     }
                     }
@@ -3406,30 +3411,30 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                         if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
                         if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 1, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             *(uint8 *)maddr = (uint8)sval;
                             *(uint8 *)maddr = (uint8)sval;
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE16) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U16(maddr, (uint16)sval);
                             STORE_U16(maddr, (uint16)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
                         else if (opcode == WASM_OP_ATOMIC_I64_STORE32) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_U32(maddr, (uint32)sval);
                             STORE_U32(maddr, (uint32)sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             STORE_I64(maddr, sval);
                             STORE_I64(maddr, sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         break;
                         break;
                     }
                     }
@@ -3449,32 +3454,32 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
 
 
                             expect = (uint8)expect;
                             expect = (uint8)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)(*(uint8 *)maddr);
                             readv = (uint32)(*(uint8 *)maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 *(uint8 *)maddr = (uint8)(sval);
                                 *(uint8 *)maddr = (uint8)(sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
 
 
                             expect = (uint16)expect;
                             expect = (uint16)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint32)LOAD_U16(maddr);
                             readv = (uint32)LOAD_U16(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U16(maddr, (uint16)(sval));
                                 STORE_U16(maddr, (uint16)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
 
 
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = LOAD_I32(maddr);
                             readv = LOAD_I32(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U32(maddr, sval);
                                 STORE_U32(maddr, sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         PUSH_I32(readv);
                         PUSH_I32(readv);
                         break;
                         break;
@@ -3495,44 +3500,44 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
                             CHECK_ATOMIC_MEMORY_ACCESS(1);
 
 
                             expect = (uint8)expect;
                             expect = (uint8)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)(*(uint8 *)maddr);
                             readv = (uint64)(*(uint8 *)maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 *(uint8 *)maddr = (uint8)(sval);
                                 *(uint8 *)maddr = (uint8)(sval);
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG16_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 2, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
                             CHECK_ATOMIC_MEMORY_ACCESS(2);
 
 
                             expect = (uint16)expect;
                             expect = (uint16)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U16(maddr);
                             readv = (uint64)LOAD_U16(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U16(maddr, (uint16)(sval));
                                 STORE_U16(maddr, (uint16)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
                         else if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U) {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 4, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
                             CHECK_ATOMIC_MEMORY_ACCESS(4);
 
 
                             expect = (uint32)expect;
                             expect = (uint32)expect;
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_U32(maddr);
                             readv = (uint64)LOAD_U32(maddr);
                             if (readv == expect)
                             if (readv == expect)
                                 STORE_U32(maddr, (uint32)(sval));
                                 STORE_U32(maddr, (uint32)(sval));
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         else {
                         else {
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_BULK_MEMORY_OVERFLOW(addr + offset, 8, maddr);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
                             CHECK_ATOMIC_MEMORY_ACCESS(8);
 
 
-                            os_mutex_lock(&module->e->mem_lock);
+                            os_mutex_lock(&node->shared_mem_lock);
                             readv = (uint64)LOAD_I64(maddr);
                             readv = (uint64)LOAD_I64(maddr);
                             if (readv == expect) {
                             if (readv == expect) {
                                 STORE_I64(maddr, sval);
                                 STORE_I64(maddr, sval);
                             }
                             }
-                            os_mutex_unlock(&module->e->mem_lock);
+                            os_mutex_unlock(&node->shared_mem_lock);
                         }
                         }
                         PUSH_I64(readv);
                         PUSH_I64(readv);
                         break;
                         break;
@@ -3901,6 +3906,7 @@ wasm_interp_call_wasm(WASMModuleInstance *module_inst, WASMExecEnv *exec_env,
     }
     }
     argc = function->param_cell_num;
     argc = function->param_cell_num;
 
 
+    RECORD_STACK_USAGE(exec_env, (uint8 *)&prev_frame);
 #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
 #if !(defined(OS_ENABLE_HW_BOUND_CHECK) \
       && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
       && WASM_DISABLE_STACK_HW_BOUND_CHECK == 0)
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {
     if ((uint8 *)&prev_frame < exec_env->native_stack_boundary) {

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

@@ -1399,6 +1399,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
     WASMModule *sub_module = NULL;
     WASMModule *sub_module = NULL;
     WASMGlobal *linked_global = NULL;
     WASMGlobal *linked_global = NULL;
 #endif
 #endif
+    bool ret = false;
 
 
     CHECK_BUF(p, p_end, 2);
     CHECK_BUF(p, p_end, 2);
     declare_type = read_uint8(p);
     declare_type = read_uint8(p);
@@ -1411,15 +1412,16 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
     }
     }
 
 
 #if WASM_ENABLE_LIBC_BUILTIN != 0
 #if WASM_ENABLE_LIBC_BUILTIN != 0
-    global->is_linked = wasm_native_lookup_libc_builtin_global(
-        sub_module_name, global_name, global);
-    if (global->is_linked) {
+    ret = wasm_native_lookup_libc_builtin_global(sub_module_name, global_name,
+                                                 global);
+    if (ret) {
         if (global->type != declare_type
         if (global->type != declare_type
             || global->is_mutable != declare_mutable) {
             || global->is_mutable != declare_mutable) {
             set_error_buf(error_buf, error_buf_size,
             set_error_buf(error_buf, error_buf_size,
                           "incompatible import type");
                           "incompatible import type");
             return false;
             return false;
         }
         }
+        global->is_linked = true;
     }
     }
 #endif
 #endif
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
@@ -1449,6 +1451,7 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
     global->is_mutable = (declare_mutable == 1);
     global->is_mutable = (declare_mutable == 1);
 
 
     (void)parent_module;
     (void)parent_module;
+    (void)ret;
     return true;
     return true;
 fail:
 fail:
     return false;
     return false;
@@ -2989,6 +2992,7 @@ static bool
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
                                uint32 error_buf_size)
                                uint32 error_buf_size)
 {
 {
+    LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
     AOTCompOption option = { 0 };
     AOTCompOption option = { 0 };
     char *aot_last_error;
     char *aot_last_error;
     uint64 size;
     uint64 size;
@@ -3027,8 +3031,11 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     }
     }
 
 
     option.is_jit_mode = true;
     option.is_jit_mode = true;
-    option.opt_level = 3;
-    option.size_level = 3;
+
+    llvm_jit_options = wasm_runtime_get_llvm_jit_options();
+    option.opt_level = llvm_jit_options.opt_level;
+    option.size_level = llvm_jit_options.size_level;
+
 #if WASM_ENABLE_BULK_MEMORY != 0
 #if WASM_ENABLE_BULK_MEMORY != 0
     option.enable_bulk_memory = true;
     option.enable_bulk_memory = true;
 #endif
 #endif
@@ -3048,6 +3055,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
 #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
     option.enable_aux_stack_frame = true;
     option.enable_aux_stack_frame = true;
 #endif
 #endif
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    option.enable_stack_estimation = true;
+#endif
 
 
     module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
     module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
     if (!module->comp_ctx) {
     if (!module->comp_ctx) {
@@ -3109,6 +3119,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
         module->func_ptrs[i] = (void *)func_addr;
         module->func_ptrs[i] = (void *)func_addr;
 
 
 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+        module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
+
         if (module->orcjit_stop_compiling)
         if (module->orcjit_stop_compiling)
             return false;
             return false;
 #endif
 #endif
@@ -3199,9 +3211,9 @@ orcjit_thread_callback(void *arg)
 
 
     /* Wait until init_llvm_jit_functions_stage2 finishes */
     /* Wait until init_llvm_jit_functions_stage2 finishes */
     os_mutex_lock(&module->tierup_wait_lock);
     os_mutex_lock(&module->tierup_wait_lock);
-    while (!module->llvm_jit_inited) {
+    while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) {
         os_cond_reltimedwait(&module->tierup_wait_cond,
         os_cond_reltimedwait(&module->tierup_wait_cond,
-                             &module->tierup_wait_lock, 10);
+                             &module->tierup_wait_lock, 10000);
         if (module->orcjit_stop_compiling) {
         if (module->orcjit_stop_compiling) {
             /* init_llvm_jit_functions_stage2 failed */
             /* init_llvm_jit_functions_stage2 failed */
             os_mutex_unlock(&module->tierup_wait_lock);
             os_mutex_unlock(&module->tierup_wait_lock);
@@ -3852,8 +3864,8 @@ create_module(char *error_buf, uint32 error_buf_size)
     bh_assert(ret == BH_LIST_SUCCESS);
     bh_assert(ret == BH_LIST_SUCCESS);
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                    \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
+#if WASM_ENABLE_DEBUG_INTERP != 0                         \
+    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
         && WASM_ENABLE_LAZY_JIT != 0)
         && WASM_ENABLE_LAZY_JIT != 0)
     if (os_mutex_init(&module->instance_list_lock) != 0) {
     if (os_mutex_init(&module->instance_list_lock) != 0) {
         set_error_buf(error_buf, error_buf_size,
         set_error_buf(error_buf, error_buf_size,
@@ -4148,10 +4160,8 @@ check_wasi_abi_compatibility(const WASMModule *module,
 
 
     /* should have one at least */
     /* should have one at least */
     if (module->import_wasi_api && !start && !initialize) {
     if (module->import_wasi_api && !start && !initialize) {
-        set_error_buf(
-            error_buf, error_buf_size,
-            "a module with WASI apis must be either a command or a reactor");
-        return false;
+        LOG_WARNING("warning: a module with WASI apis should be either "
+                    "a command or a reactor");
     }
     }
 
 
     /*
     /*
@@ -4256,7 +4266,8 @@ wasm_loader_unload(WASMModule *module)
     if (!module)
     if (!module)
         return;
         return;
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     module->orcjit_stop_compiling = true;
     module->orcjit_stop_compiling = true;
     if (module->llvm_jit_init_thread)
     if (module->llvm_jit_init_thread)
         os_thread_join(module->llvm_jit_init_thread, NULL);
         os_thread_join(module->llvm_jit_init_thread, NULL);
@@ -4277,7 +4288,8 @@ wasm_loader_unload(WASMModule *module)
         aot_destroy_comp_data(module->comp_data);
         aot_destroy_comp_data(module->comp_data);
 #endif
 #endif
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     if (module->tierup_wait_lock_inited) {
     if (module->tierup_wait_lock_inited) {
         os_mutex_destroy(&module->tierup_wait_lock);
         os_mutex_destroy(&module->tierup_wait_lock);
         os_cond_destroy(&module->tierup_wait_cond);
         os_cond_destroy(&module->tierup_wait_cond);
@@ -4312,9 +4324,9 @@ wasm_loader_unload(WASMModule *module)
                         module->functions[i]->fast_jit_jitted_code);
                         module->functions[i]->fast_jit_jitted_code);
                 }
                 }
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
-                if (module->functions[i]->llvm_jit_func_ptr) {
+                if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
                     jit_code_cache_free(
                     jit_code_cache_free(
-                        module->functions[i]->llvm_jit_func_ptr);
+                        module->functions[i]->call_to_fast_jit_from_llvm_jit);
                 }
                 }
 #endif
 #endif
 #endif
 #endif
@@ -4406,8 +4418,8 @@ wasm_loader_unload(WASMModule *module)
     }
     }
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                    \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
+#if WASM_ENABLE_DEBUG_INTERP != 0                         \
+    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
         && WASM_ENABLE_LAZY_JIT != 0)
         && WASM_ENABLE_LAZY_JIT != 0)
     os_mutex_destroy(&module->instance_list_lock);
     os_mutex_destroy(&module->instance_list_lock);
 #endif
 #endif

+ 21 - 10
core/iwasm/interpreter/wasm_mini_loader.c

@@ -1835,6 +1835,7 @@ static bool
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
                                uint32 error_buf_size)
                                uint32 error_buf_size)
 {
 {
+    LLVMJITOptions llvm_jit_options = wasm_runtime_get_llvm_jit_options();
     AOTCompOption option = { 0 };
     AOTCompOption option = { 0 };
     char *aot_last_error;
     char *aot_last_error;
     uint64 size;
     uint64 size;
@@ -1873,8 +1874,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
     }
     }
 
 
     option.is_jit_mode = true;
     option.is_jit_mode = true;
-    option.opt_level = 3;
-    option.size_level = 3;
+    option.opt_level = llvm_jit_options.opt_level;
+    option.size_level = llvm_jit_options.size_level;
+
 #if WASM_ENABLE_BULK_MEMORY != 0
 #if WASM_ENABLE_BULK_MEMORY != 0
     option.enable_bulk_memory = true;
     option.enable_bulk_memory = true;
 #endif
 #endif
@@ -1894,6 +1896,9 @@ init_llvm_jit_functions_stage1(WASMModule *module, char *error_buf,
 #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
 #if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
     option.enable_aux_stack_frame = true;
     option.enable_aux_stack_frame = true;
 #endif
 #endif
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    option.enable_stack_estimation = true;
+#endif
 
 
     module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
     module->comp_ctx = aot_create_comp_context(module->comp_data, &option);
     if (!module->comp_ctx) {
     if (!module->comp_ctx) {
@@ -1957,6 +1962,8 @@ init_llvm_jit_functions_stage2(WASMModule *module, char *error_buf,
         module->func_ptrs[i] = (void *)func_addr;
         module->func_ptrs[i] = (void *)func_addr;
 
 
 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
+        module->functions[i]->llvm_jit_func_ptr = (void *)func_addr;
+
         if (module->orcjit_stop_compiling)
         if (module->orcjit_stop_compiling)
             return false;
             return false;
 #endif
 #endif
@@ -2047,9 +2054,9 @@ orcjit_thread_callback(void *arg)
 
 
     /* Wait until init_llvm_jit_functions_stage2 finishes */
     /* Wait until init_llvm_jit_functions_stage2 finishes */
     os_mutex_lock(&module->tierup_wait_lock);
     os_mutex_lock(&module->tierup_wait_lock);
-    while (!module->llvm_jit_inited) {
+    while (!(module->llvm_jit_inited && module->enable_llvm_jit_compilation)) {
         os_cond_reltimedwait(&module->tierup_wait_cond,
         os_cond_reltimedwait(&module->tierup_wait_cond,
-                             &module->tierup_wait_lock, 10);
+                             &module->tierup_wait_lock, 10000);
         if (module->orcjit_stop_compiling) {
         if (module->orcjit_stop_compiling) {
             /* init_llvm_jit_functions_stage2 failed */
             /* init_llvm_jit_functions_stage2 failed */
             os_mutex_unlock(&module->tierup_wait_lock);
             os_mutex_unlock(&module->tierup_wait_lock);
@@ -2718,7 +2725,8 @@ create_module(char *error_buf, uint32 error_buf_size)
     bh_assert(ret == BH_LIST_SUCCESS);
     bh_assert(ret == BH_LIST_SUCCESS);
 #endif
 #endif
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     if (os_mutex_init(&module->instance_list_lock) != 0) {
     if (os_mutex_init(&module->instance_list_lock) != 0) {
         set_error_buf(error_buf, error_buf_size,
         set_error_buf(error_buf, error_buf_size,
                       "init instance list lock failed");
                       "init instance list lock failed");
@@ -2939,7 +2947,8 @@ wasm_loader_unload(WASMModule *module)
     if (!module)
     if (!module)
         return;
         return;
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     module->orcjit_stop_compiling = true;
     module->orcjit_stop_compiling = true;
     if (module->llvm_jit_init_thread)
     if (module->llvm_jit_init_thread)
         os_thread_join(module->llvm_jit_init_thread, NULL);
         os_thread_join(module->llvm_jit_init_thread, NULL);
@@ -2960,7 +2969,8 @@ wasm_loader_unload(WASMModule *module)
         aot_destroy_comp_data(module->comp_data);
         aot_destroy_comp_data(module->comp_data);
 #endif
 #endif
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     if (module->tierup_wait_lock_inited) {
     if (module->tierup_wait_lock_inited) {
         os_mutex_destroy(&module->tierup_wait_lock);
         os_mutex_destroy(&module->tierup_wait_lock);
         os_cond_destroy(&module->tierup_wait_cond);
         os_cond_destroy(&module->tierup_wait_cond);
@@ -2995,9 +3005,9 @@ wasm_loader_unload(WASMModule *module)
                         module->functions[i]->fast_jit_jitted_code);
                         module->functions[i]->fast_jit_jitted_code);
                 }
                 }
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
 #if WASM_ENABLE_JIT != 0 && WASM_ENABLE_LAZY_JIT != 0
-                if (module->functions[i]->llvm_jit_func_ptr) {
+                if (module->functions[i]->call_to_fast_jit_from_llvm_jit) {
                     jit_code_cache_free(
                     jit_code_cache_free(
-                        module->functions[i]->llvm_jit_func_ptr);
+                        module->functions[i]->call_to_fast_jit_from_llvm_jit);
                 }
                 }
 #endif
 #endif
 #endif
 #endif
@@ -3056,7 +3066,8 @@ wasm_loader_unload(WASMModule *module)
     }
     }
 #endif
 #endif
 
 
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT && WASM_ENABLE_LAZY_JIT != 0
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
     os_mutex_destroy(&module->instance_list_lock);
     os_mutex_destroy(&module->instance_list_lock);
 #endif
 #endif
 
 

+ 234 - 56
core/iwasm/interpreter/wasm_runtime.c

@@ -737,13 +737,12 @@ functions_instantiate(const WASMModule *module, WASMModuleInstance *module_inst,
 
 
         function++;
         function++;
     }
     }
+    bh_assert((uint32)(function - functions) == function_count);
 
 
 #if WASM_ENABLE_FAST_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0
     module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
     module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
 #endif
 #endif
 
 
-    bh_assert((uint32)(function - functions) == function_count);
-    (void)module_inst;
     return functions;
     return functions;
 }
 }
 
 
@@ -1288,9 +1287,8 @@ init_func_ptrs(WASMModuleInstance *module_inst, WASMModule *module,
         *func_ptrs = import_func->func_ptr_linked;
         *func_ptrs = import_func->func_ptr_linked;
     }
     }
 
 
-    /* Set defined function pointers */
-    bh_memcpy_s(func_ptrs, sizeof(void *) * module->function_count,
-                module->func_ptrs, sizeof(void *) * module->function_count);
+    /* The defined function pointers will be set in
+       wasm_runtime_set_running_mode, no need to set them here */
     return true;
     return true;
 }
 }
 #endif /* end of WASM_ENABLE_JIT != 0 */
 #endif /* end of WASM_ENABLE_JIT != 0 */
@@ -1336,6 +1334,173 @@ init_func_type_indexes(WASMModuleInstance *module_inst, char *error_buf,
 }
 }
 #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
 #endif /* end of WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 */
 
 
+static bool
+set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode,
+                 bool first_time_set)
+{
+    WASMModule *module = module_inst->module;
+
+    if (running_mode == Mode_Default) {
+#if WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT == 0
+        running_mode = Mode_Interp;
+#elif WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT == 0
+        running_mode = Mode_Fast_JIT;
+#elif WASM_ENABLE_FAST_JIT == 0 && WASM_ENABLE_JIT != 0
+        running_mode = Mode_LLVM_JIT;
+#else /* WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 */
+#if WASM_ENABLE_LAZY_JIT == 0
+        running_mode = Mode_LLVM_JIT;
+#else
+        running_mode = Mode_Multi_Tier_JIT;
+#endif
+#endif
+    }
+
+    if (!wasm_runtime_is_running_mode_supported(running_mode))
+        return false;
+
+#if !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+      && WASM_ENABLE_LAZY_JIT != 0) /* No possible multi-tier JIT */
+    module_inst->e->running_mode = running_mode;
+
+    if (running_mode == Mode_Interp) {
+        /* Do nothing for Mode_Interp */
+    }
+    else if (running_mode == Mode_Fast_JIT) {
+        /* Do nothing for Mode_Fast_JIT since
+           module_inst->fast_jit_func_ptrs is same as
+           module->fast_jit_func_ptrs */
+    }
+#if WASM_ENABLE_JIT != 0
+    else if (running_mode == Mode_LLVM_JIT) {
+        /* Set defined function pointers */
+        bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
+                    sizeof(void *) * module->function_count, module->func_ptrs,
+                    sizeof(void *) * module->function_count);
+    }
+#endif
+    else {
+        bh_assert(0);
+    }
+#else /* Possible multi-tier JIT */
+    os_mutex_lock(&module->instance_list_lock);
+
+    module_inst->e->running_mode = running_mode;
+
+    if (running_mode == Mode_Interp) {
+        /* Do nothing for Mode_Interp */
+    }
+#if WASM_ENABLE_FAST_JIT != 0
+    else if (running_mode == Mode_Fast_JIT) {
+        JitGlobals *jit_globals = jit_compiler_get_jit_globals();
+        uint32 i;
+
+        /* Allocate memory for fast_jit_func_ptrs if needed */
+        if (!module_inst->fast_jit_func_ptrs
+            || module_inst->fast_jit_func_ptrs == module->fast_jit_func_ptrs) {
+            uint64 total_size = (uint64)sizeof(void *) * module->function_count;
+            if (!(module_inst->fast_jit_func_ptrs =
+                      runtime_malloc(total_size, NULL, 0))) {
+                os_mutex_unlock(&module->instance_list_lock);
+                return false;
+            }
+        }
+
+        for (i = 0; i < module->function_count; i++) {
+            if (module->functions[i]->fast_jit_jitted_code) {
+                /* current fast jit function has been compiled */
+                module_inst->fast_jit_func_ptrs[i] =
+                    module->functions[i]->fast_jit_jitted_code;
+            }
+            else {
+                module_inst->fast_jit_func_ptrs[i] =
+                    jit_globals->compile_fast_jit_and_then_call;
+            }
+        }
+    }
+#endif
+#if WASM_ENABLE_JIT != 0
+    else if (running_mode == Mode_LLVM_JIT) {
+        void **llvm_jit_func_ptrs;
+        uint32 i;
+
+        /* Notify backend threads to start llvm jit compilation */
+        module->enable_llvm_jit_compilation = true;
+
+        /* Wait until llvm jit finishes initialization */
+        os_mutex_lock(&module->tierup_wait_lock);
+        while (!module->llvm_jit_inited) {
+            os_cond_reltimedwait(&module->tierup_wait_cond,
+                                 &module->tierup_wait_lock, 10);
+            if (module->orcjit_stop_compiling) {
+                /* init_llvm_jit_functions_stage2 failed */
+                os_mutex_unlock(&module->tierup_wait_lock);
+                os_mutex_unlock(&module->instance_list_lock);
+                return false;
+            }
+        }
+        os_mutex_unlock(&module->tierup_wait_lock);
+
+        llvm_jit_func_ptrs =
+            module_inst->func_ptrs + module->import_function_count;
+        for (i = 0; i < module->function_count; i++) {
+            llvm_jit_func_ptrs[i] = module->functions[i]->llvm_jit_func_ptr;
+        }
+    }
+#endif
+    else if (running_mode == Mode_Multi_Tier_JIT) {
+        /* Notify backend threads to start llvm jit compilation */
+        module->enable_llvm_jit_compilation = true;
+
+        /* Free fast_jit_func_ptrs if it is allocated before */
+        if (module_inst->fast_jit_func_ptrs
+            && module_inst->fast_jit_func_ptrs != module->fast_jit_func_ptrs) {
+            wasm_runtime_free(module_inst->fast_jit_func_ptrs);
+        }
+        module_inst->fast_jit_func_ptrs = module->fast_jit_func_ptrs;
+
+        /* Copy all llvm jit func ptrs from the module */
+        bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
+                    sizeof(void *) * module->function_count, module->func_ptrs,
+                    sizeof(void *) * module->function_count);
+    }
+    else {
+        bh_assert(0);
+    }
+
+    /* Add module instance into module's instance list if not added */
+    if (first_time_set) {
+        bool found = false;
+        WASMModuleInstance *node = module->instance_list;
+
+        while (node) {
+            if (node == module_inst) {
+                found = true;
+                break;
+            }
+            node = node->e->next;
+        }
+
+        if (!found) {
+            module_inst->e->next = module->instance_list;
+            module->instance_list = module_inst;
+        }
+    }
+
+    os_mutex_unlock(&module->instance_list_lock);
+#endif /* end of !(WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+                   && WASM_ENABLE_LAZY_JIT != 0) */
+
+    (void)module;
+    return true;
+}
+
+bool
+wasm_set_running_mode(WASMModuleInstance *module_inst, RunningMode running_mode)
+{
+    return set_running_mode(module_inst, running_mode, false);
+}
+
 /**
 /**
  * Instantiate module
  * Instantiate module
  */
  */
@@ -1422,15 +1587,6 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
     module_inst->e =
     module_inst->e =
         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
         (WASMModuleInstanceExtra *)((uint8 *)module_inst + extra_info_offset);
 
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (os_mutex_init(&module_inst->e->mem_lock) != 0) {
-        set_error_buf(error_buf, error_buf_size,
-                      "create shared memory lock failed");
-        goto fail;
-    }
-    module_inst->e->mem_lock_inited = true;
-#endif
-
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
     module_inst->e->sub_module_inst_list =
     module_inst->e->sub_module_inst_list =
         &module_inst->e->sub_module_inst_list_head;
         &module_inst->e->sub_module_inst_list_head;
@@ -1803,33 +1959,39 @@ wasm_instantiate(WASMModule *module, bool is_sub_inst, uint32 stack_size,
     }
     }
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                         \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
-        && WASM_ENABLE_LAZY_JIT != 0)
+#if WASM_ENABLE_WASI_NN != 0
+    if (!is_sub_inst) {
+        if (!(module_inst->e->wasi_nn_ctx = wasi_nn_initialize())) {
+            set_error_buf(error_buf, error_buf_size,
+                          "wasi nn initialization failed");
+            goto fail;
+        }
+    }
+#endif
+
+#if WASM_ENABLE_DEBUG_INTERP != 0
     if (!is_sub_inst) {
     if (!is_sub_inst) {
         /* Add module instance into module's instance list */
         /* Add module instance into module's instance list */
         os_mutex_lock(&module->instance_list_lock);
         os_mutex_lock(&module->instance_list_lock);
-#if WASM_ENABLE_DEBUG_INTERP != 0
         if (module->instance_list) {
         if (module->instance_list) {
             LOG_WARNING(
             LOG_WARNING(
                 "warning: multiple instances referencing to the same module "
                 "warning: multiple instances referencing to the same module "
                 "may cause unexpected behaviour during debugging");
                 "may cause unexpected behaviour during debugging");
         }
         }
-#endif
-#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
-    && WASM_ENABLE_LAZY_JIT != 0
-        /* Copy llvm func ptrs again in case that they were updated
-           after the module instance was created */
-        bh_memcpy_s(module_inst->func_ptrs + module->import_function_count,
-                    sizeof(void *) * module->function_count, module->func_ptrs,
-                    sizeof(void *) * module->function_count);
-#endif
         module_inst->e->next = module->instance_list;
         module_inst->e->next = module->instance_list;
         module->instance_list = module_inst;
         module->instance_list = module_inst;
         os_mutex_unlock(&module->instance_list_lock);
         os_mutex_unlock(&module->instance_list_lock);
     }
     }
 #endif
 #endif
 
 
+    /* Set running mode before executing wasm functions */
+    if (!set_running_mode(module_inst, wasm_runtime_get_default_running_mode(),
+                          true)) {
+        set_error_buf(error_buf, error_buf_size,
+                      "set instance running mode failed");
+        goto fail;
+    }
+
     if (module->start_function != (uint32)-1) {
     if (module->start_function != (uint32)-1) {
         /* TODO: fix start function can be import function issue */
         /* TODO: fix start function can be import function issue */
         if (module->start_function >= module->import_function_count)
         if (module->start_function >= module->import_function_count)
@@ -1895,11 +2057,48 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
     if (!module_inst)
     if (!module_inst)
         return;
         return;
 
 
+#if WASM_ENABLE_DEBUG_INTERP != 0                         \
+    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+        && WASM_ENABLE_LAZY_JIT != 0)
+    /* Remove instance from module's instance list before freeing
+       func_ptrs and fast_jit_func_ptrs of the instance, to avoid
+       accessing the freed memory in the jit backend compilation
+       threads */
+    if (!is_sub_inst) {
+        WASMModule *module = module_inst->module;
+        WASMModuleInstance *instance_prev = NULL, *instance;
+        os_mutex_lock(&module->instance_list_lock);
+
+        instance = module->instance_list;
+        while (instance) {
+            if (instance == module_inst) {
+                if (!instance_prev)
+                    module->instance_list = instance->e->next;
+                else
+                    instance_prev->e->next = instance->e->next;
+                break;
+            }
+            instance_prev = instance;
+            instance = instance->e->next;
+        }
+
+        os_mutex_unlock(&module->instance_list_lock);
+    }
+#endif
+
 #if WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_JIT != 0
     if (module_inst->func_ptrs)
     if (module_inst->func_ptrs)
         wasm_runtime_free(module_inst->func_ptrs);
         wasm_runtime_free(module_inst->func_ptrs);
 #endif
 #endif
 
 
+#if WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
+    && WASM_ENABLE_LAZY_JIT != 0
+    if (module_inst->fast_jit_func_ptrs
+        && module_inst->fast_jit_func_ptrs
+               != module_inst->module->fast_jit_func_ptrs)
+        wasm_runtime_free(module_inst->fast_jit_func_ptrs);
+#endif
+
 #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
 #if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0
     if (module_inst->func_type_indexes)
     if (module_inst->func_type_indexes)
         wasm_runtime_free(module_inst->func_type_indexes);
         wasm_runtime_free(module_inst->func_type_indexes);
@@ -1951,39 +2150,17 @@ wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst)
     }
     }
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                         \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
-        && WASM_ENABLE_LAZY_JIT != 0)
-    if (!is_sub_inst) {
-        WASMModule *module = module_inst->module;
-        WASMModuleInstance *instance_prev = NULL, *instance;
-        os_mutex_lock(&module->instance_list_lock);
-
-        instance = module->instance_list;
-        while (instance) {
-            if (instance == module_inst) {
-                if (!instance_prev)
-                    module->instance_list = instance->e->next;
-                else
-                    instance_prev->e->next = instance->e->next;
-                break;
-            }
-            instance_prev = instance;
-            instance = instance->e->next;
-        }
+    if (module_inst->e->c_api_func_imports)
+        wasm_runtime_free(module_inst->e->c_api_func_imports);
 
 
-        os_mutex_unlock(&module->instance_list_lock);
+#if WASM_ENABLE_WASI_NN != 0
+    if (!is_sub_inst) {
+        WASINNContext *wasi_nn_ctx = module_inst->e->wasi_nn_ctx;
+        if (wasi_nn_ctx)
+            wasi_nn_destroy(wasi_nn_ctx);
     }
     }
 #endif
 #endif
 
 
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    if (module_inst->e->mem_lock_inited)
-        os_mutex_destroy(&module_inst->e->mem_lock);
-#endif
-
-    if (module_inst->e->c_api_func_imports)
-        wasm_runtime_free(module_inst->e->c_api_func_imports);
-
     wasm_runtime_free(module_inst);
     wasm_runtime_free(module_inst);
 }
 }
 
 
@@ -2056,6 +2233,7 @@ call_wasm_with_hw_bound_check(WASMModuleInstance *module_inst,
     /* Check native stack overflow firstly to ensure we have enough
     /* Check native stack overflow firstly to ensure we have enough
        native stack to run the following codes before actually calling
        native stack to run the following codes before actually calling
        the aot function in invokeNative function. */
        the aot function in invokeNative function. */
+    RECORD_STACK_USAGE(exec_env, (uint8 *)&exec_env_tls);
     if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary
     if ((uint8 *)&exec_env_tls < exec_env->native_stack_boundary
                                      + page_size * (guard_page_count + 1)) {
                                      + page_size * (guard_page_count + 1)) {
         wasm_set_exception(module_inst, "native stack overflow");
         wasm_set_exception(module_inst, "native stack overflow");

+ 20 - 11
core/iwasm/interpreter/wasm_runtime.h

@@ -11,6 +11,10 @@
 #include "../common/wasm_runtime_common.h"
 #include "../common/wasm_runtime_common.h"
 #include "../common/wasm_exec_env.h"
 #include "../common/wasm_exec_env.h"
 
 
+#if WASM_ENABLE_WASI_NN != 0
+#include "../libraries/wasi-nn/src/wasi_nn_private.h"
+#endif
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 extern "C" {
 extern "C" {
 #endif
 #endif
@@ -59,9 +63,7 @@ typedef enum WASMExceptionID {
     EXCE_AUX_STACK_UNDERFLOW,
     EXCE_AUX_STACK_UNDERFLOW,
     EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
     EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
     EXCE_OPERAND_STACK_OVERFLOW,
     EXCE_OPERAND_STACK_OVERFLOW,
-#if WASM_ENABLE_FAST_JIT != 0
     EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
     EXCE_FAILED_TO_COMPILE_FAST_JIT_FUNC,
-#endif
     EXCE_ALREADY_THROWN,
     EXCE_ALREADY_THROWN,
     EXCE_NUM,
     EXCE_NUM,
 } WASMExceptionID;
 } WASMExceptionID;
@@ -219,12 +221,7 @@ typedef struct WASMModuleInstanceExtra {
     WASMFunctionInstance *retain_function;
     WASMFunctionInstance *retain_function;
 
 
     CApiFuncImport *c_api_func_imports;
     CApiFuncImport *c_api_func_imports;
-
-#if WASM_ENABLE_SHARED_MEMORY != 0
-    /* lock for shared memory atomic operations */
-    korp_mutex mem_lock;
-    bool mem_lock_inited;
-#endif
+    RunningMode running_mode;
 
 
 #if WASM_ENABLE_MULTI_MODULE != 0
 #if WASM_ENABLE_MULTI_MODULE != 0
     bh_list sub_module_inst_list_head;
     bh_list sub_module_inst_list_head;
@@ -237,11 +234,15 @@ typedef struct WASMModuleInstanceExtra {
     uint32 max_aux_stack_used;
     uint32 max_aux_stack_used;
 #endif
 #endif
 
 
-#if WASM_ENABLE_DEBUG_INTERP != 0                    \
-    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT \
+#if WASM_ENABLE_DEBUG_INTERP != 0                         \
+    || (WASM_ENABLE_FAST_JIT != 0 && WASM_ENABLE_JIT != 0 \
         && WASM_ENABLE_LAZY_JIT != 0)
         && WASM_ENABLE_LAZY_JIT != 0)
     WASMModuleInstance *next;
     WASMModuleInstance *next;
 #endif
 #endif
+
+#if WASM_ENABLE_WASI_NN != 0
+    WASINNContext *wasi_nn_ctx;
+#endif
 } WASMModuleInstanceExtra;
 } WASMModuleInstanceExtra;
 
 
 struct AOTFuncPerfProfInfo;
 struct AOTFuncPerfProfInfo;
@@ -298,7 +299,11 @@ struct WASMModuleInstance {
        not available in AOTModuleInstance */
        not available in AOTModuleInstance */
     DefPointer(void **, import_func_ptrs);
     DefPointer(void **, import_func_ptrs);
     /* Array of function pointers to fast jit functions,
     /* Array of function pointers to fast jit functions,
-       not available in AOTModuleInstance */
+       not available in AOTModuleInstance:
+       Only when the multi-tier JIT macros are all enabled and the running
+       mode of current module instance is set to Mode_Fast_JIT, runtime
+       will allocate new memory for it, otherwise it always points to the
+       module->fast_jit_func_ptrs */
     DefPointer(void **, fast_jit_func_ptrs);
     DefPointer(void **, fast_jit_func_ptrs);
     /* The custom data that can be set/get by wasm_{get|set}_custom_data */
     /* The custom data that can be set/get by wasm_{get|set}_custom_data */
     DefPointer(void *, custom_data);
     DefPointer(void *, custom_data);
@@ -402,6 +407,10 @@ wasm_dump_perf_profiling(const WASMModuleInstance *module_inst);
 void
 void
 wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
 wasm_deinstantiate(WASMModuleInstance *module_inst, bool is_sub_inst);
 
 
+bool
+wasm_set_running_mode(WASMModuleInstance *module_inst,
+                      RunningMode running_mode);
+
 WASMFunctionInstance *
 WASMFunctionInstance *
 wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
 wasm_lookup_function(const WASMModuleInstance *module_inst, const char *name,
                      const char *signature);
                      const char *signature);

+ 41 - 0
core/iwasm/libraries/lib-pthread/lib_pthread_wrapper.c

@@ -565,6 +565,7 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
 #if WASM_ENABLE_LIBC_WASI != 0
 #if WASM_ENABLE_LIBC_WASI != 0
     WASIContext *wasi_ctx;
     WASIContext *wasi_ctx;
 #endif
 #endif
+    CApiFuncImport **new_c_api_func_imports = NULL;
 
 
     bh_assert(module);
     bh_assert(module);
     bh_assert(module_inst);
     bh_assert(module_inst);
@@ -597,6 +598,46 @@ pthread_create_wrapper(wasm_exec_env_t exec_env,
         wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
         wasm_runtime_set_wasi_ctx(new_module_inst, wasi_ctx);
 #endif
 #endif
 
 
+    /* workaround about passing instantiate-linking information */
+    {
+        CApiFuncImport *c_api_func_imports;
+        uint32 import_func_count = 0;
+        uint32 size_in_bytes = 0;
+
+#if WASM_ENABLE_INTERP != 0
+        if (module_inst->module_type == Wasm_Module_Bytecode) {
+            new_c_api_func_imports = &(
+                ((WASMModuleInstance *)new_module_inst)->e->c_api_func_imports);
+            c_api_func_imports =
+                ((WASMModuleInstance *)module_inst)->e->c_api_func_imports;
+            import_func_count = ((WASMModule *)module)->import_function_count;
+        }
+#endif
+#if WASM_ENABLE_AOT != 0
+        if (module_inst->module_type == Wasm_Module_AoT) {
+            AOTModuleInstanceExtra *e =
+                (AOTModuleInstanceExtra *)((AOTModuleInstance *)new_module_inst)
+                    ->e;
+            new_c_api_func_imports = &(e->c_api_func_imports);
+
+            e = (AOTModuleInstanceExtra *)((AOTModuleInstance *)module_inst)->e;
+            c_api_func_imports = e->c_api_func_imports;
+
+            import_func_count = ((AOTModule *)module)->import_func_count;
+        }
+#endif
+
+        if (import_func_count != 0 && c_api_func_imports) {
+            size_in_bytes = sizeof(CApiFuncImport *) * import_func_count;
+            *new_c_api_func_imports = wasm_runtime_malloc(size_in_bytes);
+            if (!(*new_c_api_func_imports))
+                goto fail;
+
+            bh_memcpy_s(*new_c_api_func_imports, size_in_bytes,
+                        c_api_func_imports, size_in_bytes);
+        }
+    }
+
     if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
     if (!(info_node = wasm_runtime_malloc(sizeof(ThreadInfoNode))))
         goto fail;
         goto fail;
 
 

+ 103 - 7
core/iwasm/libraries/libc-wasi/libc_wasi_wrapper.c

@@ -63,6 +63,12 @@ typedef struct WASIContext {
 wasi_ctx_t
 wasi_ctx_t
 wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
 wasm_runtime_get_wasi_ctx(wasm_module_inst_t module_inst);
 
 
+static inline size_t
+min(size_t a, size_t b)
+{
+    return a > b ? b : a;
+}
+
 static inline struct fd_table *
 static inline struct fd_table *
 wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
 wasi_ctx_get_curfds(wasm_module_inst_t module_inst, wasi_ctx_t wasi_ctx)
 {
 {
@@ -951,6 +957,97 @@ wasi_path_remove_directory(wasm_exec_env_t exec_env, wasi_fd_t fd,
     return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
     return wasmtime_ssp_path_remove_directory(curfds, fd, path, path_len);
 }
 }
 
 
+#if WASM_ENABLE_THREAD_MGR != 0
+static __wasi_timestamp_t
+get_timeout_for_poll_oneoff(const wasi_subscription_t *in,
+                            uint32 nsubscriptions)
+{
+    __wasi_timestamp_t timeout = (__wasi_timestamp_t)-1;
+    uint32 i = 0;
+
+    for (i = 0; i < nsubscriptions; ++i) {
+        const __wasi_subscription_t *s = &in[i];
+        if (s->u.type == __WASI_EVENTTYPE_CLOCK
+            && (s->u.u.clock.flags & __WASI_SUBSCRIPTION_CLOCK_ABSTIME) == 0) {
+            timeout = min(timeout, s->u.u.clock.timeout);
+        }
+    }
+    return timeout;
+}
+
+static void
+update_clock_subscription_data(wasi_subscription_t *in, uint32 nsubscriptions,
+                               const wasi_timestamp_t new_timeout)
+{
+    uint32 i = 0;
+    for (i = 0; i < nsubscriptions; ++i) {
+        __wasi_subscription_t *s = &in[i];
+        if (s->u.type == __WASI_EVENTTYPE_CLOCK) {
+            s->u.u.clock.timeout = new_timeout;
+        }
+    }
+}
+
+static wasi_errno_t
+execute_interruptible_poll_oneoff(wasm_module_inst_t module_inst,
+#if !defined(WASMTIME_SSP_STATIC_CURFDS)
+                                  struct fd_table *curfds,
+#endif
+                                  const __wasi_subscription_t *in,
+                                  __wasi_event_t *out, size_t nsubscriptions,
+                                  size_t *nevents)
+{
+    if (nsubscriptions == 0) {
+        *nevents = 0;
+        return __WASI_ESUCCESS;
+    }
+
+    wasi_errno_t err;
+    __wasi_timestamp_t elapsed = 0;
+
+    const __wasi_timestamp_t timeout = get_timeout_for_poll_oneoff(
+                                 in, nsubscriptions),
+                             time_quant = 1e9;
+    const uint64 size_to_copy =
+        nsubscriptions * (uint64)sizeof(wasi_subscription_t);
+    __wasi_subscription_t *in_copy = NULL;
+
+    if (size_to_copy >= UINT32_MAX
+        || !(in_copy = (__wasi_subscription_t *)wasm_runtime_malloc(
+                 (uint32)size_to_copy))) {
+        return __WASI_ENOMEM;
+    }
+
+    bh_memcpy_s(in_copy, size_to_copy, in, size_to_copy);
+
+    while (timeout == (__wasi_timestamp_t)-1 || elapsed <= timeout) {
+        elapsed += time_quant;
+
+        /* update timeout for clock subscription events */
+        update_clock_subscription_data(in_copy, nsubscriptions,
+                                       min(time_quant, timeout - elapsed));
+        err = wasmtime_ssp_poll_oneoff(curfds, in_copy, out, nsubscriptions,
+                                       nevents);
+        if (err) {
+            wasm_runtime_free(in_copy);
+            return err;
+        }
+
+        if (wasm_runtime_get_exception(module_inst) || *nevents > 0) {
+            wasm_runtime_free(in_copy);
+
+            if (*nevents) {
+                return __WASI_ESUCCESS;
+            }
+            return EINTR;
+        }
+    }
+
+    wasm_runtime_free(in_copy);
+    return __WASI_ESUCCESS;
+}
+#endif
+
 static wasi_errno_t
 static wasi_errno_t
 wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
 wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
                  wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
                  wasi_event_t *out, uint32 nsubscriptions, uint32 *nevents_app)
@@ -958,7 +1055,7 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasm_module_inst_t module_inst = get_module_inst(exec_env);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
     wasi_ctx_t wasi_ctx = get_wasi_ctx(module_inst);
     struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
     struct fd_table *curfds = wasi_ctx_get_curfds(module_inst, wasi_ctx);
-    size_t nevents;
+    size_t nevents = 0;
     wasi_errno_t err;
     wasi_errno_t err;
 
 
     if (!wasi_ctx)
     if (!wasi_ctx)
@@ -969,7 +1066,12 @@ wasi_poll_oneoff(wasm_exec_env_t exec_env, const wasi_subscription_t *in,
         || !validate_native_addr(nevents_app, sizeof(uint32)))
         || !validate_native_addr(nevents_app, sizeof(uint32)))
         return (wasi_errno_t)-1;
         return (wasi_errno_t)-1;
 
 
+#if WASM_ENABLE_THREAD_MGR == 0
     err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
     err = wasmtime_ssp_poll_oneoff(curfds, in, out, nsubscriptions, &nevents);
+#else
+    err = execute_interruptible_poll_oneoff(module_inst, curfds, in, out,
+                                            nsubscriptions, &nevents);
+#endif
     if (err)
     if (err)
         return err;
         return err;
 
 
@@ -1861,12 +1963,6 @@ allocate_iovec_app_buffer(wasm_module_inst_t module_inst,
     return __WASI_ESUCCESS;
     return __WASI_ESUCCESS;
 }
 }
 
 
-static inline size_t
-min(size_t a, size_t b)
-{
-    return a > b ? b : a;
-}
-
 static wasi_errno_t
 static wasi_errno_t
 copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
 copy_buffer_to_iovec_app(wasm_module_inst_t module_inst, uint8 *buf_begin,
                          uint32 buf_size, iovec_app_t *data, uint32 data_len,
                          uint32 buf_size, iovec_app_t *data, uint32 data_len,

+ 14 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/gnuc.h

@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2023 Amazon.com, Inc. or its affiliates. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#if !defined(__GNUC_PREREQ) && (defined(__GNUC__) || defined(__GNUG__)) \
+    && !defined(__clang__) && defined(__GNUC_MINOR__)
+/* Depending on the platform the macro is defined in sys/features.h or
+   features.h Given the macro is simple, we re-implement it here instead of
+   dealing with two different paths.
+ */
+#define __GNUC_PREREQ(maj, min) \
+    ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+#endif

+ 0 - 42
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/numeric_limits.h

@@ -1,42 +0,0 @@
-// Part of the Wasmtime Project, under the Apache License v2.0 with LLVM
-// Exceptions. See
-// https://github.com/bytecodealliance/wasmtime/blob/main/LICENSE for license
-// information.
-//
-// Significant parts of this file are derived from cloudabi-utils. See
-// https://github.com/bytecodealliance/wasmtime/blob/main/lib/wasi/sandboxed-system-primitives/src/LICENSE
-// for license information.
-//
-// The upstream file contains the following copyright notice:
-//
-// Copyright (c) 2015 Nuxi, https://nuxi.nl/
-
-#ifndef COMMON_LIMITS_H
-#define COMMON_LIMITS_H
-
-#define NUMERIC_MIN(t)                                    \
-    _Generic((t)0, char                                   \
-             : CHAR_MIN, signed char                      \
-             : SCHAR_MIN, unsigned char : 0, short        \
-             : SHRT_MIN, unsigned short : 0, int          \
-             : INT_MIN, unsigned int : 0, long            \
-             : LONG_MIN, unsigned long : 0, long long     \
-             : LLONG_MIN, unsigned long long : 0, default \
-             : (void)0)
-
-#define NUMERIC_MAX(t)                       \
-    _Generic((t)0, char                      \
-             : CHAR_MAX, signed char         \
-             : SCHAR_MAX, unsigned char      \
-             : UCHAR_MAX, short              \
-             : SHRT_MAX, unsigned short      \
-             : USHRT_MAX, int                \
-             : INT_MAX, unsigned int         \
-             : UINT_MAX, long                \
-             : LONG_MAX, unsigned long       \
-             : ULONG_MAX, long long          \
-             : LLONG_MAX, unsigned long long \
-             : ULLONG_MAX, default           \
-             : (void)0)
-
-#endif

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

@@ -15,7 +15,6 @@
 #include "bh_platform.h"
 #include "bh_platform.h"
 #include "wasmtime_ssp.h"
 #include "wasmtime_ssp.h"
 #include "locking.h"
 #include "locking.h"
-#include "numeric_limits.h"
 #include "posix.h"
 #include "posix.h"
 #include "random.h"
 #include "random.h"
 #include "refcount.h"
 #include "refcount.h"
@@ -2257,8 +2256,7 @@ convert_timestamp(__wasi_timestamp_t in, struct timespec *out)
     in /= 1000000000;
     in /= 1000000000;
 
 
     // Clamp to the maximum in case it would overflow our system's time_t.
     // Clamp to the maximum in case it would overflow our system's time_t.
-    out->tv_sec =
-        (time_t)in < NUMERIC_MAX(time_t) ? (time_t)in : NUMERIC_MAX(time_t);
+    out->tv_sec = (time_t)in < BH_TIME_T_MAX ? (time_t)in : BH_TIME_T_MAX;
 }
 }
 
 
 // Converts the provided timestamps and flags to a set of arguments for
 // Converts the provided timestamps and flags to a set of arguments for
@@ -3226,6 +3224,7 @@ wasi_ssp_sock_get_reuse_port(
 #else
 #else
     errno = ENOTSUP;
     errno = ENOTSUP;
     ret = BHT_ERROR;
     ret = BHT_ERROR;
+    optval = 0;
 #endif /* defined(SO_REUSEPORT) */
 #endif /* defined(SO_REUSEPORT) */
 
 
     fd_object_release(fo);
     fd_object_release(fo);

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

@@ -16,6 +16,7 @@
 
 
 #include "bh_platform.h"
 #include "bh_platform.h"
 #include "locking.h"
 #include "locking.h"
+#include "gnuc.h"
 
 
 #define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
 #define PRODUCES(...) LOCKS_SHARED(__VA_ARGS__) NO_LOCK_ANALYSIS
 #define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS
 #define CONSUMES(...) UNLOCKS(__VA_ARGS__) NO_LOCK_ANALYSIS
@@ -95,6 +96,42 @@ refcount_release(struct refcount *r)
     return old == 1;
     return old == 1;
 }
 }
 
 
+#elif defined(__GNUC_PREREQ)
+
+#if __GNUC_PREREQ(4, 7)
+
+struct refcount {
+    unsigned int count;
+};
+
+/* Initialize the reference counter. */
+static inline void
+refcount_init(struct refcount *r, unsigned int count)
+{
+    __atomic_store_n(&r->count, count, __ATOMIC_SEQ_CST);
+}
+
+/* Increment the reference counter. */
+static inline void
+refcount_acquire(struct refcount *r)
+{
+    __atomic_fetch_add(&r->count, 1, __ATOMIC_ACQUIRE);
+}
+
+/* Decrement the reference counter, returning whether the reference
+   dropped to zero. */
+static inline bool
+refcount_release(struct refcount *r)
+{
+    int old = (int)__atomic_fetch_sub(&r->count, 1, __ATOMIC_RELEASE);
+    bh_assert(old != 0 && "Reference count becoming negative");
+    return old == 1;
+}
+
+#else /* else of __GNUC_PREREQ (4.7) */
+#error "Reference counter isn't implemented"
+#endif /* end of __GNUC_PREREQ (4.7) */
+
 #else /* else of CONFIG_HAS_STD_ATOMIC */
 #else /* else of CONFIG_HAS_STD_ATOMIC */
 #error "Reference counter isn't implemented"
 #error "Reference counter isn't implemented"
 #endif /* end of CONFIG_HAS_STD_ATOMIC */
 #endif /* end of CONFIG_HAS_STD_ATOMIC */

+ 22 - 0
core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/ssp_config.h

@@ -14,6 +14,7 @@
 #ifndef SSP_CONFIG_H
 #ifndef SSP_CONFIG_H
 #define SSP_CONFIG_H
 #define SSP_CONFIG_H
 
 
+#include "gnuc.h"
 #include <stdlib.h>
 #include <stdlib.h>
 
 
 #if defined(__FreeBSD__) || defined(__APPLE__) \
 #if defined(__FreeBSD__) || defined(__APPLE__) \
@@ -107,10 +108,31 @@
 #endif
 #endif
 
 
 #if !defined(BH_PLATFORM_LINUX_SGX)
 #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)
 #define CONFIG_HAS_STD_ATOMIC 1
 #define CONFIG_HAS_STD_ATOMIC 1
 #else
 #else
 #define CONFIG_HAS_STD_ATOMIC 0
 #define CONFIG_HAS_STD_ATOMIC 0
 #endif
 #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 */
+#if __GNUC_PREREQ(4, 9)
+#define CONFIG_HAS_STD_ATOMIC 1
+#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) */
+#define CONFIG_HAS_STD_ATOMIC 1
+#endif /* end of defined(__GNUC_PREREQ) */
+#else  /* else of !defined(BH_PLATFORM_LINUX_SGX) */
+#define CONFIG_HAS_STD_ATOMIC 0
+#endif /* end of !defined(BH_PLATFORM_LINUX_SGX) */
 
 
 #if !defined(__NuttX__)
 #if !defined(__NuttX__)
 #define CONFIG_HAS_D_INO 1
 #define CONFIG_HAS_D_INO 1

+ 76 - 20
core/iwasm/libraries/thread-mgr/thread_manager.c

@@ -76,6 +76,58 @@ traverse_list(bh_list *l, list_visitor visitor, void *user_data)
     }
     }
 }
 }
 
 
+/* Assumes cluster->lock is locked */
+static bool
+safe_traverse_exec_env_list(WASMCluster *cluster, list_visitor visitor,
+                            void *user_data)
+{
+    Vector proc_nodes;
+    void *node;
+    bool ret = true;
+
+    if (!bh_vector_init(&proc_nodes, cluster->exec_env_list.len, sizeof(void *),
+                        false)) {
+        ret = false;
+        goto final;
+    }
+
+    node = bh_list_first_elem(&cluster->exec_env_list);
+
+    while (node) {
+        bool already_processed = false;
+        void *proc_node;
+        for (size_t i = 0; i < bh_vector_size(&proc_nodes); i++) {
+            if (!bh_vector_get(&proc_nodes, i, &proc_node)) {
+                ret = false;
+                goto final;
+            }
+            if (proc_node == node) {
+                already_processed = true;
+                break;
+            }
+        }
+        if (already_processed) {
+            node = bh_list_elem_next(node);
+            continue;
+        }
+
+        os_mutex_unlock(&cluster->lock);
+        visitor(node, user_data);
+        os_mutex_lock(&cluster->lock);
+        if (!bh_vector_append(&proc_nodes, &node)) {
+            ret = false;
+            goto final;
+        }
+
+        node = bh_list_first_elem(&cluster->exec_env_list);
+    }
+
+final:
+    bh_vector_destroy(&proc_nodes);
+
+    return ret;
+}
+
 /* The caller must lock cluster->lock */
 /* The caller must lock cluster->lock */
 static bool
 static bool
 allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
 allocate_aux_stack(WASMExecEnv *exec_env, uint32 *start, uint32 *size)
@@ -344,7 +396,6 @@ wasm_cluster_del_exec_env(WASMCluster *cluster, WASMExecEnv *exec_env)
         os_mutex_unlock(&cluster->debug_inst->wait_lock);
         os_mutex_unlock(&cluster->debug_inst->wait_lock);
     }
     }
 #endif
 #endif
-
     if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
     if (bh_list_remove(&cluster->exec_env_list, exec_env) != 0)
         ret = false;
         ret = false;
 
 
@@ -478,7 +529,7 @@ fail4:
     /* free the allocated aux stack space */
     /* free the allocated aux stack space */
     free_aux_stack(exec_env, aux_stack_start);
     free_aux_stack(exec_env, aux_stack_start);
 fail3:
 fail3:
-    wasm_exec_env_destroy(new_exec_env);
+    wasm_exec_env_destroy_internal(new_exec_env);
 fail2:
 fail2:
     wasm_runtime_deinstantiate_internal(new_module_inst, true);
     wasm_runtime_deinstantiate_internal(new_module_inst, true);
 fail1:
 fail1:
@@ -616,7 +667,7 @@ fail3:
     if (alloc_aux_stack)
     if (alloc_aux_stack)
         free_aux_stack(exec_env, aux_stack_start);
         free_aux_stack(exec_env, aux_stack_start);
 fail2:
 fail2:
-    wasm_exec_env_destroy(new_exec_env);
+    wasm_exec_env_destroy_internal(new_exec_env);
 fail1:
 fail1:
     os_mutex_unlock(&cluster->lock);
     os_mutex_unlock(&cluster->lock);
 
 
@@ -786,16 +837,22 @@ wasm_cluster_join_thread(WASMExecEnv *exec_env, void **ret_val)
     korp_tid handle;
     korp_tid handle;
 
 
     os_mutex_lock(&cluster_list_lock);
     os_mutex_lock(&cluster_list_lock);
+    os_mutex_lock(&exec_env->cluster->lock);
+
     if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
     if (!clusters_have_exec_env(exec_env) || exec_env->thread_is_detached) {
         /* Invalid thread, thread has exited or thread has been detached */
         /* Invalid thread, thread has exited or thread has been detached */
         if (ret_val)
         if (ret_val)
             *ret_val = NULL;
             *ret_val = NULL;
+        os_mutex_unlock(&exec_env->cluster->lock);
         os_mutex_unlock(&cluster_list_lock);
         os_mutex_unlock(&cluster_list_lock);
         return 0;
         return 0;
     }
     }
     exec_env->wait_count++;
     exec_env->wait_count++;
     handle = exec_env->handle;
     handle = exec_env->handle;
+
+    os_mutex_unlock(&exec_env->cluster->lock);
     os_mutex_unlock(&cluster_list_lock);
     os_mutex_unlock(&cluster_list_lock);
+
     return os_thread_join(handle, ret_val);
     return os_thread_join(handle, ret_val);
 }
 }
 
 
@@ -878,15 +935,22 @@ int32
 wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
 wasm_cluster_cancel_thread(WASMExecEnv *exec_env)
 {
 {
     os_mutex_lock(&cluster_list_lock);
     os_mutex_lock(&cluster_list_lock);
+    os_mutex_lock(&exec_env->cluster->lock);
+
+    if (!exec_env->cluster) {
+        goto final;
+    }
     if (!clusters_have_exec_env(exec_env)) {
     if (!clusters_have_exec_env(exec_env)) {
         /* Invalid thread or the thread has exited */
         /* Invalid thread or the thread has exited */
-        os_mutex_unlock(&cluster_list_lock);
-        return 0;
+        goto final;
     }
     }
-    os_mutex_unlock(&cluster_list_lock);
 
 
     set_thread_cancel_flags(exec_env);
     set_thread_cancel_flags(exec_env);
 
 
+final:
+    os_mutex_unlock(&exec_env->cluster->lock);
+    os_mutex_unlock(&cluster_list_lock);
+
     return 0;
     return 0;
 }
 }
 
 
@@ -908,11 +972,9 @@ wasm_cluster_terminate_all(WASMCluster *cluster)
 {
 {
     os_mutex_lock(&cluster->lock);
     os_mutex_lock(&cluster->lock);
     cluster->processing = true;
     cluster->processing = true;
-    os_mutex_unlock(&cluster->lock);
 
 
-    traverse_list(&cluster->exec_env_list, terminate_thread_visitor, NULL);
+    safe_traverse_exec_env_list(cluster, terminate_thread_visitor, NULL);
 
 
-    os_mutex_lock(&cluster->lock);
     cluster->processing = false;
     cluster->processing = false;
     os_mutex_unlock(&cluster->lock);
     os_mutex_unlock(&cluster->lock);
 }
 }
@@ -923,12 +985,10 @@ wasm_cluster_terminate_all_except_self(WASMCluster *cluster,
 {
 {
     os_mutex_lock(&cluster->lock);
     os_mutex_lock(&cluster->lock);
     cluster->processing = true;
     cluster->processing = true;
-    os_mutex_unlock(&cluster->lock);
 
 
-    traverse_list(&cluster->exec_env_list, terminate_thread_visitor,
-                  (void *)exec_env);
+    safe_traverse_exec_env_list(cluster, terminate_thread_visitor,
+                                (void *)exec_env);
 
 
-    os_mutex_lock(&cluster->lock);
     cluster->processing = false;
     cluster->processing = false;
     os_mutex_unlock(&cluster->lock);
     os_mutex_unlock(&cluster->lock);
 }
 }
@@ -950,11 +1010,9 @@ wams_cluster_wait_for_all(WASMCluster *cluster)
 {
 {
     os_mutex_lock(&cluster->lock);
     os_mutex_lock(&cluster->lock);
     cluster->processing = true;
     cluster->processing = true;
-    os_mutex_unlock(&cluster->lock);
 
 
-    traverse_list(&cluster->exec_env_list, wait_for_thread_visitor, NULL);
+    safe_traverse_exec_env_list(cluster, wait_for_thread_visitor, NULL);
 
 
-    os_mutex_lock(&cluster->lock);
     cluster->processing = false;
     cluster->processing = false;
     os_mutex_unlock(&cluster->lock);
     os_mutex_unlock(&cluster->lock);
 }
 }
@@ -965,12 +1023,10 @@ wasm_cluster_wait_for_all_except_self(WASMCluster *cluster,
 {
 {
     os_mutex_lock(&cluster->lock);
     os_mutex_lock(&cluster->lock);
     cluster->processing = true;
     cluster->processing = true;
-    os_mutex_unlock(&cluster->lock);
 
 
-    traverse_list(&cluster->exec_env_list, wait_for_thread_visitor,
-                  (void *)exec_env);
+    safe_traverse_exec_env_list(cluster, wait_for_thread_visitor,
+                                (void *)exec_env);
 
 
-    os_mutex_lock(&cluster->lock);
     cluster->processing = false;
     cluster->processing = false;
     os_mutex_unlock(&cluster->lock);
     os_mutex_unlock(&cluster->lock);
 }
 }

+ 0 - 1
core/iwasm/libraries/wasi-nn/.dockerignore

@@ -1 +0,0 @@
-**/Dockerfile

+ 56 - 7
core/iwasm/libraries/wasi-nn/README.md

@@ -17,17 +17,38 @@ By only including this file in your WASM application you will bind WASI-NN into
 To run the tests we assume that the current directory is the root of the repository.
 To run the tests we assume that the current directory is the root of the repository.
 
 
 
 
-1. Build the docker image,
+### Build the runtime
+
+Build the runtime base image,
 
 
 ```
 ```
-docker build -t wasi-nn -f core/iwasm/libraries/wasi-nn/test/Dockerfile .
+docker build -t wasi-nn-base -f core/iwasm/libraries/wasi-nn/test/Dockerfile.base .
 ```
 ```
 
 
-2. Run the container
+Build the runtime image for your execution target type.
+
+`EXECUTION_TYPE` can be:
+* `cpu`
+* `nvidia-gpu`
 
 
 ```
 ```
-docker run wasi-nn
+EXECUTION_TYPE=cpu
+docker build -t wasi-nn-${EXECUTION_TYPE} -f core/iwasm/libraries/wasi-nn/test/Dockerfile.${EXECUTION_TYPE} .
+```
+
+
+### Build wasm app
+
 ```
 ```
+docker build -t wasi-nn-compile -f core/iwasm/libraries/wasi-nn/test/Dockerfile.compile .
+```
+
+```
+docker run -v $PWD/core/iwasm/libraries/wasi-nn:/wasi-nn wasi-nn-compile
+```
+
+
+### Run wasm app
 
 
 If all the tests have run properly you will the the following message in the terminal,
 If all the tests have run properly you will the the following message in the terminal,
 
 
@@ -35,9 +56,37 @@ If all the tests have run properly you will the the following message in the ter
 Tests: passed!
 Tests: passed!
 ```
 ```
 
 
+* CPU
+
+```
+docker run \
+    -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-cpu \
+    --dir=/assets \
+    --env="TARGET=cpu" \
+    /assets/test_tensorflow.wasm
+```
+
+* (NVIDIA) GPU
+
+```
+docker run \
+    --runtime=nvidia \
+    -v $PWD/core/iwasm/libraries/wasi-nn/test:/assets wasi-nn-nvidia-gpu \
+    --dir=/assets \
+    --env="TARGET=gpu" \
+    /assets/test_tensorflow.wasm
+```
+
+Requirements:
+* [NVIDIA docker](https://github.com/NVIDIA/nvidia-docker).
+
 ## What is missing
 ## What is missing
 
 
-* Only 1 model at a time is supported.
+Supported:
+
+* Only 1 WASM app at a time.
+* Only 1 model at a time.
     * `graph` and `graph-execution-context` are ignored.
     * `graph` and `graph-execution-context` are ignored.
-* Only `tensorflow` (lite) is supported.
-* Only `cpu` is supported.
+* Graph encoding: `tensorflowlite`.
+* Execution target: `cpu` and `gpu`.
+* Tensor type: `fp32`.

+ 0 - 55
core/iwasm/libraries/wasi-nn/logger.h

@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2019 Intel Corporation.  All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
-
-#ifndef WASI_NN_LOGGER_H
-#define WASI_NN_LOGGER_H
-
-#include <stdio.h>
-#include <string.h>
-
-#define __FILENAME__ \
-    (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
-
-/* Disable a level by removing the define */
-#define ENABLE_ERR_LOG
-#define ENABLE_WARN_LOG
-#define ENABLE_DBG_LOG
-#define ENABLE_INFO_LOG
-
-// Definition of the levels
-#ifdef ENABLE_ERR_LOG
-#define NN_ERR_PRINTF(fmt, ...)                                    \
-    printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
-    printf("\n");                                                  \
-    fflush(stdout)
-#else
-#define NN_ERR_PRINTF(fmt, ...)
-#endif
-#ifdef ENABLE_WARN_LOG
-#define NN_WARN_PRINTF(fmt, ...)                                   \
-    printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
-    printf("\n");                                                  \
-    fflush(stdout)
-#else
-#define NN_WARN_PRINTF(fmt, ...)
-#endif
-#ifdef ENABLE_DBG_LOG
-#define NN_DBG_PRINTF(fmt, ...)                                    \
-    printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
-    printf("\n");                                                  \
-    fflush(stdout)
-#else
-#define NN_DBG_PRINTF(fmt, ...)
-#endif
-#ifdef ENABLE_INFO_LOG
-#define NN_INFO_PRINTF(fmt, ...)                                   \
-    printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
-    printf("\n");                                                  \
-    fflush(stdout)
-#else
-#define NN_INFO_PRINTF(fmt, ...)
-#endif
-
-#endif

+ 63 - 0
core/iwasm/libraries/wasi-nn/src/utils/logger.h

@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_LOGGER_H
+#define WASI_NN_LOGGER_H
+
+#include <stdio.h>
+#include <string.h>
+
+#define __FILENAME__ \
+    (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
+
+/* Disable a level by removing the define */
+#define ENABLE_ERR_LOG
+#define ENABLE_WARN_LOG
+#define ENABLE_DBG_LOG
+#define ENABLE_INFO_LOG
+
+// Definition of the levels
+#ifdef ENABLE_ERR_LOG
+#define NN_ERR_PRINTF(fmt, ...)                                        \
+    do {                                                               \
+        printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+        printf("\n");                                                  \
+        fflush(stdout);                                                \
+    } while (0)
+#else
+#define NN_ERR_PRINTF(fmt, ...)
+#endif
+#ifdef ENABLE_WARN_LOG
+#define NN_WARN_PRINTF(fmt, ...)                                       \
+    do {                                                               \
+        printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+        printf("\n");                                                  \
+        fflush(stdout);                                                \
+    } while (0)
+#else
+#define NN_WARN_PRINTF(fmt, ...)
+#endif
+#ifdef ENABLE_DBG_LOG
+#define NN_DBG_PRINTF(fmt, ...)                                        \
+    do {                                                               \
+        printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+        printf("\n");                                                  \
+        fflush(stdout);                                                \
+    } while (0)
+#else
+#define NN_DBG_PRINTF(fmt, ...)
+#endif
+#ifdef ENABLE_INFO_LOG
+#define NN_INFO_PRINTF(fmt, ...)                                       \
+    do {                                                               \
+        printf("[%s:%d] " fmt, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+        printf("\n");                                                  \
+        fflush(stdout);                                                \
+    } while (0)
+#else
+#define NN_INFO_PRINTF(fmt, ...)
+#endif
+
+#endif

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

@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasi_nn_app_native.h"
+
+static error
+graph_builder_app_native(wasm_module_inst_t instance,
+                         graph_builder_wasm *builder_wasm,
+                         graph_builder *builder)
+{
+    if (!wasm_runtime_validate_app_addr(instance, builder_wasm->buf_offset,
+                                        builder_wasm->size * sizeof(uint8_t))) {
+        NN_ERR_PRINTF("builder_wasm->buf_offset is invalid");
+        return invalid_argument;
+    }
+
+    builder->buf = (uint8_t *)wasm_runtime_addr_app_to_native(
+        instance, builder_wasm->buf_offset);
+    builder->size = builder_wasm->size;
+    return success;
+}
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+                               graph_builder_array_wasm *builder_array_wasm,
+                               graph_builder_array *builder_array)
+{
+    if (!wasm_runtime_validate_native_addr(instance, builder_array_wasm,
+                                           sizeof(graph_builder_array_wasm))) {
+        NN_ERR_PRINTF("builder_array_wasm is invalid");
+        return invalid_argument;
+    }
+
+    NN_DBG_PRINTF("Graph builder array contains %d elements",
+                  builder_array_wasm->size);
+
+    if (!wasm_runtime_validate_app_addr(
+            instance, builder_array_wasm->buf_offset,
+            builder_array_wasm->size * sizeof(graph_builder_wasm))) {
+        NN_ERR_PRINTF("builder_array_wasm->buf_offset is invalid");
+        return invalid_argument;
+    }
+
+    graph_builder_wasm *builder_wasm =
+        (graph_builder_wasm *)wasm_runtime_addr_app_to_native(
+            instance, builder_array_wasm->buf_offset);
+
+    graph_builder *builder = (graph_builder *)wasm_runtime_malloc(
+        builder_array_wasm->size * sizeof(graph_builder));
+    if (builder == NULL)
+        return missing_memory;
+
+    for (uint32_t i = 0; i < builder_array_wasm->size; ++i) {
+        error res;
+        if (success
+            != (res = graph_builder_app_native(instance, &builder_wasm[i],
+                                               &builder[i]))) {
+            wasm_runtime_free(builder);
+            return res;
+        }
+
+        NN_DBG_PRINTF("Graph builder %d contains %d elements", i,
+                      builder->size);
+    }
+
+    builder_array->buf = builder;
+    builder_array->size = builder_array_wasm->size;
+    return success;
+}
+
+static error
+tensor_data_app_native(wasm_module_inst_t instance, uint32_t total_elements,
+                       tensor_wasm *input_tensor_wasm, tensor_data *data)
+{
+    if (!wasm_runtime_validate_app_addr(
+            instance, input_tensor_wasm->data_offset, total_elements)) {
+        NN_ERR_PRINTF("input_tensor_wasm->data_offset is invalid");
+        return invalid_argument;
+    }
+    *data = (tensor_data)wasm_runtime_addr_app_to_native(
+        instance, input_tensor_wasm->data_offset);
+    return success;
+}
+
+static error
+tensor_dimensions_app_native(wasm_module_inst_t instance,
+                             tensor_wasm *input_tensor_wasm,
+                             tensor_dimensions **dimensions)
+{
+    if (!wasm_runtime_validate_app_addr(instance,
+                                        input_tensor_wasm->dimensions_offset,
+                                        sizeof(tensor_dimensions_wasm))) {
+        NN_ERR_PRINTF("input_tensor_wasm->dimensions_offset is invalid");
+        return invalid_argument;
+    }
+
+    tensor_dimensions_wasm *dimensions_wasm =
+        (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native(
+            instance, input_tensor_wasm->dimensions_offset);
+
+    if (!wasm_runtime_validate_app_addr(instance, dimensions_wasm->buf_offset,
+                                        sizeof(tensor_dimensions))) {
+        NN_ERR_PRINTF("dimensions_wasm->buf_offset is invalid");
+        return invalid_argument;
+    }
+
+    *dimensions =
+        (tensor_dimensions *)wasm_runtime_malloc(sizeof(tensor_dimensions));
+    if (dimensions == NULL)
+        return missing_memory;
+
+    (*dimensions)->size = dimensions_wasm->size;
+    (*dimensions)->buf = (uint32_t *)wasm_runtime_addr_app_to_native(
+        instance, dimensions_wasm->buf_offset);
+
+    NN_DBG_PRINTF("Number of dimensions: %d", (*dimensions)->size);
+    return success;
+}
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor_wasm,
+                  tensor *input_tensor)
+{
+    NN_DBG_PRINTF("Converting tensor_wasm to tensor");
+    if (!wasm_runtime_validate_native_addr(instance, input_tensor_wasm,
+                                           sizeof(tensor_wasm))) {
+        NN_ERR_PRINTF("input_tensor_wasm is invalid");
+        return invalid_argument;
+    }
+
+    error res;
+
+    tensor_dimensions *dimensions = NULL;
+    if (success
+        != (res = tensor_dimensions_app_native(instance, input_tensor_wasm,
+                                               &dimensions))) {
+        NN_ERR_PRINTF("error when parsing dimensions");
+        return res;
+    }
+
+    uint32_t total_elements = 1;
+    for (uint32_t i = 0; i < dimensions->size; ++i) {
+        total_elements *= dimensions->buf[i];
+        NN_DBG_PRINTF("Dimension %d: %d", i, dimensions->buf[i]);
+    }
+    NN_DBG_PRINTF("Tensor type: %d", input_tensor_wasm->type);
+    NN_DBG_PRINTF("Total number of elements: %d", total_elements);
+
+    tensor_data data = NULL;
+    if (success
+        != (res = tensor_data_app_native(instance, total_elements,
+                                         input_tensor_wasm, &data))) {
+        wasm_runtime_free(dimensions);
+        return res;
+    }
+
+    input_tensor->type = input_tensor_wasm->type;
+    input_tensor->dimensions = dimensions;
+    input_tensor->data = data;
+    return success;
+}

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

@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_APP_NATIVE
+#define WASI_NN_APP_NATIVE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "logger.h"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+
+typedef struct {
+    uint32_t buf_offset;
+    uint32_t size;
+} graph_builder_wasm;
+
+typedef struct {
+    uint32_t buf_offset;
+    uint32_t size;
+} graph_builder_array_wasm;
+
+typedef struct {
+    uint32_t buf_offset;
+    uint32_t size;
+} tensor_dimensions_wasm;
+
+typedef struct {
+    uint32_t dimensions_offset;
+    tensor_type type;
+    uint32_t data_offset;
+} tensor_wasm;
+
+error
+graph_builder_array_app_native(wasm_module_inst_t instance,
+                               graph_builder_array_wasm *builder,
+                               graph_builder_array *builder_native);
+
+error
+tensor_app_native(wasm_module_inst_t instance, tensor_wasm *input_tensor,
+                  tensor *input_tensor_native);
+
+#endif

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

@@ -0,0 +1,302 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+
+#include "wasi_nn.h"
+#include "wasi_nn_app_native.h"
+#include "logger.h"
+#include "wasi_nn_tensorflowlite.hpp"
+
+#include "bh_platform.h"
+#include "wasm_export.h"
+#include "wasm_runtime.h"
+#include "aot_runtime.h"
+
+/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
+
+typedef error (*LOAD)(graph_builder_array *, graph_encoding, execution_target,
+                      graph *);
+typedef error (*INIT_EXECUTION_CONTEXT)(graph, graph_execution_context *);
+typedef error (*SET_INPUT)(graph_execution_context, uint32_t, tensor *);
+typedef error (*COMPUTE)(graph_execution_context);
+typedef error (*GET_OUTPUT)(graph_execution_context, uint32_t, tensor_data,
+                            uint32_t *);
+
+typedef struct {
+    LOAD load;
+    INIT_EXECUTION_CONTEXT init_execution_context;
+    SET_INPUT set_input;
+    COMPUTE compute;
+    GET_OUTPUT get_output;
+} api_function;
+
+/* Global variables */
+
+static api_function lookup[] = {
+    { NULL, NULL, NULL, NULL, NULL },
+    { NULL, NULL, NULL, NULL, NULL },
+    { NULL, NULL, NULL, NULL, NULL },
+    { NULL, NULL, NULL, NULL, NULL },
+    { tensorflowlite_load, tensorflowlite_init_execution_context,
+      tensorflowlite_set_input, tensorflowlite_compute,
+      tensorflowlite_get_output }
+};
+
+/* Utils */
+
+static bool
+is_encoding_implemented(graph_encoding encoding)
+{
+    return lookup[encoding].load && lookup[encoding].init_execution_context
+           && lookup[encoding].set_input && lookup[encoding].compute
+           && lookup[encoding].get_output;
+}
+
+static error
+is_model_initialized(WASINNContext *wasi_nn_ctx)
+{
+    if (!wasi_nn_ctx->is_initialized) {
+        NN_ERR_PRINTF("Model not initialized.");
+        return runtime_error;
+    }
+    return success;
+}
+
+WASINNContext *
+wasm_runtime_get_wasi_nn_ctx(wasm_module_inst_t instance)
+{
+    WASINNContext *wasi_nn_ctx = NULL;
+#if WASM_ENABLE_INTERP != 0
+    if (instance->module_type == Wasm_Module_Bytecode) {
+        NN_DBG_PRINTF("Getting ctx from WASM");
+        WASMModuleInstance *module_inst = (WASMModuleInstance *)instance;
+        wasi_nn_ctx = ((WASMModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (instance->module_type == Wasm_Module_AoT) {
+        NN_DBG_PRINTF("Getting ctx from AOT");
+        AOTModuleInstance *module_inst = (AOTModuleInstance *)instance;
+        wasi_nn_ctx = ((AOTModuleInstanceExtra *)module_inst->e)->wasi_nn_ctx;
+    }
+#endif
+    bh_assert(wasi_nn_ctx != NULL);
+    NN_DBG_PRINTF("Returning ctx");
+    return wasi_nn_ctx;
+}
+
+/* WASI-NN implementation */
+
+error
+wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
+             graph_encoding encoding, execution_target target, graph *g)
+{
+    NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding,
+                  target);
+
+    if (!is_encoding_implemented(encoding)) {
+        NN_ERR_PRINTF("Encoding not supported.");
+        return invalid_encoding;
+    }
+
+    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(instance);
+
+    error res;
+    graph_builder_array builder_native = { 0 };
+    if (success
+        != (res = graph_builder_array_app_native(instance, builder,
+                                                 &builder_native)))
+        return res;
+
+    if (!wasm_runtime_validate_native_addr(instance, g, sizeof(graph))) {
+        NN_ERR_PRINTF("graph is invalid");
+        res = invalid_argument;
+        goto fail;
+    }
+
+    res = lookup[encoding].load(&builder_native, encoding, target, g);
+
+    NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res, *g);
+
+    WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+    wasi_nn_ctx->current_encoding = encoding;
+    wasi_nn_ctx->is_initialized = true;
+
+fail:
+    // XXX: Free intermediate structure pointers
+    if (builder_native.buf)
+        wasm_runtime_free(builder_native.buf);
+
+    return res;
+}
+
+error
+wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph g,
+                               graph_execution_context *ctx)
+{
+    NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...", g);
+
+    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(instance);
+    WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+    error res;
+    if (success != (res = is_model_initialized(wasi_nn_ctx)))
+        return res;
+
+    if (!wasm_runtime_validate_native_addr(instance, ctx,
+                                           sizeof(graph_execution_context))) {
+        NN_ERR_PRINTF("ctx is invalid");
+        return invalid_argument;
+    }
+
+    res = lookup[wasi_nn_ctx->current_encoding].init_execution_context(g, ctx);
+    *ctx = g;
+    NN_DBG_PRINTF(
+        "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res,
+        *ctx);
+    return res;
+}
+
+error
+wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
+                  uint32_t index, tensor_wasm *input_tensor)
+{
+    NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx,
+                  index);
+
+    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(instance);
+    WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+    error res;
+    if (success != (res = is_model_initialized(wasi_nn_ctx)))
+        return res;
+
+    tensor input_tensor_native = { 0 };
+    if (success
+        != (res = tensor_app_native(instance, input_tensor,
+                                    &input_tensor_native)))
+        return res;
+
+    res = lookup[wasi_nn_ctx->current_encoding].set_input(ctx, index,
+                                                          &input_tensor_native);
+
+    // XXX: Free intermediate structure pointers
+    if (input_tensor_native.dimensions)
+        wasm_runtime_free(input_tensor_native.dimensions);
+
+    NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res);
+    return res;
+}
+
+error
+wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
+{
+    NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx);
+
+    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(instance);
+    WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+    error res;
+    if (success != (res = is_model_initialized(wasi_nn_ctx)))
+        return res;
+
+    res = lookup[wasi_nn_ctx->current_encoding].compute(ctx);
+    NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res);
+    return res;
+}
+
+error
+wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
+                   uint32_t index, tensor_data output_tensor,
+                   uint32_t *output_tensor_size)
+{
+    NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx,
+                  index);
+
+    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
+    bh_assert(instance);
+    WASINNContext *wasi_nn_ctx = wasm_runtime_get_wasi_nn_ctx(instance);
+
+    error res;
+    if (success != (res = is_model_initialized(wasi_nn_ctx)))
+        return res;
+
+    if (!wasm_runtime_validate_native_addr(instance, output_tensor_size,
+                                           sizeof(uint32_t))) {
+        NN_ERR_PRINTF("output_tensor_size is invalid");
+        return invalid_argument;
+    }
+
+    res = lookup[wasi_nn_ctx->current_encoding].get_output(
+        ctx, index, output_tensor, output_tensor_size);
+    NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]",
+                  res, *output_tensor_size);
+    return res;
+}
+
+/* Non-exposed public functions */
+
+WASINNContext *
+wasi_nn_initialize()
+{
+    NN_DBG_PRINTF("Initializing wasi-nn");
+    WASINNContext *wasi_nn_ctx =
+        (WASINNContext *)wasm_runtime_malloc(sizeof(WASINNContext));
+    if (wasi_nn_ctx == NULL) {
+        NN_ERR_PRINTF("Error when allocating memory for WASI-NN context");
+        return NULL;
+    }
+    wasi_nn_ctx->is_initialized = true;
+    wasi_nn_ctx->current_encoding = 3;
+    return wasi_nn_ctx;
+}
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx)
+{
+    if (wasi_nn_ctx == NULL) {
+        NN_ERR_PRINTF(
+            "Error when deallocating memory. WASI-NN context is NULL");
+        return;
+    }
+    NN_DBG_PRINTF("Freeing wasi-nn");
+    NN_DBG_PRINTF("-> is_initialized: %d", wasi_nn_ctx->is_initialized);
+    NN_DBG_PRINTF("-> current_encoding: %d", wasi_nn_ctx->current_encoding);
+    tensorflowlite_destroy();
+    wasm_runtime_free(wasi_nn_ctx);
+}
+
+/* Register WASI-NN in WAMR */
+
+/* clang-format off */
+#define REG_NATIVE_FUNC(func_name, signature) \
+    { #func_name, wasi_nn_##func_name, signature, NULL }
+/* clang-format on */
+
+static NativeSymbol native_symbols_wasi_nn[] = {
+    REG_NATIVE_FUNC(load, "(*ii*)i"),
+    REG_NATIVE_FUNC(init_execution_context, "(i*)i"),
+    REG_NATIVE_FUNC(set_input, "(ii*)i"),
+    REG_NATIVE_FUNC(compute, "(i)i"),
+    REG_NATIVE_FUNC(get_output, "(ii**)i"),
+};
+
+uint32_t
+get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis)
+{
+    *p_libc_wasi_apis = native_symbols_wasi_nn;
+    return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol);
+}

+ 30 - 0
core/iwasm/libraries/wasi-nn/src/wasi_nn_private.h

@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_PRIVATE_H
+#define WASI_NN_PRIVATE_H
+
+#include "wasi_nn_types.h"
+
+typedef struct {
+    bool is_initialized;
+    graph_encoding current_encoding;
+} WASINNContext;
+
+/**
+ * @brief Initialize wasi-nn
+ *
+ */
+WASINNContext *
+wasi_nn_initialize();
+/**
+ * @brief Destroy wasi-nn on app exists
+ *
+ */
+
+void
+wasi_nn_destroy(WASINNContext *wasi_nn_ctx);
+
+#endif

+ 66 - 20
core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.cpp → core/iwasm/libraries/wasi-nn/src/wasi_nn_tensorflowlite.cpp

@@ -3,8 +3,10 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
  */
 
 
-#include "wasi_nn_tensorflow.hpp"
-#include "wasi_nn_common.h"
+#include "wasi_nn.h"
+#include "wasi_nn_tensorflowlite.hpp"
+#include "logger.h"
+
 #include "bh_common.h"
 #include "bh_common.h"
 #include "bh_platform.h"
 #include "bh_platform.h"
 #include "platform_common.h"
 #include "platform_common.h"
@@ -14,6 +16,7 @@
 #include <tensorflow/lite/model.h>
 #include <tensorflow/lite/model.h>
 #include <tensorflow/lite/optional_debug_tools.h>
 #include <tensorflow/lite/optional_debug_tools.h>
 #include <tensorflow/lite/error_reporter.h>
 #include <tensorflow/lite/error_reporter.h>
+#include <tensorflow/lite/delegates/gpu/delegate.h>
 
 
 /* Global variables */
 /* Global variables */
 
 
@@ -25,30 +28,30 @@ static char *model_pointer = NULL;
 /* WASI-NN (tensorflow) implementation */
 /* WASI-NN (tensorflow) implementation */
 
 
 error
 error
-tensorflow_load(graph_builder_array builder, graph_encoding encoding,
-                execution_target target, graph *graph)
+tensorflowlite_load(graph_builder_array *builder, graph_encoding encoding,
+                    execution_target target, graph *g)
 {
 {
     if (model_pointer != NULL) {
     if (model_pointer != NULL) {
         wasm_runtime_free(model_pointer);
         wasm_runtime_free(model_pointer);
         model_pointer = NULL;
         model_pointer = NULL;
     }
     }
 
 
-    if (builder.size != 1) {
+    if (builder->size != 1) {
         NN_ERR_PRINTF("Unexpected builder format.");
         NN_ERR_PRINTF("Unexpected builder format.");
         return invalid_argument;
         return invalid_argument;
     }
     }
 
 
-    if (encoding != tensorflow) {
-        NN_ERR_PRINTF("Encoding is not tensorflow.");
+    if (encoding != tensorflowlite) {
+        NN_ERR_PRINTF("Encoding is not tensorflowlite.");
         return invalid_argument;
         return invalid_argument;
     }
     }
 
 
-    if (target != cpu) {
-        NN_ERR_PRINTF("Only CPU target is supported.");
+    if (target != cpu && target != gpu) {
+        NN_ERR_PRINTF("Only CPU and GPU target is supported.");
         return invalid_argument;
         return invalid_argument;
     }
     }
 
 
-    uint32_t size = builder.buf[0].size;
+    uint32_t size = builder->buf[0].size;
 
 
     model_pointer = (char *)wasm_runtime_malloc(size);
     model_pointer = (char *)wasm_runtime_malloc(size);
     if (model_pointer == NULL) {
     if (model_pointer == NULL) {
@@ -56,7 +59,7 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding,
         return missing_memory;
         return missing_memory;
     }
     }
 
 
-    bh_memcpy_s(model_pointer, size, builder.buf[0].buf, size);
+    bh_memcpy_s(model_pointer, size, builder->buf[0].buf, size);
 
 
     model = tflite::FlatBufferModel::BuildFromBuffer(model_pointer, size, NULL);
     model = tflite::FlatBufferModel::BuildFromBuffer(model_pointer, size, NULL);
     if (model == NULL) {
     if (model == NULL) {
@@ -77,11 +80,34 @@ tensorflow_load(graph_builder_array builder, graph_encoding encoding,
         return missing_memory;
         return missing_memory;
     }
     }
 
 
+    bool use_default = false;
+    switch (target) {
+        case gpu:
+        {
+            // https://www.tensorflow.org/lite/performance/gpu
+            auto options = TfLiteGpuDelegateOptionsV2Default();
+            options.inference_preference =
+                TFLITE_GPU_INFERENCE_PREFERENCE_SUSTAINED_SPEED;
+            options.inference_priority1 =
+                TFLITE_GPU_INFERENCE_PRIORITY_MIN_LATENCY;
+            auto *delegate = TfLiteGpuDelegateV2Create(&options);
+            if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) {
+                NN_ERR_PRINTF("Error when enabling GPU delegate.");
+                use_default = true;
+            }
+            break;
+        }
+        default:
+            use_default = true;
+    }
+    if (use_default)
+        NN_WARN_PRINTF("Default encoding is CPU.");
+
     return success;
     return success;
 }
 }
 
 
 error
 error
-tensorflow_init_execution_context(graph graph)
+tensorflowlite_init_execution_context(graph g, graph_execution_context *ctx)
 {
 {
     if (interpreter == NULL) {
     if (interpreter == NULL) {
         NN_ERR_PRINTF("Non-initialized interpreter.");
         NN_ERR_PRINTF("Non-initialized interpreter.");
@@ -92,8 +118,8 @@ tensorflow_init_execution_context(graph graph)
 }
 }
 
 
 error
 error
-tensorflow_set_input(graph_execution_context ctx, uint32_t index,
-                     tensor *input_tensor)
+tensorflowlite_set_input(graph_execution_context ctx, uint32_t index,
+                         tensor *input_tensor)
 {
 {
     if (interpreter == NULL) {
     if (interpreter == NULL) {
         NN_ERR_PRINTF("Non-initialized interpreter.");
         NN_ERR_PRINTF("Non-initialized interpreter.");
@@ -113,11 +139,11 @@ tensorflow_set_input(graph_execution_context ctx, uint32_t index,
     }
     }
 
 
     uint32_t model_tensor_size = 1;
     uint32_t model_tensor_size = 1;
-    for (int i = 0; i < (int)tensor->dims->size; ++i)
+    for (int i = 0; i < tensor->dims->size; ++i)
         model_tensor_size *= (uint32_t)tensor->dims->data[i];
         model_tensor_size *= (uint32_t)tensor->dims->data[i];
 
 
     uint32_t input_tensor_size = 1;
     uint32_t input_tensor_size = 1;
-    for (int i = 0; i < input_tensor->dimensions->size; i++)
+    for (uint32_t i = 0; i < input_tensor->dimensions->size; i++)
         input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i];
         input_tensor_size *= (uint32_t)input_tensor->dimensions->buf[i];
 
 
     if (model_tensor_size != input_tensor_size) {
     if (model_tensor_size != input_tensor_size) {
@@ -136,7 +162,7 @@ tensorflow_set_input(graph_execution_context ctx, uint32_t index,
 }
 }
 
 
 error
 error
-tensorflow_compute(graph_execution_context ctx)
+tensorflowlite_compute(graph_execution_context ctx)
 {
 {
     if (interpreter == NULL) {
     if (interpreter == NULL) {
         NN_ERR_PRINTF("Non-initialized interpreter.");
         NN_ERR_PRINTF("Non-initialized interpreter.");
@@ -147,8 +173,9 @@ tensorflow_compute(graph_execution_context ctx)
 }
 }
 
 
 error
 error
-tensorflow_get_output(graph_execution_context context, uint32_t index,
-                      tensor_data output_tensor, uint32_t *output_tensor_size)
+tensorflowlite_get_output(graph_execution_context ctx, uint32_t index,
+                          tensor_data output_tensor,
+                          uint32_t *output_tensor_size)
 {
 {
     if (interpreter == NULL) {
     if (interpreter == NULL) {
         NN_ERR_PRINTF("Non-initialized interpreter.");
         NN_ERR_PRINTF("Non-initialized interpreter.");
@@ -178,7 +205,7 @@ tensorflow_get_output(graph_execution_context context, uint32_t index,
     }
     }
 
 
     float *tensor_f = interpreter->typed_output_tensor<float>(index);
     float *tensor_f = interpreter->typed_output_tensor<float>(index);
-    for (int i = 0; i < model_tensor_size; ++i)
+    for (uint32_t i = 0; i < model_tensor_size; ++i)
         NN_DBG_PRINTF("output: %f", tensor_f[i]);
         NN_DBG_PRINTF("output: %f", tensor_f[i]);
 
 
     *output_tensor_size = model_tensor_size;
     *output_tensor_size = model_tensor_size;
@@ -186,3 +213,22 @@ tensorflow_get_output(graph_execution_context context, uint32_t index,
                 model_tensor_size * sizeof(float));
                 model_tensor_size * sizeof(float));
     return success;
     return success;
 }
 }
+
+void
+tensorflowlite_destroy()
+{
+    /*
+        TensorFlow Lite memory is man
+
+        Related issues:
+        * https://github.com/tensorflow/tensorflow/issues/15880
+    */
+    NN_DBG_PRINTF("Freeing memory.");
+    model.reset(nullptr);
+    model = NULL;
+    interpreter.reset(nullptr);
+    interpreter = NULL;
+    wasm_runtime_free(model_pointer);
+    model_pointer = NULL;
+    NN_DBG_PRINTF("Memory free'd.");
+}

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

@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TENSORFLOWLITE_HPP
+#define WASI_NN_TENSORFLOWLITE_HPP
+
+#include "wasi_nn.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+error
+tensorflowlite_load(graph_builder_array *builder, graph_encoding encoding,
+                    execution_target target, graph *g);
+
+error
+tensorflowlite_init_execution_context(graph g, graph_execution_context *ctx);
+
+error
+tensorflowlite_set_input(graph_execution_context ctx, uint32_t index,
+                         tensor *input_tensor);
+
+error
+tensorflowlite_compute(graph_execution_context ctx);
+
+error
+tensorflowlite_get_output(graph_execution_context ctx, uint32_t index,
+                          tensor_data output_tensor,
+                          uint32_t *output_tensor_size);
+
+void
+tensorflowlite_destroy();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 2 - 2
core/iwasm/libraries/wasi-nn/test/CMakeLists.txt

@@ -7,10 +7,10 @@ project (iwasm)
 
 
 set (CMAKE_VERBOSE_MAKEFILE OFF)
 set (CMAKE_VERBOSE_MAKEFILE OFF)
 # Reset default linker flags
 # Reset default linker flags
-set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
-set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
 set (CMAKE_C_STANDARD 99)
 set (CMAKE_C_STANDARD 99)
 set (CMAKE_CXX_STANDARD 14)
 set (CMAKE_CXX_STANDARD 14)
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
 
 
 if (NOT DEFINED WAMR_BUILD_PLATFORM)
 if (NOT DEFINED WAMR_BUILD_PLATFORM)
   set (WAMR_BUILD_PLATFORM "linux")
   set (WAMR_BUILD_PLATFORM "linux")

+ 0 - 32
core/iwasm/libraries/wasi-nn/test/Dockerfile

@@ -1,32 +0,0 @@
-# Copyright (C) 2019 Intel Corporation.  All rights reserved.
-# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-
-FROM ubuntu:22.04
-
-ENV DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && apt-get install -y \
-    cmake build-essential git wget python3.10 python3-pip
-
-RUN wget -q https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-14/wasi-sdk-14.0-linux.tar.gz && \
-    tar xf wasi-sdk-*-linux.tar.gz -C /opt && rm -f wasi-sdk-*-linux.tar.gz && \
-    mv /opt/wasi-sdk-14.0 /opt/wasi-sdk
-
-WORKDIR /home/wamr
-
-COPY core core
-COPY build-scripts build-scripts
-COPY product-mini product-mini
-
-RUN pip3 install -r core/iwasm/libraries/wasi-nn/test/requirements.txt
-
-WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build
-
-RUN cmake -DWAMR_BUILD_WASI_NN=1 ..
-RUN make -j $(grep -c ^processor /proc/cpuinfo)
-
-WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test
-
-RUN ./build.sh
-
-ENTRYPOINT [ "./build/iwasm",  "--dir=.", "test_tensorflow.wasm" ]

+ 22 - 0
core/iwasm/libraries/wasi-nn/test/Dockerfile.base

@@ -0,0 +1,22 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM ubuntu:20.04 AS base
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y \
+    cmake build-essential git
+
+WORKDIR /home/wamr
+
+COPY . .
+
+WORKDIR /home/wamr/core/iwasm/libraries/wasi-nn/test/build
+
+RUN cmake \
+  -DWAMR_BUILD_WASI_NN=1 \
+  -DTFLITE_ENABLE_GPU=ON \
+  ..
+
+RUN make -j $(grep -c ^processor /proc/cpuinfo)

+ 23 - 0
core/iwasm/libraries/wasi-nn/test/Dockerfile.compile

@@ -0,0 +1,23 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM ubuntu:20.04
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+RUN apt-get update && apt-get install -y \
+    cmake build-essential git wget python3.10 python3-pip
+
+ARG WASI_SDK_VER=19
+RUN wget -c --progress=dot:giga https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VER}/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -P /opt \
+  && tar xf /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz -C /opt \
+  && ln -fs /opt/wasi-sdk-${WASI_SDK_VER}.0 /opt/wasi-sdk \
+  && rm /opt/wasi-sdk-${WASI_SDK_VER}.0-linux.tar.gz
+
+WORKDIR /wasi-nn/test
+
+COPY core/iwasm/libraries/wasi-nn/test/requirements.txt .
+
+RUN pip3 install -r requirements.txt && rm requirements.txt
+
+ENTRYPOINT [ "bash", "./build.sh" ]

+ 8 - 0
core/iwasm/libraries/wasi-nn/test/Dockerfile.cpu

@@ -0,0 +1,8 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM ubuntu:20.04
+
+COPY --from=wasi-nn-base /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm
+
+ENTRYPOINT [ "/run/iwasm" ]

+ 20 - 0
core/iwasm/libraries/wasi-nn/test/Dockerfile.nvidia-gpu

@@ -0,0 +1,20 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM nvidia/cuda:11.3.0-runtime-ubuntu20.04
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+        ocl-icd-libopencl1 \
+        ocl-icd-opencl-dev \
+        clinfo && \
+    rm -rf /var/lib/apt/lists/*
+
+RUN mkdir -p /etc/OpenCL/vendors && \
+    echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
+
+ENV NVIDIA_VISIBLE_DEVICES=all
+ENV NVIDIA_DRIVER_CAPABILITIES=compute,utility
+
+COPY --from=wasi-nn-base /home/wamr/core/iwasm/libraries/wasi-nn/test/build/iwasm /run/iwasm
+
+ENTRYPOINT [ "/run/iwasm" ]

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

@@ -7,7 +7,7 @@
     -Wl,--allow-undefined \
     -Wl,--allow-undefined \
     -Wl,--strip-all,--no-entry \
     -Wl,--strip-all,--no-entry \
     --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
     --sysroot=/opt/wasi-sdk/share/wasi-sysroot \
-    -I/home/wamr/core/iwasm/libraries/wasi-nn \
+    -I.. \
     -o test_tensorflow.wasm test_tensorflow.c
     -o test_tensorflow.wasm test_tensorflow.c
 
 
 # TFLite models to use in the tests
 # TFLite models to use in the tests

+ 48 - 30
core/iwasm/libraries/wasi-nn/test/test_tensorflow.c

@@ -28,7 +28,7 @@ typedef struct {
 // WASI-NN wrappers
 // WASI-NN wrappers
 
 
 error
 error
-wasm_load(char *model_name, graph *graph)
+wasm_load(char *model_name, graph *g, execution_target target)
 {
 {
     FILE *pFile = fopen(model_name, "r");
     FILE *pFile = fopen(model_name, "r");
     if (pFile == NULL)
     if (pFile == NULL)
@@ -64,7 +64,7 @@ wasm_load(char *model_name, graph *graph)
     arr.buf[0].size = result;
     arr.buf[0].size = result;
     arr.buf[0].buf = buffer;
     arr.buf[0].buf = buffer;
 
 
-    error res = load(&arr, tensorflow, cpu, graph);
+    error res = load(&arr, tensorflowlite, target, g);
 
 
     fclose(pFile);
     fclose(pFile);
     free(buffer);
     free(buffer);
@@ -73,13 +73,13 @@ wasm_load(char *model_name, graph *graph)
 }
 }
 
 
 error
 error
-wasm_init_execution_context(graph graph, graph_execution_context *ctx)
+wasm_init_execution_context(graph g, graph_execution_context *ctx)
 {
 {
-    return init_execution_context(graph, ctx);
+    return init_execution_context(g, ctx);
 }
 }
 
 
 error
 error
-wasm_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
+wasm_set_input(graph_execution_context ctx, float *input_tensor, uint32_t *dim)
 {
 {
     tensor_dimensions dims;
     tensor_dimensions dims;
     dims.size = INPUT_TENSOR_DIMS;
     dims.size = INPUT_TENSOR_DIMS;
@@ -115,11 +115,12 @@ wasm_get_output(graph_execution_context ctx, uint32_t index, float *out_tensor,
 // Inference
 // Inference
 
 
 float *
 float *
-run_inference(float *input, uint32_t *input_size, uint32_t *output_size,
-              char *model_name, uint32_t num_output_tensors)
+run_inference(execution_target target, float *input, uint32_t *input_size,
+              uint32_t *output_size, char *model_name,
+              uint32_t num_output_tensors)
 {
 {
     graph graph;
     graph graph;
-    if (wasm_load(model_name, &graph) != success) {
+    if (wasm_load(model_name, &graph, target) != success) {
         fprintf(stderr, "Error when loading model.");
         fprintf(stderr, "Error when loading model.");
         exit(1);
         exit(1);
     }
     }
@@ -130,7 +131,7 @@ run_inference(float *input, uint32_t *input_size, uint32_t *output_size,
         exit(1);
         exit(1);
     }
     }
 
 
-    if (wasm_input(ctx, input, input_size) != success) {
+    if (wasm_set_input(ctx, input, input_size) != success) {
         fprintf(stderr, "Error when setting input tensor.");
         fprintf(stderr, "Error when setting input tensor.");
         exit(1);
         exit(1);
     }
     }
@@ -151,7 +152,7 @@ run_inference(float *input, uint32_t *input_size, uint32_t *output_size,
         *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size;
         *output_size = MAX_OUTPUT_TENSOR_SIZE - *output_size;
         if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
         if (wasm_get_output(ctx, i, &out_tensor[offset], output_size)
             != success) {
             != success) {
-            fprintf(stderr, "Error when getting input .");
+            fprintf(stderr, "Error when getting output .");
             exit(1);
             exit(1);
         }
         }
 
 
@@ -185,14 +186,14 @@ create_input(int *dims)
 // TESTS
 // TESTS
 
 
 void
 void
-test_sum()
+test_sum(execution_target target)
 {
 {
     int dims[] = { 1, 5, 5, 1 };
     int dims[] = { 1, 5, 5, 1 };
     input_info input = create_input(dims);
     input_info input = create_input(dims);
 
 
     uint32_t output_size = 0;
     uint32_t output_size = 0;
-    float *output = run_inference(input.input_tensor, input.dim, &output_size,
-                                  "models/sum.tflite", 1);
+    float *output = run_inference(target, input.input_tensor, input.dim,
+                                  &output_size, "/assets/models/sum.tflite", 1);
 
 
     assert(output_size == 1);
     assert(output_size == 1);
     assert(fabs(output[0] - 300.0) < EPSILON);
     assert(fabs(output[0] - 300.0) < EPSILON);
@@ -203,14 +204,14 @@ test_sum()
 }
 }
 
 
 void
 void
-test_max()
+test_max(execution_target target)
 {
 {
     int dims[] = { 1, 5, 5, 1 };
     int dims[] = { 1, 5, 5, 1 };
     input_info input = create_input(dims);
     input_info input = create_input(dims);
 
 
     uint32_t output_size = 0;
     uint32_t output_size = 0;
-    float *output = run_inference(input.input_tensor, input.dim, &output_size,
-                                  "models/max.tflite", 1);
+    float *output = run_inference(target, input.input_tensor, input.dim,
+                                  &output_size, "/assets/models/max.tflite", 1);
 
 
     assert(output_size == 1);
     assert(output_size == 1);
     assert(fabs(output[0] - 24.0) < EPSILON);
     assert(fabs(output[0] - 24.0) < EPSILON);
@@ -222,14 +223,15 @@ test_max()
 }
 }
 
 
 void
 void
-test_average()
+test_average(execution_target target)
 {
 {
     int dims[] = { 1, 5, 5, 1 };
     int dims[] = { 1, 5, 5, 1 };
     input_info input = create_input(dims);
     input_info input = create_input(dims);
 
 
     uint32_t output_size = 0;
     uint32_t output_size = 0;
-    float *output = run_inference(input.input_tensor, input.dim, &output_size,
-                                  "models/average.tflite", 1);
+    float *output =
+        run_inference(target, input.input_tensor, input.dim, &output_size,
+                      "/assets/models/average.tflite", 1);
 
 
     assert(output_size == 1);
     assert(output_size == 1);
     assert(fabs(output[0] - 12.0) < EPSILON);
     assert(fabs(output[0] - 12.0) < EPSILON);
@@ -241,14 +243,15 @@ test_average()
 }
 }
 
 
 void
 void
-test_mult_dimensions()
+test_mult_dimensions(execution_target target)
 {
 {
     int dims[] = { 1, 3, 3, 1 };
     int dims[] = { 1, 3, 3, 1 };
     input_info input = create_input(dims);
     input_info input = create_input(dims);
 
 
     uint32_t output_size = 0;
     uint32_t output_size = 0;
-    float *output = run_inference(input.input_tensor, input.dim, &output_size,
-                                  "models/mult_dim.tflite", 1);
+    float *output =
+        run_inference(target, input.input_tensor, input.dim, &output_size,
+                      "/assets/models/mult_dim.tflite", 1);
 
 
     assert(output_size == 9);
     assert(output_size == 9);
     for (int i = 0; i < 9; i++)
     for (int i = 0; i < 9; i++)
@@ -260,14 +263,15 @@ test_mult_dimensions()
 }
 }
 
 
 void
 void
-test_mult_outputs()
+test_mult_outputs(execution_target target)
 {
 {
     int dims[] = { 1, 4, 4, 1 };
     int dims[] = { 1, 4, 4, 1 };
     input_info input = create_input(dims);
     input_info input = create_input(dims);
 
 
     uint32_t output_size = 0;
     uint32_t output_size = 0;
-    float *output = run_inference(input.input_tensor, input.dim, &output_size,
-                                  "models/mult_out.tflite", 2);
+    float *output =
+        run_inference(target, input.input_tensor, input.dim, &output_size,
+                      "/assets/models/mult_out.tflite", 2);
 
 
     assert(output_size == 8);
     assert(output_size == 8);
     // first tensor check
     // first tensor check
@@ -285,16 +289,30 @@ test_mult_outputs()
 int
 int
 main()
 main()
 {
 {
+    char *env = getenv("TARGET");
+    if (env == NULL) {
+        printf("Usage:\n--env=\"TARGET=[cpu|gpu]\"\n");
+        return 1;
+    }
+    execution_target target;
+    if (strcmp(env, "cpu") == 0)
+        target = cpu;
+    else if (strcmp(env, "gpu") == 0)
+        target = gpu;
+    else {
+        printf("Wrong target!");
+        return 1;
+    }
     printf("################### Testing sum...\n");
     printf("################### Testing sum...\n");
-    test_sum();
+    test_sum(target);
     printf("################### Testing max...\n");
     printf("################### Testing max...\n");
-    test_max();
+    test_max(target);
     printf("################### Testing average...\n");
     printf("################### Testing average...\n");
-    test_average();
+    test_average(target);
     printf("################### Testing multiple dimensions...\n");
     printf("################### Testing multiple dimensions...\n");
-    test_mult_dimensions();
+    test_mult_dimensions(target);
     printf("################### Testing multiple outputs...\n");
     printf("################### Testing multiple outputs...\n");
-    test_mult_outputs();
+    test_mult_outputs(target);
 
 
     printf("Tests: passed!\n");
     printf("Tests: passed!\n");
     return 0;
     return 0;

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

@@ -5,6 +5,15 @@ set (WASI_NN_DIR ${CMAKE_CURRENT_LIST_DIR})
 
 
 add_definitions (-DWASM_ENABLE_WASI_NN=1)
 add_definitions (-DWASM_ENABLE_WASI_NN=1)
 
 
-set (LIBC_WASI_NN_SOURCE ${WASI_NN_DIR}/wasi_nn_native.c ${WASI_NN_DIR}/wasi_nn_tensorflow.cpp)
+include_directories (${WASI_NN_DIR})
+include_directories (${WASI_NN_DIR}/src)
+include_directories (${WASI_NN_DIR}/src/utils)
+
+set (
+    LIBC_WASI_NN_SOURCE
+    ${WASI_NN_DIR}/src/wasi_nn.c
+    ${WASI_NN_DIR}/src/wasi_nn_tensorflowlite.cpp
+    ${WASI_NN_DIR}/src/utils/wasi_nn_app_native.c
+)
 
 
 set (TENSORFLOW_LIB tensorflow-lite)
 set (TENSORFLOW_LIB tensorflow-lite)

+ 19 - 62
core/iwasm/libraries/wasi-nn/wasi_nn.h

@@ -3,63 +3,17 @@
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
  */
 
 
-#ifndef WASI_NN_WASM_H
-#define WASI_NN_WASM_H
-
-#include "wasi_nn_common.h"
-
 /**
 /**
  * Following definition from:
  * Following definition from:
- * [Aug 10th, 2022]
- * https://github.com/WebAssembly/wasi-nn/blob/e5e1a6c31f424c7cd63026cd270e9746775675a0/wasi-nn.wit.md
+ * [Oct 25th, 2022]
+ * https://github.com/WebAssembly/wasi-nn/blob/0f77c48ec195748990ff67928a4b3eef5f16c2de/wasi-nn.wit.md
  */
  */
 
 
-/* The graph initialization data. */
-
-// This consists of an array of buffers because implementing backends may encode
-// their graph IR in parts (e.g., OpenVINO stores its IR and weights
-// separately).
-typedef struct {
-    uint8_t *buf;
-    uint32_t size;
-} graph_builder;
-
-typedef struct {
-    graph_builder *buf;
-    uint32_t size;
-} graph_builder_array;
-
-/* The dimensions of a tensor. */
-
-// The array length matches the tensor rank and each element in the array
-// describes the size of each dimension.
-typedef struct {
-    uint32_t *buf;
-    uint32_t size;
-} tensor_dimensions;
-
-/* The tensor data. */
+#ifndef WASI_NN_H
+#define WASI_NN_H
 
 
-// Initially conceived as a sparse representation, each empty cell would be
-// filled with zeros and the array length must match the product of all of the
-// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with
-// 4-byte f32 elements would have a data array of length 16). Naturally, this
-// representation requires some knowledge of how to lay out data in
-// memory--e.g., using row-major ordering--and could perhaps be improved.
-typedef uint8_t *tensor_data;
-
-/* A tensor. */
-
-typedef struct {
-    // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To
-    // represent a tensor containing a single value, use `[1]` for the tensor
-    // dimensions.
-    tensor_dimensions *dimensions;
-    // Describe the type of element in the tensor (e.g., f32).
-    tensor_type type;
-    // Contains the tensor data.
-    tensor_data data;
-} tensor;
+#include <stdint.h>
+#include "wasi_nn_types.h"
 
 
 /**
 /**
  * @brief Load an opaque sequence of bytes to use for inference.
  * @brief Load an opaque sequence of bytes to use for inference.
@@ -67,25 +21,31 @@ typedef struct {
  * @param builder   Model builder.
  * @param builder   Model builder.
  * @param encoding  Model encoding.
  * @param encoding  Model encoding.
  * @param target    Execution target.
  * @param target    Execution target.
- * @param graph     Graph.
+ * @param g         Graph.
  * @return error    Execution status.
  * @return error    Execution status.
  */
  */
 error
 error
 load(graph_builder_array *builder, graph_encoding encoding,
 load(graph_builder_array *builder, graph_encoding encoding,
-     execution_target target, graph *graph)
-    __attribute__((export_module("wasi_nn")))
+     execution_target target, graph *g)
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));
 
 
+/**
+ * INFERENCE
+ *
+ */
+
+// Bind a `graph` to the input and output tensors for an inference.
+typedef uint32_t graph_execution_context;
+
 /**
 /**
  * @brief Create an execution instance of a loaded graph.
  * @brief Create an execution instance of a loaded graph.
  *
  *
- * @param graph     Graph.
+ * @param g         Graph.
  * @param ctx       Execution context.
  * @param ctx       Execution context.
  * @return error    Execution status.
  * @return error    Execution status.
  */
  */
 error
 error
-init_execution_context(graph graph, graph_execution_context *ctx)
-    __attribute__((export_module("wasi_nn")))
+init_execution_context(graph g, graph_execution_context *ctx)
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));
 
 
 /**
 /**
@@ -98,7 +58,6 @@ init_execution_context(graph graph, graph_execution_context *ctx)
  */
  */
 error
 error
 set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
 set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
-    __attribute__((export_module("wasi_nn")))
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));
 
 
 /**
 /**
@@ -108,8 +67,7 @@ set_input(graph_execution_context ctx, uint32_t index, tensor *tensor)
  * @return error    Execution status.
  * @return error    Execution status.
  */
  */
 error
 error
-compute(graph_execution_context ctx) __attribute__((export_module("wasi_nn")))
-__attribute__((import_module("wasi_nn")));
+compute(graph_execution_context ctx) __attribute__((import_module("wasi_nn")));
 
 
 /**
 /**
  * @brief Extract the outputs after inference.
  * @brief Extract the outputs after inference.
@@ -126,7 +84,6 @@ __attribute__((import_module("wasi_nn")));
 error
 error
 get_output(graph_execution_context ctx, uint32_t index,
 get_output(graph_execution_context ctx, uint32_t index,
            tensor_data output_tensor, uint32_t *output_tensor_size)
            tensor_data output_tensor, uint32_t *output_tensor_size)
-    __attribute__((export_module("wasi_nn")))
     __attribute__((import_module("wasi_nn")));
     __attribute__((import_module("wasi_nn")));
 
 
 #endif
 #endif

+ 0 - 44
core/iwasm/libraries/wasi-nn/wasi_nn_common.h

@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2019 Intel Corporation.  All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
-
-#ifndef WASI_NN_COMMON_H
-#define WASI_NN_COMMON_H
-
-#include <stdint.h>
-
-// The type of the elements in a tensor.
-typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
-
-// Describes the encoding of the graph. This allows the API to be implemented by
-// various backends that encode (i.e., serialize) their graph IR with different
-// formats.
-typedef enum { openvino = 0, onnx, tensorflow, pytorch } graph_encoding;
-
-// Define where the graph should be executed.
-typedef enum { cpu = 0, gpu, tpu } execution_target;
-
-// Error codes returned by functions in this API.
-typedef enum {
-    // No error occurred.
-    success = 0,
-    // Caller module passed an invalid argument.
-    invalid_argument,
-    // Invalid encoding.
-    invalid_encoding,
-    // Caller module is missing a memory export.
-    missing_memory,
-    // Device or resource busy.
-    busy,
-    // Runtime Error.
-    runtime_error,
-} error;
-
-// An execution graph for performing inference (i.e., a model).
-typedef uint32_t graph;
-
-// Bind a `graph` to the input and output tensors for an inference.
-typedef uint32_t graph_execution_context;
-
-#endif

+ 0 - 264
core/iwasm/libraries/wasi-nn/wasi_nn_native.c

@@ -1,264 +0,0 @@
-/*
- * Copyright (C) 2019 Intel Corporation.  All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
-
-#include <stdio.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-
-#include "wasi_nn_common.h"
-#include "wasm_export.h"
-#include "bh_platform.h"
-
-#include "wasi_nn.h"
-#include "wasi_nn_tensorflow.hpp"
-#include "logger.h"
-
-/* Definition of 'wasi_nn.h' structs in WASM app format (using offset) */
-
-typedef struct {
-    uint32_t buf_offset;
-    uint32_t size;
-} graph_builder_wasm;
-
-typedef struct {
-    uint32_t buf_offset;
-    uint32_t size;
-} graph_builder_array_wasm;
-
-typedef struct {
-    uint32_t dimensions_offset;
-    tensor_type type;
-    uint32_t data_offset;
-} tensor_wasm;
-
-typedef struct {
-    uint32_t buf_offset;
-    uint32_t size;
-} tensor_dimensions_wasm;
-
-/* Global variables */
-
-static uint8_t _is_initialized;
-static graph_encoding _encoding;
-
-/* Utils */
-
-static error
-check_initialized()
-{
-    if (!_is_initialized) {
-        NN_ERR_PRINTF("Model not initialized.");
-        return invalid_argument;
-    }
-    if (_encoding != tensorflow) {
-        NN_ERR_PRINTF("Model encoding is not tensorflow.");
-        return invalid_argument;
-    }
-    return success;
-}
-
-/* WASI-NN implementation */
-
-error
-wasi_nn_load(wasm_exec_env_t exec_env, graph_builder_array_wasm *builder,
-             graph_encoding encoding, execution_target target, graph *graph)
-{
-    NN_DBG_PRINTF("Running wasi_nn_load [encoding=%d, target=%d]...", encoding,
-                  target);
-
-    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
-    bh_assert(instance);
-
-    if (!wasm_runtime_validate_native_addr(instance, builder,
-                                           sizeof(graph_builder_array_wasm)))
-        return invalid_argument;
-
-    if (!wasm_runtime_validate_app_addr(instance, builder->buf_offset,
-                                        builder->size * sizeof(uint32_t)))
-        return invalid_argument;
-
-    NN_DBG_PRINTF("Graph builder array contains %d elements", builder->size);
-
-    graph_builder_wasm *gb_wasm =
-        (graph_builder_wasm *)wasm_runtime_addr_app_to_native(
-            instance, builder->buf_offset);
-
-    graph_builder *gb_native = (graph_builder *)wasm_runtime_malloc(
-        builder->size * sizeof(graph_builder));
-    if (gb_native == NULL)
-        return missing_memory;
-
-    for (int i = 0; i < builder->size; ++i) {
-        if (!wasm_runtime_validate_app_addr(instance, gb_wasm[i].buf_offset,
-                                            gb_wasm[i].size
-                                                * sizeof(uint8_t))) {
-            wasm_runtime_free(gb_native);
-            return invalid_argument;
-        }
-
-        gb_native[i].buf = (uint8_t *)wasm_runtime_addr_app_to_native(
-            instance, gb_wasm[i].buf_offset);
-        gb_native[i].size = gb_wasm[i].size;
-
-        NN_DBG_PRINTF("Graph builder %d contains %d elements", i,
-                      gb_wasm[i].size);
-    }
-
-    graph_builder_array gba_native = { .buf = gb_native,
-                                       .size = builder->size };
-
-    if (!wasm_runtime_validate_native_addr(instance, graph, sizeof(graph))) {
-        wasm_runtime_free(gb_native);
-        return invalid_argument;
-    }
-
-    switch (encoding) {
-        case tensorflow:
-            break;
-        default:
-            NN_ERR_PRINTF("Only tensorflow is supported.");
-            wasm_runtime_free(gb_native);
-            return invalid_argument;
-    }
-
-    _encoding = encoding;
-    _is_initialized = 1;
-
-    error res = tensorflow_load(gba_native, _encoding, target, graph);
-    NN_DBG_PRINTF("wasi_nn_load finished with status %d [graph=%d]", res,
-                  *graph);
-
-    wasm_runtime_free(gb_native);
-    return res;
-}
-
-error
-wasi_nn_init_execution_context(wasm_exec_env_t exec_env, graph graph,
-                               graph_execution_context *ctx)
-{
-    NN_DBG_PRINTF("Running wasi_nn_init_execution_context [graph=%d]...",
-                  graph);
-    error res;
-    if (success != (res = check_initialized()))
-        return res;
-    res = tensorflow_init_execution_context(graph);
-    *ctx = graph;
-    NN_DBG_PRINTF(
-        "wasi_nn_init_execution_context finished with status %d [ctx=%d]", res,
-        *ctx);
-    return res;
-}
-
-error
-wasi_nn_set_input(wasm_exec_env_t exec_env, graph_execution_context ctx,
-                  uint32_t index, tensor_wasm *input_tensor)
-{
-    NN_DBG_PRINTF("Running wasi_nn_set_input [ctx=%d, index=%d]...", ctx,
-                  index);
-
-    error res;
-    if (success != (res = check_initialized()))
-        return res;
-
-    wasm_module_inst_t instance = wasm_runtime_get_module_inst(exec_env);
-    bh_assert(instance);
-
-    if (!wasm_runtime_validate_native_addr(instance, input_tensor,
-                                           sizeof(tensor_wasm)))
-        return invalid_argument;
-
-    if (!wasm_runtime_validate_app_addr(
-            instance, input_tensor->dimensions_offset, sizeof(uint32_t)))
-        return invalid_argument;
-
-    tensor_dimensions_wasm *dimensions_w =
-        (tensor_dimensions_wasm *)wasm_runtime_addr_app_to_native(
-            instance, input_tensor->dimensions_offset);
-
-    if (!wasm_runtime_validate_app_addr(instance, dimensions_w->buf_offset,
-                                        dimensions_w->size * sizeof(uint32_t)))
-        return invalid_argument;
-
-    tensor_dimensions dimensions = {
-        .buf = (uint32_t *)wasm_runtime_addr_app_to_native(
-            instance, dimensions_w->buf_offset),
-        .size = dimensions_w->size
-    };
-
-    NN_DBG_PRINTF("Number of dimensions: %d", dimensions.size);
-    int total_elements = 1;
-    for (int i = 0; i < dimensions.size; ++i) {
-        NN_DBG_PRINTF("Dimension %d: %d", i, dimensions.buf[i]);
-        total_elements *= dimensions.buf[i];
-    }
-    NN_DBG_PRINTF("Tensor type: %d", input_tensor->type);
-
-    if (!wasm_runtime_validate_app_addr(instance, input_tensor->data_offset,
-                                        total_elements))
-        return invalid_argument;
-
-    tensor tensor = { .type = input_tensor->type,
-                      .dimensions = &dimensions,
-                      .data = (uint8_t *)wasm_runtime_addr_app_to_native(
-                          instance, input_tensor->data_offset) };
-
-    res = tensorflow_set_input(ctx, index, &tensor);
-    NN_DBG_PRINTF("wasi_nn_set_input finished with status %d", res);
-    return res;
-}
-
-error
-wasi_nn_compute(wasm_exec_env_t exec_env, graph_execution_context ctx)
-{
-    NN_DBG_PRINTF("Running wasi_nn_compute [ctx=%d]...", ctx);
-    error res;
-    if (success != (res = check_initialized()))
-        return res;
-
-    res = tensorflow_compute(ctx);
-    NN_DBG_PRINTF("wasi_nn_compute finished with status %d", res);
-    return res;
-}
-
-error
-wasi_nn_get_output(wasm_exec_env_t exec_env, graph_execution_context ctx,
-                   uint32_t index, tensor_data output_tensor,
-                   uint32_t *output_tensor_size)
-{
-    NN_DBG_PRINTF("Running wasi_nn_get_output [ctx=%d, index=%d]...", ctx,
-                  index);
-    error res;
-    if (success != (res = check_initialized()))
-        return res;
-
-    res = tensorflow_get_output(ctx, index, output_tensor, output_tensor_size);
-    NN_DBG_PRINTF("wasi_nn_get_output finished with status %d [data_size=%d]",
-                  res, *output_tensor_size);
-    return res;
-}
-
-/* Register WASI-NN in WAMR */
-
-/* clang-format off */
-#define REG_NATIVE_FUNC(func_name, signature) \
-    { #func_name, wasi_nn_##func_name, signature, NULL }
-/* clang-format on */
-
-static NativeSymbol native_symbols_wasi_nn[] = {
-    REG_NATIVE_FUNC(load, "(*ii*)i"),
-    REG_NATIVE_FUNC(init_execution_context, "(i*)i"),
-    REG_NATIVE_FUNC(set_input, "(ii*)i"),
-    REG_NATIVE_FUNC(compute, "(i)i"),
-    REG_NATIVE_FUNC(get_output, "(ii**)i"),
-};
-
-uint32_t
-get_wasi_nn_export_apis(NativeSymbol **p_libc_wasi_apis)
-{
-    *p_libc_wasi_apis = native_symbols_wasi_nn;
-    return sizeof(native_symbols_wasi_nn) / sizeof(NativeSymbol);
-}

+ 0 - 40
core/iwasm/libraries/wasi-nn/wasi_nn_tensorflow.hpp

@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2019 Intel Corporation.  All rights reserved.
- * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- */
-
-#ifndef WASI_NN_TENSORFLOW_HPP
-#define WASI_NN_TENSORFLOW_HPP
-
-#include <stdio.h>
-
-#include "wasi_nn.h"
-#include "logger.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-error
-tensorflow_load(graph_builder_array builder, graph_encoding encoding,
-                execution_target target, graph *graph);
-
-error
-tensorflow_init_execution_context(graph graph);
-
-error
-tensorflow_set_input(graph_execution_context ctx, uint32_t index,
-                     tensor *input_tensor);
-
-error
-tensorflow_compute(graph_execution_context ctx);
-
-error
-tensorflow_get_output(graph_execution_context context, uint32_t index,
-                      tensor_data output_tensor, uint32_t *output_tensor_size);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif

+ 106 - 0
core/iwasm/libraries/wasi-nn/wasi_nn_types.h

@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef WASI_NN_TYPES_H
+#define WASI_NN_TYPES_H
+
+/**
+ * ERRORS
+ *
+ */
+
+// Error codes returned by functions in this API.
+typedef enum {
+    // No error occurred.
+    success = 0,
+    // Caller module passed an invalid argument.
+    invalid_argument,
+    // Invalid encoding.
+    invalid_encoding,
+    // Caller module is missing a memory export.
+    missing_memory,
+    // Device or resource busy.
+    busy,
+    // Runtime Error.
+    runtime_error,
+} error;
+
+/**
+ * TENSOR
+ *
+ */
+
+// The dimensions of a tensor.
+//
+// The array length matches the tensor rank and each element in the array
+// describes the size of each dimension.
+typedef struct {
+    uint32_t *buf;
+    uint32_t size;
+} tensor_dimensions;
+
+// The type of the elements in a tensor.
+typedef enum { fp16 = 0, fp32, up8, ip32 } tensor_type;
+
+// The tensor data.
+//
+// Initially conceived as a sparse representation, each empty cell would be
+// filled with zeros and the array length must match the product of all of the
+// dimensions and the number of bytes in the type (e.g., a 2x2 tensor with
+// 4-byte f32 elements would have a data array of length 16). Naturally, this
+// representation requires some knowledge of how to lay out data in
+// memory--e.g., using row-major ordering--and could perhaps be improved.
+typedef uint8_t *tensor_data;
+
+// A tensor.
+typedef struct {
+    // Describe the size of the tensor (e.g., 2x2x2x2 -> [2, 2, 2, 2]). To
+    // represent a tensor containing a single value, use `[1]` for the tensor
+    // dimensions.
+    tensor_dimensions *dimensions;
+    // Describe the type of element in the tensor (e.g., f32).
+    tensor_type type;
+    // Contains the tensor data.
+    tensor_data data;
+} tensor;
+
+/**
+ * GRAPH
+ *
+ */
+
+// The graph initialization data.
+//
+// This consists of an array of buffers because implementing backends may encode
+// their graph IR in parts (e.g., OpenVINO stores its IR and weights
+// separately).
+typedef struct {
+    uint8_t *buf;
+    uint32_t size;
+} graph_builder;
+
+typedef struct {
+    graph_builder *buf;
+    uint32_t size;
+} graph_builder_array;
+
+// An execution graph for performing inference (i.e., a model).
+typedef uint32_t graph;
+
+// Describes the encoding of the graph. This allows the API to be implemented by
+// various backends that encode (i.e., serialize) their graph IR with different
+// formats.
+typedef enum {
+    openvino = 0,
+    onnx,
+    tensorflow,
+    pytorch,
+    tensorflowlite
+} graph_encoding;
+
+// Define where the graph should be executed.
+typedef enum execution_target { cpu = 0, gpu, tpu } execution_target;
+
+#endif

+ 4 - 4
core/shared/platform/esp-idf/espidf_socket.c

@@ -77,7 +77,7 @@ os_socket_bind(bh_socket_t socket, const char *host, int *port)
     }
     }
 
 
     socklen = sizeof(addr);
     socklen = sizeof(addr);
-    if (getsockname(socket, (void *)&addr, &socklen) == -1) {
+    if (getsockname(socket, (struct sockaddr *)&addr, &socklen) == -1) {
         goto fail;
         goto fail;
     }
     }
 
 
@@ -120,7 +120,7 @@ os_socket_accept(bh_socket_t server_sock, bh_socket_t *sock, void *addr,
                  unsigned int *addrlen)
                  unsigned int *addrlen)
 {
 {
     struct sockaddr addr_tmp;
     struct sockaddr addr_tmp;
-    unsigned int len = sizeof(struct sockaddr);
+    socklen_t len = sizeof(struct sockaddr);
 
 
     *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
     *sock = accept(server_sock, (struct sockaddr *)&addr_tmp, &len);
 
 
@@ -205,7 +205,7 @@ os_socket_addr_remote(bh_socket_t socket, bh_sockaddr_t *sockaddr)
     struct sockaddr_in addr;
     struct sockaddr_in addr;
     socklen_t addr_len = sizeof(addr);
     socklen_t addr_len = sizeof(addr);
 
 
-    if (getpeername(socket, &addr, &addr_len) == -1) {
+    if (getpeername(socket, (struct sockaddr *)&addr, &addr_len) == -1) {
         return BHT_ERROR;
         return BHT_ERROR;
     }
     }
 
 
@@ -219,7 +219,7 @@ os_socket_addr_local(bh_socket_t socket, bh_sockaddr_t *sockaddr)
     struct sockaddr_in addr;
     struct sockaddr_in addr;
     socklen_t addr_len = sizeof(addr);
     socklen_t addr_len = sizeof(addr);
 
 
-    if (getsockname(socket, &addr, &addr_len) == -1) {
+    if (getsockname(socket, (struct sockaddr *)&addr, &addr_len) == -1) {
         return BHT_ERROR;
         return BHT_ERROR;
     }
     }
 
 

+ 60 - 14
core/shared/platform/linux-sgx/sgx_ipfs.c

@@ -16,6 +16,11 @@
 #define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
 #define SGX_ERROR_FILE_LOWEST_ERROR_ID SGX_ERROR_FILE_BAD_STATUS
 #define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
 #define SGX_ERROR_FILE_HIGHEST_ERROR_ID SGX_ERROR_FILE_CLOSE_FAILED
 
 
+// Internal buffer filled with zeroes and used when extending the size of
+// protected files.
+#define ZEROES_PADDING_LENGTH 32 * 1024
+char zeroes_padding[ZEROES_PADDING_LENGTH] = { 0 };
+
 // The mapping between file descriptors and IPFS file pointers.
 // The mapping between file descriptors and IPFS file pointers.
 static HashMap *ipfs_file_list;
 static HashMap *ipfs_file_list;
 
 
@@ -78,6 +83,27 @@ ipfs_file_destroy(void *sgx_file)
     sgx_fclose(sgx_file);
     sgx_fclose(sgx_file);
 }
 }
 
 
+// Writes a given number of zeroes in file at the current offset.
+// The return value is zero if successful; otherwise non-zero.
+static int
+ipfs_write_zeroes(void *sgx_file, size_t len)
+{
+    int min_count;
+
+    while (len > 0) {
+        min_count = len < ZEROES_PADDING_LENGTH ? len : ZEROES_PADDING_LENGTH;
+
+        if (sgx_fwrite(zeroes_padding, 1, min_count, sgx_file) == 0) {
+            errno = convert_sgx_errno(sgx_ferror(sgx_file));
+            return -1;
+        }
+
+        len -= min_count;
+    }
+
+    return 0;
+}
+
 int
 int
 ipfs_init()
 ipfs_init()
 {
 {
@@ -104,7 +130,7 @@ ipfs_posix_fallocate(int fd, off_t offset, size_t len)
 
 
     // The wrapper for fseek takes care of extending the file if sought beyond
     // The wrapper for fseek takes care of extending the file if sought beyond
     // the end
     // the end
-    if (ipfs_lseek(fd, offset + len, SEEK_CUR) == -1) {
+    if (ipfs_lseek(fd, offset + len, SEEK_SET) == -1) {
         return errno;
         return errno;
     }
     }
 
 
@@ -354,7 +380,7 @@ ipfs_fflush(int fd)
 off_t
 off_t
 ipfs_lseek(int fd, off_t offset, int nwhence)
 ipfs_lseek(int fd, off_t offset, int nwhence)
 {
 {
-    off_t new_offset;
+    off_t cursor_current_location;
     void *sgx_file = fd2file(fd);
     void *sgx_file = fd2file(fd);
     if (!sgx_file) {
     if (!sgx_file) {
         errno = EBADF;
         errno = EBADF;
@@ -364,20 +390,20 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
     // Optimization: if the offset is 0 and the whence is SEEK_CUR,
     // Optimization: if the offset is 0 and the whence is SEEK_CUR,
     // this is equivalent of a call to ftell.
     // this is equivalent of a call to ftell.
     if (offset == 0 && nwhence == SEEK_CUR) {
     if (offset == 0 && nwhence == SEEK_CUR) {
-        int64_t ftell_result = (off_t)sgx_ftell(sgx_file);
+        cursor_current_location = (off_t)sgx_ftell(sgx_file);
 
 
-        if (ftell_result == -1) {
+        if (cursor_current_location == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             return -1;
             return -1;
         }
         }
 
 
-        return ftell_result;
+        return cursor_current_location;
     }
     }
 
 
     int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
     int fseek_result = sgx_fseek(sgx_file, offset, nwhence);
 
 
     if (fseek_result == 0) {
     if (fseek_result == 0) {
-        new_offset = (__wasi_filesize_t)sgx_ftell(sgx_file);
+        off_t new_offset = (off_t)sgx_ftell(sgx_file);
 
 
         if (new_offset == -1) {
         if (new_offset == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
@@ -405,17 +431,39 @@ ipfs_lseek(int fd, off_t offset, int nwhence)
         // manually.
         // manually.
 
 
         // Assume the error is raised because the cursor is moved beyond the end
         // Assume the error is raised because the cursor is moved beyond the end
-        // of the file. Try to move the cursor at the end of the file.
+        // of the file.
+
+        // If the whence is the current cursor location, retrieve it
+        if (nwhence == SEEK_CUR) {
+            cursor_current_location = (off_t)sgx_ftell(sgx_file);
+        }
+
+        // Move the cursor at the end of the file
         if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
         if (sgx_fseek(sgx_file, 0, SEEK_END) == -1) {
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             errno = convert_sgx_errno(sgx_ferror(sgx_file));
             return -1;
             return -1;
         }
         }
 
 
+        // Compute the number of zeroes to append.
+        int64_t number_of_zeroes;
+        switch (nwhence) {
+            case SEEK_SET:
+                number_of_zeroes = offset - sgx_ftell(sgx_file);
+                break;
+            case SEEK_END:
+                number_of_zeroes = offset;
+                break;
+            case SEEK_CUR:
+                number_of_zeroes =
+                    cursor_current_location + offset - sgx_ftell(sgx_file);
+                break;
+            default:
+                errno = EINVAL;
+                return -1;
+        }
+
         // Write the missing zeroes
         // Write the missing zeroes
-        char zero = 0;
-        int64_t number_of_zeroes = offset - sgx_ftell(sgx_file);
-        if (sgx_fwrite(&zero, 1, number_of_zeroes, sgx_file) == 0) {
-            errno = convert_sgx_errno(sgx_ferror(sgx_file));
+        if (ipfs_write_zeroes(sgx_file, number_of_zeroes) != 0) {
             return -1;
             return -1;
         }
         }
 
 
@@ -468,9 +516,7 @@ ipfs_ftruncate(int fd, off_t len)
 
 
     // Increasing the size is equal to writing from the end of the file
     // Increasing the size is equal to writing from the end of the file
     // with null bytes.
     // with null bytes.
-    char null_byte = 0;
-    if (sgx_fwrite(&null_byte, 1, len - file_size, sgx_file) == 0) {
-        errno = convert_sgx_errno(sgx_ferror(sgx_file));
+    if (ipfs_write_zeroes(sgx_file, len - file_size) != 0) {
         return -1;
         return -1;
     }
     }
 
 

+ 2 - 2
doc/build_wasm_app.md

@@ -3,12 +3,12 @@
 Prepare WASM building environments
 Prepare WASM building environments
 ==================================
 ==================================
 
 
-For C and C++, WASI-SDK version 12.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md).
+For C and C++, WASI-SDK version 19.0+ is the major tool supported by WAMR to build WASM applications. Also, we can use [Emscripten SDK (EMSDK)](https://github.com/emscripten-core/emsdk), but it is not recommended. And there are some other compilers such as the standard clang compiler, which might also work [here](./other_wasm_compilers.md).
 
 
 To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`.
 To install WASI SDK, please download the [wasi-sdk release](https://github.com/CraneStation/wasi-sdk/releases) and extract the archive to default path `/opt/wasi-sdk`.
 
 
 The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WAMR provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate
 The official *wasi-sdk release* doesn't fully support *latest 128-bit SIMD spec* yet. WAMR provides a script in [build-wasi-sdk](../test-tools/build-wasi-sdk/) to generate
-another wasi-sdk with *llvm-13* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release.
+another wasi-sdk with *llvm-15* from source code and installs it at *../test-tools/wasi-sdk*. If you plan to build WASM applications with *latest 128-bit SIMD*, please use it instead of the official release.
 
 
 And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk.
 And [sample workloads](../samples/workload) are using the self-compiled wasi-sdk.
 
 

+ 17 - 8
doc/port_wamr.md

@@ -10,9 +10,13 @@ This document describes how to port WAMR to a new platform "**new-os**"
 # Step 1: Implement platform API layer
 # Step 1: Implement platform API layer
 
 
 -------------------------
 -------------------------
-Firstly create the folder **`core/shared/platform/new-os`** for platform API layer implementations. In the folder you just created, you must provide the following files:
+Firstly create the folder for platform API layer implementations:
+* for common platforms, create a folder in **`core/shared/platform/new-os`** in WAMR repository folder, so the implementation can be upstreamed
+* for platforms that are internal and its implementation shouldn't be published, it's recommended to create a folder outside of the WAMR repository folder (e.g. have separate repository for platform API layer implementation)
 
 
-- `platform_internal.h`: It can be used for any platform specific definitions such as macros, data types and internal APIs.
+In the folder you just created, you must provide the following files:
+
+- `platform_internal.h`: It can be used for any platform-specific definitions such as macros, data types and internal APIs.
 
 
 - `shared_platform.cmake`: the cmake file will be included by the building script. It is recommended to add a definition for your platform:
 - `shared_platform.cmake`: the cmake file will be included by the building script. It is recommended to add a definition for your platform:
 
 
@@ -20,29 +24,29 @@ Firstly create the folder **`core/shared/platform/new-os`** for platform API lay
     add_definitions(-DBH_PLATFORM_YOUR_NAME)
     add_definitions(-DBH_PLATFORM_YOUR_NAME)
     ```
     ```
 
 
-Then go to implement the APIs defined in following header files for the platform abstraction layer:
+Then go to implement the APIs defined in the following header files for the platform abstraction layer:
 
 
-- [`platform_api_vmcore.h`](../core/shared/platform/include/platform_api_vmcore.h):   mandatory for building mini-product (vmcore only). Part of APIs are needed only for Ahead of Time compilation support. 
+- [`platform_api_vmcore.h`](../core/shared/platform/include/platform_api_vmcore.h):   mandatory for building mini-product (vmcore only). Part of the APIs is needed only for Ahead of Time compilation support.
 - [`platform_api_extension.h`](../core/shared/platform/include/platform_api_extension.h): mandatory for app-mgr and app-framework. Given that the app-mgr and app-framework are not required for your target platform, you won't have to implement the API defined in the `platform_api_extension.h`.
 - [`platform_api_extension.h`](../core/shared/platform/include/platform_api_extension.h): mandatory for app-mgr and app-framework. Given that the app-mgr and app-framework are not required for your target platform, you won't have to implement the API defined in the `platform_api_extension.h`.
 
 
 
 
 
 
 **common/posix:**
 **common/posix:**
 
 
-There is posix based implementation of the platform API located in the `platform/common/posix` folder. You can include it if your platform support posix API. refer to platform linux implementation.
+There is posix based implementation of the platform API located in the `platform/common/posix` folder. You can include it if your platform supports posix API. refer to platform linux implementation.
 
 
 
 
 
 
 **common/math:**
 **common/math:**
 
 
-Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and isnan, then you should include source files under the folder `platform/common/math`. 
+Some platforms such as ZephyrOS don't provide math functions e.g. sqrt, fabs and isnan, then you should include source files under the folder `platform/common/math`.
 
 
 
 
 
 
 # Step 2: Create the mini product for the platform
 # Step 2: Create the mini product for the platform
 
 
 -------------------------
 -------------------------
-You can build a mini WAMR product which is only the vmcore for you platform. Normally you need to implement the main function which loads a WASM file and run it with the WASM runtime. You don't have to do this step if there is no mini-product need for your platform porting.
+You can build a mini WAMR product which is only the vmcore for your platform. Normally you need to implement the main function which loads a WASM file and run it with the WASM runtime. You don't have to do this step if there is no mini-product need for your platform porting.
 
 
 
 
 
 
@@ -55,9 +59,14 @@ You should set cmake variable `WAMR_BUILD_PLATFORM` to your platform name while
 ```
 ```
 mkdir build
 mkdir build
 cd build
 cd build
-cmake .. -DWAMR_BUILD_PLATFORM=new-os 
+cmake .. -DWAMR_BUILD_PLATFORM=new-os
 ```
 ```
 
 
+For platform implementations that are outside of the WAMR repository (e.g. internal platforms), you also need to provide `SHARED_PLATFORM_CONFIG` path:
+
+```
+cmake .. -DWAMR_BUILD_PLATFORM=new-os -DSHARED_PLATFORM_CONFIG=/path/to/new-os/shared_platform.cmake
+```
 
 
 
 
 Refer to [build_wamr.md](./build_wamr.md) for the building configurations and parameters.
 Refer to [build_wamr.md](./build_wamr.md) for the building configurations and parameters.

+ 1 - 0
language-bindings/python/MANIFEST.in

@@ -0,0 +1 @@
+include src/wamr/libs/*

+ 18 - 15
language-bindings/python/README.md

@@ -1,31 +1,34 @@
 # wamr-python
 # wamr-python
 
 
-## Installation
+The WAMR Python package contains a set of high-level bindings for WAMR API and WASM-C-API.
 
 
-### Installing from the source code
+## Installation
 
 
-Installing from local source tree is in _development mode_. The package appears to be installed but still is editable from the source tree.
+To Install from local source tree in _development mode_ run the following command,
 
 
 ```bash
 ```bash
-$ python -m pip install -e /path/to/wamr-root/binding/python
+python -m pip install -e .
 ```
 ```
 
 
-## Usage
+In this mode the package appears to be installed but still is editable from the source tree.
 
 
-```python
-import wamr.ffi as ffi
-```
+## Usage
 
 
-### Preparation
+From the same package you can use two set of APIs.
 
 
-The binding will load the shared library _libiwasm.so_ from the WAMR repo. So before running the binding, you need to build the library yourself.
+To use the WAMR API you can import the symbols as follows,
 
 
-The default compile options are good enough.
+```py
+from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv
+```
 
 
-Please be aware that `wasm_frame_xxx` and `wasm_trap_xxx` only work well when enabling `WAMR_BUILD_DUMP_CALL_STACK`.
+In the order hand, to use the WASM-C-API,
 
 
-### Examples
+```py
+import wamr.wasmcapi.ffi as ffi
+```
 
 
-There is a [simple example](./samples/hello_procedural.py) to show how to use bindings. Actually, the python binding follows C-APIs. There it should be easy if be familiar with _programming with wasm-c-api_.
+For more information:
 
 
-Unit test cases under _./tests_ could be another but more complete references.
+* [WAMR API](./wamr_api)
+* [WASM-C-API](./wasm_c_api)

+ 28 - 3
language-bindings/python/setup.py

@@ -8,7 +8,28 @@
 # pylint: disable=missing-function-docstring
 # pylint: disable=missing-function-docstring
 # pylint: disable=missing-module-docstring
 # pylint: disable=missing-module-docstring
 
 
-from setuptools import setup, find_packages
+import pathlib
+from setuptools import setup
+from setuptools.command.develop import develop
+from setuptools.command.install import install
+from subprocess import check_call
+
+
+def build_library():
+    cur_path = pathlib.Path(__file__).parent
+    check_call(f"{cur_path}/utils/create_lib.sh".split())
+
+class PreDevelopCommand(develop):
+    """Pre-installation for development mode."""
+    def run(self):
+        build_library()
+        develop.run(self)
+
+class PreInstallCommand(install):
+    """Pre-installation for installation mode."""
+    def run(self):
+        build_library()
+        install.run(self)
 
 
 
 
 with open("README.md") as f:
 with open("README.md") as f:
@@ -24,7 +45,11 @@ setup(
     long_description=readme,
     long_description=readme,
     author="The WAMR Project Developers",
     author="The WAMR Project Developers",
     author_email="hello@bytecodealliance.org",
     author_email="hello@bytecodealliance.org",
-    url="https://github.com/bytecodealliance/wamr-python",
+    url="https://github.com/bytecodealliance/wasm-micro-runtime",
     license=license,
     license=license,
-    packages=["wamr"],
+    include_package_data=True,
+    cmdclass={
+        'develop': PreDevelopCommand,
+        'install': PreInstallCommand,
+    },
 )
 )

+ 0 - 0
language-bindings/python/src/wamr/__init__.py


+ 0 - 0
language-bindings/python/src/wamr/libs/.placeholder


+ 0 - 0
language-bindings/python/src/wamr/wamrapi/__init__.py


+ 1779 - 0
language-bindings/python/src/wamr/wamrapi/iwasm.py

@@ -0,0 +1,1779 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+r"""Wrapper for wasm_export.h
+
+Generated with:
+ctypesgen ../../../../core/iwasm/include/wasm_export.h -l ../libs/libiwasm.so -o iwasm.py
+
+Do not modify this file.
+"""
+
+__docformat__ = "restructuredtext"
+
+# Begin preamble for Python
+
+import ctypes
+import sys
+from ctypes import *  # noqa: F401, F403
+
+_int_types = (ctypes.c_int16, ctypes.c_int32)
+if hasattr(ctypes, "c_int64"):
+    # Some builds of ctypes apparently do not have ctypes.c_int64
+    # defined; it's a pretty good bet that these builds do not
+    # have 64-bit pointers.
+    _int_types += (ctypes.c_int64,)
+for t in _int_types:
+    if ctypes.sizeof(t) == ctypes.sizeof(ctypes.c_size_t):
+        c_ptrdiff_t = t
+del t
+del _int_types
+
+
+
+class UserString:
+    def __init__(self, seq):
+        if isinstance(seq, bytes):
+            self.data = seq
+        elif isinstance(seq, UserString):
+            self.data = seq.data[:]
+        else:
+            self.data = str(seq).encode()
+
+    def __bytes__(self):
+        return self.data
+
+    def __str__(self):
+        return self.data.decode()
+
+    def __repr__(self):
+        return repr(self.data)
+
+    def __int__(self):
+        return int(self.data.decode())
+
+    def __long__(self):
+        return int(self.data.decode())
+
+    def __float__(self):
+        return float(self.data.decode())
+
+    def __complex__(self):
+        return complex(self.data.decode())
+
+    def __hash__(self):
+        return hash(self.data)
+
+    def __le__(self, string):
+        if isinstance(string, UserString):
+            return self.data <= string.data
+        else:
+            return self.data <= string
+
+    def __lt__(self, string):
+        if isinstance(string, UserString):
+            return self.data < string.data
+        else:
+            return self.data < string
+
+    def __ge__(self, string):
+        if isinstance(string, UserString):
+            return self.data >= string.data
+        else:
+            return self.data >= string
+
+    def __gt__(self, string):
+        if isinstance(string, UserString):
+            return self.data > string.data
+        else:
+            return self.data > string
+
+    def __eq__(self, string):
+        if isinstance(string, UserString):
+            return self.data == string.data
+        else:
+            return self.data == string
+
+    def __ne__(self, string):
+        if isinstance(string, UserString):
+            return self.data != string.data
+        else:
+            return self.data != string
+
+    def __contains__(self, char):
+        return char in self.data
+
+    def __len__(self):
+        return len(self.data)
+
+    def __getitem__(self, index):
+        return self.__class__(self.data[index])
+
+    def __getslice__(self, start, end):
+        start = max(start, 0)
+        end = max(end, 0)
+        return self.__class__(self.data[start:end])
+
+    def __add__(self, other):
+        if isinstance(other, UserString):
+            return self.__class__(self.data + other.data)
+        elif isinstance(other, bytes):
+            return self.__class__(self.data + other)
+        else:
+            return self.__class__(self.data + str(other).encode())
+
+    def __radd__(self, other):
+        if isinstance(other, bytes):
+            return self.__class__(other + self.data)
+        else:
+            return self.__class__(str(other).encode() + self.data)
+
+    def __mul__(self, n):
+        return self.__class__(self.data * n)
+
+    __rmul__ = __mul__
+
+    def __mod__(self, args):
+        return self.__class__(self.data % args)
+
+    # the following methods are defined in alphabetical order:
+    def capitalize(self):
+        return self.__class__(self.data.capitalize())
+
+    def center(self, width, *args):
+        return self.__class__(self.data.center(width, *args))
+
+    def count(self, sub, start=0, end=sys.maxsize):
+        return self.data.count(sub, start, end)
+
+    def decode(self, encoding=None, errors=None):  # XXX improve this?
+        if encoding:
+            if errors:
+                return self.__class__(self.data.decode(encoding, errors))
+            else:
+                return self.__class__(self.data.decode(encoding))
+        else:
+            return self.__class__(self.data.decode())
+
+    def encode(self, encoding=None, errors=None):  # XXX improve this?
+        if encoding:
+            if errors:
+                return self.__class__(self.data.encode(encoding, errors))
+            else:
+                return self.__class__(self.data.encode(encoding))
+        else:
+            return self.__class__(self.data.encode())
+
+    def endswith(self, suffix, start=0, end=sys.maxsize):
+        return self.data.endswith(suffix, start, end)
+
+    def expandtabs(self, tabsize=8):
+        return self.__class__(self.data.expandtabs(tabsize))
+
+    def find(self, sub, start=0, end=sys.maxsize):
+        return self.data.find(sub, start, end)
+
+    def index(self, sub, start=0, end=sys.maxsize):
+        return self.data.index(sub, start, end)
+
+    def isalpha(self):
+        return self.data.isalpha()
+
+    def isalnum(self):
+        return self.data.isalnum()
+
+    def isdecimal(self):
+        return self.data.isdecimal()
+
+    def isdigit(self):
+        return self.data.isdigit()
+
+    def islower(self):
+        return self.data.islower()
+
+    def isnumeric(self):
+        return self.data.isnumeric()
+
+    def isspace(self):
+        return self.data.isspace()
+
+    def istitle(self):
+        return self.data.istitle()
+
+    def isupper(self):
+        return self.data.isupper()
+
+    def join(self, seq):
+        return self.data.join(seq)
+
+    def ljust(self, width, *args):
+        return self.__class__(self.data.ljust(width, *args))
+
+    def lower(self):
+        return self.__class__(self.data.lower())
+
+    def lstrip(self, chars=None):
+        return self.__class__(self.data.lstrip(chars))
+
+    def partition(self, sep):
+        return self.data.partition(sep)
+
+    def replace(self, old, new, maxsplit=-1):
+        return self.__class__(self.data.replace(old, new, maxsplit))
+
+    def rfind(self, sub, start=0, end=sys.maxsize):
+        return self.data.rfind(sub, start, end)
+
+    def rindex(self, sub, start=0, end=sys.maxsize):
+        return self.data.rindex(sub, start, end)
+
+    def rjust(self, width, *args):
+        return self.__class__(self.data.rjust(width, *args))
+
+    def rpartition(self, sep):
+        return self.data.rpartition(sep)
+
+    def rstrip(self, chars=None):
+        return self.__class__(self.data.rstrip(chars))
+
+    def split(self, sep=None, maxsplit=-1):
+        return self.data.split(sep, maxsplit)
+
+    def rsplit(self, sep=None, maxsplit=-1):
+        return self.data.rsplit(sep, maxsplit)
+
+    def splitlines(self, keepends=0):
+        return self.data.splitlines(keepends)
+
+    def startswith(self, prefix, start=0, end=sys.maxsize):
+        return self.data.startswith(prefix, start, end)
+
+    def strip(self, chars=None):
+        return self.__class__(self.data.strip(chars))
+
+    def swapcase(self):
+        return self.__class__(self.data.swapcase())
+
+    def title(self):
+        return self.__class__(self.data.title())
+
+    def translate(self, *args):
+        return self.__class__(self.data.translate(*args))
+
+    def upper(self):
+        return self.__class__(self.data.upper())
+
+    def zfill(self, width):
+        return self.__class__(self.data.zfill(width))
+
+
+class MutableString(UserString):
+    """mutable string objects
+
+    Python strings are immutable objects.  This has the advantage, that
+    strings may be used as dictionary keys.  If this property isn't needed
+    and you insist on changing string values in place instead, you may cheat
+    and use MutableString.
+
+    But the purpose of this class is an educational one: to prevent
+    people from inventing their own mutable string class derived
+    from UserString and than forget thereby to remove (override) the
+    __hash__ method inherited from UserString.  This would lead to
+    errors that would be very hard to track down.
+
+    A faster and better solution is to rewrite your program using lists."""
+
+    def __init__(self, string=""):
+        self.data = string
+
+    def __hash__(self):
+        raise TypeError("unhashable type (it is mutable)")
+
+    def __setitem__(self, index, sub):
+        if index < 0:
+            index += len(self.data)
+        if index < 0 or index >= len(self.data):
+            raise IndexError
+        self.data = self.data[:index] + sub + self.data[index + 1 :]
+
+    def __delitem__(self, index):
+        if index < 0:
+            index += len(self.data)
+        if index < 0 or index >= len(self.data):
+            raise IndexError
+        self.data = self.data[:index] + self.data[index + 1 :]
+
+    def __setslice__(self, start, end, sub):
+        start = max(start, 0)
+        end = max(end, 0)
+        if isinstance(sub, UserString):
+            self.data = self.data[:start] + sub.data + self.data[end:]
+        elif isinstance(sub, bytes):
+            self.data = self.data[:start] + sub + self.data[end:]
+        else:
+            self.data = self.data[:start] + str(sub).encode() + self.data[end:]
+
+    def __delslice__(self, start, end):
+        start = max(start, 0)
+        end = max(end, 0)
+        self.data = self.data[:start] + self.data[end:]
+
+    def immutable(self):
+        return UserString(self.data)
+
+    def __iadd__(self, other):
+        if isinstance(other, UserString):
+            self.data += other.data
+        elif isinstance(other, bytes):
+            self.data += other
+        else:
+            self.data += str(other).encode()
+        return self
+
+    def __imul__(self, n):
+        self.data *= n
+        return self
+
+
+class String(MutableString, ctypes.Union):
+
+    _fields_ = [("raw", ctypes.POINTER(ctypes.c_char)), ("data", ctypes.c_char_p)]
+
+    def __init__(self, obj=b""):
+        if isinstance(obj, (bytes, UserString)):
+            self.data = bytes(obj)
+        else:
+            self.raw = obj
+
+    def __len__(self):
+        return self.data and len(self.data) or 0
+
+    def from_param(cls, obj):
+        # Convert None or 0
+        if obj is None or obj == 0:
+            return cls(ctypes.POINTER(ctypes.c_char)())
+
+        # Convert from String
+        elif isinstance(obj, String):
+            return obj
+
+        # Convert from bytes
+        elif isinstance(obj, bytes):
+            return cls(obj)
+
+        # Convert from str
+        elif isinstance(obj, str):
+            return cls(obj.encode())
+
+        # Convert from c_char_p
+        elif isinstance(obj, ctypes.c_char_p):
+            return obj
+
+        # Convert from POINTER(ctypes.c_char)
+        elif isinstance(obj, ctypes.POINTER(ctypes.c_char)):
+            return obj
+
+        # Convert from raw pointer
+        elif isinstance(obj, int):
+            return cls(ctypes.cast(obj, ctypes.POINTER(ctypes.c_char)))
+
+        # Convert from ctypes.c_char array
+        elif isinstance(obj, ctypes.c_char * len(obj)):
+            return obj
+
+        # Convert from object
+        else:
+            return String.from_param(obj._as_parameter_)
+
+    from_param = classmethod(from_param)
+
+
+def ReturnString(obj, func=None, arguments=None):
+    return String.from_param(obj)
+
+
+# As of ctypes 1.0, ctypes does not support custom error-checking
+# functions on callbacks, nor does it support custom datatypes on
+# callbacks, so we must ensure that all callbacks return
+# primitive datatypes.
+#
+# Non-primitive return values wrapped with UNCHECKED won't be
+# typechecked, and will be converted to ctypes.c_void_p.
+def UNCHECKED(type):
+    if hasattr(type, "_type_") and isinstance(type._type_, str) and type._type_ != "P":
+        return type
+    else:
+        return ctypes.c_void_p
+
+
+# ctypes doesn't have direct support for variadic functions, so we have to write
+# our own wrapper class
+class _variadic_function(object):
+    def __init__(self, func, restype, argtypes, errcheck):
+        self.func = func
+        self.func.restype = restype
+        self.argtypes = argtypes
+        if errcheck:
+            self.func.errcheck = errcheck
+
+    def _as_parameter_(self):
+        # So we can pass this variadic function as a function pointer
+        return self.func
+
+    def __call__(self, *args):
+        fixed_args = []
+        i = 0
+        for argtype in self.argtypes:
+            # Typecheck what we can
+            fixed_args.append(argtype.from_param(args[i]))
+            i += 1
+        return self.func(*fixed_args + list(args[i:]))
+
+
+def ord_if_char(value):
+    """
+    Simple helper used for casts to simple builtin types:  if the argument is a
+    string type, it will be converted to it's ordinal value.
+
+    This function will raise an exception if the argument is string with more
+    than one characters.
+    """
+    return ord(value) if (isinstance(value, bytes) or isinstance(value, str)) else value
+
+# End preamble
+
+_libs = {}
+_libdirs = []
+
+# Begin loader
+
+"""
+Load libraries - appropriately for all our supported platforms
+"""
+# ----------------------------------------------------------------------------
+# Copyright (c) 2008 David James
+# Copyright (c) 2006-2008 Alex Holkner
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+#  * Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+#  * Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in
+#    the documentation and/or other materials provided with the
+#    distribution.
+#  * Neither the name of pyglet nor the names of its
+#    contributors may be used to endorse or promote products
+#    derived from this software without specific prior written
+#    permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+# ----------------------------------------------------------------------------
+
+import ctypes
+import ctypes.util
+import glob
+import os.path
+import platform
+import re
+import sys
+
+
+def _environ_path(name):
+    """Split an environment variable into a path-like list elements"""
+    if name in os.environ:
+        return os.environ[name].split(":")
+    return []
+
+
+class LibraryLoader:
+    """
+    A base class For loading of libraries ;-)
+    Subclasses load libraries for specific platforms.
+    """
+
+    # library names formatted specifically for platforms
+    name_formats = ["%s"]
+
+    class Lookup:
+        """Looking up calling conventions for a platform"""
+
+        mode = ctypes.DEFAULT_MODE
+
+        def __init__(self, path):
+            super(LibraryLoader.Lookup, self).__init__()
+            self.access = dict(cdecl=ctypes.CDLL(path, self.mode))
+
+        def get(self, name, calling_convention="cdecl"):
+            """Return the given name according to the selected calling convention"""
+            if calling_convention not in self.access:
+                raise LookupError(
+                    "Unknown calling convention '{}' for function '{}'".format(
+                        calling_convention, name
+                    )
+                )
+            return getattr(self.access[calling_convention], name)
+
+        def has(self, name, calling_convention="cdecl"):
+            """Return True if this given calling convention finds the given 'name'"""
+            if calling_convention not in self.access:
+                return False
+            return hasattr(self.access[calling_convention], name)
+
+        def __getattr__(self, name):
+            return getattr(self.access["cdecl"], name)
+
+    def __init__(self):
+        self.other_dirs = []
+
+    def __call__(self, libname):
+        """Given the name of a library, load it."""
+        paths = self.getpaths(libname)
+
+        for path in paths:
+            # noinspection PyBroadException
+            try:
+                return self.Lookup(path)
+            except Exception:  # pylint: disable=broad-except
+                pass
+
+        raise ImportError("Could not load %s." % libname)
+
+    def getpaths(self, libname):
+        """Return a list of paths where the library might be found."""
+        if os.path.isabs(libname):
+            yield libname
+        else:
+            # search through a prioritized series of locations for the library
+
+            # we first search any specific directories identified by user
+            for dir_i in self.other_dirs:
+                for fmt in self.name_formats:
+                    # dir_i should be absolute already
+                    yield os.path.join(dir_i, fmt % libname)
+
+            # check if this code is even stored in a physical file
+            try:
+                this_file = __file__
+            except NameError:
+                this_file = None
+
+            # then we search the directory where the generated python interface is stored
+            if this_file is not None:
+                for fmt in self.name_formats:
+                    yield os.path.abspath(os.path.join(os.path.dirname(__file__), fmt % libname))
+
+            # now, use the ctypes tools to try to find the library
+            for fmt in self.name_formats:
+                path = ctypes.util.find_library(fmt % libname)
+                if path:
+                    yield path
+
+            # then we search all paths identified as platform-specific lib paths
+            for path in self.getplatformpaths(libname):
+                yield path
+
+            # Finally, we'll try the users current working directory
+            for fmt in self.name_formats:
+                yield os.path.abspath(os.path.join(os.path.curdir, fmt % libname))
+
+    def getplatformpaths(self, _libname):  # pylint: disable=no-self-use
+        """Return all the library paths available in this platform"""
+        return []
+
+
+# Darwin (Mac OS X)
+
+
+class DarwinLibraryLoader(LibraryLoader):
+    """Library loader for MacOS"""
+
+    name_formats = [
+        "lib%s.dylib",
+        "lib%s.so",
+        "lib%s.bundle",
+        "%s.dylib",
+        "%s.so",
+        "%s.bundle",
+        "%s",
+    ]
+
+    class Lookup(LibraryLoader.Lookup):
+        """
+        Looking up library files for this platform (Darwin aka MacOS)
+        """
+
+        # Darwin requires dlopen to be called with mode RTLD_GLOBAL instead
+        # of the default RTLD_LOCAL.  Without this, you end up with
+        # libraries not being loadable, resulting in "Symbol not found"
+        # errors
+        mode = ctypes.RTLD_GLOBAL
+
+    def getplatformpaths(self, libname):
+        if os.path.pathsep in libname:
+            names = [libname]
+        else:
+            names = [fmt % libname for fmt in self.name_formats]
+
+        for directory in self.getdirs(libname):
+            for name in names:
+                yield os.path.join(directory, name)
+
+    @staticmethod
+    def getdirs(libname):
+        """Implements the dylib search as specified in Apple documentation:
+
+        http://developer.apple.com/documentation/DeveloperTools/Conceptual/
+            DynamicLibraries/Articles/DynamicLibraryUsageGuidelines.html
+
+        Before commencing the standard search, the method first checks
+        the bundle's ``Frameworks`` directory if the application is running
+        within a bundle (OS X .app).
+        """
+
+        dyld_fallback_library_path = _environ_path("DYLD_FALLBACK_LIBRARY_PATH")
+        if not dyld_fallback_library_path:
+            dyld_fallback_library_path = [
+                os.path.expanduser("~/lib"),
+                "/usr/local/lib",
+                "/usr/lib",
+            ]
+
+        dirs = []
+
+        if "/" in libname:
+            dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
+        else:
+            dirs.extend(_environ_path("LD_LIBRARY_PATH"))
+            dirs.extend(_environ_path("DYLD_LIBRARY_PATH"))
+            dirs.extend(_environ_path("LD_RUN_PATH"))
+
+        if hasattr(sys, "frozen") and getattr(sys, "frozen") == "macosx_app":
+            dirs.append(os.path.join(os.environ["RESOURCEPATH"], "..", "Frameworks"))
+
+        dirs.extend(dyld_fallback_library_path)
+
+        return dirs
+
+
+# Posix
+
+
+class PosixLibraryLoader(LibraryLoader):
+    """Library loader for POSIX-like systems (including Linux)"""
+
+    _ld_so_cache = None
+
+    _include = re.compile(r"^\s*include\s+(?P<pattern>.*)")
+
+    name_formats = ["lib%s.so", "%s.so", "%s"]
+
+    class _Directories(dict):
+        """Deal with directories"""
+
+        def __init__(self):
+            dict.__init__(self)
+            self.order = 0
+
+        def add(self, directory):
+            """Add a directory to our current set of directories"""
+            if len(directory) > 1:
+                directory = directory.rstrip(os.path.sep)
+            # only adds and updates order if exists and not already in set
+            if not os.path.exists(directory):
+                return
+            order = self.setdefault(directory, self.order)
+            if order == self.order:
+                self.order += 1
+
+        def extend(self, directories):
+            """Add a list of directories to our set"""
+            for a_dir in directories:
+                self.add(a_dir)
+
+        def ordered(self):
+            """Sort the list of directories"""
+            return (i[0] for i in sorted(self.items(), key=lambda d: d[1]))
+
+    def _get_ld_so_conf_dirs(self, conf, dirs):
+        """
+        Recursive function to help parse all ld.so.conf files, including proper
+        handling of the `include` directive.
+        """
+
+        try:
+            with open(conf) as fileobj:
+                for dirname in fileobj:
+                    dirname = dirname.strip()
+                    if not dirname:
+                        continue
+
+                    match = self._include.match(dirname)
+                    if not match:
+                        dirs.add(dirname)
+                    else:
+                        for dir2 in glob.glob(match.group("pattern")):
+                            self._get_ld_so_conf_dirs(dir2, dirs)
+        except IOError:
+            pass
+
+    def _create_ld_so_cache(self):
+        # Recreate search path followed by ld.so.  This is going to be
+        # slow to build, and incorrect (ld.so uses ld.so.cache, which may
+        # not be up-to-date).  Used only as fallback for distros without
+        # /sbin/ldconfig.
+        #
+        # We assume the DT_RPATH and DT_RUNPATH binary sections are omitted.
+
+        directories = self._Directories()
+        for name in (
+            "LD_LIBRARY_PATH",
+            "SHLIB_PATH",  # HP-UX
+            "LIBPATH",  # OS/2, AIX
+            "LIBRARY_PATH",  # BE/OS
+        ):
+            if name in os.environ:
+                directories.extend(os.environ[name].split(os.pathsep))
+
+        self._get_ld_so_conf_dirs("/etc/ld.so.conf", directories)
+
+        bitage = platform.architecture()[0]
+
+        unix_lib_dirs_list = []
+        if bitage.startswith("64"):
+            # prefer 64 bit if that is our arch
+            unix_lib_dirs_list += ["/lib64", "/usr/lib64"]
+
+        # must include standard libs, since those paths are also used by 64 bit
+        # installs
+        unix_lib_dirs_list += ["/lib", "/usr/lib"]
+        if sys.platform.startswith("linux"):
+            # Try and support multiarch work in Ubuntu
+            # https://wiki.ubuntu.com/MultiarchSpec
+            if bitage.startswith("32"):
+                # Assume Intel/AMD x86 compat
+                unix_lib_dirs_list += ["/lib/i386-linux-gnu", "/usr/lib/i386-linux-gnu"]
+            elif bitage.startswith("64"):
+                # Assume Intel/AMD x86 compatible
+                unix_lib_dirs_list += [
+                    "/lib/x86_64-linux-gnu",
+                    "/usr/lib/x86_64-linux-gnu",
+                ]
+            else:
+                # guess...
+                unix_lib_dirs_list += glob.glob("/lib/*linux-gnu")
+        directories.extend(unix_lib_dirs_list)
+
+        cache = {}
+        lib_re = re.compile(r"lib(.*)\.s[ol]")
+        # ext_re = re.compile(r"\.s[ol]$")
+        for our_dir in directories.ordered():
+            try:
+                for path in glob.glob("%s/*.s[ol]*" % our_dir):
+                    file = os.path.basename(path)
+
+                    # Index by filename
+                    cache_i = cache.setdefault(file, set())
+                    cache_i.add(path)
+
+                    # Index by library name
+                    match = lib_re.match(file)
+                    if match:
+                        library = match.group(1)
+                        cache_i = cache.setdefault(library, set())
+                        cache_i.add(path)
+            except OSError:
+                pass
+
+        self._ld_so_cache = cache
+
+    def getplatformpaths(self, libname):
+        if self._ld_so_cache is None:
+            self._create_ld_so_cache()
+
+        result = self._ld_so_cache.get(libname, set())
+        for i in result:
+            # we iterate through all found paths for library, since we may have
+            # actually found multiple architectures or other library types that
+            # may not load
+            yield i
+
+
+# Windows
+
+
+class WindowsLibraryLoader(LibraryLoader):
+    """Library loader for Microsoft Windows"""
+
+    name_formats = ["%s.dll", "lib%s.dll", "%slib.dll", "%s"]
+
+    class Lookup(LibraryLoader.Lookup):
+        """Lookup class for Windows libraries..."""
+
+        def __init__(self, path):
+            super(WindowsLibraryLoader.Lookup, self).__init__(path)
+            self.access["stdcall"] = ctypes.windll.LoadLibrary(path)
+
+
+# Platform switching
+
+# If your value of sys.platform does not appear in this dict, please contact
+# the Ctypesgen maintainers.
+
+loaderclass = {
+    "darwin": DarwinLibraryLoader,
+    "cygwin": WindowsLibraryLoader,
+    "win32": WindowsLibraryLoader,
+    "msys": WindowsLibraryLoader,
+}
+
+load_library = loaderclass.get(sys.platform, PosixLibraryLoader)()
+
+
+def add_library_search_dirs(other_dirs):
+    """
+    Add libraries to search paths.
+    If library paths are relative, convert them to absolute with respect to this
+    file's directory
+    """
+    for path in other_dirs:
+        if not os.path.isabs(path):
+            path = os.path.abspath(path)
+        load_library.other_dirs.append(path)
+
+
+del loaderclass
+
+# End loader
+
+add_library_search_dirs([])
+
+# Begin libraries
+_libs["../libs/libiwasm.so"] = load_library("../libs/libiwasm.so")
+
+# 1 libraries
+# End libraries
+
+# No modules
+
+__uint8_t = c_ubyte# /usr/include/x86_64-linux-gnu/bits/types.h: 38
+
+__uint32_t = c_uint# /usr/include/x86_64-linux-gnu/bits/types.h: 42
+
+uint8_t = __uint8_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 24
+
+uint32_t = __uint32_t# /usr/include/x86_64-linux-gnu/bits/stdint-uintn.h: 26
+
+uintptr_t = c_ulong# /usr/include/stdint.h: 90
+
+# wasm-micro-runtime/core/iwasm/include/lib_export.h: 22
+class struct_NativeSymbol(Structure):
+    pass
+
+struct_NativeSymbol.__slots__ = [
+    'symbol',
+    'func_ptr',
+    'signature',
+    'attachment',
+]
+struct_NativeSymbol._fields_ = [
+    ('symbol', String),
+    ('func_ptr', POINTER(None)),
+    ('signature', String),
+    ('attachment', POINTER(None)),
+]
+
+NativeSymbol = struct_NativeSymbol# wasm-micro-runtime/core/iwasm/include/lib_export.h: 22
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 62
+class struct_WASMModuleCommon(Structure):
+    pass
+
+wasm_module_t = POINTER(struct_WASMModuleCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 63
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 67
+class struct_WASMModuleInstanceCommon(Structure):
+    pass
+
+wasm_module_inst_t = POINTER(struct_WASMModuleInstanceCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 68
+
+WASMFunctionInstanceCommon = None# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 71
+
+wasm_function_inst_t = POINTER(WASMFunctionInstanceCommon)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 72
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 75
+class struct_wasm_section_t(Structure):
+    pass
+
+struct_wasm_section_t.__slots__ = [
+    'next',
+    'section_type',
+    'section_body',
+    'section_body_size',
+]
+struct_wasm_section_t._fields_ = [
+    ('next', POINTER(struct_wasm_section_t)),
+    ('section_type', c_int),
+    ('section_body', POINTER(uint8_t)),
+    ('section_body_size', uint32_t),
+]
+
+wasm_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83
+
+aot_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83
+
+wasm_section_list_t = POINTER(struct_wasm_section_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83
+
+aot_section_list_t = POINTER(struct_wasm_section_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 83
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 86
+class struct_WASMExecEnv(Structure):
+    pass
+
+wasm_exec_env_t = POINTER(struct_WASMExecEnv)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 87
+
+enum_anon_2 = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94
+
+Wasm_Module_Bytecode = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94
+
+Wasm_Module_AoT = (Wasm_Module_Bytecode + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94
+
+Package_Type_Unknown = 0xFFFF# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94
+
+package_type_t = enum_anon_2# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 94
+
+enum_anon_3 = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108
+
+Alloc_With_Pool = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108
+
+Alloc_With_Allocator = (Alloc_With_Pool + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108
+
+Alloc_With_System_Allocator = (Alloc_With_Allocator + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108
+
+mem_alloc_type_t = enum_anon_3# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 108
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 112
+class struct_anon_4(Structure):
+    pass
+
+struct_anon_4.__slots__ = [
+    'heap_buf',
+    'heap_size',
+]
+struct_anon_4._fields_ = [
+    ('heap_buf', POINTER(None)),
+    ('heap_size', uint32_t),
+]
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 116
+class struct_anon_5(Structure):
+    pass
+
+struct_anon_5.__slots__ = [
+    'malloc_func',
+    'realloc_func',
+    'free_func',
+    'user_data',
+]
+struct_anon_5._fields_ = [
+    ('malloc_func', POINTER(None)),
+    ('realloc_func', POINTER(None)),
+    ('free_func', POINTER(None)),
+    ('user_data', POINTER(None)),
+]
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124
+class union_MemAllocOption(Union):
+    pass
+
+union_MemAllocOption.__slots__ = [
+    'pool',
+    'allocator',
+]
+union_MemAllocOption._fields_ = [
+    ('pool', struct_anon_4),
+    ('allocator', struct_anon_5),
+]
+
+MemAllocOption = union_MemAllocOption# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132
+class struct_mem_alloc_info_t(Structure):
+    pass
+
+struct_mem_alloc_info_t.__slots__ = [
+    'total_size',
+    'total_free_size',
+    'highmark_size',
+]
+struct_mem_alloc_info_t._fields_ = [
+    ('total_size', uint32_t),
+    ('total_free_size', uint32_t),
+    ('highmark_size', uint32_t),
+]
+
+mem_alloc_info_t = struct_mem_alloc_info_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132
+
+enum_RunningMode = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+Mode_Interp = 1# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+Mode_Fast_JIT = (Mode_Interp + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+Mode_LLVM_JIT = (Mode_Fast_JIT + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+Mode_Multi_Tier_JIT = (Mode_LLVM_JIT + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+RunningMode = enum_RunningMode# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 140
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170
+class struct_RuntimeInitArgs(Structure):
+    pass
+
+struct_RuntimeInitArgs.__slots__ = [
+    'mem_alloc_type',
+    'mem_alloc_option',
+    'native_module_name',
+    'native_symbols',
+    'n_native_symbols',
+    'max_thread_num',
+    'ip_addr',
+    'unused',
+    'instance_port',
+    'fast_jit_code_cache_size',
+    'running_mode',
+    'llvm_jit_opt_level',
+    'llvm_jit_size_level',
+]
+struct_RuntimeInitArgs._fields_ = [
+    ('mem_alloc_type', mem_alloc_type_t),
+    ('mem_alloc_option', MemAllocOption),
+    ('native_module_name', String),
+    ('native_symbols', POINTER(NativeSymbol)),
+    ('n_native_symbols', uint32_t),
+    ('max_thread_num', uint32_t),
+    ('ip_addr', c_char * int(128)),
+    ('unused', c_int),
+    ('instance_port', c_int),
+    ('fast_jit_code_cache_size', uint32_t),
+    ('running_mode', RunningMode),
+    ('llvm_jit_opt_level', uint32_t),
+    ('llvm_jit_size_level', uint32_t),
+]
+
+RuntimeInitArgs = struct_RuntimeInitArgs# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170
+
+wasm_valkind_t = uint8_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 174
+
+enum_wasm_valkind_enum = c_int# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_I32 = 0# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_I64 = (WASM_I32 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_F32 = (WASM_I64 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_F64 = (WASM_F32 + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_ANYREF = 128# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+WASM_FUNCREF = (WASM_ANYREF + 1)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 175
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 190
+class union_anon_6(Union):
+    pass
+
+union_anon_6.__slots__ = [
+    'i32',
+    'i64',
+    'f32',
+    'f64',
+    'foreign',
+]
+union_anon_6._fields_ = [
+    ('i32', c_int32),
+    ('i64', c_int64),
+    ('f32', c_float),
+    ('f64', c_double),
+    ('foreign', uintptr_t),
+]
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199
+class struct_wasm_val_t(Structure):
+    pass
+
+struct_wasm_val_t.__slots__ = [
+    'kind',
+    'of',
+]
+struct_wasm_val_t._fields_ = [
+    ('kind', wasm_valkind_t),
+    ('of', union_anon_6),
+]
+
+wasm_val_t = struct_wasm_val_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 210
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_init", "cdecl"):
+    wasm_runtime_init = _libs["../libs/libiwasm.so"].get("wasm_runtime_init", "cdecl")
+    wasm_runtime_init.argtypes = []
+    wasm_runtime_init.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 222
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_full_init", "cdecl"):
+    wasm_runtime_full_init = _libs["../libs/libiwasm.so"].get("wasm_runtime_full_init", "cdecl")
+    wasm_runtime_full_init.argtypes = [POINTER(RuntimeInitArgs)]
+    wasm_runtime_full_init.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 232
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_is_running_mode_supported", "cdecl"):
+        continue
+    wasm_runtime_is_running_mode_supported = _lib.get("wasm_runtime_is_running_mode_supported", "cdecl")
+    wasm_runtime_is_running_mode_supported.argtypes = [RunningMode]
+    wasm_runtime_is_running_mode_supported.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 244
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_set_default_running_mode", "cdecl"):
+        continue
+    wasm_runtime_set_default_running_mode = _lib.get("wasm_runtime_set_default_running_mode", "cdecl")
+    wasm_runtime_set_default_running_mode.argtypes = [RunningMode]
+    wasm_runtime_set_default_running_mode.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 250
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy", "cdecl"):
+    wasm_runtime_destroy = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy", "cdecl")
+    wasm_runtime_destroy.argtypes = []
+    wasm_runtime_destroy.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 259
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_malloc", "cdecl"):
+    wasm_runtime_malloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_malloc", "cdecl")
+    wasm_runtime_malloc.argtypes = [c_uint]
+    wasm_runtime_malloc.restype = POINTER(c_ubyte)
+    wasm_runtime_malloc.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 270
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_realloc", "cdecl"):
+    wasm_runtime_realloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_realloc", "cdecl")
+    wasm_runtime_realloc.argtypes = [POINTER(None), c_uint]
+    wasm_runtime_realloc.restype = POINTER(c_ubyte)
+    wasm_runtime_realloc.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 277
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_free", "cdecl"):
+    wasm_runtime_free = _libs["../libs/libiwasm.so"].get("wasm_runtime_free", "cdecl")
+    wasm_runtime_free.argtypes = [POINTER(None)]
+    wasm_runtime_free.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 283
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_mem_alloc_info", "cdecl"):
+    wasm_runtime_get_mem_alloc_info = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_mem_alloc_info", "cdecl")
+    wasm_runtime_get_mem_alloc_info.argtypes = [POINTER(mem_alloc_info_t)]
+    wasm_runtime_get_mem_alloc_info.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 294
+if _libs["../libs/libiwasm.so"].has("get_package_type", "cdecl"):
+    get_package_type = _libs["../libs/libiwasm.so"].get("get_package_type", "cdecl")
+    get_package_type.argtypes = [POINTER(uint8_t), uint32_t]
+    get_package_type.restype = package_type_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 305
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_is_xip_file", "cdecl"):
+    wasm_runtime_is_xip_file = _libs["../libs/libiwasm.so"].get("wasm_runtime_is_xip_file", "cdecl")
+    wasm_runtime_is_xip_file.argtypes = [POINTER(uint8_t), uint32_t]
+    wasm_runtime_is_xip_file.restype = c_bool
+
+module_reader = CFUNCTYPE(UNCHECKED(c_bool), String, POINTER(POINTER(uint8_t)), POINTER(uint32_t))# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 310
+
+module_destroyer = CFUNCTYPE(UNCHECKED(None), POINTER(uint8_t), uint32_t)# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 316
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 325
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_set_module_reader", "cdecl"):
+        continue
+    wasm_runtime_set_module_reader = _lib.get("wasm_runtime_set_module_reader", "cdecl")
+    wasm_runtime_set_module_reader.argtypes = [module_reader, module_destroyer]
+    wasm_runtime_set_module_reader.restype = None
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 339
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_register_module", "cdecl"):
+        continue
+    wasm_runtime_register_module = _lib.get("wasm_runtime_register_module", "cdecl")
+    wasm_runtime_register_module.argtypes = [String, wasm_module_t, String, uint32_t]
+    wasm_runtime_register_module.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 351
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_find_module_registered", "cdecl"):
+        continue
+    wasm_runtime_find_module_registered = _lib.get("wasm_runtime_find_module_registered", "cdecl")
+    wasm_runtime_find_module_registered.argtypes = [String]
+    wasm_runtime_find_module_registered.restype = wasm_module_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 375
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_load", "cdecl"):
+    wasm_runtime_load = _libs["../libs/libiwasm.so"].get("wasm_runtime_load", "cdecl")
+    wasm_runtime_load.argtypes = [POINTER(uint8_t), uint32_t, String, uint32_t]
+    wasm_runtime_load.restype = wasm_module_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 389
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_load_from_sections", "cdecl"):
+    wasm_runtime_load_from_sections = _libs["../libs/libiwasm.so"].get("wasm_runtime_load_from_sections", "cdecl")
+    wasm_runtime_load_from_sections.argtypes = [wasm_section_list_t, c_bool, String, uint32_t]
+    wasm_runtime_load_from_sections.restype = wasm_module_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 398
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_unload", "cdecl"):
+    wasm_runtime_unload = _libs["../libs/libiwasm.so"].get("wasm_runtime_unload", "cdecl")
+    wasm_runtime_unload.argtypes = [wasm_module_t]
+    wasm_runtime_unload.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 408
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_get_module_hash", "cdecl"):
+        continue
+    wasm_runtime_get_module_hash = _lib.get("wasm_runtime_get_module_hash", "cdecl")
+    wasm_runtime_get_module_hash.argtypes = [wasm_module_t]
+    if sizeof(c_int) == sizeof(c_void_p):
+        wasm_runtime_get_module_hash.restype = ReturnString
+    else:
+        wasm_runtime_get_module_hash.restype = String
+        wasm_runtime_get_module_hash.errcheck = ReturnString
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 438
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_args_ex", "cdecl"):
+    wasm_runtime_set_wasi_args_ex = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_args_ex", "cdecl")
+    wasm_runtime_set_wasi_args_ex.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), c_int, c_int, c_int, c_int]
+    wasm_runtime_set_wasi_args_ex.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 452
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_args", "cdecl"):
+    wasm_runtime_set_wasi_args = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_args", "cdecl")
+    wasm_runtime_set_wasi_args.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), uint32_t, POINTER(POINTER(c_char)), c_int]
+    wasm_runtime_set_wasi_args.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 459
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_addr_pool", "cdecl"):
+    wasm_runtime_set_wasi_addr_pool = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_addr_pool", "cdecl")
+    wasm_runtime_set_wasi_addr_pool.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t]
+    wasm_runtime_set_wasi_addr_pool.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 463
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_wasi_ns_lookup_pool", "cdecl"):
+    wasm_runtime_set_wasi_ns_lookup_pool = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_wasi_ns_lookup_pool", "cdecl")
+    wasm_runtime_set_wasi_ns_lookup_pool.argtypes = [wasm_module_t, POINTER(POINTER(c_char)), uint32_t]
+    wasm_runtime_set_wasi_ns_lookup_pool.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 486
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_instantiate", "cdecl"):
+    wasm_runtime_instantiate = _libs["../libs/libiwasm.so"].get("wasm_runtime_instantiate", "cdecl")
+    wasm_runtime_instantiate.argtypes = [wasm_module_t, uint32_t, uint32_t, String, uint32_t]
+    wasm_runtime_instantiate.restype = wasm_module_inst_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 502
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_set_running_mode", "cdecl"):
+        continue
+    wasm_runtime_set_running_mode = _lib.get("wasm_runtime_set_running_mode", "cdecl")
+    wasm_runtime_set_running_mode.argtypes = [wasm_module_inst_t, RunningMode]
+    wasm_runtime_set_running_mode.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 516
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_get_running_mode", "cdecl"):
+        continue
+    wasm_runtime_get_running_mode = _lib.get("wasm_runtime_get_running_mode", "cdecl")
+    wasm_runtime_get_running_mode.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_running_mode.restype = RunningMode
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 524
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_deinstantiate", "cdecl"):
+    wasm_runtime_deinstantiate = _libs["../libs/libiwasm.so"].get("wasm_runtime_deinstantiate", "cdecl")
+    wasm_runtime_deinstantiate.argtypes = [wasm_module_inst_t]
+    wasm_runtime_deinstantiate.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 534
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_module", "cdecl"):
+    wasm_runtime_get_module = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_module", "cdecl")
+    wasm_runtime_get_module.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_module.restype = wasm_module_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 537
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_is_wasi_mode", "cdecl"):
+    wasm_runtime_is_wasi_mode = _libs["../libs/libiwasm.so"].get("wasm_runtime_is_wasi_mode", "cdecl")
+    wasm_runtime_is_wasi_mode.argtypes = [wasm_module_inst_t]
+    wasm_runtime_is_wasi_mode.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 540
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_lookup_wasi_start_function", "cdecl"):
+    wasm_runtime_lookup_wasi_start_function = _libs["../libs/libiwasm.so"].get("wasm_runtime_lookup_wasi_start_function", "cdecl")
+    wasm_runtime_lookup_wasi_start_function.argtypes = [wasm_module_inst_t]
+    wasm_runtime_lookup_wasi_start_function.restype = wasm_function_inst_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 552
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_wasi_exit_code", "cdecl"):
+    wasm_runtime_get_wasi_exit_code = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_wasi_exit_code", "cdecl")
+    wasm_runtime_get_wasi_exit_code.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_wasi_exit_code.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 564
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_lookup_function", "cdecl"):
+    wasm_runtime_lookup_function = _libs["../libs/libiwasm.so"].get("wasm_runtime_lookup_function", "cdecl")
+    wasm_runtime_lookup_function.argtypes = [wasm_module_inst_t, String, String]
+    wasm_runtime_lookup_function.restype = wasm_function_inst_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 576
+if _libs["../libs/libiwasm.so"].has("wasm_func_get_param_count", "cdecl"):
+    wasm_func_get_param_count = _libs["../libs/libiwasm.so"].get("wasm_func_get_param_count", "cdecl")
+    wasm_func_get_param_count.argtypes = [wasm_function_inst_t, wasm_module_inst_t]
+    wasm_func_get_param_count.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 588
+if _libs["../libs/libiwasm.so"].has("wasm_func_get_result_count", "cdecl"):
+    wasm_func_get_result_count = _libs["../libs/libiwasm.so"].get("wasm_func_get_result_count", "cdecl")
+    wasm_func_get_result_count.argtypes = [wasm_function_inst_t, wasm_module_inst_t]
+    wasm_func_get_result_count.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 599
+if _libs["../libs/libiwasm.so"].has("wasm_func_get_param_types", "cdecl"):
+    wasm_func_get_param_types = _libs["../libs/libiwasm.so"].get("wasm_func_get_param_types", "cdecl")
+    wasm_func_get_param_types.argtypes = [wasm_function_inst_t, wasm_module_inst_t, POINTER(wasm_valkind_t)]
+    wasm_func_get_param_types.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 611
+if _libs["../libs/libiwasm.so"].has("wasm_func_get_result_types", "cdecl"):
+    wasm_func_get_result_types = _libs["../libs/libiwasm.so"].get("wasm_func_get_result_types", "cdecl")
+    wasm_func_get_result_types.argtypes = [wasm_function_inst_t, wasm_module_inst_t, POINTER(wasm_valkind_t)]
+    wasm_func_get_result_types.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 625
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_create_exec_env", "cdecl"):
+    wasm_runtime_create_exec_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_create_exec_env", "cdecl")
+    wasm_runtime_create_exec_env.argtypes = [wasm_module_inst_t, uint32_t]
+    wasm_runtime_create_exec_env.restype = wasm_exec_env_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 634
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy_exec_env", "cdecl"):
+    wasm_runtime_destroy_exec_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy_exec_env", "cdecl")
+    wasm_runtime_destroy_exec_env.argtypes = [wasm_exec_env_t]
+    wasm_runtime_destroy_exec_env.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 651
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_exec_env_singleton", "cdecl"):
+    wasm_runtime_get_exec_env_singleton = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_exec_env_singleton", "cdecl")
+    wasm_runtime_get_exec_env_singleton.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_exec_env_singleton.restype = wasm_exec_env_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 674
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_start_debug_instance_with_port", "cdecl"):
+        continue
+    wasm_runtime_start_debug_instance_with_port = _lib.get("wasm_runtime_start_debug_instance_with_port", "cdecl")
+    wasm_runtime_start_debug_instance_with_port.argtypes = [wasm_exec_env_t, c_int32]
+    wasm_runtime_start_debug_instance_with_port.restype = uint32_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 680
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_start_debug_instance", "cdecl"):
+        continue
+    wasm_runtime_start_debug_instance = _lib.get("wasm_runtime_start_debug_instance", "cdecl")
+    wasm_runtime_start_debug_instance.argtypes = [wasm_exec_env_t]
+    wasm_runtime_start_debug_instance.restype = uint32_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 695
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_init_thread_env", "cdecl"):
+    wasm_runtime_init_thread_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_init_thread_env", "cdecl")
+    wasm_runtime_init_thread_env.argtypes = []
+    wasm_runtime_init_thread_env.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 701
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_destroy_thread_env", "cdecl"):
+    wasm_runtime_destroy_thread_env = _libs["../libs/libiwasm.so"].get("wasm_runtime_destroy_thread_env", "cdecl")
+    wasm_runtime_destroy_thread_env.argtypes = []
+    wasm_runtime_destroy_thread_env.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 707
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_thread_env_inited", "cdecl"):
+    wasm_runtime_thread_env_inited = _libs["../libs/libiwasm.so"].get("wasm_runtime_thread_env_inited", "cdecl")
+    wasm_runtime_thread_env_inited.argtypes = []
+    wasm_runtime_thread_env_inited.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 717
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_module_inst", "cdecl"):
+    wasm_runtime_get_module_inst = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_module_inst", "cdecl")
+    wasm_runtime_get_module_inst.argtypes = [wasm_exec_env_t]
+    wasm_runtime_get_module_inst.restype = wasm_module_inst_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 731
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_module_inst", "cdecl"):
+    wasm_runtime_set_module_inst = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_module_inst", "cdecl")
+    wasm_runtime_set_module_inst.argtypes = [wasm_exec_env_t, wasm_module_inst_t]
+    wasm_runtime_set_module_inst.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 755
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm", "cdecl"):
+    wasm_runtime_call_wasm = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm", "cdecl")
+    wasm_runtime_call_wasm.argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(uint32_t)]
+    wasm_runtime_call_wasm.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 776
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm_a", "cdecl"):
+    wasm_runtime_call_wasm_a = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm_a", "cdecl")
+    wasm_runtime_call_wasm_a.argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(wasm_val_t), uint32_t, POINTER(wasm_val_t)]
+    wasm_runtime_call_wasm_a.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 798
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_call_wasm_v", "cdecl"):
+    _func = _libs["../libs/libiwasm.so"].get("wasm_runtime_call_wasm_v", "cdecl")
+    _restype = c_bool
+    _errcheck = None
+    _argtypes = [wasm_exec_env_t, wasm_function_inst_t, uint32_t, POINTER(wasm_val_t), uint32_t]
+    wasm_runtime_call_wasm_v = _variadic_function(_func,_restype,_argtypes,_errcheck)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 818
+if _libs["../libs/libiwasm.so"].has("wasm_application_execute_main", "cdecl"):
+    wasm_application_execute_main = _libs["../libs/libiwasm.so"].get("wasm_application_execute_main", "cdecl")
+    wasm_application_execute_main.argtypes = [wasm_module_inst_t, c_int32, POINTER(POINTER(c_char))]
+    wasm_application_execute_main.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 837
+if _libs["../libs/libiwasm.so"].has("wasm_application_execute_func", "cdecl"):
+    wasm_application_execute_func = _libs["../libs/libiwasm.so"].get("wasm_application_execute_func", "cdecl")
+    wasm_application_execute_func.argtypes = [wasm_module_inst_t, String, c_int32, POINTER(POINTER(c_char))]
+    wasm_application_execute_func.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 846
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_exception", "cdecl"):
+    wasm_runtime_get_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_exception", "cdecl")
+    wasm_runtime_get_exception.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_exception.restype = c_char_p
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 857
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_exception", "cdecl"):
+    wasm_runtime_set_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_exception", "cdecl")
+    wasm_runtime_set_exception.argtypes = [wasm_module_inst_t, String]
+    wasm_runtime_set_exception.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 866
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_clear_exception", "cdecl"):
+    wasm_runtime_clear_exception = _libs["../libs/libiwasm.so"].get("wasm_runtime_clear_exception", "cdecl")
+    wasm_runtime_clear_exception.argtypes = [wasm_module_inst_t]
+    wasm_runtime_clear_exception.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 878
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_custom_data", "cdecl"):
+    wasm_runtime_set_custom_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_custom_data", "cdecl")
+    wasm_runtime_set_custom_data.argtypes = [wasm_module_inst_t, POINTER(None)]
+    wasm_runtime_set_custom_data.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 887
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_custom_data", "cdecl"):
+    wasm_runtime_get_custom_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_custom_data", "cdecl")
+    wasm_runtime_get_custom_data.argtypes = [wasm_module_inst_t]
+    wasm_runtime_get_custom_data.restype = POINTER(c_ubyte)
+    wasm_runtime_get_custom_data.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 910
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_malloc", "cdecl"):
+    wasm_runtime_module_malloc = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_malloc", "cdecl")
+    wasm_runtime_module_malloc.argtypes = [wasm_module_inst_t, uint32_t, POINTER(POINTER(None))]
+    wasm_runtime_module_malloc.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 920
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_free", "cdecl"):
+    wasm_runtime_module_free = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_free", "cdecl")
+    wasm_runtime_module_free.argtypes = [wasm_module_inst_t, uint32_t]
+    wasm_runtime_module_free.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 936
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_module_dup_data", "cdecl"):
+    wasm_runtime_module_dup_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_module_dup_data", "cdecl")
+    wasm_runtime_module_dup_data.argtypes = [wasm_module_inst_t, String, uint32_t]
+    wasm_runtime_module_dup_data.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 951
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_app_addr", "cdecl"):
+    wasm_runtime_validate_app_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_app_addr", "cdecl")
+    wasm_runtime_validate_app_addr.argtypes = [wasm_module_inst_t, uint32_t, uint32_t]
+    wasm_runtime_validate_app_addr.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 973
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_app_str_addr", "cdecl"):
+    wasm_runtime_validate_app_str_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_app_str_addr", "cdecl")
+    wasm_runtime_validate_app_str_addr.argtypes = [wasm_module_inst_t, uint32_t]
+    wasm_runtime_validate_app_str_addr.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 989
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_validate_native_addr", "cdecl"):
+    wasm_runtime_validate_native_addr = _libs["../libs/libiwasm.so"].get("wasm_runtime_validate_native_addr", "cdecl")
+    wasm_runtime_validate_native_addr.argtypes = [wasm_module_inst_t, POINTER(None), uint32_t]
+    wasm_runtime_validate_native_addr.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1004
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_addr_app_to_native", "cdecl"):
+    wasm_runtime_addr_app_to_native = _libs["../libs/libiwasm.so"].get("wasm_runtime_addr_app_to_native", "cdecl")
+    wasm_runtime_addr_app_to_native.argtypes = [wasm_module_inst_t, uint32_t]
+    wasm_runtime_addr_app_to_native.restype = POINTER(c_ubyte)
+    wasm_runtime_addr_app_to_native.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1017
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_addr_native_to_app", "cdecl"):
+    wasm_runtime_addr_native_to_app = _libs["../libs/libiwasm.so"].get("wasm_runtime_addr_native_to_app", "cdecl")
+    wasm_runtime_addr_native_to_app.argtypes = [wasm_module_inst_t, POINTER(None)]
+    wasm_runtime_addr_native_to_app.restype = uint32_t
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1031
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_app_addr_range", "cdecl"):
+    wasm_runtime_get_app_addr_range = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_app_addr_range", "cdecl")
+    wasm_runtime_get_app_addr_range.argtypes = [wasm_module_inst_t, uint32_t, POINTER(uint32_t), POINTER(uint32_t)]
+    wasm_runtime_get_app_addr_range.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1050
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_native_addr_range", "cdecl"):
+    wasm_runtime_get_native_addr_range = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_native_addr_range", "cdecl")
+    wasm_runtime_get_native_addr_range.argtypes = [wasm_module_inst_t, POINTER(uint8_t), POINTER(POINTER(uint8_t)), POINTER(POINTER(uint8_t))]
+    wasm_runtime_get_native_addr_range.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1089
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_register_natives", "cdecl"):
+    wasm_runtime_register_natives = _libs["../libs/libiwasm.so"].get("wasm_runtime_register_natives", "cdecl")
+    wasm_runtime_register_natives.argtypes = [String, POINTER(NativeSymbol), uint32_t]
+    wasm_runtime_register_natives.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1104
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_register_natives_raw", "cdecl"):
+    wasm_runtime_register_natives_raw = _libs["../libs/libiwasm.so"].get("wasm_runtime_register_natives_raw", "cdecl")
+    wasm_runtime_register_natives_raw.argtypes = [String, POINTER(NativeSymbol), uint32_t]
+    wasm_runtime_register_natives_raw.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1123
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_unregister_natives", "cdecl"):
+    wasm_runtime_unregister_natives = _libs["../libs/libiwasm.so"].get("wasm_runtime_unregister_natives", "cdecl")
+    wasm_runtime_unregister_natives.argtypes = [String, POINTER(NativeSymbol)]
+    wasm_runtime_unregister_natives.restype = c_bool
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1133
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_function_attachment", "cdecl"):
+    wasm_runtime_get_function_attachment = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_function_attachment", "cdecl")
+    wasm_runtime_get_function_attachment.argtypes = [wasm_exec_env_t]
+    wasm_runtime_get_function_attachment.restype = POINTER(c_ubyte)
+    wasm_runtime_get_function_attachment.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1143
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_set_user_data", "cdecl"):
+    wasm_runtime_set_user_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_set_user_data", "cdecl")
+    wasm_runtime_set_user_data.argtypes = [wasm_exec_env_t, POINTER(None)]
+    wasm_runtime_set_user_data.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1152
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_user_data", "cdecl"):
+    wasm_runtime_get_user_data = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_user_data", "cdecl")
+    wasm_runtime_get_user_data.argtypes = [wasm_exec_env_t]
+    wasm_runtime_get_user_data.restype = POINTER(c_ubyte)
+    wasm_runtime_get_user_data.errcheck = lambda v,*a : cast(v, c_void_p)
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1165
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_dump_mem_consumption", "cdecl"):
+        continue
+    wasm_runtime_dump_mem_consumption = _lib.get("wasm_runtime_dump_mem_consumption", "cdecl")
+    wasm_runtime_dump_mem_consumption.argtypes = [wasm_exec_env_t]
+    wasm_runtime_dump_mem_consumption.restype = None
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1173
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_dump_perf_profiling", "cdecl"):
+        continue
+    wasm_runtime_dump_perf_profiling = _lib.get("wasm_runtime_dump_perf_profiling", "cdecl")
+    wasm_runtime_dump_perf_profiling.argtypes = [wasm_module_inst_t]
+    wasm_runtime_dump_perf_profiling.restype = None
+    break
+
+wasm_thread_callback_t = CFUNCTYPE(UNCHECKED(POINTER(c_ubyte)), wasm_exec_env_t, POINTER(None))# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1176
+
+wasm_thread_t = uintptr_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1178
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1186
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_set_max_thread_num", "cdecl"):
+        continue
+    wasm_runtime_set_max_thread_num = _lib.get("wasm_runtime_set_max_thread_num", "cdecl")
+    wasm_runtime_set_max_thread_num.argtypes = [uint32_t]
+    wasm_runtime_set_max_thread_num.restype = None
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1197
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_spawn_exec_env", "cdecl"):
+        continue
+    wasm_runtime_spawn_exec_env = _lib.get("wasm_runtime_spawn_exec_env", "cdecl")
+    wasm_runtime_spawn_exec_env.argtypes = [wasm_exec_env_t]
+    wasm_runtime_spawn_exec_env.restype = wasm_exec_env_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1205
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_destroy_spawned_exec_env", "cdecl"):
+        continue
+    wasm_runtime_destroy_spawned_exec_env = _lib.get("wasm_runtime_destroy_spawned_exec_env", "cdecl")
+    wasm_runtime_destroy_spawned_exec_env.argtypes = [wasm_exec_env_t]
+    wasm_runtime_destroy_spawned_exec_env.restype = None
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1218
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_spawn_thread", "cdecl"):
+        continue
+    wasm_runtime_spawn_thread = _lib.get("wasm_runtime_spawn_thread", "cdecl")
+    wasm_runtime_spawn_thread.argtypes = [wasm_exec_env_t, POINTER(wasm_thread_t), wasm_thread_callback_t, POINTER(None)]
+    wasm_runtime_spawn_thread.restype = c_int32
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1230
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_join_thread", "cdecl"):
+        continue
+    wasm_runtime_join_thread = _lib.get("wasm_runtime_join_thread", "cdecl")
+    wasm_runtime_join_thread.argtypes = [wasm_thread_t, POINTER(POINTER(None))]
+    wasm_runtime_join_thread.restype = c_int32
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1244
+for _lib in _libs.values():
+    if not _lib.has("wasm_externref_obj2ref", "cdecl"):
+        continue
+    wasm_externref_obj2ref = _lib.get("wasm_externref_obj2ref", "cdecl")
+    wasm_externref_obj2ref.argtypes = [wasm_module_inst_t, POINTER(None), POINTER(uint32_t)]
+    wasm_externref_obj2ref.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1257
+for _lib in _libs.values():
+    if not _lib.has("wasm_externref_ref2obj", "cdecl"):
+        continue
+    wasm_externref_ref2obj = _lib.get("wasm_externref_ref2obj", "cdecl")
+    wasm_externref_ref2obj.argtypes = [uint32_t, POINTER(POINTER(None))]
+    wasm_externref_ref2obj.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1269
+for _lib in _libs.values():
+    if not _lib.has("wasm_externref_retain", "cdecl"):
+        continue
+    wasm_externref_retain = _lib.get("wasm_externref_retain", "cdecl")
+    wasm_externref_retain.argtypes = [uint32_t]
+    wasm_externref_retain.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1277
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_dump_call_stack", "cdecl"):
+        continue
+    wasm_runtime_dump_call_stack = _lib.get("wasm_runtime_dump_call_stack", "cdecl")
+    wasm_runtime_dump_call_stack.argtypes = [wasm_exec_env_t]
+    wasm_runtime_dump_call_stack.restype = None
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1288
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_get_call_stack_buf_size", "cdecl"):
+        continue
+    wasm_runtime_get_call_stack_buf_size = _lib.get("wasm_runtime_get_call_stack_buf_size", "cdecl")
+    wasm_runtime_get_call_stack_buf_size.argtypes = [wasm_exec_env_t]
+    wasm_runtime_get_call_stack_buf_size.restype = uint32_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1304
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_dump_call_stack_to_buf", "cdecl"):
+        continue
+    wasm_runtime_dump_call_stack_to_buf = _lib.get("wasm_runtime_dump_call_stack_to_buf", "cdecl")
+    wasm_runtime_dump_call_stack_to_buf.argtypes = [wasm_exec_env_t, String, uint32_t]
+    wasm_runtime_dump_call_stack_to_buf.restype = uint32_t
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1317
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_get_custom_section", "cdecl"):
+        continue
+    wasm_runtime_get_custom_section = _lib.get("wasm_runtime_get_custom_section", "cdecl")
+    wasm_runtime_get_custom_section.argtypes = [wasm_module_t, String, POINTER(uint32_t)]
+    wasm_runtime_get_custom_section.restype = POINTER(uint8_t)
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1326
+if _libs["../libs/libiwasm.so"].has("wasm_runtime_get_version", "cdecl"):
+    wasm_runtime_get_version = _libs["../libs/libiwasm.so"].get("wasm_runtime_get_version", "cdecl")
+    wasm_runtime_get_version.argtypes = [POINTER(uint32_t), POINTER(uint32_t), POINTER(uint32_t)]
+    wasm_runtime_get_version.restype = None
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1333
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_is_import_func_linked", "cdecl"):
+        continue
+    wasm_runtime_is_import_func_linked = _lib.get("wasm_runtime_is_import_func_linked", "cdecl")
+    wasm_runtime_is_import_func_linked.argtypes = [String, String]
+    wasm_runtime_is_import_func_linked.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 1341
+for _lib in _libs.values():
+    if not _lib.has("wasm_runtime_is_import_global_linked", "cdecl"):
+        continue
+    wasm_runtime_is_import_global_linked = _lib.get("wasm_runtime_is_import_global_linked", "cdecl")
+    wasm_runtime_is_import_global_linked.argtypes = [String, String]
+    wasm_runtime_is_import_global_linked.restype = c_bool
+    break
+
+# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 31
+def get_module_inst(exec_env):
+    return (wasm_runtime_get_module_inst (exec_env))
+
+WASMModuleCommon = struct_WASMModuleCommon# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 62
+
+WASMModuleInstanceCommon = struct_WASMModuleInstanceCommon# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 67
+
+wasm_section_t = struct_wasm_section_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 75
+
+WASMExecEnv = struct_WASMExecEnv# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 86
+
+MemAllocOption = union_MemAllocOption# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 124
+
+mem_alloc_info_t = struct_mem_alloc_info_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 132
+
+RuntimeInitArgs = struct_RuntimeInitArgs# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 170
+
+wasm_val_t = struct_wasm_val_t# wasm-micro-runtime/core/iwasm/include/wasm_export.h: 199
+
+# No inserted files
+
+# No prefix-stripping
+

+ 123 - 0
language-bindings/python/src/wamr/wamrapi/wamr.py

@@ -0,0 +1,123 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+from ctypes import Array
+from ctypes import c_char
+from ctypes import c_uint
+from ctypes import c_uint8
+from ctypes import c_void_p
+from ctypes import cast
+from ctypes import create_string_buffer
+from ctypes import POINTER
+from ctypes import pointer
+
+from wamr.wamrapi.iwasm import Alloc_With_Pool
+from wamr.wamrapi.iwasm import RuntimeInitArgs
+from wamr.wamrapi.iwasm import wasm_exec_env_t
+from wamr.wamrapi.iwasm import wasm_function_inst_t
+from wamr.wamrapi.iwasm import wasm_module_inst_t
+from wamr.wamrapi.iwasm import wasm_module_t
+from wamr.wamrapi.iwasm import wasm_runtime_call_wasm
+from wamr.wamrapi.iwasm import wasm_runtime_create_exec_env
+from wamr.wamrapi.iwasm import wasm_runtime_deinstantiate
+from wamr.wamrapi.iwasm import wasm_runtime_destroy
+from wamr.wamrapi.iwasm import wasm_runtime_destroy_exec_env
+from wamr.wamrapi.iwasm import wasm_runtime_full_init
+from wamr.wamrapi.iwasm import wasm_runtime_instantiate
+from wamr.wamrapi.iwasm import wasm_runtime_load
+from wamr.wamrapi.iwasm import wasm_runtime_lookup_function
+from wamr.wamrapi.iwasm import wasm_runtime_unload
+
+
+class Engine:
+    def __init__(self):
+        self.init_args = self._get_init_args()
+        wasm_runtime_full_init(pointer(self.init_args))
+
+    def __del__(self):
+        print("deleting Engine")
+        wasm_runtime_destroy()
+
+    def _get_init_args(self, heap_size: int = 1024 * 512) -> RuntimeInitArgs:
+        init_args = RuntimeInitArgs()
+        init_args.mem_alloc_type = Alloc_With_Pool
+        init_args.mem_alloc_option.pool.heap_buf = cast(
+            (c_char * heap_size)(), c_void_p
+        )
+        init_args.mem_alloc_option.pool.heap_size = heap_size
+        return init_args
+
+
+class Module:
+    __create_key = object()
+
+    @classmethod
+    def from_file(cls, engine: Engine, fp: str) -> "Module":
+        return Module(cls.__create_key, engine, fp)
+
+    def __init__(self, create_key: object, engine: Engine, fp: str) -> None:
+        assert (
+            create_key == Module.__create_key
+        ), "Module objects must be created using Module.from_file"
+        self.engine = engine
+        self.module, self.file_data = self._create_module(fp)
+
+    def __del__(self):
+        print("deleting Module")
+        wasm_runtime_unload(self.module)
+
+    def _create_module(self, fp: str) -> tuple[wasm_module_t, Array[c_uint]]:
+        with open(fp, "rb") as f:
+            data = f.read()
+            data = (c_uint8 * len(data))(*data)
+
+        error_buf = create_string_buffer(128)
+        module = wasm_runtime_load(data, len(data), error_buf, len(error_buf))
+        if not module:
+            raise Exception("Error while creating module")
+        return module, data
+
+
+class Instance:
+    def __init__(self, module: Module, stack_size: int = 65536, heap_size: int = 16384):
+        self.module = module
+        self.module_inst = self._create_module_inst(module, stack_size, heap_size)
+
+    def __del__(self):
+        print("deleting Instance")
+        wasm_runtime_deinstantiate(self.module_inst)
+
+    def lookup_function(self, name: str):
+        func = wasm_runtime_lookup_function(self.module_inst, name, None)
+        if not func:
+            raise Exception("Error while looking-up function")
+        return func
+
+    def _create_module_inst(self, module: Module, stack_size: int, heap_size: int) -> wasm_module_inst_t:
+        error_buf = create_string_buffer(128)
+        module_inst = wasm_runtime_instantiate(
+            module.module, stack_size, heap_size, error_buf, len(error_buf)
+        )
+        if not module_inst:
+            raise Exception("Error while creating module instance")
+        return module_inst
+
+
+class ExecEnv:
+    def __init__(self, module_inst: Instance, stack_size: int = 65536):
+        self.module_inst = module_inst
+        self.exec_env = self._create_exec_env(module_inst, stack_size)
+
+    def __del__(self):
+        print("deleting ExecEnv")
+        wasm_runtime_destroy_exec_env(self.exec_env)
+
+    def call(self, func: wasm_function_inst_t, argc: int, argv: "POINTER[c_uint]"):
+        if not wasm_runtime_call_wasm(self.exec_env, func, argc, argv):
+            raise Exception("Error while calling function")
+
+    def _create_exec_env(self, module_inst: Instance, stack_size: int) -> wasm_exec_env_t:
+        exec_env = wasm_runtime_create_exec_env(module_inst.module_inst, stack_size)
+        if not exec_env:
+            raise Exception("Error while creating execution environment")
+        return exec_env

+ 0 - 0
language-bindings/python/wamr/__init__.py → language-bindings/python/src/wamr/wasmcapi/__init__.py


+ 0 - 0
language-bindings/python/wamr/binding.py → language-bindings/python/src/wamr/wasmcapi/binding.py


+ 2 - 2
language-bindings/python/wamr/ffi.py → language-bindings/python/src/wamr/wasmcapi/ffi.py

@@ -36,8 +36,8 @@ current_file = Path(__file__)
 if current_file.is_symlink():
 if current_file.is_symlink():
     current_file = Path(os.readlink(current_file))
     current_file = Path(os.readlink(current_file))
 current_dir = current_file.parent.resolve()
 current_dir = current_file.parent.resolve()
-root_dir = current_dir.parent.parent.parent.parent.resolve()
-wamr_dir = root_dir.joinpath("wasm-micro-runtime").resolve()
+root_dir = current_dir.parents[4].resolve()
+wamr_dir = root_dir.resolve()
 if not wamr_dir.exists():
 if not wamr_dir.exists():
     raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}")
     raise RuntimeError(f"not found the repo of wasm-micro-runtime under {root_dir}")
 
 

+ 17 - 0
language-bindings/python/utils/create_lib.sh

@@ -0,0 +1,17 @@
+#!/bin/sh
+
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+CUR_DIR=$(cd $(dirname $0) && pwd -P)
+ROOT_DIR=${CUR_DIR}/../../..
+
+WAMR_BUILD_PLATFORM=${WAMR_BUILD_PLATFORM:-"linux"}
+
+cd ${ROOT_DIR}/product-mini/platforms/${WAMR_BUILD_PLATFORM}
+
+mkdir -p build && cd build
+cmake ..
+make -j
+
+cp libiwasm.so ${CUR_DIR}/../src/wamr/libs

+ 25 - 0
language-bindings/python/wamr-api/README.md

@@ -0,0 +1,25 @@
+# WARM API
+
+## Examples
+
+Copy in `language-bindings/python/wamr/libs` the library `libiwasm` generated from `product-mini/platforms`.
+
+There is a [simple example](./samples/main.py) to show how to use bindings.
+
+```
+python samples/main.py
+```
+
+## Update WAMR API bindings
+
+Install requirements,
+
+```
+pip install -r requirements.txt
+```
+
+Run the following command,
+
+```sh
+ctypesgen ../../../../core/iwasm/include/wasm_export.h -l ../libs/libiwasm.so -o iwasm.py
+```

+ 1 - 0
language-bindings/python/wamr-api/requirements.txt

@@ -0,0 +1 @@
+ctypesgen==1.1.1

+ 11 - 0
language-bindings/python/wamr-api/samples/compile.sh

@@ -0,0 +1,11 @@
+#!/bin/sh
+
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+/opt/wasi-sdk/bin/clang     \
+    -O0 -z stack-size=4096 -Wl,--initial-memory=65536 \
+    -Wl,--strip-all,--no-entry -nostdlib \
+    -Wl,--export=sum\
+    -Wl,--allow-undefined \
+    -o test.wasm sum.c

+ 22 - 0
language-bindings/python/wamr-api/samples/main.py

@@ -0,0 +1,22 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+from wamr.wamrapi.wamr import Engine, Module, Instance, ExecEnv
+from ctypes import c_uint
+import pathlib
+
+def main():
+    engine = Engine()
+    module = Module.from_file(engine, pathlib.Path(__file__).parent / "sum.wasm")
+    module_inst = Instance(module)
+    exec_env = ExecEnv(module_inst)
+
+    func = module_inst.lookup_function("sum")
+
+    argv = (c_uint * 2)(*[10, 11])
+    exec_env.call(func, len(argv), argv)
+    print(argv[0])
+
+
+if __name__ == "__main__":
+    main()

+ 12 - 0
language-bindings/python/wamr-api/samples/sum.c

@@ -0,0 +1,12 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <stdio.h>
+
+int
+sum(int a, int b)
+{
+    return a + b;
+}

+ 7 - 0
language-bindings/python/wasm-c-api/README.md

@@ -0,0 +1,7 @@
+# WASM-C-API
+
+## Examples
+
+There is a [simple example](./samples/hello_procedural.py) to show how to use bindings. Actually, the python binding follows C-APIs. There it should be easy if be familiar with _programming with wasm-c-api_.
+
+Unit test cases under _./tests_ could be another but more complete references.

+ 0 - 0
language-bindings/python/docs/design.md → language-bindings/python/wasm-c-api/docs/design.md


+ 0 - 0
language-bindings/python/docs/images/python_package_life_cycle.png → language-bindings/python/wasm-c-api/docs/images/python_package_life_cycle.png


+ 0 - 0
language-bindings/python/docs/setup_dev_env.md → language-bindings/python/wasm-c-api/docs/setup_dev_env.md


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません