Sfoglia il codice sorgente

Merge branch 'bytecodealliance:main' into master

Wang Xin 4 anni fa
parent
commit
85c0bc2d9d
100 ha cambiato i file con 17527 aggiunte e 2630 eliminazioni
  1. 51 17
      .clang-format
  2. 91 0
      .github/workflows/android.yml
  3. 133 0
      .github/workflows/linux.yml
  4. 101 0
      .github/workflows/mac.yml
  5. 63 0
      .github/workflows/windows.yml
  6. 7 3
      .gitignore
  7. 33 298
      ATTRIBUTIONS.md
  8. 139 0
      CMakeLists.txt
  9. 0 21
      Dockerfile
  10. 53 45
      README.md
  11. 33 0
      SConscript
  12. 1 27
      SECURITY.md
  13. 177 0
      TSC_Charter.md
  14. 1 0
      assembly-script/.gitignore
  15. 8 8
      assembly-script/package-lock.json
  16. 6 6
      assembly-script/package.json
  17. 88 0
      build-scripts/SConscript
  18. 121 0
      build-scripts/SConscript_config
  19. 114 14
      build-scripts/config_common.cmake
  20. 39 8
      build-scripts/runtime_lib.cmake
  21. 18 0
      ci/Dockerfile
  22. 24 0
      ci/build_wamr.sh
  23. 13 6
      core/app-framework/app-native-shared/attr_container.c
  24. 1 1
      core/app-framework/app-native-shared/bi-inc/attr_container.h
  25. 0 5
      core/app-framework/app-native-shared/restful_utils.c
  26. 14 0
      core/app-framework/base/app/bh_platform.h
  27. 47 35
      core/app-framework/base/native/timer_wrapper.c
  28. 40 29
      core/app-mgr/app-manager/app_manager.c
  29. 60 33
      core/app-mgr/app-manager/app_manager_host.c
  30. 2 2
      core/app-mgr/app-manager/message.c
  31. 5 6
      core/app-mgr/app-manager/module_utils.c
  32. 141 74
      core/app-mgr/app-manager/module_wasm_app.c
  33. 4 3
      core/app-mgr/app-manager/resource_reg.c
  34. 6 0
      core/app-mgr/app-manager/watchdog.c
  35. 3 0
      core/app-mgr/app-manager/watchdog.h
  36. 11 12
      core/app-mgr/app-mgr-shared/app_manager_export.h
  37. 134 25
      core/config.h
  38. 1 1
      core/deps/download.sh
  39. 31 0
      core/iwasm/aot/SConscript
  40. 395 191
      core/iwasm/aot/aot_loader.c
  41. 45 3
      core/iwasm/aot/aot_reloc.h
  42. 755 149
      core/iwasm/aot/aot_runtime.c
  43. 301 45
      core/iwasm/aot/aot_runtime.h
  44. 174 25
      core/iwasm/aot/arch/aot_reloc_aarch64.c
  45. 21 11
      core/iwasm/aot/arch/aot_reloc_arm.c
  46. 47 11
      core/iwasm/aot/arch/aot_reloc_thumb.c
  47. 30 1
      core/iwasm/aot/arch/aot_reloc_x86_32.c
  48. 82 13
      core/iwasm/aot/arch/aot_reloc_x86_64.c
  49. 1 1
      core/iwasm/aot/arch/aot_reloc_xtensa.c
  50. 26 0
      core/iwasm/common/SConscript
  51. 10 5
      core/iwasm/common/arch/invokeNative_aarch64.s
  52. 79 0
      core/iwasm/common/arch/invokeNative_aarch64_simd.s
  53. 10 4
      core/iwasm/common/arch/invokeNative_arm.s
  54. 9 4
      core/iwasm/common/arch/invokeNative_arm_vfp.s
  55. 62 0
      core/iwasm/common/arch/invokeNative_em64.asm
  56. 62 0
      core/iwasm/common/arch/invokeNative_em64_simd.asm
  57. 64 0
      core/iwasm/common/arch/invokeNative_em64_simd.s
  58. 27 0
      core/iwasm/common/arch/invokeNative_ia32.asm
  59. 95 0
      core/iwasm/common/arch/invokeNative_riscv32_ilp32.s
  60. 104 0
      core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s
  61. 95 0
      core/iwasm/common/arch/invokeNative_riscv64_lp64.s
  62. 108 0
      core/iwasm/common/arch/invokeNative_riscv64_lp64d.s
  63. 8 3
      core/iwasm/common/arch/invokeNative_thumb.s
  64. 8 3
      core/iwasm/common/arch/invokeNative_thumb_vfp.s
  65. 46 12
      core/iwasm/common/iwasm_common.cmake
  66. 676 0
      core/iwasm/common/wasm_application.c
  67. 3784 0
      core/iwasm/common/wasm_c_api.c
  68. 174 0
      core/iwasm/common/wasm_c_api_internal.h
  69. 142 5
      core/iwasm/common/wasm_exec_env.c
  70. 116 12
      core/iwasm/common/wasm_exec_env.h
  71. 33 238
      core/iwasm/common/wasm_memory.c
  72. 144 17
      core/iwasm/common/wasm_native.c
  73. 837 29
      core/iwasm/common/wasm_runtime_common.c
  74. 535 65
      core/iwasm/common/wasm_runtime_common.h
  75. 421 0
      core/iwasm/common/wasm_shared_memory.c
  76. 68 0
      core/iwasm/common/wasm_shared_memory.h
  77. 134 67
      core/iwasm/compilation/aot.c
  78. 130 31
      core/iwasm/compilation/aot.h
  79. 1357 39
      core/iwasm/compilation/aot_compiler.c
  80. 154 13
      core/iwasm/compilation/aot_compiler.h
  81. 402 92
      core/iwasm/compilation/aot_emit_aot_file.c
  82. 1 1
      core/iwasm/compilation/aot_emit_const.c
  83. 531 116
      core/iwasm/compilation/aot_emit_control.c
  84. 7 1
      core/iwasm/compilation/aot_emit_control.h
  85. 265 16
      core/iwasm/compilation/aot_emit_conversion.c
  86. 12 4
      core/iwasm/compilation/aot_emit_conversion.h
  87. 8 65
      core/iwasm/compilation/aot_emit_exception.c
  88. 752 96
      core/iwasm/compilation/aot_emit_function.c
  89. 15 3
      core/iwasm/compilation/aot_emit_function.h
  90. 789 155
      core/iwasm/compilation/aot_emit_memory.c
  91. 54 4
      core/iwasm/compilation/aot_emit_memory.h
  92. 63 183
      core/iwasm/compilation/aot_emit_numberic.c
  93. 12 4
      core/iwasm/compilation/aot_emit_parametric.c
  94. 487 0
      core/iwasm/compilation/aot_emit_table.c
  95. 71 0
      core/iwasm/compilation/aot_emit_table.h
  96. 83 9
      core/iwasm/compilation/aot_emit_variable.c
  97. 1 1
      core/iwasm/compilation/aot_emit_variable.h
  98. 506 187
      core/iwasm/compilation/aot_llvm.c
  99. 137 17
      core/iwasm/compilation/aot_llvm.h
  100. 148 0
      core/iwasm/compilation/aot_llvm_extra.cpp

+ 51 - 17
_clang-format → .clang-format

@@ -1,32 +1,67 @@
----
-BasedOnStyle: Mozilla
-IndentWidth: 4
+RawStringFormats:
+  - Language:        Cpp
+    Delimiters:
+      - c
+      - C
+      - cc
+      - CC
+      - cpp
+      - Cpp
+      - CPP
+      - 'c++'
+      - 'C++'
+      - h
+      - hpp
+    CanonicalDelimiter: ''
+    BasedOnStyle:    google
+  - Language:        TextProto
+    Delimiters:
+      - pb
+      - PB
+      - proto
+      - PROTO
+    EnclosingFunctions:
+      - EqualsProto
+      - EquivToProto
+      - PARSE_PARTIAL_TEXT_PROTO
+      - PARSE_TEST_PROTO
+      - PARSE_TEXT_PROTO
+      - ParseTextOrDie
+      - ParseTextProtoOrDie
+    CanonicalDelimiter: ''
+    BasedOnStyle:    google
 
----
 Language: Cpp
+BasedOnStyle: Mozilla
+IndentWidth: 4
+AlignAfterOpenBracket: Align
+AllowAllArgumentsOnNextLine: false
 AlignConsecutiveMacros: true
 AllowShortBlocksOnASingleLine: true
+AlwaysBreakAfterReturnType: All
 BinPackArguments: true
-BinPackParameters: true
+BinPackParameters: false
+BreakBeforeBinaryOperators: NonAssignment
 BreakBeforeBraces: Custom
 BraceWrapping:
-  AfterCaseLabel: false
+  AfterCaseLabel: true
   AfterClass: true
   AfterControlStatement: false
-  AfterEnum: true
+  AfterEnum: false
   AfterFunction: true
   AfterNamespace: false
   AfterObjCDeclaration: false
-  AfterStruct: true
+  AfterStruct: false
   AfterUnion: false
-  AfterExternBlock: true
+  AfterExternBlock: false
   BeforeCatch: false
-  BeforeElse: false
+  BeforeElse: true
   IndentBraces: false
   SplitEmptyFunction: true
   SplitEmptyRecord: false
   SplitEmptyNamespace: true
 ColumnLimit: 79
+ContinuationIndentWidth: 2
 DerivePointerAlignment: false
 IncludeBlocks: Regroup
 IncludeCategories:
@@ -36,20 +71,23 @@ IncludeCategories:
     Priority: 1
   - Regex: ".*"
     Priority: 3
+IndentPPDirectives: None
+KeepEmptyLinesAtTheStartOfBlocks: false
+NamespaceIndentation: None
 PointerAlignment: Right
 ReflowComments: false
-Standard: Cpp03
+SortIncludes:   false
+Standard: Auto
 StatementMacros:
   - Q_UNUSED
   - QT_REQUIRE_VERSION
+
 # AccessModifierOffset: -2
-# AlignAfterOpenBracket: Align
 # AlignConsecutiveAssignments: false
 # AlignConsecutiveDeclarations: false
 # AlignEscapedNewlines: Right
 # AlignOperands:   true
 # AlignTrailingComments: true
-# AllowAllArgumentsOnNextLine: true
 # AllowAllConstructorInitializersOnNextLine: true
 # AllowAllParametersOfDeclarationOnNextLine: false
 # AllowShortCaseLabelsOnASingleLine: false
@@ -61,7 +99,6 @@ StatementMacros:
 # AlwaysBreakAfterReturnType: TopLevel
 # AlwaysBreakBeforeMultilineStrings: false
 # AlwaysBreakTemplateDeclarations: Yes
-# BreakBeforeBinaryOperators: None
 # BreakBeforeInheritanceComma: false
 # BreakInheritanceList: BeforeComma
 # BreakBeforeTernaryOperators: true
@@ -73,7 +110,6 @@ StatementMacros:
 # CompactNamespaces: false
 # ConstructorInitializerAllOnOneLineOrOnePerLine: false
 # ConstructorInitializerIndentWidth: 2
-# ContinuationIndentWidth: 2
 # Cpp11BracedListStyle: false
 # DisableFormat:   false
 # ExperimentalAutoDetectBinPacking: false
@@ -84,7 +120,6 @@ StatementMacros:
 #   - BOOST_FOREACH
 # IncludeIsMainRegex: '(Test)?$'
 # IndentCaseLabels: true
-# IndentPPDirectives: None
 # IndentWrappedFunctionNames: false
 # JavaScriptQuotes: Leave
 # JavaScriptWrapImports: true
@@ -92,7 +127,6 @@ StatementMacros:
 # MacroBlockBegin: ''
 # MacroBlockEnd:   ''
 # MaxEmptyLinesToKeep: 1
-# NamespaceIndentation: None
 # ObjCBinPackProtocolList: Auto
 # ObjCBlockIndentWidth: 2
 # ObjCSpaceAfterProperty: true

+ 91 - 0
.github/workflows/android.yml

@@ -0,0 +1,91 @@
+# This is a basic workflow to help you get started with Actions
+
+name: android
+
+# Controls when the action will run. 
+on:
+  # Triggers the workflow on push or pull request events but only for the master branch
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+  # Allows you to run this workflow manually from the Actions tab
+  workflow_dispatch:
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+  # This workflow contains a single job called "build"
+  build:
+    # The type of runner that the job will run on
+    runs-on: ubuntu-latest
+
+    # Steps represent a sequence of tasks that will be executed as part of the job
+    steps:
+      
+      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+      - uses: actions/checkout@v2
+      
+      - name: Build iwasm [default]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake ..
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [Classic interp]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_FAST_INTERP=0
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [Multi module]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_MULTI_MODULE=1
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [lib-pthread]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [aot only]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [interp only]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_AOT=0
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [memory profiling]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [tail call]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_TAIL_CALL=1
+          make
+          cd .. && rm -rf build
+      - name: Build iwasm [custom name section]
+        run: |
+          cd product-mini/platforms/android
+          mkdir build && cd build
+          cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
+          make
+          cd .. && rm -rf build

+ 133 - 0
.github/workflows/linux.yml

@@ -0,0 +1,133 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Linux
+
+# Controls when the action will run. Triggers the workflow on push or pull request
+# events but only for the main branch
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [ubuntu-18.04, ubuntu-20.04]
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Build iwasm [default]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake ..
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [Classic interp]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_FAST_INTERP=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [Multi module]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_MULTI_MODULE=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [lib-pthread]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [aot only]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [interp only]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [memory profiling]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [tail call]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_TAIL_CALL=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [custom name section]
+      run: |
+        cd product-mini/platforms/linux
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
+        make
+        cd .. && rm -rf build
+    - name: download and install wasi-sdk
+      run: |
+        cd /opt
+        wget https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-8/wasi-sdk-8.0-linux.tar.gz
+        tar -xzf wasi-sdk-8.0-linux.tar.gz
+        mv wasi-sdk-8.0 wasi-sdk
+    - name: download and install wabt
+      run: |
+        cd /opt
+        wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-ubuntu.tar.gz
+        tar -xzf wabt-1.0.19-ubuntu.tar.gz
+        mv wabt-1.0.19 wabt
+    - name: Build Sample [wasm-c-api]
+      run: |
+        cd samples/wasm-c-api
+        mkdir build && cd build
+        cmake ..
+        make
+        ./hello
+        ./global
+        ./callback
+    - name: Build Sample [basic]
+      run: |
+        cd samples/basic
+        ./build.sh
+        ./run.sh
+    - name: Build Sample [multi-thread]
+      run: |
+        cd samples/multi-thread
+        mkdir build && cd build
+        cmake ..
+        make
+        ./iwasm wasm-apps/test.wasm
+    - name: Build Sample [multi-module]
+      run: |
+        cd samples/multi-module
+        mkdir build && cd build
+        cmake ..
+        make
+        ./multi_module
+    - name: Build Sample [spawn-thread]
+      run: |
+        cd samples/spawn-thread
+        mkdir build && cd build
+        cmake ..
+        make
+        ./spawn_thread

+ 101 - 0
.github/workflows/mac.yml

@@ -0,0 +1,101 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Mac
+
+# Controls when the action will run. Triggers the workflow on push or pull request
+# events but only for the main branch
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [macos-latest]
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: Build iwasm [default]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake ..
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [Classic interp]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_FAST_INTERP=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [Multi module]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_MULTI_MODULE=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [lib-pthread]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_LIB_PTHREAD=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [aot only]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [interp only]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=0
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [memory profiling]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_MEMORY_PROFILING=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [tail call]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_TAIL_CALL=1
+        make
+        cd .. && rm -rf build
+    - name: Build iwasm [custom name section]
+      run: |
+        cd product-mini/platforms/darwin
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
+        make
+        cd .. && rm -rf build
+    - name: download and install wabt
+      run: |
+        cd /opt
+        sudo wget https://github.com/WebAssembly/wabt/releases/download/1.0.19/wabt-1.0.19-macos.tar.gz
+        sudo tar -xzf wabt-1.0.19-macos.tar.gz
+        sudo mv wabt-1.0.19 wabt
+    - name: Build Sample [wasm-c-api]
+      run: |
+        cd samples/wasm-c-api
+        mkdir build && cd build
+        cmake ..
+        make
+        ./hello
+        ./global
+        ./callback

+ 63 - 0
.github/workflows/windows.yml

@@ -0,0 +1,63 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+name: Windows
+
+# Controls when the action will run. Triggers the workflow on push or pull request
+# events but only for the main branch
+on:
+  push:
+    branches: [ main ]
+  pull_request:
+    branches: [ main ]
+
+jobs:
+
+  build:
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: [windows-latest]
+    steps:
+    - uses: actions/checkout@v2
+
+    - name: clone uvwasi library
+      run: |
+        cd core/deps
+        git clone https://github.com/nodejs/uvwasi.git
+    - name: Build iwasm [default]
+      run: |
+        cd product-mini/platforms/windows
+        mkdir build && cd build
+        cmake ..
+        cmake --build . --config Release
+        cd .. && rm -force -r build
+    - name: Build iwasm [aot only]
+      run: |
+        cd product-mini/platforms/windows
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=1 -DWAMR_BUILD_INTERP=0
+        cmake --build . --config Release
+        cd .. && rm -force -r build
+    - name: Build iwasm [interp only]
+      run: |
+        cd product-mini/platforms/windows
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_AOT=0
+        cmake --build . --config Release
+        cd .. && rm -force -r build
+    - name: Build iwasm [tail call]
+      run: |
+        cd product-mini/platforms/windows
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_TAIL_CALL=1
+        cmake --build . --config Release
+        cd .. && rm -force -r build
+    - name: Build iwasm [custom name section]
+      run: |
+        cd product-mini/platforms/windows
+        mkdir build && cd build
+        cmake .. -DWAMR_BUILD_CUSTOM_NAME_SECTION=1
+        cmake --build . --config Release
+        cd .. && rm -force -r build
+

+ 7 - 3
.gitignore

@@ -1,10 +1,14 @@
+
+.vs
 .vscode
 **/*build/
-core/deps/lv_drivers
-core/deps/llvm
-core/deps/lvgl
+core/deps/**
 core/shared/mem-alloc/tlsf
+core/app-framework/wgl
 
 wamr-sdk/out/
 wamr-sdk/runtime/build_runtime_sdk/
 test-tools/host-tool/bin/
+product-mini/app-samples/hello-world/test.wasm
+
+build_out

+ 33 - 298
ATTRIBUTIONS.md

@@ -2,329 +2,64 @@ WebAssembly Micro Runtime Attributions
 ======================================
 
 WAMR project reused some components from other open source project:
-- **wasmtime**: for the wasi libc implementation
 - **cJson**: used in the host_tool for remotely managing wasm applications
 - **contiki-ng**: for the coap protocol implementation
 - **freebsd libm**: used in core/shared/platform/alios/bh_math.c
-- **littlevgl**: for the gui samples and wrapped the wasm graphic layer.
-
-The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by  [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location.
-
-## Licenses
-
-### wasmtime
-
-```
- Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
-   APPENDIX: How to apply the Apache License to your work.
-
-      To apply the Apache License to your work, attach the following
-      boilerplate notice, with the fields enclosed by brackets "[]"
-      replaced with your own identifying information. (Don't include
-      the brackets!)  The text should be enclosed in the appropriate
-      comment syntax for the file format. We also recommend that a
-      file or class name and description of purpose be included on the
-      same "printed page" as the copyright notice for easier
-      identification within third-party archives.
-
-   Copyright [yyyy] [name of copyright owner]
-
-   Licensed under the Apache License, Version 2.0 (the "License");
-   you may not use this file except in compliance with the License.
-   You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-   Unless required by applicable law or agreed to in writing, software
-   distributed under the License is distributed on an "AS IS" BASIS,
-   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-   See the License for the specific language governing permissions and
-   limitations under the License.
-
+- **littlevgl**: for the gui samples and wrapped the wasm graphic layer
+- **llvm**. for the AOT/JIT compilation
+- **wasm-c-api**. to implement the C-APIs of wasm. using headers and sameples
+- **wasmtime**: for the wasi libc implementation
+- **zephyr**. for several platform specific examples
 
---- LLVM Exceptions to the Apache 2.0 License ----
+The WAMR fast interpreter is a clean room development. We would acknowledge the inspirations by [WASM3](https://github.com/wasm3/wasm3) open source project for the approach of pre-calculated oprand stack location.
 
-As an exception, if, as a result of your compiling your source code, portions
-of this Software are embedded into an Object form of such source code, you
-may redistribute such embedded portions in such Object form without complying
-with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+|  third party components | version number | latest release | vendor pages | CVE details |
+| --- | --- | --- | --- | --- |
+| cjson | 1.7.10 | 1.7.14 | https://github.com/DaveGamble/cJSON | https://www.cvedetails.com/vendor/19164/Cjson-Project.html |
+| contiki-ng (er-coap) | unspecified | 3.0 | https://github.com/contiki-os/contiki | https://www.cvedetails.com/vendor/16528/Contiki-os.html |
+| freebsd libm | unspecified | 13.0 | https://www.freebsd.org/ | https://www.cvedetails.com/vendor/6/Freebsd.html |
+| littlevgl | 6.0.1 | 7.11.0 | https://lvgl.io/ | |
+| llvm | 11.0.1 | 12.0.0 | https://llvm.org | https://www.cvedetails.com/vendor/13260/Llvm.html |
+| wasm-c-api | ac9b509f4df86e40e56e9b01f3f49afab0100037 | c9d31284651b975f05ac27cee0bab1377560b87e | https://github.com/WebAssembly/wasm-c-api | |
+| wasmtime | unspecified | v0.26.0 | https://github.com/bytecodealliance/wasmtime | |
+| zephyr | unspecified | v2.5.0 | https://www.zephyrproject.org/ | https://www.cvedetails.com/vendor/19255/Zephyrproject.html |
 
-In addition, if you combine or link compiled forms of this Software with
-software that is licensed under the GPLv2 ("Combined Software") and if a
-court of competent jurisdiction determines that the patent provision (Section
-3), the indemnity provision (Section 9) or other Section of the License
-conflicts with the conditions of the GPLv2, you may retroactively and
-prospectively choose to deem waived or otherwise exclude such Section(s) of
-the License, but only in their entirety and only with respect to the Combined
-Software.
-```
+## Licenses
 
 ### cJson
 
-```
-Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-```
+[LICENSE](./test-tools/host-tool/external/cJSON/LICENSE)
 
 ### contiki-ng
 
-```
-
-
-Copyright (c) (Year), (Name of copyright holder) 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 the copyright holder 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 HOLDER 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.
-
-```
+[LICENSE](./core/shared/coap/er-coap/LICENSE.md)
 
 ### freebsd libm
 
-```
-Copyright 1992-2011 The FreeBSD Project. All rights reserved.
-
-  Redistribution and use in source and binary forms, with or without
-  modification, are permitted provided that the following conditions are
-  met:
+[COPYRIGHT](./core/shared/platform/common/math/COPYRIGHT)
 
-  1. Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
+### littlevgl
 
-  2. 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.
-  THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``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 FREEBSD PROJECT 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.
+[LICENCE](./samples/littlevgl/LICENCE.txt)
 
-  The views and conclusions contained in the software and documentation
-  are those of the authors and should not be interpreted as representing
-  official policies, either expressed or implied, of the FreeBSD
-  Project.
-```
+[LICENSE](./core/deps/lvgl/LICENCE.txt)
 
-### littlevgl
+### llvm
 
-```
-MIT licence
-Copyright (c) 2016 Gábor Kiss-Vámosi
+[LICENSE](./core/deps/llvm/llvm/LICENCE.txt)
 
-Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+### wasm-c-api
 
-The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+[LICENSE](./samples/wasm-c-api/src/LICENSE)
 
-THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-```
+### wasmtime
 
+[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/LICENSE)
 
+[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/LICENSE)
 
+[LICENSE](./core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/include/LICENSE)
 
+### zephyr
 
+[LICENSE](./samples/gui/wasm-runtime-wgl/src/platform/zephyr/LICENSE)

+ 139 - 0
CMakeLists.txt

@@ -0,0 +1,139 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+cmake_minimum_required (VERSION 2.8...3.16)
+
+project (iwasm)
+# set (CMAKE_VERBOSE_MAKEFILE 1)
+
+set (WAMR_BUILD_PLATFORM "linux")
+
+# Reset default linker flags
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+set (CMAKE_C_STANDARD 99)
+
+# Set WAMR_BUILD_TARGET, currently values supported:
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
+# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
+if (NOT DEFINED WAMR_BUILD_TARGET)
+  if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+    set (WAMR_BUILD_TARGET "AARCH64")
+  elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
+    set (WAMR_BUILD_TARGET "RISCV64")
+  elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
+    # Build as X86_64 by default in 64-bit platform
+    set (WAMR_BUILD_TARGET "X86_64")
+  else ()
+    # Build as X86_32 by default in 32-bit platform
+    set (WAMR_BUILD_TARGET "X86_32")
+  endif ()
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE)
+  set(CMAKE_BUILD_TYPE Release)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_INTERP)
+  # Enable Interpreter by default
+  set (WAMR_BUILD_INTERP 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_AOT)
+  # Enable AOT by default.
+  set (WAMR_BUILD_AOT 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_JIT)
+  # Disable JIT by default.
+  set (WAMR_BUILD_JIT 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIBC_BUILTIN)
+  # Enable libc builtin support by default
+  set (WAMR_BUILD_LIBC_BUILTIN 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIBC_WASI)
+  # Enable libc wasi support by default
+  set (WAMR_BUILD_LIBC_WASI 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_FAST_INTERP)
+  # Enable fast interpreter
+  set (WAMR_BUILD_FAST_INTERP 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MULTI_MODULE)
+  # Enable multiple modules
+  set (WAMR_BUILD_MULTI_MODULE 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_LIB_PTHREAD)
+  # Disable pthread library by default
+  set (WAMR_BUILD_LIB_PTHREAD 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_MINI_LOADER)
+  # Disable wasm mini loader by default
+  set (WAMR_BUILD_MINI_LOADER 0)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_SIMD)
+  # Enable SIMD by default
+  set (WAMR_BUILD_SIMD 1)
+endif ()
+
+if (NOT DEFINED WAMR_BUILD_REF_TYPES)
+  # Disable reference types by default
+  set (WAMR_BUILD_REF_TYPES 0)
+endif ()
+
+if (COLLECT_CODE_COVERAGE EQUAL 1)
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage")
+endif ()
+
+set (WAMR_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR})
+
+include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
+
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections -pie -fPIE")
+
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wformat -Wformat-security")
+# set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wconversion -Wsign-conversion")
+
+if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+  if (NOT (CMAKE_C_COMPILER MATCHES ".*clang.*" OR CMAKE_C_COMPILER_ID MATCHES ".*Clang"))
+    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mindirect-branch-register")
+  endif ()
+endif ()
+
+# The following flags are to enhance security, but it may impact performance,
+# we disable them by default.
+#if (WAMR_BUILD_TARGET MATCHES "X86_.*" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+#  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ftrapv -D_FORTIFY_SOURCE=2")
+#endif ()
+#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong --param ssp-buffer-size=4")
+#set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,-z,noexecstack,-z,relro,-z,now")
+
+include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
+
+# STATIC LIBRARY
+add_library(iwasm_static STATIC ${WAMR_RUNTIME_LIB_SOURCE})
+set_target_properties (iwasm_static PROPERTIES OUTPUT_NAME vmlib)
+
+install (TARGETS iwasm_static ARCHIVE DESTINATION lib)
+
+# SHARED LIBRARY
+add_library (iwasm_shared SHARED ${WAMR_RUNTIME_LIB_SOURCE})
+set_target_properties (iwasm_shared PROPERTIES OUTPUT_NAME iwasm)
+target_link_libraries (iwasm_shared ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS} -lm -ldl -lpthread)
+
+install (TARGETS iwasm_shared LIBRARY DESTINATION lib)
+
+# HEADERS
+install (FILES
+    ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_c_api.h
+    ${WAMR_ROOT_DIR}/core/iwasm/include/wasm_export.h
+    DESTINATION include)

+ 0 - 21
Dockerfile

@@ -1,21 +0,0 @@
-# Currently supports clang-8 compiler
-# Using the "test.c" app from the README.md:
-# clang-8 --target=wasm32 -O3 -Wl,--initial-memory=131072,--allow-undefined,--export=main,--no-threads,--strip-all,--no-entry -nostdlib -o test.wasm test.c
-# Pay attention to spacing above! ^
-# iwasm test.wasm
-
-FROM ubuntu:latest
-
-RUN apt-get update && \
-  apt-get -y upgrade && \
-  apt-get install -y build-essential clang-8 cmake g++-multilib git lib32gcc-5-dev llvm-8 lld-8 nano
-
-WORKDIR /root
-
-RUN git clone https://github.com/intel/wasm-micro-runtime
-
-RUN cd wasm-micro-runtime/product-mini/platforms/linux/ && mkdir build && \
-  cd build && cmake .. && make
-
-RUN cd /usr/bin && ln -s wasm-ld-8 wasm-ld
-RUN cd /usr/bin && ln -s ~/wasm-micro-runtime/product-mini/platforms/linux/build/iwasm iwasm

+ 53 - 45
README.md

@@ -1,6 +1,6 @@
 WebAssembly Micro Runtime
 =========================
-[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples-and-demos)
+[Build WAMR VM core](./doc/build_wamr.md) | [Embed WAMR](./doc/embed_wamr.md) | [Export native function](./doc/export_native_api.md) | [Build WASM applications](./doc/build_wasm_app.md) | [Samples](https://github.com/bytecodealliance/wasm-micro-runtime#samples)
 
 **A [Bytecode Alliance][BA] project**
 
@@ -13,8 +13,6 @@ WebAssembly Micro Runtime (WAMR) is a standalone WebAssembly (WASM) runtime with
 
 - The **dynamic management** of the WASM applications
 
-
-
 iwasm VM core
 =========================
 
@@ -22,14 +20,24 @@ iwasm VM core
 
 - 100% compliant to the W3C WASM MVP
 - Small runtime binary size (85K for interpreter and 50K for AoT) and low memory usage
-- Near to native speed by AoT 
+- Near to native speed by AoT
 - Self-implemented module loader enables AoT working cross Linux, SGX and MCU systems
 - Choices of WASM application libc support: the built-in libc subset for the embedded environment or [WASI](https://github.com/WebAssembly/WASI) for standard libc
 - [Embeddable with the supporting C API's](./doc/embed_wamr.md)
 - [The mechanism for exporting native API's to WASM applications](./doc/export_native_api.md)
-
-### Performance and memory usage
-The WAMR performance, footprint and memory usage data are available at the [performance](../../wiki/Performance) wiki page.
+- [Multiple modules as dependencies](./doc/multi_module.md), ref to [sample](samples/multi-module)
+- [Thread management and pthread library](./doc/pthread_library.md), ref to [sample](samples/multi-thread)
+
+### post-MVP features
+- [Non-trapping float-to-int conversions](https://github.com/WebAssembly/nontrapping-float-to-int-conversions)
+- [Sign-extension operators](https://github.com/WebAssembly/sign-extension-ops)
+- [Bulk memory operations](https://github.com/WebAssembly/bulk-memory-operations)
+- [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory)
+- [Multi-value](https://github.com/WebAssembly/multi-value)
+- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api)
+- [Tail-call](https://github.com/WebAssembly/tail-call)
+- [128-bit SIMD](https://github.com/WebAssembly/simd), ref to [samples/workload](samples/workload)
+- [Reference Types](https://github.com/WebAssembly/reference-types), ref to [document](doc/ref_types.md) and [sample](samples/ref-types)
 
 ### Supported architectures and platforms
 
@@ -40,31 +48,41 @@ The iwasm supports the following architectures:
 - AArch64 (Cortex-A57 and Cortex-A53 are tested)
 - MIPS
 - XTENSA
+- RISCV64, RISCV32 (interpreter only)
 
 Following platforms are supported. Refer to [WAMR porting guide](./doc/port_wamr.md) for how to port WAMR to a new platform.
 
-- [Linux](./doc/build_wamr.md#linux), [Zephyr](./doc/build_wamr.md#zephyr), [MacOS](./doc/build_wamr.md#macos), [VxWorks](./doc/build_wamr.md#vxworks), [AliOS-Things](./doc/build_wamr.md#alios-things), [Intel Software Guard Extention (Linux)](./doc/build_wamr.md#linux-sgx-intel-software-guard-extention), [Android](./doc/build_wamr.md#android)
+- [Linux](./doc/build_wamr.md#linux),  [Linux SGX (Intel Software Guard Extension)](./doc/linux_sgx.md),  [MacOS](./doc/build_wamr.md#macos),  [Android](./doc/build_wamr.md#android), [Windows](./doc/build_wamr.md#windows)
+- [Zephyr](./doc/build_wamr.md#zephyr),  [AliOS-Things](./doc/build_wamr.md#alios-things),  [VxWorks](./doc/build_wamr.md#vxworks), [NuttX](./doc/build_wamr.md#nuttx), [RT-Thread](./doc/build_wamr.md#RT-Thread)
 
+### Build iwasm VM core (mini product)
 
+WAMR supports building the iwasm VM core only (no app framework) to the mini product. The WAMR mini product takes the WASM application file name or AoT file name as input and then executes it. For the detailed procedure, please see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**. Also we can click the link of each platform above to see how to build iwasm on it.
 
 ### Build wamrc AoT compiler
 
-Execute following commands to build **wamrc** compiler:
+Both wasm binary file and AoT file are supported by iwasm. The wamrc AoT compiler is to compile wasm binary file to AoT file which can also be run by iwasm. Execute following commands to build **wamrc** compiler for Linux:
 
 ```shell
 cd wamr-compiler
-./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target)
+./build_llvm.sh (or "./build_llvm_xtensa.sh" to support xtensa target)
 mkdir build && cd build
-cmake ..
+cmake .. (or "cmake .. -DWAMR_BUILD_TARGET=darwin" for MacOS)
 make
-ln -s {current path}/wamrc /usr/bin/wamrc
+# wamrc is generated under current directory
 ```
 
-### Build the mini product
-
-WAMR supports building the iwasm VM core only (no app framework) to the mini product.  The WAMR mini product takes the WASM application file name as input and then executes it. For the detailed procedure, see **[build WAMR VM core](./doc/build_wamr.md)** and **[build and run WASM application](./doc/build_wasm_app.md)**.
-
-
+For **Windows**:
+```shell
+cd wamr-compiler
+python build_llvm.py
+open LLVM.sln in wasm-micro-runtime\core\deps\llvm\win32build with Visual Studio
+build LLVM.sln Release
+mkdir build && cd build
+cmake ..
+cmake --build . --config Release
+# wamrc.exe is generated under .\Release directory
+```
 
 Application framework
 ===================================
@@ -77,8 +95,6 @@ The WAMR has offered a comprehensive framework for programming WASM applications
 
 Browse the folder  [core/app-framework](./core/app-framework) for how to extend the application framework.
 
-
-
 # Remote application management
 
 The WAMR application manager supports [remote application management](./core/app-mgr) from the host environment or the cloud through any physical communications such as TCP, UPD, UART, BLE, etc. Its modular design makes it able to support application management for different managed runtimes.
@@ -102,28 +118,16 @@ Samples
 
 The WAMR [samples](./samples) integrate the iwasm VM core, application manager and selected application framework components.
 
-- [**Basic**](./samples/basic): Demonstrating how host runtime calls WASM function as well as WASM function calls native function.
-- **[Simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default.
-- **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittlevGL](https://github.com/littlevgl/) 2D user graphic library and the UI application is built into WASM application.  It uses **WASI libc** and executes apps in **AoT mode** by default.
-- **[gui](./samples/gui/README.md)**: Moved the [LittlevGL](https://github.com/littlevgl/) library into the runtime and defined a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default.
-
-
-
-
-Releases and acknowledgments
-============================
-
-WAMR is a community effort. Since Intel Corp contributed the first release of this open source project, this project has received many good contributions from the community.
-
-See the [major features releasing history and contributor names](./doc/release_ack.md)
-
-
-Roadmap
-=======
-
-See the [roadmap](./doc/roadmap.md) to understand what major features are planned or under development.
-
-Please submit issues for any new feature request or your plan for contributing new features.
+- [**basic**](./samples/basic): Demonstrating how to use runtime exposed API's to call WASM functions, how to register native functions and call them, and how to call WASM function from native function.
+- **[simple](./samples/simple/README.md)**: The runtime is integrated with most of the WAMR APP libraries, and a few WASM applications are provided for testing the WAMR APP API set. It uses **built-in libc** and executes apps in **interpreter** mode by default.
+- **[littlevgl](./samples/littlevgl/README.md)**: Demonstrating the graphic user interface application usage on WAMR. The whole [LittleVGL](https://github.com/lvgl/) 2D user graphic library and the UI application are built into WASM application.  It uses **WASI libc** and executes apps in **AoT mode** by default.
+- **[gui](./samples/gui/README.md)**: Move the [LittleVGL](https://github.com/lvgl/) library into the runtime and define a WASM application interface by wrapping the littlevgl API. It uses **WASI libc** and executes apps in **interpreter** mode by default.
+- **[multi-thread](./samples/multi-thread/)**: Demonstrating how to run wasm application which creates multiple threads to execute wasm functions concurrently, and uses mutex/cond by calling pthread related API's.
+- **[spawn-thread](./samples/spawn-thread)**: Demonstrating how to execute wasm functions of the same wasm application concurrently, in threads created by host embedder or runtime, but not the wasm application itself.
+- **[multi-module](./samples/multi-module)**: Demonstrating the [multiple modules as dependencies](./doc/multi_module.md) feature which implements the [load-time dynamic linking](https://webassembly.org/docs/dynamic-linking/).
+- **[ref-types](./samples/ref-types)**: Demonstrating how to call wasm functions with argument of externref type introduced by [reference types proposal](https://github.com/WebAssembly/reference-types).
+- **[wasm-c-api](./samples/wasm-c-api/README.md)**: Demonstrating how to run some samples from [wasm-c-api proposal](https://github.com/WebAssembly/wasm-c-api) and showing the supported API's.
+- **[workload](./samples/workload/README.md)**: Demonstrating how to build and run some complex workloads, e.g. tensorflow-lite, XNNPACK, wasm-av1, meshoptimizer and bwa.
 
 
 License
@@ -134,9 +138,13 @@ use, modify, distribute and sell your own products based on WAMR.
 Any contributions you make will be under the same license.
 
 
-Submit issues and contact the maintainers
-=========================================
-[Click here to submit. Your feedback is always welcome!](https://github.com/intel/wasm-micro-runtime/issues/new)
 
+# More resources
+
+Check out the [Wiki documents ](../../wiki) for more resources:
+
+- [Performance and footprint data](../../wiki/Performance)
+- Community news and events
+- Roadmap
+- Technical documents
 
-Contact the maintainers: imrt-public@intel.com

+ 33 - 0
SConscript

@@ -0,0 +1,33 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+# for module compiling
+import os
+
+from building import *
+
+objs = []
+cwd  = GetCurrentDir()
+list = os.listdir(cwd)
+
+if GetDepend(['PKG_USING_WAMR']):
+    wamr_entry_sconscript = os.path.join(cwd, "product-mini", "platforms", "rt-thread", 'SConscript')
+
+    if os.path.isfile(wamr_entry_sconscript):
+        objs = objs + SConscript(wamr_entry_sconscript)
+    else:
+        print("[WAMR] entry script wrong:", wamr_entry_sconscript)
+        Return('objs')
+
+    wamr_runlib_sconsript = os.path.join(cwd, "build-scripts", 'SConscript')
+
+    if os.path.isfile(wamr_runlib_sconsript):
+        objs = objs + SConscript(wamr_runlib_sconsript)
+    else:
+        print("[WAMR] runtime lib script wrong:", wamr_runlib_sconsript)
+
+Return('objs')
+

+ 1 - 27
SECURITY.md

@@ -1,29 +1,3 @@
 # Security Policy
 
-Building secure foundations for software development is at the core of what we do in the Bytecode Alliance. Contributions of external security researchers are a vital part of that.
-
-## Scope
-
-If you believe you've found a security issue in any website, service, or software owned or operated by the Bytecode Alliance, we encourage you to notify us.
-
-## How to Submit a Report
-
-To submit a vulnerability report to the Bytecode Alliance, please contact us at [security@bytecodealliance.org](mailto:security@bytecodealliance.org). Your submission will be reviewed and validated by a member of our security team.
-
-## Safe Harbor
-
-The Bytecode Alliance supports safe harbor for security researchers who:
-
-*   Make a good faith effort to avoid privacy violations, destruction of data, and interruption or degradation of our services.
-*   Only interact with accounts you own or with explicit permission of the account holder. If you do encounter Personally Identifiable Information (PII) contact us immediately, do not proceed with access, and immediately purge any local information.
-*   Provide us with a reasonable amount of time to resolve vulnerabilities prior to any disclosure to the public or a third-party.
-
-We will consider activities conducted consistent with this policy to constitute "authorized" conduct and will not pursue civil action or initiate a complaint to law enforcement. We will help to the extent we can if legal action is initiated by a third party against you.
-
-Please submit a report to us before engaging in conduct that may be inconsistent with or unaddressed by this policy.
-
-## Preferences
-
-*   Please provide detailed reports with reproducible steps and a clearly defined impact.
-*   Submit one vulnerability per report.
-*   Social engineering (e.g. phishing, vishing, smishing) is prohibited.
+Please refer to the [Bytecode Alliance security policy](https://bytecodealliance.org/security) for details on how to report security issues in WebAssembly Micro Runtime, our disclosure policy, and how to receive notifications about security issues.

+ 177 - 0
TSC_Charter.md

@@ -0,0 +1,177 @@
+# Project Technical Steering Committee (PTSC) Charter
+
+## Section 1. Guiding Principle
+
+The WebAssembly Micro Runtime (WAMR) project is part of the 
+
+Bytecode Alliance (BA) which operates transparently, openly, 
+
+collaboratively, and ethically. Project proposals, timelines, and status 
+
+must not merely be open, but also easily visible to outsiders.
+
+## Section 2. Project Governance under Bytecode Alliance
+
+Technical leadership for the WAMR projects within the Bytecode Alliance 
+
+is delegated to the projects through the project charter. Though the BA TSC 
+
+will not interfere with day-to-day discussions, votes or meetings of the PTSC,
+
+the BA TSC may request additional amendments to the PTSC charter when 
+
+there is misalignment between the project charter and the BA mission and values.
+
+
+
+The PTSC structure described in this document may be overhauled as part of 
+
+establishing a BA TSC in order to adhere to constraints or requirements that 
+
+TSC will impose on project-level governance.
+
+## Section 3. Establishment of the PTSC
+
+PTSC memberships are not time-limited. There is no maximum size of the PTSC.
+The size is expected to vary in order to ensure adequate coverage of important
+areas of expertise, balanced with the ability to make decisions efficiently.
+The PTSC must have at least four members. 
+
+There is no specific set of requirements or qualifications for PTSC
+membership beyond these rules. The PTSC may add additional members to the
+PTSC by a standard PTSC motion and vote. A PTSC member may be removed from the
+PTSC by voluntary resignation, by a standard PTSC motion, or in accordance to the
+participation rules described below.
+
+Changes to PTSC membership should be posted in the agenda, and may be suggested
+as any other agenda item.
+
+The PTSC may, at its discretion, invite any number of non-voting observers to
+participate in the public portion of PTSC discussions and meetings.
+
+The PTSC shall meet regularly using tools that enable participation by the
+community (e.g. weekly on a Zulip channel, or through any other
+appropriate means selected by the PTSC ). The meeting shall be directed by
+the PTSC Chairperson. Responsibility for directing individual meetings may be
+delegated by the PTSC Chairperson to any other PTSC member. Minutes or an
+appropriate recording shall be taken and made available to the community
+through accessible public postings.
+
+PTSC members are expected to regularly participate in PTSC activities.
+
+In the case where an individual PTSC member -- within any three month period --
+attends fewer than 25% of the regularly scheduled meetings, does not
+participate in PTSC discussions, *and* does not participate in PTSC votes, the
+member shall be automatically removed from the PTSC. The member may be invited
+to continue attending PTSC meetings as an observer.
+
+## Section 4. Responsibilities of the PTSC
+
+Subject to such policies as may be set by the BA TSC, the WAMR PTSC is
+responsible for all technical development within the WAMR  project,
+including:
+
+* Setting release dates.
+* Release quality standards.
+* Technical direction.
+* Project governance and process.
+* GitHub repository hosting.
+* Conduct guidelines.
+* Maintaining the list of additional Collaborators.
+* Development process and any coding standards.
+* Mediating technical conflicts between Collaborators or Foundation
+projects.
+
+The PTSC will define WAMR project’s release vehicles.
+
+## Section 5. WAMR Project Operations
+
+The PTSC will establish and maintain a development process for the WAMR 
+project. The development process will establish guidelines
+for how the developers and community will operate. It will, for example,
+establish appropriate timelines for PTSC review (e.g. agenda items must be
+published at least a certain number of hours in advance of a PTSC 
+meeting).
+
+The PTSC and entire technical community will follow any processes as may
+be specified by the Bytecode Alliance Board relating to the intake and license compliance
+review of contributions, including the Bytecode Alliance IP Policy.
+
+## Section 6. Elections
+
+Leadership roles in the WAMR project will be peer elected
+representatives of the community.
+
+For election of persons (such as the PTSC Chairperson), a multiple-candidate
+method should be used, such as:
+
+* [Condorcet][] or
+* [Single Transferable Vote][]
+
+Multiple-candidate methods may be reduced to simple election by plurality
+when there are only two candidates for one position to be filled. No
+election is required if there is only one candidate and no objections to
+the candidate's election. Elections shall be done within the projects by
+the Collaborators active in the project.
+
+The PTSC will elect from amongst voting PTSC members a PTSC Chairperson to
+work on building an agenda for PTSC meetings. The PTSC shall hold annual 
+
+elections to select a PTSC Chairperson; there are no limits on the number
+of terms a PTSC Chairperson may serve.
+
+## Section 7. Voting
+
+For internal project decisions, Collaborators shall operate under Lazy
+Consensus. The PTSC shall establish appropriate guidelines for
+implementing Lazy Consensus (e.g. expected notification and review time
+periods) within the development process.
+
+The PTSC follows a [Consensus Seeking][] decision making model. When an agenda
+item has appeared to reach a consensus the moderator will ask "Does anyone
+object?" as a final call for dissent from the consensus.
+
+If an agenda item cannot reach a consensus a PTSC member can call for
+either a closing vote or a vote to table the issue to the next meeting.
+The call for a vote must be seconded by a majority of the PTSC or else the
+discussion will continue.
+
+For all votes, a simple majority of all PTSC members for, or against, the issue
+wins. A PTSC member may choose to participate in any vote through abstention.
+
+## Section 8. Project Roles
+
+The WAMR git repository is maintained by the PTSC and
+additional Collaborators who are added by the PTSC on an ongoing basis.
+
+Individuals making significant and valuable contributions,
+“Contributor(s)”, are made Collaborators and given commit-access to the
+project. These individuals are identified by the PTSC and their addition
+as Collaborators is discussed during a PTSC meeting. Modifications of the
+contents of the git repository are made on a collaborative basis as defined in
+the development process.
+
+Collaborators may opt to elevate significant or controversial
+modifications, or modifications that have not found consensus to the PTSC
+for discussion by assigning the `tsc-agenda` tag to a pull request or
+issue. The PTSC should serve as the final arbiter where required. The PTSC
+will maintain and publish a list of current Collaborators, as
+well as a development process guide for Collaborators and Contributors
+looking to participate in the development effort.
+
+## Section 9. Definitions
+
+* **Contributors**: contribute code or other artifacts, but do not have
+the right to commit to the code base. Contributors work with the
+project’s Collaborators to have code committed to the code base. A
+Contributor may be promoted to a Collaborator by the PTSC. Contributors should
+rarely be encumbered by the PTSC.
+
+* **Project**: a technical collaboration effort, e.g. a subsystem, that
+is organized through the project creation process and approved by the
+PTSC.
+
+[Consensus Seeking]: https://en.wikipedia.org/wiki/Consensus-seeking_decision-making
+[Condorcet]: https://en.wikipedia.org/wiki/Condorcet_method
+[Single Transferable Vote]: https://en.wikipedia.org/wiki/Single_transferable_vote
+

+ 1 - 0
assembly-script/.gitignore

@@ -0,0 +1 @@
+/node_modules

+ 8 - 8
assembly-script/package-lock.json

@@ -5,24 +5,24 @@
   "requires": true,
   "dependencies": {
     "assemblyscript": {
-      "version": "0.8.1",
-      "resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.8.1.tgz",
-      "integrity": "sha1-xcYnSSQG5th/QmiXs9kr0qUz9/4=",
+      "version": "0.17.4",
+      "resolved": "https://registry.npm.taobao.org/assemblyscript/download/assemblyscript-0.17.4.tgz",
+      "integrity": "sha1-1GEduJpClDNa1H7DxmYaJqRCh3E=",
       "dev": true,
       "requires": {
-        "binaryen": "89.0.0-nightly.20191113",
+        "binaryen": "98.0.0-nightly.20201109",
         "long": "^4.0.0"
       }
     },
     "binaryen": {
-      "version": "89.0.0-nightly.20191113",
-      "resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-89.0.0-nightly.20191113.tgz",
-      "integrity": "sha1-oNORTzXJKXhzQeApELf/rrfYl6k=",
+      "version": "98.0.0-nightly.20201109",
+      "resolved": "https://registry.npm.taobao.org/binaryen/download/binaryen-98.0.0-nightly.20201109.tgz",
+      "integrity": "sha1-USv2yhXGe/dAIURzSkg25jmTqgU=",
       "dev": true
     },
     "long": {
       "version": "4.0.0",
-      "resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz",
+      "resolved": "https://registry.npm.taobao.org/long/download/long-4.0.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Flong%2Fdownload%2Flong-4.0.0.tgz",
       "integrity": "sha1-mntxz7fTYaGU6lVSQckvdGjVvyg=",
       "dev": true
     }

+ 6 - 6
assembly-script/package.json

@@ -5,16 +5,16 @@
   "main": "index.js",
   "scripts": {
     "test": "echo \"Error: no test specified\" && exit 1",
-    "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --validate --optimize --use abort=",
-    "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --validate --optimize --use abort=",
-    "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --validate --optimize --use abort=",
-    "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --validate --optimize --use abort=",
-    "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --validate --optimize --use abort=",
+    "build:request_handler": "asc samples/request_handler.ts -b build/request_handler.wasm -t build/request_handler.wat --sourceMap --optimize --exportRuntime --use abort=",
+    "build:request_sender": "asc samples/request_sender.ts -b build/request_sender.wasm -t build/request_sender.wat --sourceMap --optimize --exportRuntime --use abort=",
+    "build:timer": "asc samples/timer.ts -b build/timer.wasm -t build/timer.wat --sourceMap --optimize --exportRuntime --use abort=",
+    "build:publisher": "asc samples/event_publisher.ts -b build/event_publisher.wasm -t build/event_publisher.wat --sourceMap --optimize --exportRuntime --use abort=",
+    "build:subscriber": "asc samples/event_subscriber.ts -b build/event_subscriber.wasm -t build/event_subscriber.wat --sourceMap --optimize --exportRuntime --use abort=",
     "build:all": "npm run build:request_handler; npm run build:request_sender; npm run build:timer; npm run build:subscriber; npm run build:publisher"
   },
   "author": "",
   "license": "ISC",
   "devDependencies": {
-    "assemblyscript": "^0.8.1"
+    "assemblyscript": "^0.18.15"
   }
 }

+ 88 - 0
build-scripts/SConscript

@@ -0,0 +1,88 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+from building import *
+
+cwd  = GetCurrentDir()
+objs = []
+
+WAMR_ROOT_DIR = os.path.join(cwd, "..")
+
+
+SHARED_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'shared')
+
+IWASM_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'iwasm')
+
+APP_MGR_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-mgr')
+
+APP_FRAMEWORK_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'app-framework')
+
+DEPS_DIR = os.path.join(WAMR_ROOT_DIR, 'core', 'deps')
+
+if GetDepend(['WAMR_BUILD_INTERP']):
+    script_path = os.path.join(IWASM_DIR, 'interpreter', 'SConscript')
+    objs += SConscript(script_path)
+
+
+if GetDepend(['WAMR_BUILD_AOT']):
+    script_path = os.path.join(IWASM_DIR, 'aot', 'SConscript')
+    objs += SConscript(script_path)
+    if GetDepend(['WAMR_BUILD_JIT']):
+        script_path = os.path.join(IWASM_DIR, 'compilation', 'SConscript')
+        objs += SConscript(script_path)
+
+
+if GetDepend(['WAMR_BUILD_APP_FRAMEWORK']):
+    objs += SConscript(os.path.join(APP_FRAMEWORK_DIR, 'SConscript'))
+    objs += SConscript(os.path.join(SHARED_DIR, 'coap', 'SConscript'))
+    objs += SConscript(os.path.join(APP_MGR_DIR, 'app-manager', 'SConscript'))
+    objs += SConscript(os.path.join(APP_MGR_DIR, 'app-mgr-shared', 'SConscript'))
+
+
+
+if GetDepend(['WAMR_BUILD_LIBC_BUILTIN']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-builtin', 'SConscript'))
+
+
+
+if GetDepend(['WAMR_BUILD_LIBC_WASI']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-wasi', 'SConscript'))
+
+
+if GetDepend(['WAMR_BUILD_LIB_PTHREAD']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-pthread', 'SConscript'))
+    # TODO: 这里加一下
+
+
+
+# if (WAMR_BUILD_THREAD_MGR EQUAL 1)
+#     include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
+# endif ()
+
+if GetDepend(['WAMR_BUILD_THREAD_MGR']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'thread-mgr', 'SConscript'))
+
+
+
+# if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
+#     include (${IWASM_DIR}/libraries/libc-emcc/libc_emcc.cmake)
+# endif()
+
+if GetDepend(['WAMR_BUILD_LIBC_EMCC']):
+    objs += SConscript(os.path.join(IWASM_DIR, 'libraries', 'libc-emmc', 'SConscript'))
+
+objs += SConscript(os.path.join(cwd, 'SConscript_config'));
+
+
+objs += SConscript(os.path.join(SHARED_DIR, 'platform', 'rt-thread', 'SConscript'))
+objs += SConscript(os.path.join(SHARED_DIR, 'mem-alloc', 'SConscript'))
+objs += SConscript(os.path.join(IWASM_DIR, 'common', 'SConscript'))
+objs += SConscript(os.path.join(SHARED_DIR, 'utils', 'SConscript'))
+
+
+
+Return('objs')

+ 121 - 0
build-scripts/SConscript_config

@@ -0,0 +1,121 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+import os
+import re
+
+from building import *
+
+Import('rtconfig')
+
+src = Split('''
+''')
+objs = []
+cwd  = GetCurrentDir()
+
+IWASM_INC_DIR = os.path.join(cwd, '..', 'core', 'iwasm', 'include')
+
+# include_directories (${IWASM_DIR}/include)
+
+CPPPATH = [IWASM_INC_DIR]
+
+if rtconfig.BUILD == 'debug':
+    CPPDEFINES = ['BH_DEBUG=1']
+else:
+    CPPDEFINES = ['BH_DEBUG=0']
+
+if rtconfig.ARCH == 'arm':
+    if re.match('^cortex-m.*', rtconfig.CPU):
+        print('[WAMR] using thumbv4t')
+        CPPDEFINES += ['BUILD_TARGET_THUMB']
+        CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_THUMB']
+    elif re.match('^cortex-a.*', rtconfig.CPU):
+        print('[WAMR] using armv7')
+        CPPDEFINES += ['BUILD_TARGET_ARM']
+        CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV7']
+    elif re.match('^cortex-r.*', rtconfig.CPU):
+        print('[WAMR] using armv7')
+        CPPDEFINES += ['BUILD_TARGET_ARM']
+        CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV7']
+    elif rtconfig.CPU == 'armv6':
+        print('[WAMR] using armv6')
+        CPPDEFINES += ['BUILD_TARGET_ARM']
+        CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV6']
+    elif re.match('^arm9*', rtconfig.CPU):
+        print('[WAMR] using armv4')
+        CPPDEFINES += ['BUILD_TARGET_ARM']
+        CPPDEFINES += ['RTT_WAMR_BUILD_TARGET_ARMV4']
+else:
+    print("[WAMR] unknown arch", rtconfig.ARCH)
+
+
+LIBS = ['m']
+
+if GetDepend(['WAMR_BUILD_INTERP']):
+    CPPDEFINES += ['WASM_ENABLE_INTERP=1']
+    if GetDepend(['WAMR_BUILD_FAST_INTERP']):
+        CPPDEFINES += ['WASM_ENABLE_FAST_INTERP=1']
+        print("[WAMR] fast interpreter was enabled")
+    else:
+        CPPDEFINES += ['WASM_ENABLE_FAST_INTERP=0']
+        print("[WAMR] fast interpreter was disabled")
+else:
+    CPPDEFINES += ['WASM_ENABLE_INTERP=0']
+
+CPPDEFINES += ['WASM_ENABLE_JIT=0']
+
+if GetDepend(['WAMR_BUILD_MULTI_MODULE']):
+    CPPDEFINES += ['WASM_ENABLE_MULTI_MODULE=1']
+else:
+    CPPDEFINES += ['WASM_ENABLE_MULTI_MODULE=0']
+
+if GetDepend(['WAMR_BUILD_SPEC_TEST']):
+    CPPDEFINES += ['WASM_ENABLE_SPEC_TEST=1']
+    print("[WAMR] spec test compatible mode was enabled")
+
+if GetDepend(['WAMR_BUILD_BULK_MEMORY']):
+    CPPDEFINES += ['WASM_ENABLE_BULK_MEMORY=1']
+    print("[WAMR] Bulk memory feature was enabled")
+else:
+    CPPDEFINES += ['WASM_ENABLE_BULK_MEMORY=0']
+
+if GetDepend(['WAMR_BUILD_SHARED_MEMORY']):
+    CPPDEFINES += ['WASM_ENABLE_SHARED_MEMORY=1']
+    print("[WAMR] Shared memory enabled")
+else:
+    CPPDEFINES += ['WASM_ENABLE_SHARED_MEMORY=0']
+
+if GetDepend(['WAMR_BUILD_MINI_LOADER']):
+    CPPDEFINES += ['WASM_ENABLE_MINI_LOADER=1']
+    print("[WAMR] mini loader enabled")
+else:
+    CPPDEFINES += ['WASM_ENABLE_MINI_LOADER=0']
+
+if GetDepend(['WAMR_DISABLE_HW_BOUND_CHECK']):
+    CPPDEFINES += ['WASM_DISABLE_HW_BOUND_CHECK=1']
+    print("[WAMR] Hardware boundary check disabled")
+
+if GetDepend(['WAMR_BUILD_SIMD']):
+    CPPDEFINES += ['WASM_ENABLE_SIMD=1']
+    print('[WAMR] SIMD enabled')
+
+if GetDepend(['WAMR_BUILD_MEMORY_PROFILING']):
+    CPPDEFINES += ['WASM_ENABLE_MEMORY_PROFILING=1']
+    print('[WAMR] Memory profiling enabled')
+
+if GetDepend(['WAMR_BUILD_CUSTOM_NAME_SECTION']):
+    CPPDEFINES += ['WASM_ENABLE_CUSTOM_NAME_SECTION=1']
+    print('[WAMR] Custom name section enabled')
+
+if GetDepend(['WAMR_BUILD_TAIL_CALL']):
+    CPPDEFINES += ['WASM_ENABLE_TAIL_CALL=1']
+    print('[WAMR] Tail call enabledd')
+
+
+group = DefineGroup('wamr_config_common', src, depend = ['PKG_USING_WAMR'], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES, LIBS = LIBS)
+
+Return('group')
+

+ 114 - 14
build-scripts/config_common.cmake

@@ -34,8 +34,16 @@ elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
   add_definitions(-DBUILD_TARGET_MIPS)
 elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
   add_definitions(-DBUILD_TARGET_XTENSA)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D")
+  add_definitions(-DBUILD_TARGET_RISCV64_LP64D)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64")
+  add_definitions(-DBUILD_TARGET_RISCV64_LP64)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D")
+  add_definitions(-DBUILD_TARGET_RISCV32_ILP32D)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
+  add_definitions(-DBUILD_TARGET_RISCV32_ILP32)
 else ()
-   message (FATAL_ERROR "-- WAMR build target isn't set")
+  message (FATAL_ERROR "-- WAMR build target isn't set")
 endif ()
 
 if (CMAKE_BUILD_TYPE STREQUAL "Debug")
@@ -43,10 +51,12 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
 endif ()
 
 if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*")
-    # Add -fPIC flag if build as 64-bit
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-    set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+  if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64" OR WAMR_BUILD_TARGET MATCHES "AARCH64.*" OR WAMR_BUILD_TARGET MATCHES "RISCV64.*")
+    if (NOT WAMR_BUILD_PLATFORM STREQUAL "windows")
+      # Add -fPIC flag if build as 64-bit
+      set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+      set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+    endif ()
   else ()
     add_definitions (-m32)
     set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
@@ -55,10 +65,10 @@ if (CMAKE_SIZEOF_VOID_P EQUAL 8)
 endif ()
 
 if (WAMR_BUILD_TARGET MATCHES "ARM.*")
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -marm")
 elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
-    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
-    set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb")
+  set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mthumb")
+  set (CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,-mthumb")
 endif ()
 
 if (NOT WAMR_BUILD_INTERP EQUAL 1)
@@ -70,11 +80,17 @@ endif ()
 if (WAMR_BUILD_JIT EQUAL 1)
   if (WAMR_BUILD_AOT EQUAL 1)
     add_definitions("-DWASM_ENABLE_JIT=1")
-    set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
-    if (NOT EXISTS "${LLVM_SRC_ROOT}/build")
-      message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_SRC_ROOT}/build")
+    if (NOT DEFINED LLVM_DIR)
+      set (LLVM_SRC_ROOT "${WAMR_ROOT_DIR}/core/deps/llvm")
+      set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/build")
+      if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+        set (LLVM_BUILD_ROOT "${LLVM_SRC_ROOT}/win32build")
+      endif ()
+      if (NOT EXISTS "${LLVM_BUILD_ROOT}")
+        message (FATAL_ERROR "Cannot find LLVM dir: ${LLVM_BUILD_ROOT}")
+      endif ()
+      set (CMAKE_PREFIX_PATH "${LLVM_BUILD_ROOT};${CMAKE_PREFIX_PATH}")
     endif ()
-    set (CMAKE_PREFIX_PATH "${LLVM_SRC_ROOT}/build;${CMAKE_PREFIX_PATH}")
     find_package(LLVM REQUIRED CONFIG)
     include_directories(${LLVM_INCLUDE_DIRS})
     add_definitions(${LLVM_DEFINITIONS})
@@ -111,7 +127,9 @@ if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
 else ()
   message ("     Libc builtin disabled")
 endif ()
-if (WAMR_BUILD_LIBC_WASI EQUAL 1)
+if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
+  message ("     Libc WASI enabled with uvwasi implementation")
+elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
   message ("     Libc WASI enabled")
 else ()
   message ("     Libc WASI disabled")
@@ -123,4 +141,86 @@ else ()
   add_definitions (-DWASM_ENABLE_FAST_INTERP=0)
   message ("     Fast interpreter disabled")
 endif ()
-
+if (WAMR_BUILD_MULTI_MODULE EQUAL 1)
+  add_definitions (-DWASM_ENABLE_MULTI_MODULE=1)
+  message ("     Multiple modules enabled")
+else ()
+  add_definitions (-DWASM_ENABLE_MULTI_MODULE=0)
+  message ("     Multiple modules disabled")
+endif ()
+if (WAMR_BUILD_SPEC_TEST EQUAL 1)
+  add_definitions (-DWASM_ENABLE_SPEC_TEST=1)
+  message ("     spec test compatible mode is on")
+endif ()
+if (WAMR_BUILD_BULK_MEMORY EQUAL 1)
+  add_definitions (-DWASM_ENABLE_BULK_MEMORY=1)
+  message ("     Bulk memory feature enabled")
+else ()
+  add_definitions (-DWASM_ENABLE_BULK_MEMORY=0)
+endif ()
+if (WAMR_BUILD_SHARED_MEMORY EQUAL 1)
+  add_definitions (-DWASM_ENABLE_SHARED_MEMORY=1)
+  message ("     Shared memory enabled")
+else ()
+  add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0)
+endif ()
+if (WAMR_BUILD_THREAD_MGR EQUAL 1)
+  message ("     Thread manager enabled")
+endif ()
+if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
+  message ("     Lib pthread enabled")
+endif ()
+if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
+  message ("     Libc emcc enabled")
+endif ()
+if (WAMR_BUILD_MINI_LOADER EQUAL 1)
+  add_definitions (-DWASM_ENABLE_MINI_LOADER=1)
+  message ("     WASM mini loader enabled")
+else ()
+  add_definitions (-DWASM_ENABLE_MINI_LOADER=0)
+endif ()
+if (WAMR_DISABLE_HW_BOUND_CHECK EQUAL 1)
+  add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=1)
+  message ("     Hardware boundary check disabled")
+else ()
+  add_definitions (-DWASM_DISABLE_HW_BOUND_CHECK=0)
+endif ()
+if (WAMR_BUILD_SIMD EQUAL 1)
+  add_definitions (-DWASM_ENABLE_SIMD=1)
+  message ("     SIMD enabled")
+endif ()
+if (WAMR_BUILD_MEMORY_PROFILING EQUAL 1)
+  add_definitions (-DWASM_ENABLE_MEMORY_PROFILING=1)
+  message ("     Memory profiling enabled")
+endif ()
+if (WAMR_BUILD_PERF_PROFILING EQUAL 1)
+  add_definitions (-DWASM_ENABLE_PERF_PROFILING=1)
+  message ("     Performance profiling enabled")
+endif ()
+if (DEFINED WAMR_APP_THREAD_STACK_SIZE_MAX)
+  add_definitions (-DAPP_THREAD_STACK_SIZE_MAX=${WAMR_APP_THREAD_STACK_SIZE_MAX})
+endif ()
+if (WAMR_BUILD_CUSTOM_NAME_SECTION EQUAL 1)
+  add_definitions (-DWASM_ENABLE_CUSTOM_NAME_SECTION=1)
+  message ("     Custom name section enabled")
+endif ()
+if (WAMR_BUILD_DUMP_CALL_STACK EQUAL 1)
+  add_definitions (-DWASM_ENABLE_DUMP_CALL_STACK=1)
+  message ("     Dump call stack enabled")
+endif ()
+if (WAMR_BUILD_TAIL_CALL EQUAL 1)
+  add_definitions (-DWASM_ENABLE_TAIL_CALL=1)
+  message ("     Tail call enabled")
+endif ()
+if (WAMR_BUILD_REF_TYPES EQUAL 1)
+  add_definitions (-DWASM_ENABLE_REF_TYPES=1)
+  message ("     Reference types enabled")
+else ()
+  message ("     Reference types disabled")
+endif ()
+if (DEFINED WAMR_BH_VPRINTF)
+  add_definitions (-DBH_VPRINTF=${WAMR_BH_VPRINTF})
+endif ()
+if (WAMR_DISABLE_APP_ENTRY EQUAL 1)
+  message ("     WAMR application entry functions excluded")
+endif ()

+ 39 - 8
build-scripts/runtime_lib.cmake

@@ -31,9 +31,14 @@ endif ()
 # Set default options
 
 # Set WAMR_BUILD_TARGET, currently values supported:
-# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]", "MIPS", "XTENSA"
+# "X86_64", "AMD_64", "X86_32", "AARCH64[sub]", "ARM[sub]", "THUMB[sub]",
+# "MIPS", "XTENSA", "RISCV64[sub]", "RISCV32[sub]"
 if (NOT DEFINED WAMR_BUILD_TARGET)
-    if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+    if (CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64")
+        set (WAMR_BUILD_TARGET "AARCH64")
+    elseif (CMAKE_SYSTEM_PROCESSOR STREQUAL "riscv64")
+        set (WAMR_BUILD_TARGET "RISCV64")
+    elseif (CMAKE_SIZEOF_VOID_P EQUAL 8)
         # Build as X86_64 by default in 64-bit platform
         set (WAMR_BUILD_TARGET "X86_64")
     else ()
@@ -47,6 +52,11 @@ if (WAMR_BUILD_INTERP EQUAL 1 OR WAMR_BUILD_JIT EQUAL 1)
     include (${IWASM_DIR}/interpreter/iwasm_interp.cmake)
 endif ()
 
+if (WAMR_BUILD_TARGET MATCHES "RISCV.*" AND WAMR_BUILD_AOT EQUAL 1)
+    set (WAMR_BUILD_AOT 0)
+    message ("-- WAMR AOT disabled as it isn't supported by riscv currently")
+endif ()
+
 if (WAMR_BUILD_AOT EQUAL 1)
     include (${IWASM_DIR}/aot/iwasm_aot.cmake)
     if (WAMR_BUILD_JIT EQUAL 1)
@@ -65,22 +75,40 @@ if (WAMR_BUILD_LIBC_BUILTIN EQUAL 1)
     include (${IWASM_DIR}/libraries/libc-builtin/libc_builtin.cmake)
 endif ()
 
-if (WAMR_BUILD_LIBC_WASI EQUAL 1)
+if (WAMR_BUILD_LIBC_UVWASI EQUAL 1)
+    include (${IWASM_DIR}/libraries/libc-uvwasi/libc_uvwasi.cmake)
+elseif (WAMR_BUILD_LIBC_WASI EQUAL 1)
     include (${IWASM_DIR}/libraries/libc-wasi/libc_wasi.cmake)
 endif ()
 
+if (WAMR_BUILD_LIB_PTHREAD EQUAL 1)
+    include (${IWASM_DIR}/libraries/lib-pthread/lib_pthread.cmake)
+    # Enable the dependent feature if lib pthread is enabled
+    set (WAMR_BUILD_THREAD_MGR 1)
+    set (WAMR_BUILD_BULK_MEMORY 1)
+    set (WAMR_BUILD_SHARED_MEMORY 1)
+endif ()
+
+if (WAMR_BUILD_THREAD_MGR EQUAL 1)
+    include (${IWASM_DIR}/libraries/thread-mgr/thread_mgr.cmake)
+endif ()
+
+if (WAMR_BUILD_LIBC_EMCC EQUAL 1)
+    include (${IWASM_DIR}/libraries/libc-emcc/libc_emcc.cmake)
+endif()
+
 ####################### Common sources #######################
-set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
-                                     -Wall -Wno-unused-parameter -Wno-pedantic")
+if (NOT MSVC)
+    set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99 -ffunction-sections -fdata-sections \
+                                         -Wall -Wno-unused-parameter -Wno-pedantic")
+endif ()
 
 # include the build config template file
 include (${CMAKE_CURRENT_LIST_DIR}/config_common.cmake)
 
-include_directories (${SHARED_DIR}/include
-                     ${IWASM_DIR}/include)
+include_directories (${IWASM_DIR}/include)
 
 file (GLOB header
-    ${SHARED_DIR}/include/*.h
     ${IWASM_DIR}/include/*.h
 )
 LIST (APPEND RUNTIME_LIB_HEADER_LIST ${header})
@@ -106,6 +134,9 @@ set (source_all
     ${WASM_APP_LIB_SOURCE_ALL}
     ${NATIVE_INTERFACE_SOURCE}
     ${APP_MGR_SOURCE}
+    ${LIB_PTHREAD_SOURCE}
+    ${THREAD_MGR_SOURCE}
+    ${LIBC_EMCC_SOURCE}
 )
 
 set (WAMR_RUNTIME_LIB_SOURCE ${source_all})

+ 18 - 0
ci/Dockerfile

@@ -0,0 +1,18 @@
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+FROM ubuntu:18.04
+
+RUN apt update \
+  && apt install -y apt-transport-https ca-certificates gnupg \
+       software-properties-common wget lsb-release curl build-essential
+
+#
+# CMAKE (https://apt.kitware.com/)
+RUN wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | tee /etc/apt/trusted.gpg.d/kitware.gpg >/dev/null \
+  && apt purge --auto-remove cmake \
+  && apt-add-repository 'deb https://apt.kitware.com/ubuntu/ bionic main' \
+  && apt update \
+  && apt-get install -y kitware-archive-keyring \
+  && rm /etc/apt/trusted.gpg.d/kitware.gpg \
+  && apt-get install -y cmake

+ 24 - 0
ci/build_wamr.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# Copyright (C) 2019 Intel Corporation.  All rights reserved.
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+
+docker build -t wamr_dev:0.1 -f Dockerfile . \
+  && docker run --rm -it \
+       --name wamr_building \
+       --mount type=bind,src=$(realpath .)/..,dst=/source \
+       --workdir /source \
+       wamr_dev:0.1 \
+       /bin/bash -c "\
+         pushd product-mini/platforms/linux \
+           && mkdir -p build  \
+           && pushd build \
+           && rm -rf * \
+           && cmake .. \
+           && make \
+           && popd \
+           && popd \
+           && echo 'Copying binary for image build' \
+           && mkdir -p build_out \
+           && rm build_out/* \
+           && cp -f product-mini/platforms/linux/build/iwasm build_out/iwasm"

+ 13 - 6
core/app-framework/app-native-shared/attr_container.c

@@ -106,13 +106,13 @@ attr_container_get_attr_begin(const attr_container_t *attr_cont,
 
     /* tag content */
     p += str_len;
-    if (p - attr_cont->buf >= total_length)
+    if ((uint32_t)(p - attr_cont->buf) >= total_length)
         return NULL;
 
     /* attribute num */
     attr_num = get_uint16(p);
     p += sizeof(uint16_t);
-    if (p - attr_cont->buf >= total_length)
+    if ((uint32_t)(p - attr_cont->buf) >= total_length)
         return NULL;
 
     if (p_total_length)
@@ -174,7 +174,8 @@ attr_container_find_attr(const attr_container_t *attr_cont, const char *key)
 
         if (str_len == strlen(key) + 1
                 && memcmp(p + sizeof(uint16_t), key, str_len) == 0) {
-            if (p + sizeof(uint16_t) + str_len - attr_cont->buf >= total_length)
+            if ((uint32_t)(p + sizeof(uint16_t) + str_len
+                           - attr_cont->buf) >= total_length)
                 return NULL;
             return p;
         }
@@ -337,7 +338,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
     }
 
     /* Set the attr buf */
-    str_len = strlen(key) + 1;
+    str_len = (uint16_t)(strlen(key) + 1);
     set_uint16(p, str_len);
     p += sizeof(uint16_t);
     bh_memcpy_s(p, str_len, key, str_len);
@@ -366,7 +367,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
             return true;
         }
 
-        if (p1 - p + msg_end - attr_end >= attr_len) {
+        if ((uint32_t)(p1 - p + msg_end - attr_end) >= attr_len) {
             memmove(p, p1, attr_end - p1);
             bh_memcpy_s(p + (attr_end - p1), attr_len, attr_buf, attr_len);
             attr_container_free(attr_buf);
@@ -399,7 +400,7 @@ bool attr_container_set_attr(attr_container_t **p_attr_cont, const char *key,
         return true;
     } else {
         /* key not found */
-        if (msg_end - attr_end >= attr_len) {
+        if ((uint32_t)(msg_end - attr_end) >= attr_len) {
             bh_memcpy_s(attr_end, msg_end - attr_end, attr_buf, attr_len);
             attr_container_inc_attr_num(attr_cont);
             attr_container_free(attr_buf);
@@ -564,6 +565,9 @@ attr_container_get_attr(const attr_container_t *attr_cont, const char *key)
         bh_memcpy_s(&val.var_name, sizeof(val.var_name), addr, len); \
         break;                                              \
       }                                                     \
+      default:                                              \
+        bh_assert(0);                                       \
+        break;                                              \
     }                                                       \
     return val.var_name;                                    \
   } while (0)
@@ -819,6 +823,9 @@ void attr_container_dump(const attr_container_t *attr_cont)
                     get_uint32(p));
             p += sizeof(uint32_t) + get_uint32(p);
             break;
+        default:
+            bh_assert(0);
+            break;
         }
     }
 

+ 1 - 1
core/app-framework/app-native-shared/bi-inc/attr_container.h

@@ -6,7 +6,7 @@
 #ifndef _ATTR_CONTAINER_H_
 #define _ATTR_CONTAINER_H_
 
-#include <inttypes.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>

+ 0 - 5
core/app-framework/app-native-shared/restful_utils.c

@@ -71,23 +71,18 @@ void free_req_resp_packet(char * packet)
 request_t * unpack_request(char * packet, int size, request_t * request)
 {
     if (*packet != REQUES_PACKET_VER) {
-        printf("version fail\n");
         return NULL;
     }
     if (size < REQUEST_PACKET_FIX_PART_LEN) {
-        printf("size error: %d\n", size);
         return NULL;
     }
     uint16 url_len = ntohs(*((uint16*) (packet + 12)));
     uint32 payload_len = ntohl(*((uint32*) (packet + 14)));
 
     if (size != ( REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len)) {
-        printf("size error: %d, expect: %d\n", size,
-        REQUEST_PACKET_FIX_PART_LEN + url_len + payload_len);
         return NULL;
     }
     if (*(packet + REQUEST_PACKET_FIX_PART_LEN + url_len - 1) != 0) {
-        printf("url not end with 0\n");
         return NULL;
     }
 

+ 14 - 0
core/app-framework/base/app/bh_platform.h

@@ -45,4 +45,18 @@ uint16 ntohs(uint16 value);
 // We are not worried for the WASM world since the sandbox will catch it.
 #define bh_memcpy_s(dst, dst_len, src, src_len)  memcpy(dst, src, src_len)
 
+#ifdef NDEBUG
+#define bh_assert(v) (void)0
+#else
+#define bh_assert(v) do {                             \
+    if (!(v)) {                                       \
+        int _count;                                   \
+        printf("ASSERTION FAILED: %s, at %s, line %d",\
+               #v, __FILE__, __LINE__);               \
+        _count = printf("\n");                        \
+        printf("%d\n", _count / (_count - 1));        \
+    }                                                 \
+  } while (0)
+#endif
+
 #endif /* DEPS_IWASM_APP_LIBS_BASE_BH_PLATFORM_H_ */

+ 47 - 35
core/app-framework/base/native/timer_wrapper.c

@@ -5,20 +5,22 @@
 
 #include "bh_platform.h"
 #include "app_manager_export.h"
-#include "module_wasm_app.h"
+#include "../app-manager/module_wasm_app.h"
 #include "timer_native_api.h"
 
-static bool timer_thread_run = true;
-
-bh_list g_timer_ctx_list;
-korp_cond g_timer_ctx_list_cond;
-korp_mutex g_timer_ctx_list_mutex;
 typedef struct {
     bh_list_link l;
     timer_ctx_t timer_ctx;
 } timer_ctx_node_t;
 
-void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
+static bool timer_thread_run = true;
+
+static bh_list g_timer_ctx_list;
+static korp_cond g_timer_ctx_list_cond;
+static korp_mutex g_timer_ctx_list_mutex;
+
+void
+wasm_timer_callback(timer_id_t id, unsigned int mod_id)
 {
     module_data* module = module_data_list_lookup_id(mod_id);
     if (module == NULL)
@@ -29,27 +31,29 @@ void wasm_timer_callback(timer_id_t id, unsigned int mod_id)
     bh_post_msg(module->queue, TIMER_EVENT_WASM, (char *)(uintptr_t)id, 0);
 }
 
-///
-/// why we create a separate link for module timer contexts
-/// rather than traverse the module list?
-/// It helps to reduce the lock frequency for the module list.
-/// Also when we lock the module list and then call the callback for
-/// timer expire, the callback is request the list lock again for lookup
-/// the module from module id. It is for avoiding that situation.
+/**
+ * why we create a separate link for module timer contexts
+ * rather than traverse the module list?
+ * It helps to reduce the lock frequency for the module list.
+ * Also when we lock the module list and then call the callback for
+ * timer expire, the callback is request the list lock again for lookup
+ * the module from module id. It is for avoiding that situation.
+ */
 
 void * thread_modulers_timer_check(void * arg)
 {
-    int ms_to_expiry;
+    uint32 ms_to_expiry;
+    uint64 us_to_wait;
 
     while (timer_thread_run) {
-        ms_to_expiry = -1;
+        ms_to_expiry = (uint32)-1;
         os_mutex_lock(&g_timer_ctx_list_mutex);
         timer_ctx_node_t* elem = (timer_ctx_node_t*)
                                  bh_list_first_elem(&g_timer_ctx_list);
         while (elem) {
-            int next = check_app_timers(elem->timer_ctx);
-            if (next != -1) {
-                if (ms_to_expiry == -1 || ms_to_expiry > next)
+            uint32 next = check_app_timers(elem->timer_ctx);
+            if (next != (uint32)-1) {
+                if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
                     ms_to_expiry = next;
             }
 
@@ -57,48 +61,54 @@ void * thread_modulers_timer_check(void * arg)
         }
         os_mutex_unlock(&g_timer_ctx_list_mutex);
 
-        if (ms_to_expiry == -1)
-            ms_to_expiry = 60 * 1000;
+        if (ms_to_expiry == (uint32)-1)
+            us_to_wait = BHT_WAIT_FOREVER;
+        else
+            us_to_wait = (uint64)ms_to_expiry * 1000;
         os_mutex_lock(&g_timer_ctx_list_mutex);
         os_cond_reltimedwait(&g_timer_ctx_list_cond, &g_timer_ctx_list_mutex,
-                             ms_to_expiry * 1000);
+                             us_to_wait);
         os_mutex_unlock(&g_timer_ctx_list_mutex);
     }
 
     return NULL;
 }
 
-void wakeup_modules_timer_thread(timer_ctx_t ctx)
+void
+wakeup_modules_timer_thread(timer_ctx_t ctx)
 {
     os_mutex_lock(&g_timer_ctx_list_mutex);
     os_cond_signal(&g_timer_ctx_list_cond);
     os_mutex_unlock(&g_timer_ctx_list_mutex);
 }
 
-void init_wasm_timer()
+void
+init_wasm_timer()
 {
     korp_tid tm_tid;
     bh_list_init(&g_timer_ctx_list);
 
     os_cond_init(&g_timer_ctx_list_cond);
-    /* temp solution for: thread_modulers_timer_check thread would recursive lock the mutex */
+    /* temp solution for: thread_modulers_timer_check thread
+       would recursive lock the mutex */
     os_recursive_mutex_init(&g_timer_ctx_list_mutex);
 
     os_thread_create(&tm_tid, thread_modulers_timer_check,
                      NULL, BH_APPLET_PRESERVED_STACK_SIZE);
 }
 
-void exit_wasm_timer()
+void
+exit_wasm_timer()
 {
     timer_thread_run = false;
 }
 
-timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
+timer_ctx_t
+create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
 {
     timer_ctx_t ctx = create_timer_ctx(wasm_timer_callback,
                                        wakeup_modules_timer_thread,
-                                       prealloc_num,
-                                       module_id);
+                                       prealloc_num, module_id);
 
     if (ctx == NULL)
         return NULL;
@@ -119,11 +129,14 @@ timer_ctx_t create_wasm_timer_ctx(unsigned int module_id, int prealloc_num)
     return ctx;
 }
 
-void destroy_module_timer_ctx(unsigned int module_id)
+void
+destroy_module_timer_ctx(unsigned int module_id)
 {
+    timer_ctx_node_t* elem;
+
     os_mutex_lock(&g_timer_ctx_list_mutex);
-    timer_ctx_node_t* elem = (timer_ctx_node_t*)
-                             bh_list_first_elem(&g_timer_ctx_list);
+    elem = (timer_ctx_node_t*)
+           bh_list_first_elem(&g_timer_ctx_list);
     while (elem) {
         if (timer_ctx_get_owner(elem->timer_ctx) == module_id) {
             bh_list_remove(&g_timer_ctx_list, elem);
@@ -137,7 +150,8 @@ void destroy_module_timer_ctx(unsigned int module_id)
     os_mutex_unlock(&g_timer_ctx_list_mutex);
 }
 
-timer_ctx_t get_wasm_timer_ctx(wasm_module_inst_t module_inst)
+timer_ctx_t
+get_wasm_timer_ctx(wasm_module_inst_t module_inst)
 {
     module_data * m = app_manager_get_module_data(Module_WASM_App,
                                                   module_inst);
@@ -184,8 +198,6 @@ wasm_timer_restart(wasm_exec_env_t exec_env,
     sys_timer_restart(timer_ctx, timer_id, interval);
 }
 
-extern uint32 get_sys_tick_ms();
-
 uint32
 wasm_get_sys_tick_ms(wasm_exec_env_t exec_env)
 {

+ 40 - 29
core/app-mgr/app-manager/app_manager.c

@@ -32,8 +32,8 @@ void app_manager_post_applets_update_event()
         return;
 
     if (!(attr_cont = attr_container_create("All Applets"))) {
-        app_manager_printf(
-                "Post applets update event failed: allocate memory failed.");
+        app_manager_printf("Post applets update event failed: "
+                           "allocate memory failed.");
         return;
     }
 
@@ -46,8 +46,8 @@ void app_manager_post_applets_update_event()
     }
 
     if (!(attr_container_set_int(&attr_cont, "num", num))) {
-        app_manager_printf(
-                "Post applets update event failed: set attr container key failed.");
+        app_manager_printf("Post applets update event failed: "
+                           "set attr container key failed.");
         goto fail;
     }
 
@@ -57,14 +57,14 @@ void app_manager_post_applets_update_event()
         i++;
         snprintf(buf, sizeof(buf), "%s%d", "applet", i);
         if (!(attr_container_set_string(&attr_cont, buf, m_data->module_name))) {
-            app_manager_printf(
-                    "Post applets update event failed: set attr applet name key failed.");
+            app_manager_printf("Post applets update event failed: "
+                               "set attr applet name key failed.");
             goto fail;
         }
         snprintf(buf, sizeof(buf), "%s%d", "heap", i);
         if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
-            app_manager_printf(
-                    "Post applets update event failed: set attr heap key failed.");
+            app_manager_printf("Post applets update event failed: "
+                               "set attr heap key failed.");
             goto fail;
         }
         m_data = m_data->next;
@@ -114,7 +114,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
     attr_cont = attr_container_create("Applets Info");
     if (!attr_cont) {
         SEND_ERR_RESPONSE(msg->mid,
-                "Query Applets failed: allocate memory failed.");
+                          "Query Applets failed: allocate memory failed.");
         return false;
     }
 
@@ -128,7 +128,7 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
 
     if (name == NULL && !(attr_container_set_int(&attr_cont, "num", num))) {
         SEND_ERR_RESPONSE(msg->mid,
-                "Query Applets failed: set attr container key failed.");
+                          "Query Applets failed: set attr container key failed.");
         goto fail;
     }
 
@@ -142,26 +142,31 @@ static bool app_manager_query_applets(request_t *msg, const char *name)
             if (!(attr_container_set_string(&attr_cont, buf,
                     m_data->module_name))) {
                 SEND_ERR_RESPONSE(msg->mid,
-                        "Query Applets failed: set attr container key failed.");
+                                  "Query Applets failed: "
+                                  "set attr container key failed.");
                 goto fail;
             }
             snprintf(buf, sizeof(buf), "%s%d", "heap", i);
             if (!(attr_container_set_int(&attr_cont, buf, m_data->heap_size))) {
                 SEND_ERR_RESPONSE(msg->mid,
-                        "Query Applets failed: set attr container heap key failed.");
+                                  "Query Applets failed: "
+                                  "set attr container heap key failed.");
                 goto fail;
             }
-        } else if (!strcmp(name, m_data->module_name)) {
+        }
+        else if (!strcmp(name, m_data->module_name)) {
             found = true;
             if (!(attr_container_set_string(&attr_cont, "name",
                     m_data->module_name))) {
                 SEND_ERR_RESPONSE(msg->mid,
-                        "Query Applet failed: set attr container key failed.");
+                                  "Query Applet failed: "
+                                  "set attr container key failed.");
                 goto fail;
             }
             if (!(attr_container_set_int(&attr_cont, "heap", m_data->heap_size))) {
                 SEND_ERR_RESPONSE(msg->mid,
-                        "Query Applet failed: set attr container heap key failed.");
+                                  "Query Applet failed: "
+                                  "set attr container heap key failed.");
                 goto fail;
             }
         }
@@ -266,7 +271,7 @@ static void app_manager_queue_callback(void *message, void *arg)
                 goto fail;
             }
             if (g_module_interfaces[module_type]
-                    && g_module_interfaces[module_type]->module_install) {
+                && g_module_interfaces[module_type]->module_install) {
                 if (!g_module_interfaces[module_type]->module_install(request))
                     goto fail;
             }
@@ -276,14 +281,13 @@ static void app_manager_queue_callback(void *message, void *arg)
             module_type = get_module_type(request->url + offset);
             if (module_type == -1) {
                 SEND_ERR_RESPONSE(mid,
-                        "Uninstall Applet failed: invalid module type.");
+                                  "Uninstall Applet failed: invalid module type.");
                 goto fail;
             }
 
             if (g_module_interfaces[module_type]
                     && g_module_interfaces[module_type]->module_uninstall) {
-                if (!g_module_interfaces[module_type]->module_uninstall(
-                        request))
+                if (!g_module_interfaces[module_type]->module_uninstall(request))
                     goto fail;
             }
         }
@@ -292,18 +296,19 @@ static void app_manager_queue_callback(void *message, void *arg)
             char name[APP_NAME_MAX_LEN] = { 0 };
             char *properties = request->url + offset;
             find_key_value(properties, strlen(properties), "name", name,
-                    sizeof(name) - 1, '&');
+                           sizeof(name) - 1, '&');
             if (strlen(name) > 0)
                 app_manager_query_applets(request, name);
             else
                 app_manager_query_applets(request, NULL);
-        } else {
+        }
+        else {
             SEND_ERR_RESPONSE(mid, "Invalid request of applet: invalid action");
         }
     }
     /* Event Register/Unregister */
     else if ((offset = check_url_start(request->url, strlen(request->url),
-            "/event/")) > 0) {
+                                       "/event/")) > 0) {
         char url_buf[256] = { 0 };
 
         strncpy(url_buf, request->url + offset, sizeof(url_buf) - 1);
@@ -313,11 +318,12 @@ static void app_manager_queue_callback(void *message, void *arg)
             goto fail;
         }
         send_error_response_to_host(mid, CONTENT_2_05, NULL); /* OK */
-    } else {
+    }
+    else {
         int i;
         for (i = 0; i < Module_Max; i++) {
             if (g_module_interfaces[i]
-                    && g_module_interfaces[i]->module_handle_host_url) {
+                && g_module_interfaces[i]->module_handle_host_url) {
                 if (g_module_interfaces[i]->module_handle_host_url(request))
                     break;
             }
@@ -325,10 +331,8 @@ static void app_manager_queue_callback(void *message, void *arg)
 
     }
 
-    fail:
-
+fail:
     return;
-
 }
 
 static void module_interfaces_init()
@@ -360,7 +364,7 @@ void app_manager_startup(host_interface *interface)
 
     am_register_resource("/app/", targeted_app_request_handler, ID_APP_MGR);
 
-    /*/app/ and /event/ are both processed by applet_mgt_reqeust_handler*/
+    /* /app/ and /event/ are both processed by applet_mgt_reqeust_handler */
     am_register_resource("/applet", applet_mgt_reqeust_handler, ID_APP_MGR);
     am_register_resource("/event/", applet_mgt_reqeust_handler, ID_APP_MGR);
 
@@ -369,6 +373,12 @@ void app_manager_startup(host_interface *interface)
     /* Enter loop run */
     bh_queue_enter_loop_run(g_app_mgr_queue, app_manager_queue_callback, NULL);
 
+    /* Destroy registered resources */
+    am_cleanup_registeration(ID_APP_MGR);
+
+    /* Destroy watchdog */
+    watchdog_destroy();
+
 fail2:
     module_data_list_destroy();
 
@@ -396,4 +406,5 @@ module_interface *g_module_interfaces[Module_Max] = {
 #else
         NULL
 #endif
-    };
+};
+

+ 60 - 33
core/app-mgr/app-manager/app_manager_host.c

@@ -13,11 +13,19 @@
 static host_interface host_commu;
 
 /* IMRTLink Two leading bytes */
-static unsigned char leadings[] = { (unsigned char) 0x12, (unsigned char) 0x34 };
+static unsigned char leadings[] = {
+    (unsigned char)0x12,
+    (unsigned char)0x34
+};
 
 /* IMRTLink Receiving Phase */
 typedef enum recv_phase_t {
-    Phase_Non_Start, Phase_Leading, Phase_Type, Phase_Size, Phase_Payload
+    Phase_Non_Start,
+    Phase_Leading,
+    Phase_Type,
+    Phase_Size,
+    Phase_Payload,
+    Phase_Ignoring
 } recv_phase_t;
 
 /* IMRTLink Receive Context */
@@ -74,7 +82,8 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
         }
 
         return 0;
-    } else if (ctx->phase == Phase_Leading) {
+    }
+    else if (ctx->phase == Phase_Leading) {
         if (ch == leadings[1]) {
             if (enable_log)
                 app_manager_printf("##On byte arrive: got leading 1\n");
@@ -83,12 +92,14 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
             ctx->phase = Phase_Non_Start;
 
         return 0;
-    } else if (ctx->phase == Phase_Type) {
+    }
+    else if (ctx->phase == Phase_Type) {
         if (ctx->size_in_phase++ == 0) {
             if (enable_log)
                 app_manager_printf("##On byte arrive: got type 0\n");
             ctx->message.message_type = ch;
-        } else {
+        }
+        else {
             if (enable_log)
                 app_manager_printf("##On byte arrive: got type 1\n");
             ctx->message.message_type |= (ch << 8);
@@ -98,12 +109,13 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
         }
 
         return 0;
-    } else if (ctx->phase == Phase_Size) {
+    }
+    else if (ctx->phase == Phase_Size) {
         unsigned char *p = (unsigned char *) &ctx->message.payload_size;
 
         if (enable_log)
             app_manager_printf("##On byte arrive: got payload_size, byte %d\n",
-                    ctx->size_in_phase);
+                               ctx->size_in_phase);
         p[ctx->size_in_phase++] = ch;
 
         if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) {
@@ -112,7 +124,7 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
 
             if (enable_log)
                 app_manager_printf("##On byte arrive: payload_size: %d\n",
-                        ctx->message.payload_size);
+                                   ctx->message.payload_size);
             if (ctx->message.payload) {
                 APP_MGR_FREE(ctx->message.payload);
                 ctx->message.payload = NULL;
@@ -122,16 +134,11 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
             if (ctx->message.payload_size == 0) {
                 ctx->phase = Phase_Non_Start;
                 if (enable_log)
-                    app_manager_printf(
-                            "##On byte arrive: receive end, payload_size is 0.\n");
+                    app_manager_printf("##On byte arrive: receive end, "
+                                       "payload_size is 0.\n");
                 return 1;
             }
 
-            if (ctx->message.payload_size > 1024 * 1024) {
-                ctx->phase = Phase_Non_Start;
-                return 0;
-            }
-
             if (ctx->message.message_type != INSTALL_WASM_APP) {
                 ctx->message.payload =
                     (char *) APP_MGR_MALLOC(ctx->message.payload_size);
@@ -146,7 +153,8 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
         }
 
         return 0;
-    } else if (ctx->phase == Phase_Payload) {
+    }
+    else if (ctx->phase == Phase_Payload) {
         if (ctx->message.message_type == INSTALL_WASM_APP) {
             int received_size;
             module_on_install_request_byte_arrive_func module_on_install =
@@ -162,36 +170,53 @@ static int on_imrt_link_byte_arrive(unsigned char ch, recv_context_t *ctx)
                         ctx->phase = Phase_Non_Start;
                         return 1;
                     }
-                } else {
+                }
+                else {
                     /* receive or handle fail */
-                    ctx->phase = Phase_Non_Start;
-                    ctx->size_in_phase = 0;
+                    if (ctx->size_in_phase < ctx->message.payload_size) {
+                        ctx->phase = Phase_Ignoring;
+                    }
+                    else {
+                        ctx->phase = Phase_Non_Start;
+                        ctx->size_in_phase = 0;
+                    }
                     return 0;
                 }
-                return 0;
-            } else {
+            }
+            else {
                 ctx->phase = Phase_Non_Start;
                 ctx->size_in_phase = 0;
                 return 0;
             }
-        } else {
+        }
+        else {
             ctx->message.payload[ctx->size_in_phase++] = ch;
 
             if (ctx->size_in_phase == ctx->message.payload_size) {
                 ctx->phase = Phase_Non_Start;
                 if (enable_log)
-                    app_manager_printf("##On byte arrive: receive end, payload_size is %d.\n",
+                    app_manager_printf("##On byte arrive: receive end, "
+                                       "payload_size is %d.\n",
                                        ctx->message.payload_size);
                 return 1;
             }
             return 0;
         }
     }
+    else if (ctx->phase == Phase_Ignoring) {
+        ctx->size_in_phase++;
+        if (ctx->size_in_phase == ctx->message.payload_size) {
+            if (ctx->message.payload)
+                APP_MGR_FREE(ctx->message.payload);
+            memset(ctx, 0, sizeof(*ctx));
+            return 0;
+        }
+    }
 
     return 0;
 }
 
-int aee_host_msg_callback(void *msg, uint16_t msg_len)
+int aee_host_msg_callback(void *msg, uint32_t msg_len)
 {
     unsigned char *p = msg, *p_end = p + msg_len;
 
@@ -209,14 +234,15 @@ int aee_host_msg_callback(void *msg, uint16_t msg_len)
                     memset(&request, 0, sizeof(request));
 
                     if (!unpack_request(recv_ctx.message.payload,
-                            recv_ctx.message.payload_size, &request))
+                                        recv_ctx.message.payload_size, &request))
                         continue;
 
                     request.sender = ID_HOST;
 
                     am_dispatch_request(&request);
-                } else {
-                    printf("unexpected host msg type: %d\n", msg_type);
+                }
+                else {
+                    app_manager_printf("unexpected host msg type: %d\n", msg_type);
                 }
 
                 APP_MGR_FREE(recv_ctx.message.payload);
@@ -246,7 +272,7 @@ bool app_manager_host_init(host_interface *interface)
     return true;
 }
 
-int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
+int app_manager_host_send_msg(int msg_type, const char *buf, int size)
 {
     /* send an IMRT LINK message contains the buf as payload */
     if (host_commu.send != NULL) {
@@ -258,8 +284,8 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
         bh_memcpy_s(header, 2, leadings, 2);
 
         /* message type */
-        // todo: check if use network byte order!!!
-        *((uint16*) (header + 2)) = htons(msg_type);
+        /* TODO: check if use network byte order!!! */
+        *((uint16*)(header + 2)) = htons(msg_type);
 
         /* payload length */
         if (is_little_endian())
@@ -276,10 +302,11 @@ int app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size)
         n = host_commu.send(NULL, buf, size);
         os_mutex_unlock(&host_lock);
 
-        printf("sent %d bytes to host\n", n);
+        app_manager_printf("sent %d bytes to host\n", n);
         return n;
-    } else {
-        printf("no send api provided\n");
+    }
+    else {
+        app_manager_printf("no send api provided\n");
     }
     return 0;
 }

+ 2 - 2
core/app-mgr/app-manager/message.c

@@ -73,8 +73,8 @@ bool send_error_response_to_host(int mid, int status, const char *msg)
         }
     }
 
-    set_response(response, status,
-    FMT_ATTR_CONTAINER, (const char *)payload, payload_len);
+    set_response(response, status, FMT_ATTR_CONTAINER,
+                 (const char *)payload, payload_len);
     response->mid = mid;
 
     send_response_to_host(response);

+ 5 - 6
core/app-mgr/app-manager/module_utils.c

@@ -198,17 +198,16 @@ void release_module(module_data *m_data)
     APP_MGR_FREE(m_data);
 }
 
-int check_modules_timer_expiry()
+uint32 check_modules_timer_expiry()
 {
     os_mutex_lock(&module_data_list_lock);
     module_data *p = module_data_list;
-    int ms_to_expiry = -1;
+    uint32 ms_to_expiry = (uint32)-1;
 
     while (p) {
-
-        int next = get_expiry_ms(p->timer_ctx);
-        if (next != -1) {
-            if (ms_to_expiry == -1 || ms_to_expiry > next)
+        uint32 next = get_expiry_ms(p->timer_ctx);
+        if (next != (uint32)-1) {
+            if (ms_to_expiry == (uint32)-1 || ms_to_expiry > next)
                 ms_to_expiry = next;
         }
 

+ 141 - 74
core/app-mgr/app-manager/module_wasm_app.c

@@ -13,13 +13,14 @@
 #include "event.h"
 #include "watchdog.h"
 #include "runtime_lib.h"
+#include "wasm.h"
 #if WASM_ENABLE_AOT != 0
 #include "aot_export.h"
 #endif
 
 #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
 /* Wasm bytecode file 4 version bytes */
-static uint8 wasm_bytecode_version[] = {
+static uint8 wasm_bytecode_version[4] = {
     (uint8) 0x01,
     (uint8) 0x00,
     (uint8) 0x00,
@@ -29,12 +30,13 @@ static uint8 wasm_bytecode_version[] = {
 
 #if WASM_ENABLE_AOT != 0
 /* Wasm aot file 4 version bytes */
-static uint8 wasm_aot_version[] = {
-    (uint8) 0x01,
+static uint8 wasm_aot_version[4] = {
+    (uint8) 0x02,
     (uint8) 0x00,
     (uint8) 0x00,
     (uint8) 0x00
 };
+#endif
 
 static union {
     int a;
@@ -42,8 +44,6 @@ static union {
 } __ue = { .a = 1 };
 
 #define is_little_endian() (__ue.b == 1)
-#endif
-
 /* Wasm App Install Request Receiving Phase */
 typedef enum wasm_app_install_req_recv_phase_t {
     Phase_Req_Ver,
@@ -163,14 +163,6 @@ module_interface wasm_app_module_interface = {
     wasm_app_module_on_install_request_byte_arrive
 };
 
-static unsigned
-align_uint(unsigned v, unsigned b)
-{
-    unsigned m = b - 1;
-    return (v + m) & ~m;
-}
-
-#if WASM_ENABLE_AOT != 0
 static void
 exchange_uint32(uint8 *p_data)
 {
@@ -182,7 +174,6 @@ exchange_uint32(uint8 *p_data)
     *(p_data + 1) = *(p_data + 2);
     *(p_data + 2) = value;
 }
-#endif
 
 static wasm_function_inst_t
 app_manager_lookup_function(const wasm_module_inst_t module_inst,
@@ -445,7 +436,7 @@ wasm_app_routine(void *arg)
                                         0, NULL)) {
                 const char *exception = wasm_runtime_get_exception(inst);
                 bh_assert(exception);
-                printf("Got exception running wasi start function: %s\n",
+                app_manager_printf("Got exception running wasi start function: %s\n",
                         exception);
                 wasm_runtime_clear_exception(inst);
                 goto fail1;
@@ -467,7 +458,7 @@ wasm_app_routine(void *arg)
                                 0, NULL)) {
         const char *exception = wasm_runtime_get_exception(inst);
         bh_assert(exception);
-        printf("Got exception running WASM code: %s\n",
+        app_manager_printf("Got exception running WASM code: %s\n",
                exception);
         wasm_runtime_clear_exception(inst);
         /* call on_destroy() in case some resources are opened in on_init()
@@ -513,18 +504,20 @@ cleanup_app_resource(module_data *m_data)
 
     /* Destroy remain sections (i.e. data segment section for bytecode file
      * or text section of aot file) from app file's section list. */
-    if (is_bytecode)
+    if (is_bytecode) {
 #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
         destroy_all_wasm_sections((wasm_section_list_t)(wasm_app_data->sections));
 #else
         bh_assert(0);
 #endif
-    else
+    }
+    else {
 #if WASM_ENABLE_AOT != 0
         destroy_all_aot_sections((aot_section_list_t)(wasm_app_data->sections));
 #else
         bh_assert(0);
 #endif
+    }
 
     if (wasm_app_data->wasm_module)
         wasm_runtime_unload(wasm_app_data->wasm_module);
@@ -546,7 +539,21 @@ cleanup_app_resource(module_data *m_data)
 static bool
 wasm_app_module_init(void)
 {
-    /* wasm runtime is already initialized by main func */
+    uint32 version;
+
+#if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
+    version = WASM_CURRENT_VERSION;
+    if (!is_little_endian())
+        exchange_uint32((uint8 *)&version);
+    bh_memcpy_s(wasm_bytecode_version, 4, &version, 4);
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    version = AOT_CURRENT_VERSION;
+    if (!is_little_endian())
+        exchange_uint32((uint8 *)&version);
+    bh_memcpy_s(wasm_aot_version, 4, &version, 4);
+#endif
     return true;
 }
 
@@ -556,14 +563,14 @@ wasm_app_module_init(void)
 static bool
 wasm_app_module_install(request_t * msg)
 {
-    unsigned int m_data_size, heap_size;
+    unsigned int m_data_size, heap_size, stack_size;
     unsigned int timeout, timers, err_size;
     char *properties;
     int properties_offset;
     wasm_app_file_t *wasm_app_file;
     wasm_data *wasm_app_data;
     package_type_t package_type;
-    module_data *m_data;
+    module_data *m_data = NULL;
     wasm_module_t module = NULL;
     wasm_module_inst_t inst = NULL;
     wasm_exec_env_t exec_env = NULL;
@@ -584,23 +591,30 @@ wasm_app_module_install(request_t * msg)
         return false;
     }
 
+    /* Judge the app type is AOTed or not */
+    package_type = get_package_type((uint8 *)msg->payload, msg->payload_len);
+    wasm_app_file = (wasm_app_file_t *)msg->payload;
+
     /* Check app name */
     properties_offset = check_url_start(msg->url, strlen(msg->url), "/applet");
     bh_assert(properties_offset > 0);
-    if (properties_offset <= 0)
-        return false;
+    if (properties_offset <= 0) {
+        SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid app name.");
+        goto fail;
+    }
+
     properties = msg->url + properties_offset;
     find_key_value(properties, strlen(properties), "name", m_name,
                    sizeof(m_name) - 1, '&');
 
     if (strlen(m_name) == 0) {
         SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: invalid app name.");
-        return false;
+        goto fail;
     }
 
     if (app_manager_lookup_module_data(m_name)) {
         SEND_ERR_RESPONSE(msg->mid, "Install WASM app failed: app already installed.");
-        return false;
+        goto fail;
     }
 
     /* Parse heap size */
@@ -615,9 +629,6 @@ wasm_app_module_install(request_t * msg)
             heap_size = APP_HEAP_SIZE_MAX;
     }
 
-    /* Judge the app type is AOTed or not */
-    package_type = get_package_type((uint8 *) msg->payload, msg->payload_len);
-
     /* Load WASM file and instantiate*/
     switch (package_type) {
 #if WASM_ENABLE_AOT != 0
@@ -634,8 +645,6 @@ wasm_app_module_install(request_t * msg)
                 AOT_SECTION_TYPE_SIGANATURE
             };
 
-            wasm_app_file = (wasm_app_file_t *) msg->payload;
-            bh_assert(wasm_app_file);
             aot_file = &wasm_app_file->u.aot;
 
             /* Load AOT module from sections */
@@ -644,9 +653,7 @@ wasm_app_module_install(request_t * msg)
             if (!module) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: load WASM file failed.");
-                printf("error: %s\n", err);
-                destroy_all_aot_sections(aot_file->sections);
-                return false;
+                goto fail;
             }
             /* Destroy useless sections from list after load */
             destroy_part_aot_sections(&aot_file->sections,
@@ -658,9 +665,7 @@ wasm_app_module_install(request_t * msg)
                                            wasi_dir_buf, sizeof(wasi_dir_buf))) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: prepare wasi env failed.");
-                wasm_runtime_unload(module);
-                destroy_all_aot_sections(aot_file->sections);
-                return false;
+                goto fail;
             }
             wasm_runtime_set_wasi_args(module,
                                        wasi_dir_list, 1,
@@ -674,10 +679,7 @@ wasm_app_module_install(request_t * msg)
             if (!inst) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: instantiate wasm runtime failed.");
-                printf("error: %s\n", err);
-                wasm_runtime_unload(module);
-                destroy_all_aot_sections(aot_file->sections);
-                return false;
+                goto fail;
             }
             break;
         }
@@ -698,13 +700,15 @@ wasm_app_module_install(request_t * msg)
                 SECTION_TYPE_GLOBAL,
                 SECTION_TYPE_EXPORT,
                 SECTION_TYPE_START,
-                SECTION_TYPE_ELEM
+                SECTION_TYPE_ELEM,
+#if WASM_ENABLE_BULK_MEMORY != 0
+                SECTION_TYPE_DATACOUNT
+#endif
+
             };
             /* Sections to be released after instantiating */
             uint8 sections2[] = { SECTION_TYPE_DATA };
 
-            wasm_app_file = (wasm_app_file_t *) msg->payload;
-            bh_assert(wasm_app_file);
             bytecode_file = &wasm_app_file->u.bytecode;
 
             /* Load wasm module from sections */
@@ -713,9 +717,7 @@ wasm_app_module_install(request_t * msg)
             if (!module) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: load WASM file failed.");
-                printf("error: %s\n", err);
-                destroy_all_wasm_sections(bytecode_file->sections);
-                return false;
+                goto fail;
             }
 
             /* Destroy useless sections from list after load */
@@ -728,9 +730,7 @@ wasm_app_module_install(request_t * msg)
                                            wasi_dir_buf, sizeof(wasi_dir_buf))) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: prepare wasi env failed.");
-                wasm_runtime_unload(module);
-                destroy_all_wasm_sections(bytecode_file->sections);
-                return false;
+                goto fail;
             }
             wasm_runtime_set_wasi_args(module,
                                        wasi_dir_list, 1,
@@ -744,10 +744,7 @@ wasm_app_module_install(request_t * msg)
             if (!inst) {
                 SEND_ERR_RESPONSE(msg->mid,
                                   "Install WASM app failed: instantiate wasm runtime failed.");
-                printf("error: %s\n", err);
-                wasm_runtime_unload(module);
-                destroy_all_wasm_sections(bytecode_file->sections);
-                return false;
+                goto fail;
             }
 
             /* Destroy useless sections from list after instantiate */
@@ -760,7 +757,7 @@ wasm_app_module_install(request_t * msg)
         default:
             SEND_ERR_RESPONSE(msg->mid,
                               "Install WASM app failed: invalid wasm package type.");
-            return false;
+            goto fail;
     }
 
     /* Create module data including the wasm_app_data as its internal_data*/
@@ -842,12 +839,16 @@ wasm_app_module_install(request_t * msg)
         goto fail;
     }
 
+    stack_size = APP_THREAD_STACK_SIZE_DEFAULT;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    stack_size += 4 * BH_KB;
+#endif
     /* Create WASM app thread. */
     if (os_thread_create(&wasm_app_data->thread_id, wasm_app_routine,
-                         (void*) m_data, APP_THREAD_STACK_SIZE_DEFAULT) != 0) {
+                         (void*) m_data, stack_size) != 0) {
         module_data_list_remove(m_data);
         SEND_ERR_RESPONSE(msg->mid,
-                          "Install WASM app failed: create app threadf failed.");
+                          "Install WASM app failed: create app thread failed.");
         goto fail;
     }
 
@@ -862,8 +863,13 @@ wasm_app_module_install(request_t * msg)
 fail:
     if (m_data)
         release_module(m_data);
-    wasm_runtime_deinstantiate(inst);
-    wasm_runtime_unload(module);
+
+    if (inst)
+        wasm_runtime_deinstantiate(inst);
+
+    if (module)
+        wasm_runtime_unload(module);
+
     if (exec_env)
         wasm_runtime_destroy_exec_env(exec_env);
 
@@ -956,7 +962,7 @@ wasm_app_module_uninstall(request_t *msg)
 static bool
 wasm_app_module_handle_host_url(void *queue_msg)
 {
-    //todo: implement in future
+    /* TODO: implement in future */
     app_manager_printf("App handles host url address %d\n",
                        (int)(uintptr_t)queue_msg);
     return false;
@@ -972,7 +978,7 @@ wasm_app_module_get_module_data(void *inst)
 static void
 wasm_app_module_watchdog_kill(module_data *m_data)
 {
-    //todo: implement in future
+    /* TODO: implement in future */
     app_manager_printf("Watchdog kills app: %s\n", m_data->module_name);
     return;
 }
@@ -984,7 +990,7 @@ wasm_register_msg_callback(int message_type,
     int i;
     int freeslot = -1;
     for (i = 0; i < Max_Msg_Callback; i++) {
-        // replace handler for the same event registered
+        /* replace handler for the same event registered */
         if (g_msg_type[i] == message_type)
             break;
 
@@ -1042,6 +1048,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                                                int *received_size)
 {
     uint8 *p;
+    int magic;
     package_type_t package_type = Package_Type_Unknown;
 
     if (recv_ctx.phase == Phase_Req_Ver) {
@@ -1089,6 +1096,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                 APP_MGR_MALLOC(recv_ctx.message.request_url_len + 1);
             if (NULL == recv_ctx.message.request_url) {
                 app_manager_printf("Allocate memory failed!\n");
+                SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                  "Install WASM app failed: "
+                                  "allocate memory failed.");
                 goto fail;
             }
             memset(recv_ctx.message.request_url, 0,
@@ -1118,7 +1128,7 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
 
         if (recv_ctx.size_in_phase ==
                 sizeof(recv_ctx.message.app_file_magic)) {
-            int magic = recv_ctx.message.app_file_magic;
+            magic = recv_ctx.message.app_file_magic;
             package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
             switch (package_type) {
 #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
@@ -1139,7 +1149,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
 #endif
                 default:
                     SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
-                                      "Install WASM app failed: invalid file format.");
+                                      "Install WASM app failed: "
+                                      "invalid file format.");
                     goto fail;
             }
         }
@@ -1153,6 +1164,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
             p[recv_ctx.size_in_phase++] = ch;
         else {
             app_manager_printf("Invalid WASM version!\n");
+            SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                              "Install WASM app failed: invalid WASM version.");
             goto fail;
         }
 
@@ -1165,10 +1178,19 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
     }
     else if (recv_ctx.phase == Phase_Wasm_Section_Type) {
         uint8 section_type = ch;
-        if (section_type <= SECTION_TYPE_DATA) {
+#if WASM_ENABLE_BULK_MEMORY == 0
+        uint8 section_type_max = SECTION_TYPE_DATA;
+#else
+        uint8 section_type_max = SECTION_TYPE_DATACOUNT;
+#endif
+        if (section_type <= section_type_max) {
             wasm_section_t *new_section;
-            if (!(new_section = (wasm_section_t *) APP_MGR_MALLOC(sizeof(wasm_section_t)))) {
+            if (!(new_section = (wasm_section_t *)
+                                APP_MGR_MALLOC(sizeof(wasm_section_t)))) {
                 app_manager_printf("Allocate memory failed!\n");
+                SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                  "Install WASM app failed: "
+                                  "allocate memory failed.");
                 goto fail;
             }
             memset(new_section, 0, sizeof(wasm_section_t));
@@ -1191,7 +1213,13 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
             return true;
         }
         else {
+            char error_buf[128];
+
             app_manager_printf("Invalid wasm section type: %d\n", section_type);
+            snprintf(error_buf, sizeof(error_buf),
+                     "Install WASM app failed: invalid wasm section type %d",
+                     section_type);
+            SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
             goto fail;
         }
     }
@@ -1210,7 +1238,10 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
         /* check leab128 overflow for uint32 value */
         if (recv_ctx.size_in_phase >
                 (sizeof(section->section_body_size) * 8 + 7 - 1) / 7) {
-            app_manager_printf(" LEB overflow when parsing section size\n");
+            app_manager_printf("LEB overflow when parsing section size\n");
+            SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                              "Install WASM app failed: "
+                              "LEB overflow when parsing section size");
             goto fail;
         }
 
@@ -1218,6 +1249,8 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
             /* leb128 encoded section size parsed done */
             if (!(section->section_body = APP_MGR_MALLOC(section->section_body_size))) {
                 app_manager_printf("Allocate memory failed!\n");
+                SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                  "Install WASM app failed: allocate memory failed");
                 goto fail;
             }
             recv_ctx.phase = Phase_Wasm_Section_Content;
@@ -1245,7 +1278,15 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                 }
                 else {
                     app_manager_printf("Handle install message failed!\n");
-                    goto fail;
+                    SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                      "Install WASM app failed: "
+                                      "handle install message failed");
+                    /**
+                     * The sections were destroyed inside
+                     * module_wasm_app_handle_install_msg(),
+                     * no need to destroy again.
+                     */
+                    return false;
                 }
             }
             else {
@@ -1265,7 +1306,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
         if (ch == wasm_aot_version[recv_ctx.size_in_phase])
             p[recv_ctx.size_in_phase++] = ch;
         else {
-            app_manager_printf("Invalid WASM AOT version!\n");
+            app_manager_printf("Invalid AOT version!\n");
+            SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                              "Install WASM app failed: invalid AOT version");
             goto fail;
         }
 
@@ -1287,8 +1330,12 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
             if (aot_file_cur_offset % 4)
                 return true;
 
-            if (!(cur_section = (aot_section_t *) APP_MGR_MALLOC(sizeof(aot_section_t)))) {
+            if (!(cur_section = (aot_section_t *)
+                                APP_MGR_MALLOC(sizeof(aot_section_t)))) {
                 app_manager_printf("Allocate memory failed!\n");
+                SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                  "Install WASM app failed: "
+                                  "allocate memory failed");
                 goto fail;
             }
             memset(cur_section, 0, sizeof(aot_section_t));
@@ -1318,8 +1365,14 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                 recv_ctx.size_in_phase = 0;
             }
             else {
+                char error_buf[128];
+
                 app_manager_printf("Invalid AOT section id: %d\n",
                                    cur_section->section_type);
+                snprintf(error_buf, sizeof(error_buf),
+                         "Install WASM app failed: invalid AOT section id %d",
+                         cur_section->section_type);
+                SEND_ERR_RESPONSE(recv_ctx.message.request_mid, error_buf);
                 goto fail;
             }
         }
@@ -1357,6 +1410,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                                 os_mmap(NULL, (uint32)total_size,
                                         map_prot, map_flags))) {
                         app_manager_printf("Allocate executable memory failed!\n");
+                        SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                          "Install WASM app failed: "
+                                          "allocate memory failed");
                         goto fail;
                     }
 #if defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)
@@ -1369,6 +1425,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                     if (!(section->section_body =
                                 APP_MGR_MALLOC(section->section_body_size))) {
                         app_manager_printf("Allocate memory failed!\n");
+                        SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                          "Install WASM app failed: "
+                                          "allocate memory failed");
                         goto fail;
                     }
                 }
@@ -1408,7 +1467,15 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
                 }
                 else {
                     app_manager_printf("Handle install message failed!\n");
-                    goto fail;
+                    SEND_ERR_RESPONSE(recv_ctx.message.request_mid,
+                                      "Install WASM app failed: "
+                                      "handle install message failed");
+                    /**
+                     * The sections were destroyed inside
+                     * module_wasm_app_handle_install_msg(),
+                     * no need to destroy again.
+                     */
+                    return false;
                 }
             }
             else {
@@ -1423,6 +1490,9 @@ wasm_app_module_on_install_request_byte_arrive(uint8 ch,
 #endif /* end of WASM_ENABLE_AOT != 0 */
 
 fail:
+    /* Restore the package type */
+    magic = recv_ctx.message.app_file_magic;
+    package_type = get_package_type((uint8 *)&magic, sizeof(magic) + 1);
     switch (package_type) {
 #if WASM_ENABLE_INTERP != 0 || WASM_ENABLE_JIT != 0
         case Wasm_Module_Bytecode:
@@ -1443,10 +1513,7 @@ fail:
         recv_ctx.message.request_url = NULL;
     }
 
-    recv_ctx.phase = Phase_Req_Ver;
-    recv_ctx.size_in_phase = 0;
-    recv_ctx.total_received_size = 0;
-
+    memset(&recv_ctx, 0, sizeof(recv_ctx));
     return false;
 }
 

+ 4 - 3
core/app-mgr/app-manager/resource_reg.c

@@ -71,7 +71,7 @@ void targeted_app_request_handler(request_t *request, void *unused)
     }
 
     strncpy(applet_name, request->url + offset, sizeof(applet_name) - 1);
-    char *p = strrchr(applet_name, '/');
+    char *p = strchr(applet_name, '/');
     if (p) {
         *p = 0;
     } else
@@ -136,7 +136,8 @@ void * am_dispatch_request(request_t *request)
 }
 
 bool am_register_resource(const char *url,
-        void (*request_handler)(request_t *, void *), uint32 register_id)
+                          void (*request_handler)(request_t *, void *),
+                          uint32 register_id)
 {
     app_res_register_t * r = g_resources;
     int register_num = 0;
@@ -158,7 +159,7 @@ bool am_register_resource(const char *url,
     if (register_num >= RESOURCE_REGISTRATION_NUM_MAX)
         return false;
 
-    r = (app_res_register_t *) APP_MGR_MALLOC(sizeof(app_res_register_t));
+    r = (app_res_register_t *)APP_MGR_MALLOC(sizeof(app_res_register_t));
     if (r == NULL)
         return false;
 

+ 6 - 0
core/app-mgr/app-manager/watchdog.c

@@ -124,3 +124,9 @@ bool watchdog_startup()
 #endif
     return true;
 }
+
+void watchdog_destroy()
+{
+    bh_queue_exit_loop_run(watchdog_queue);
+    bh_queue_destroy(watchdog_queue);
+}

+ 3 - 0
core/app-mgr/app-manager/watchdog.h

@@ -31,6 +31,9 @@ app_manager_get_watchdog_timer(void *timer);
 bool
 watchdog_startup();
 
+void
+watchdog_destroy();
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 11 - 12
core/app-mgr/app-mgr-shared/app_manager_export.h

@@ -173,20 +173,11 @@ typedef struct host_interface {
  * @return true if success, false otherwise
  */
 bool
-app_manager_host_init(host_interface *interface);
-
-/**
- * Send message to Host
- *
- * @param buf buffer to send
- * @param size size of buffer
- *
- * @return size of buffer sent
- */
+app_manager_host_init(host_interface *intf);
 
 /* Startup app manager */
 void
-app_manager_startup(host_interface *interface);
+app_manager_startup(host_interface *intf);
 
 /* Get queue of current applet */
 void *
@@ -284,8 +275,16 @@ send_error_response_to_host(int mid, int code, const char *msg);
 bool
 bh_applet_check_permission(const char *perm);
 
+/**
+ * Send message to Host
+ *
+ * @param buf buffer to send
+ * @param size size of buffer
+ *
+ * @return size of buffer sent
+ */
 int
-app_manager_host_send_msg(int msg_type, const unsigned char *buf, int size);
+app_manager_host_send_msg(int msg_type, const char *buf, int size);
 
 #ifdef __cplusplus
 } /* end of extern "C" */

+ 134 - 25
core/config.h

@@ -15,7 +15,11 @@
     && !defined(BUILD_TARGET_THUMB) \
     && !defined(BUILD_TARGET_THUMB_VFP) \
     && !defined(BUILD_TARGET_MIPS) \
-    && !defined(BUILD_TARGET_XTENSA)
+    && !defined(BUILD_TARGET_XTENSA) \
+    && !defined(BUILD_TARGET_RISCV64_LP64D) \
+    && !defined(BUILD_TARGET_RISCV64_LP64) \
+    && !defined(BUILD_TARGET_RISCV32_ILP32D) \
+    && !defined(BUILD_TARGET_RISCV32_ILP32)
 #if defined(__x86_64__) || defined(__x86_64)
 #define BUILD_TARGET_X86_64
 #elif defined(__amd64__) || defined(__amd64)
@@ -34,6 +38,10 @@
 #define BUILD_TARGET_MIPS
 #elif defined(__XTENSA__)
 #define BUILD_TARGET_XTENSA
+#elif defined(__riscv) && (__riscv_xlen == 64)
+#define BUILD_TARGET_RISCV64_LP64D
+#elif defined(__riscv) && (__riscv_xlen == 32)
+#define BUILD_TARGET_RISCV32_ILP32D
 #else
 #error "Build target isn't set"
 #endif
@@ -43,12 +51,8 @@
 #define BH_DEBUG 0
 #endif
 
-enum {
-    /* Memory allocator ems */
-    MEM_ALLOCATOR_EMS = 0,
-    /* Memory allocator tlsf */
-    MEM_ALLOCATOR_TLSF
-};
+#define MEM_ALLOCATOR_EMS  0
+#define MEM_ALLOCATOR_TLSF 1
 
 /* Default memory allocator */
 #define DEFAULT_MEM_ALLOCATOR MEM_ALLOCATOR_EMS
@@ -62,7 +66,7 @@ enum {
 #endif
 
 #define AOT_MAGIC_NUMBER 0x746f6100
-#define AOT_CURRENT_VERSION 1
+#define AOT_CURRENT_VERSION 3
 
 #ifndef WASM_ENABLE_JIT
 #define WASM_ENABLE_JIT 0
@@ -86,6 +90,19 @@ enum {
 #define WASM_ENABLE_LIBC_WASI 0
 #endif
 
+#ifndef WASM_ENABLE_UVWASI
+#define WASM_ENABLE_UVWASI 0
+#endif
+
+/* Default disable libc emcc */
+#ifndef WASM_ENABLE_LIBC_EMCC
+#define WASM_ENABLE_LIBC_EMCC 0
+#endif
+
+#ifndef WASM_ENABLE_LIB_PTHREAD
+#define WASM_ENABLE_LIB_PTHREAD 0
+#endif
+
 #ifndef WASM_ENABLE_BASE_LIB
 #define WASM_ENABLE_BASE_LIB 0
 #endif
@@ -94,25 +111,51 @@ enum {
 #define WASM_ENABLE_APP_FRAMEWORK 0
 #endif
 
+/* Bulk memory operation */
+#ifndef WASM_ENABLE_BULK_MEMORY
+#define WASM_ENABLE_BULK_MEMORY 0
+#endif
+
+/* Shared memory */
+#ifndef WASM_ENABLE_SHARED_MEMORY
+#define WASM_ENABLE_SHARED_MEMORY 0
+#endif
+
+/* Thread manager */
+#ifndef WASM_ENABLE_THREAD_MGR
+#define WASM_ENABLE_THREAD_MGR 0
+#endif
+
 /* WASM log system */
 #ifndef WASM_ENABLE_LOG
 #define WASM_ENABLE_LOG 1
 #endif
 
-#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64)
-#define WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS 1
+#ifndef WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS
+#if defined(BUILD_TARGET_X86_32) || defined(BUILD_TARGET_X86_64) \
+    || defined(BUILD_TARGET_AARCH64)
+#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 1
 #else
-#define WASM_CPU_SUPPORTS_UNALIGNED_64BIT_ACCESS 0
+#define WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS 0
+#endif
 #endif
 
 /* WASM Interpreter labels-as-values feature */
+#ifndef WASM_ENABLE_LABELS_AS_VALUES
+#ifdef __GNUC__
 #define WASM_ENABLE_LABELS_AS_VALUES 1
+#else
+#define WASM_ENABLE_LABELS_AS_VALUES 0
+#endif
+#endif
+
+/* Enable fast interpreter or not */
+#ifndef WASM_ENABLE_FAST_INTERP
+#define WASM_ENABLE_FAST_INTERP 0
+#endif
 
 #if WASM_ENABLE_FAST_INTERP != 0
-#define WASM_ENABLE_ABS_LABEL_ADDR 1
 #define WASM_DEBUG_PREPROCESSOR 0
-#else
-#define WASM_ENABLE_ABS_LABEL_ADDR 0
 #endif
 
 /* Enable opcode counter or not */
@@ -120,11 +163,51 @@ enum {
 #define WASM_ENABLE_OPCODE_COUNTER 0
 #endif
 
-/* Heap and stack profiling */
-#define BH_ENABLE_MEMORY_PROFILING 0
+/* Support a module with dependency, other modules */
+#ifndef WASM_ENABLE_MULTI_MODULE
+#define WASM_ENABLE_MULTI_MODULE 0
+#endif
+
+/* Enable wasm mini loader or not */
+#ifndef WASM_ENABLE_MINI_LOADER
+#define WASM_ENABLE_MINI_LOADER 0
+#endif
+
+/* Disable boundary check with hardware trap or not,
+ * enable it by default if it is supported */
+#ifndef WASM_DISABLE_HW_BOUND_CHECK
+#define WASM_DISABLE_HW_BOUND_CHECK 0
+#endif
+
+/* Disable SIMD unless it is manualy enabled somewhere */
+#ifndef WASM_ENABLE_SIMD
+#define WASM_ENABLE_SIMD 0
+#endif
+
+/* Memory profiling */
+#ifndef WASM_ENABLE_MEMORY_PROFILING
+#define WASM_ENABLE_MEMORY_PROFILING 0
+#endif
+
+/* Memory tracing */
+#ifndef WASM_ENABLE_MEMORY_TRACING
+#define WASM_ENABLE_MEMORY_TRACING 0
+#endif
+
+/* Performance profiling */
+#ifndef WASM_ENABLE_PERF_PROFILING
+#define WASM_ENABLE_PERF_PROFILING 0
+#endif
+
+/* Dump call stack */
+#ifndef WASM_ENABLE_DUMP_CALL_STACK
+#define WASM_ENABLE_DUMP_CALL_STACK 0
+#endif
 
 /* Heap verification */
+#ifndef BH_ENABLE_GC_VERIFY
 #define BH_ENABLE_GC_VERIFY 0
+#endif
 
 /* Max app number of all modules */
 #define MAX_APP_INSTALLATIONS 3
@@ -153,12 +236,9 @@ enum {
 /* The max percentage of global heap that app memory space can grow */
 #define APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT 1 / 3
 
-/* Default base offset of app heap space */
-#define DEFAULT_APP_HEAP_BASE_OFFSET (1 * BH_GB)
-
 /* Default min/max heap size of each app */
 #define APP_HEAP_SIZE_DEFAULT (8 * 1024)
-#define APP_HEAP_SIZE_MIN (2 * 1024)
+#define APP_HEAP_SIZE_MIN (256)
 #define APP_HEAP_SIZE_MAX (512 * 1024 * 1024)
 
 /* Default wasm stack size of each app */
@@ -167,25 +247,54 @@ enum {
 #else
 #define DEFAULT_WASM_STACK_SIZE (12 * 1024)
 #endif
+/* Min auxilliary stack size of each wasm thread */
+#define WASM_THREAD_AUX_STACK_SIZE_MIN (256)
 
 /* Default/min/max stack size of each app thread */
-#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS)
-#define APP_THREAD_STACK_SIZE_DEFAULT (20 * 1024)
-#define APP_THREAD_STACK_SIZE_MIN (16 * 1024)
-#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
+#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
+    && !defined(BH_PLATFORM_ESP_IDF) && !defined(BH_PLATFORM_OPENRTOS)
+#define APP_THREAD_STACK_SIZE_DEFAULT (32 * 1024)
+#define APP_THREAD_STACK_SIZE_MIN (24 * 1024)
 #else
 #define APP_THREAD_STACK_SIZE_DEFAULT (6 * 1024)
 #define APP_THREAD_STACK_SIZE_MIN (4 * 1024)
-#define APP_THREAD_STACK_SIZE_MAX (256 * 1024)
 #endif
+#if !defined(APP_THREAD_STACK_SIZE_MAX)
+#define APP_THREAD_STACK_SIZE_MAX (8 * 1024 * 1024)
+#endif
+
+/* Reserved bytes to the native thread stack boundary, throw native
+   stack overflow exception if the guard boudary is reached */
+#define RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY (512)
+
+/* Guard page count for stack overflow check with hardware trap */
+#define STACK_OVERFLOW_CHECK_GUARD_PAGE_COUNT 3
 
 /* Default wasm block address cache size and conflict list size */
+#ifndef BLOCK_ADDR_CACHE_SIZE
 #define BLOCK_ADDR_CACHE_SIZE 64
+#endif
 #define BLOCK_ADDR_CONFLICT_SIZE 2
 
 #ifndef WASM_ENABLE_SPEC_TEST
 #define WASM_ENABLE_SPEC_TEST 0
 #endif
 
+/* Default max thread num per cluster. Can be overwrite by
+    wasm_runtime_set_max_thread_num */
+#define CLUSTER_MAX_THREAD_NUM 4
+
+#ifndef WASM_ENABLE_TAIL_CALL
+#define WASM_ENABLE_TAIL_CALL 0
+#endif
+
+#ifndef WASM_ENABLE_CUSTOM_NAME_SECTION
+#define WASM_ENABLE_CUSTOM_NAME_SECTION 0
+#endif
+
+#ifndef WASM_ENABLE_REF_TYPES
+#define WASM_ENABLE_REF_TYPES 0
+#endif
+
 #endif /* end of _CONFIG_H_ */
 

+ 1 - 1
core/deps/download.sh

@@ -13,7 +13,7 @@ if [ ! -d "lvgl" ]; then
 fi
 if [ ! -d "lv_drivers" ]; then
         echo "git pull lv_drivers..."
-        git clone https://github.com/littlevgl/lv_drivers.git
+        git clone https://github.com/littlevgl/lv_drivers.git --branch v6.0.1
         [ $? -eq 0 ] || exit $?
 fi
 

+ 31 - 0
core/iwasm/aot/SConscript

@@ -0,0 +1,31 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+Import('rtconfig')
+
+cwd     = GetCurrentDir()
+
+src = Split('''
+aot_loader.c
+aot_runtime.c
+''')
+
+if rtconfig.ARCH == 'arm':
+    if re.match('^cortex-m.*', rtconfig.CPU):
+        src += ['arch/aot_reloc_thumb.c']
+    elif re.match('^cortex-a.*', rtconfig.CPU):
+        src += ['arch/aot_reloc_arm.c']
+
+
+CPPPATH = [cwd, cwd + '/../include']
+
+CPPDEFINES = ['WASM_ENABLE_AOT=1']
+
+group = DefineGroup('iwasm_aot', src, depend = [''], CPPPATH = CPPPATH, CPPDEFINES = CPPDEFINES)
+
+Return('group')

File diff suppressed because it is too large
+ 395 - 191
core/iwasm/aot/aot_loader.c


+ 45 - 3
core/iwasm/aot/aot_reloc.h

@@ -12,12 +12,50 @@ typedef struct {
 
 #define REG_SYM(symbol) { #symbol, (void*)symbol }
 
+#if WASM_ENABLE_BULK_MEMORY != 0
+#define REG_BULK_MEMORY_SYM()             \
+    REG_SYM(aot_memory_init),             \
+    REG_SYM(aot_data_drop),
+#else
+#define REG_BULK_MEMORY_SYM()
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#define REG_ATOMIC_WAIT_SYM()             \
+    REG_SYM(wasm_runtime_atomic_wait),    \
+    REG_SYM(wasm_runtime_atomic_notify),
+#else
+#define REG_ATOMIC_WAIT_SYM()
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+#define REG_REF_TYPES_SYM()               \
+    REG_SYM(aot_drop_table_seg),          \
+    REG_SYM(aot_table_init),              \
+    REG_SYM(aot_table_copy),              \
+    REG_SYM(aot_table_fill),              \
+    REG_SYM(aot_table_grow),
+#else
+#define REG_REF_TYPES_SYM()
+#endif
+
+#if (WASM_ENABLE_PERF_PROFILING != 0) || (WASM_ENABLE_DUMP_CALL_STACK != 0)
+#define REG_AOT_TRACE_SYM()               \
+    REG_SYM(aot_alloc_frame),             \
+    REG_SYM(aot_free_frame),
+#else
+#define REG_AOT_TRACE_SYM()
+#endif
+
 #define REG_COMMON_SYMBOLS                \
     REG_SYM(aot_set_exception_with_id),   \
     REG_SYM(aot_invoke_native),           \
     REG_SYM(aot_call_indirect),           \
-    REG_SYM(wasm_runtime_enlarge_memory), \
-    REG_SYM(wasm_runtime_set_exception),  \
+    REG_SYM(aot_enlarge_memory),          \
+    REG_SYM(aot_set_exception),           \
+    {"memset", (void*)aot_memset},        \
+    {"memmove", (void*)aot_memmove},      \
     REG_SYM(fmin),                        \
     REG_SYM(fminf),                       \
     REG_SYM(fmax),                        \
@@ -29,7 +67,11 @@ typedef struct {
     REG_SYM(trunc),                       \
     REG_SYM(truncf),                      \
     REG_SYM(rint),                        \
-    REG_SYM(rintf)
+    REG_SYM(rintf),                       \
+    REG_BULK_MEMORY_SYM()                 \
+    REG_ATOMIC_WAIT_SYM()                 \
+    REG_REF_TYPES_SYM()                   \
+    REG_AOT_TRACE_SYM()
 
 #define CHECK_RELOC_OFFSET(data_size) do {                                  \
     if (!check_reloc_offset(target_section_size, reloc_offset, data_size,   \

File diff suppressed because it is too large
+ 755 - 149
core/iwasm/aot/aot_runtime.c


+ 301 - 45
core/iwasm/aot/aot_runtime.h

@@ -30,6 +30,11 @@ typedef enum AOTExceptionID {
     EXCE_UNDEFINED_ELEMENT,
     EXCE_UNINITIALIZED_ELEMENT,
     EXCE_CALL_UNLINKED_IMPORT_FUNC,
+    EXCE_NATIVE_STACK_OVERFLOW,
+    EXCE_UNALIGNED_ATOMIC,
+    EXCE_AUX_STACK_OVERFLOW,
+    EXCE_AUX_STACK_UNDERFLOW,
+    EXCE_OUT_OF_BOUNDS_TABLE_ACCESS,
     EXCE_NUM,
 } AOTExceptionID;
 
@@ -68,18 +73,67 @@ typedef struct AOTRelocationGroup {
     AOTRelocation *relocations;
 } AOTRelocationGroup;
 
+/* AOT function instance */
+typedef struct AOTFunctionInstance {
+    char *func_name;
+    uint32 func_index;
+    bool is_import_func;
+    union {
+        struct {
+            AOTFuncType *func_type;
+            /* function pointer linked */
+            void *func_ptr;
+        } func;
+        AOTImportFunc *func_import;
+    } u;
+} AOTFunctionInstance;
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+typedef struct AOTUnwindInfo {
+    uint8 Version       : 3;
+    uint8 Flags         : 5;
+    uint8 SizeOfProlog;
+    uint8 CountOfCodes;
+    uint8 FrameRegister : 4;
+    uint8 FrameOffset   : 4;
+    struct {
+        struct {
+            uint8 CodeOffset;
+            uint8 UnwindOp : 4;
+            uint8 OpInfo   : 4;
+        };
+        uint16 FrameOffset;
+    } UnwindCode[1];
+} AOTUnwindInfo;
+
+/* size of mov instruction and jmp instruction */
+#define PLT_ITEM_SIZE 12
+#endif
+
 typedef struct AOTModule {
     uint32 module_type;
 
+    /* import memories */
+    uint32 import_memory_count;
+    AOTImportMemory *import_memories;
+
     /* memory info */
-    uint32 num_bytes_per_page;
-    uint32 mem_init_page_count;
-    uint32 mem_max_page_count;
+    uint32 memory_count;
+    AOTMemory *memories;
+
+    /* init data */
     uint32 mem_init_data_count;
     AOTMemInitData **mem_init_data_list;
 
-    /* table info */
-    uint32 table_size;
+    /* import tables */
+    uint32 import_table_count;
+    AOTImportTable *import_tables;
+
+    /* tables */
+    uint32 table_count;
+    AOTTable *tables;
+
+    /* table init data info */
     uint32 table_init_data_count;
     AOTTableInitData **table_init_data_list;
 
@@ -109,15 +163,19 @@ typedef struct AOTModule {
     /* function type indexes */
     uint32 *func_type_indexes;
 
-    /* export function info */
-    uint32 export_func_count;
-    AOTExportFunc *export_funcs;
+    /* export info */
+    uint32 export_count;
+    AOTExport *exports;
 
     /* start function index, -1 denotes no start function */
     uint32 start_func_index;
     /* start function, point to AOTed/JITed function */
     void *start_function;
 
+    uint32 malloc_func_index;
+    uint32 free_func_index;
+    uint32 retain_func_index;
+
     /* AOTed code, NULL for JIT mode */
     void *code;
     uint32 code_size;
@@ -126,6 +184,25 @@ typedef struct AOTModule {
     uint8 *literal;
     uint32 literal_size;
 
+#if (defined(BUILD_TARGET_X86_64) || defined(BUILD_TARGET_AMD_64)) \
+    && defined(BH_PLATFORM_WINDOWS)
+    /* extra plt data area for __xmm and __real constants
+       in Windows platform, NULL for JIT mode */
+    uint8 *extra_plt_data;
+    uint32 extra_plt_data_size;
+    uint32 xmm_plt_count;
+    uint32 real_plt_count;
+    uint32 float_plt_count;
+#endif
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    /* dynamic function table to be added by RtlAddFunctionTable(),
+       used to unwind the call stack and register exception handler
+       for AOT functions */
+    RUNTIME_FUNCTION *rtl_func_table;
+    bool rtl_func_table_registered;
+#endif
+
     /* data sections in AOT object file, including .data, .rodata
      * and .rodata.cstN. NULL for JIT mode. */
     AOTObjectDataSection *data_sections;
@@ -134,10 +211,25 @@ typedef struct AOTModule {
     /* constant string set */
     HashMap *const_str_set;
 
-    uint32 llvm_aux_data_end;
-    uint32 llvm_aux_stack_bottom;
-    uint32 llvm_aux_stack_size;
-    uint32 llvm_aux_stack_global_index;
+    /* the index of auxiliary __data_end global,
+       -1 means unexported */
+    uint32 aux_data_end_global_index;
+    /* auxiliary __data_end exported by wasm app */
+    uint32 aux_data_end;
+
+    /* the index of auxiliary __heap_base global,
+       -1 means unexported */
+    uint32 aux_heap_base_global_index;
+    /* auxiliary __heap_base exported by wasm app */
+    uint32 aux_heap_base;
+
+    /* the index of auxiliary stack top global,
+       -1 means unexported */
+    uint32 aux_stack_top_global_index;
+    /* auxiliary stack bottom resolved */
+    uint32 aux_stack_bottom;
+    /* auxiliary stack size resolved */
+    uint32 aux_stack_size;
 
     /* is jit mode or not */
     bool is_jit_mode;
@@ -159,34 +251,89 @@ typedef union {
     void *ptr;
 } AOTPointer;
 
-typedef struct AOTModuleInstance {
+typedef union {
+    uint64 u64;
+    uint32 u32[2];
+} MemBound;
+
+typedef struct AOTMemoryInstance {
     uint32 module_type;
+    /* shared memory flag */
+    bool is_shared;
 
     /* memory space info */
-    uint32 mem_cur_page_count;
-    uint32 mem_max_page_count;
+    uint32 num_bytes_per_page;
+    uint32 cur_page_count;
+    uint32 max_page_count;
     uint32 memory_data_size;
     AOTPointer memory_data;
     AOTPointer memory_data_end;
 
     /* heap space info */
-    int32 heap_base_offset;
-    uint32 heap_data_size;
     AOTPointer heap_data;
     AOTPointer heap_data_end;
     AOTPointer heap_handle;
 
+    /* boundary check constants for aot code */
+    MemBound mem_bound_check_1byte;
+    MemBound mem_bound_check_2bytes;
+    MemBound mem_bound_check_4bytes;
+    MemBound mem_bound_check_8bytes;
+    MemBound mem_bound_check_16bytes;
+} AOTMemoryInstance;
+
+typedef struct AOTTableInstance {
+    uint32 cur_size;
+    /*
+     * only grow in the range of [:max_size)
+     * if the table is growable, max_size equals to its declared maximum size
+     * otherwise, max_size equals to its declared minimum size
+     */
+    uint32 max_size;
+    /*
+     * +------------------------------+  <--- data
+     * | ref.func[] or ref.extern[]
+     * +------------------------------+
+     */
+    uint32 data[1];
+} AOTTableInstance;
+
+typedef struct AOTModuleInstance {
+    uint32 module_type;
+
+    /* memories */
+    uint32 memory_count;
+    AOTPointer memories;
+
     /* global and table info */
     uint32 global_data_size;
-    uint32 table_size;
+    /*
+     * the count of AOTTableInstance.
+     * it includes imported tables and local tables.
+     *
+     * TODO: for now we treate imported table like a local table
+     */
+    uint32 table_count;
+   /* points to global_data */
     AOTPointer global_data;
-    AOTPointer table_data;
+    /* points to AOTTableInstance[] */
+    AOTPointer tables;
 
     /* funciton pointer array */
     AOTPointer func_ptrs;
     /* function type indexes */
     AOTPointer func_type_indexes;
 
+    /* export info */
+    uint32 export_func_count;
+    uint32 export_global_count;
+    uint32 export_mem_count;
+    uint32 export_tab_count;
+    AOTPointer export_funcs;
+    AOTPointer export_globals;
+    AOTPointer export_memories;
+    AOTPointer export_tables;
+
     /* The exception buffer for current thread. */
     char cur_exception[128];
     /* The custom data that can be set/get by
@@ -196,32 +343,35 @@ typedef struct AOTModuleInstance {
     AOTPointer aot_module;
     /* WASI context */
     AOTPointer wasi_ctx;
+    /* function performance profiling info list */
+    AOTPointer func_perf_profilings;
 
-    /* total memory size: heap and linear memory */
-    uint32 total_mem_size;
-
-    /* boundary check constants for aot code */
-    uint32 mem_bound_check_1byte;
-    uint32 mem_bound_check_2bytes;
-    uint32 mem_bound_check_4bytes;
-    uint32 mem_bound_check_8bytes;
+    AOTPointer exec_env_singleton;
 
     /* others */
-    int32 temp_ret;
+    uint32 temp_ret;
     uint32 llvm_stack;
     uint32 default_wasm_stack_size;
 
     /* reserved */
-    uint32 reserved[12];
-
+    uint32 reserved[9];
+
+   /*
+    * +------------------------------+ <-- memories.ptr
+    * | #0 AOTMemoryInstance
+    * +------------------------------+ <-- global_data.ptr
+    * | global data
+    * +------------------------------+ <-- tables.ptr
+    * | AOTTableInstance[table_count]
+    * +------------------------------+
+    */
     union {
         uint64 _make_it_8_byte_aligned_;
+        AOTMemoryInstance memory_instances[1];
         uint8 bytes[1];
     } global_table_data;
 } AOTModuleInstance;
 
-typedef AOTExportFunc AOTFunctionInstance;
-
 /* Target info, read from ELF header of object file */
 typedef struct AOTTargetInfo {
     /* Binary type, elf32l/elf32b/elf64l/elf64b */
@@ -242,6 +392,24 @@ typedef struct AOTTargetInfo {
     char arch[16];
 } AOTTargetInfo;
 
+typedef struct AOTFuncPerfProfInfo
+{
+    /* total execution time */
+    uint64 total_exec_time;
+    /* total execution count */
+    uint32 total_exec_cnt;
+} AOTFuncPerfProfInfo;
+
+/* AOT auxiliary call stack */
+typedef struct AOTFrame {
+    struct AOTFrame *prev_frame;
+    uint32 func_index;
+#if WASM_ENABLE_PERF_PROFILING != 0
+    uint64 time_started;
+    AOTFuncPerfProfInfo *func_perf_prof_info;
+#endif
+} AOTFrame;
+
 /**
  * Load a AOT module from aot file buffer
  * @param buf the byte buffer which contains the AOT file data
@@ -295,6 +463,7 @@ aot_unload(AOTModule *module);
  * Instantiate a AOT module.
  *
  * @param module the AOT module to instantiate
+ * @param is_sub_inst the flag of sub instance
  * @param heap_size the default heap size of the module instance, a heap will
  *        be created besides the app memory space. Both wasm app and native
  *        function can allocate memory from the heap. If heap_size is 0, the
@@ -305,7 +474,7 @@ aot_unload(AOTModule *module);
  * @return return the instantiated AOT module instance, NULL if failed
  */
 AOTModuleInstance*
-aot_instantiate(AOTModule *module,
+aot_instantiate(AOTModule *module, bool is_sub_inst,
                 uint32 stack_size, uint32 heap_size,
                 char *error_buf, uint32 error_buf_size);
 
@@ -313,9 +482,10 @@ aot_instantiate(AOTModule *module,
  * Deinstantiate a AOT module instance, destroy the resources.
  *
  * @param module_inst the AOT module instance to destroy
+ * @param is_sub_inst the flag of sub instance
  */
 void
-aot_deinstantiate(AOTModuleInstance *module_inst);
+aot_deinstantiate(AOTModuleInstance *module_inst, bool is_sub_inst);
 
 /**
  * Lookup an exported function in the AOT module instance.
@@ -354,6 +524,10 @@ bool
 aot_create_exec_env_and_call_function(AOTModuleInstance *module_inst,
                                       AOTFunctionInstance *function,
                                       unsigned argc, uint32 argv[]);
+
+bool
+aot_create_exec_env_singleton(AOTModuleInstance *module_inst);
+
 /**
  * Set AOT module instance exception with exception string
  *
@@ -387,20 +561,24 @@ aot_get_exception(AOTModuleInstance *module_inst);
 void
 aot_clear_exception(AOTModuleInstance *module_inst);
 
-int32
+uint32
 aot_module_malloc(AOTModuleInstance *module_inst, uint32 size,
                   void **p_native_addr);
 
+uint32
+aot_module_realloc(AOTModuleInstance *module_inst, uint32 ptr,
+                   uint32 size, void **p_native_addr);
+
 void
-aot_module_free(AOTModuleInstance *module_inst, int32 ptr);
+aot_module_free(AOTModuleInstance *module_inst, uint32 ptr);
 
-int32
+uint32
 aot_module_dup_data(AOTModuleInstance *module_inst,
                     const char *src, uint32 size);
 
 bool
 aot_validate_app_addr(AOTModuleInstance *module_inst,
-                      int32 app_offset, uint32 size);
+                      uint32 app_offset, uint32 size);
 
 
 bool
@@ -408,16 +586,16 @@ aot_validate_native_addr(AOTModuleInstance *module_inst,
                          void *native_ptr, uint32 size);
 
 void *
-aot_addr_app_to_native(AOTModuleInstance *module_inst, int32 app_offset);
+aot_addr_app_to_native(AOTModuleInstance *module_inst, uint32 app_offset);
 
-int32
+uint32
 aot_addr_native_to_app(AOTModuleInstance *module_inst, void *native_ptr);
 
 bool
 aot_get_app_addr_range(AOTModuleInstance *module_inst,
-                       int32 app_offset,
-                       int32 *p_app_start_offset,
-                       int32 *p_app_end_offset);
+                       uint32 app_offset,
+                       uint32 *p_app_start_offset,
+                       uint32 *p_app_end_offset);
 
 bool
 aot_get_native_addr_range(AOTModuleInstance *module_inst,
@@ -450,13 +628,91 @@ aot_invoke_native(WASMExecEnv *exec_env, uint32 func_idx,
 
 bool
 aot_call_indirect(WASMExecEnv *exec_env,
-                  bool check_func_type, uint32 func_type_idx,
-                  uint32 table_elem_idx,
+                  uint32 tbl_idx, uint32 table_elem_idx,
                   uint32 argc, uint32 *argv);
 
 uint32
 aot_get_plt_table_size();
 
+void *
+aot_memmove(void *dest, const void *src, size_t n);
+
+void *
+aot_memset(void *s, int c, size_t n);
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+aot_memory_init(AOTModuleInstance *module_inst, uint32 seg_index,
+                uint32 offset, uint32 len, uint32 dst);
+
+bool
+aot_data_drop(AOTModuleInstance *module_inst, uint32 seg_index);
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+aot_set_aux_stack(WASMExecEnv *exec_env,
+                  uint32 start_offset, uint32 size);
+
+bool
+aot_get_aux_stack(WASMExecEnv *exec_env,
+                  uint32 *start_offset, uint32 *size);
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+bool
+aot_signal_init();
+
+void
+aot_signal_destroy();
+#endif
+
+void
+aot_get_module_mem_consumption(const AOTModule *module,
+                               WASMModuleMemConsumption *mem_conspn);
+
+void
+aot_get_module_inst_mem_consumption(const AOTModuleInstance *module_inst,
+                                    WASMModuleInstMemConsumption *mem_conspn);
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+aot_drop_table_seg(AOTModuleInstance *module_inst, uint32 tbl_seg_idx);
+
+void
+aot_table_init(AOTModuleInstance *module_inst,
+               uint32 tbl_idx, uint32 tbl_seg_idx,
+               uint32 length, uint32 src_offset, uint32 dst_offset);
+
+void
+aot_table_copy(AOTModuleInstance *module_inst,
+               uint32 src_tbl_idx, uint32 dst_tbl_idx,
+               uint32 length, uint32 src_offset, uint32 dst_offset);
+
+void
+aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx,
+               uint32 length, uint32 val, uint32 data_offset);
+
+uint32
+aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
+               uint32 inc_entries, uint32 init_val);
+#endif
+
+AOTTableInstance *
+aot_next_tbl_inst(const AOTTableInstance *tbl_inst);
+
+bool
+aot_alloc_frame(WASMExecEnv *exec_env, uint32 func_index);
+
+void
+aot_free_frame(WASMExecEnv *exec_env);
+
+void
+aot_dump_call_stack(WASMExecEnv *exec_env);
+
+void
+aot_dump_perf_profiling(const AOTModuleInstance *module_inst);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 174 - 25
core/iwasm/aot/arch/aot_reloc_aarch64.c

@@ -1,12 +1,36 @@
 /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
 #include "aot_reloc.h"
 
+#define R_AARCH64_MOVW_UABS_G0          263
+#define R_AARCH64_MOVW_UABS_G0_NC       264
+#define R_AARCH64_MOVW_UABS_G1          265
+#define R_AARCH64_MOVW_UABS_G1_NC       266
+#define R_AARCH64_MOVW_UABS_G2          267
+#define R_AARCH64_MOVW_UABS_G2_NC       268
+#define R_AARCH64_MOVW_UABS_G3          269
+
+#define R_AARCH64_MOVW_SABS_G0          270
+#define R_AARCH64_MOVW_SABS_G1          271
+#define R_AARCH64_MOVW_SABS_G2          272
+
+#define R_AARCH64_ADR_PREL_LO19         273
+#define R_AARCH64_ADR_PREL_LO21         274
 #define R_AARCH64_ADR_PREL_PG_HI21      275
+#define R_AARCH64_ADR_PREL_PG_HI21_NC   276
+
 #define R_AARCH64_ADD_ABS_LO12_NC       277
+
+#define R_AARCH64_LDST8_ABS_LO12_NC     278
+#define R_AARCH64_LDST16_ABS_LO12_NC    284
+#define R_AARCH64_LDST32_ABS_LO12_NC    285
+#define R_AARCH64_LDST64_ABS_LO12_NC    286
+#define R_AARCH64_LDST128_ABS_LO12_NC   299
+
+#define R_AARCH64_JUMP26                282
 #define R_AARCH64_CALL26                283
 
 static SymbolMap target_sym_map[] = {
@@ -27,28 +51,38 @@ get_target_symbol_map(uint32 *sym_num)
     return target_sym_map;
 }
 
+#define BUILD_TARGET_AARCH64_DEFAULT "aarch64v8"
 void
 get_current_target(char *target_buf, uint32 target_buf_size)
 {
-    char *build_target = BUILD_TARGET;
-    char *p = target_buf, *p_end;
-    snprintf(target_buf, target_buf_size, "%s", build_target);
-    p_end = p + strlen(target_buf);
-    while (p < p_end) {
-        if (*p >= 'A' && *p <= 'Z')
-            *p++ += 'a' - 'A';
+    const char * s =  BUILD_TARGET;
+    size_t s_size = sizeof(BUILD_TARGET);
+    char *d = target_buf;
+
+    /* Set to "aarch64v8" by default if sub version isn't specified */
+    if (strcmp(s, "AARCH64") == 0) {
+        s = BUILD_TARGET_AARCH64_DEFAULT;
+        s_size = sizeof(BUILD_TARGET_AARCH64_DEFAULT);
+    }
+    if(target_buf_size < s_size){
+        s_size = target_buf_size;
+    }
+    while (--s_size) {
+        if (*s >= 'A' && *s <= 'Z')
+            *d++ = *s++ + 'a' - 'A';
         else
-            p++;
+            *d++ = *s++ ;
     }
-    if (!strcmp(target_buf, "aarch64"))
-        snprintf(target_buf, target_buf_size, "aarch64v8");
+    /* Ensure the string is null byte ('\0') terminated */
+    *d = '\0';
 }
+#undef BUILD_TARGET_AARCH64_DEFAULT
 
 static uint32
 get_plt_item_size()
 {
-    /* 8*4 bytes instructions and 8 bytes symbol address */
-    return 40;
+    /* 6*4 bytes instructions and 8 bytes symbol address */
+    return 32;
 }
 
 void
@@ -57,13 +91,11 @@ init_plt_table(uint8 *plt)
     uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
     for (i = 0; i < num; i++) {
         uint32 *p = (uint32*)plt;
-        *p++ = 0xd10023ff; /* sub  sp, sp, #0x8 */
-        *p++ = 0xf90003fe; /* str  x30, [sp]    */
-        *p++ = 0x100000de; /* adr  x30, #24     */
+        *p++ = 0xf81f0ffe; /* str  x30, [sp, #-16]! */
+        *p++ = 0x100000be; /* adr  x30, #20  ;symbol addr is PC + 5 instructions below */
         *p++ = 0xf94003de; /* ldr  x30, [x30]   */
         *p++ = 0xd63f03c0; /* blr  x30          */
-        *p++ = 0xf94003fe; /* ldr  x30, [sp]    */
-        *p++ = 0x910023ff; /* add  sp, sp, #0x8 */
+        *p++ = 0xf84107fe; /* ldr  x30, [sp], #16  */
         *p++ = 0xd61f03c0; /* br   x30          */
         /* symbol addr */
         *(uint64*)p = (uint64)(uintptr_t)target_sym_map[i].symbol_addr;
@@ -163,7 +195,74 @@ apply_relocation(AOTModule *module,
             break;
         }
 
+        case R_AARCH64_MOVW_UABS_G0:
+        case R_AARCH64_MOVW_UABS_G0_NC:
+        case R_AARCH64_MOVW_UABS_G1:
+        case R_AARCH64_MOVW_UABS_G1_NC:
+        case R_AARCH64_MOVW_UABS_G2:
+        case R_AARCH64_MOVW_UABS_G2_NC:
+        case R_AARCH64_MOVW_UABS_G3:
+        {
+            void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
+            int64 X, A, initial_addend;
+            int32 insn, imm16;
+
+            CHECK_RELOC_OFFSET(sizeof(int32));
+
+            insn = *(int32*)P;
+            imm16 = (insn >> 5) & 0xFFFF;
+
+            SIGN_EXTEND_TO_INT64(imm16, 16, initial_addend);
+            A = initial_addend;
+            A += (int64)reloc_addend;
+
+            /* S + A */
+            X = (int64)S + A;
+
+            /* No need to check overflow for this reloction type */
+            switch (reloc_type) {
+                case R_AARCH64_MOVW_UABS_G0:
+                    if (X < 0 || X >= (1LL << 16))
+                        goto overflow_check_fail;
+                    break;
+                case R_AARCH64_MOVW_UABS_G1:
+                    if (X < 0 || X >= (1LL << 32))
+                        goto overflow_check_fail;
+                    break;
+                case R_AARCH64_MOVW_UABS_G2:
+                    if (X < 0 || X >= (1LL << 48))
+                        goto overflow_check_fail;
+                    break;
+                default:
+                    break;
+            }
+
+            /* write the imm16 back to bits[5:20] of instruction */
+            switch (reloc_type) {
+                case R_AARCH64_MOVW_UABS_G0:
+                case R_AARCH64_MOVW_UABS_G0_NC:
+                    *(int32*)P = (insn & 0xFFE0001F) | ((int32)((X & 0xFFFF) << 5));
+                    break;
+                case R_AARCH64_MOVW_UABS_G1:
+                case R_AARCH64_MOVW_UABS_G1_NC:
+                    *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 16) & 0xFFFF) << 5));
+                    break;
+                case R_AARCH64_MOVW_UABS_G2:
+                case R_AARCH64_MOVW_UABS_G2_NC:
+                    *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 32) & 0xFFFF) << 5));
+                    break;
+                case R_AARCH64_MOVW_UABS_G3:
+                    *(int32*)P = (insn & 0xFFE0001F) | ((int32)(((X >> 48) & 0xFFFF) << 5));
+                    break;
+                default:
+                    bh_assert(0);
+                    break;
+            }
+            break;
+        }
+
         case R_AARCH64_ADR_PREL_PG_HI21:
+        case R_AARCH64_ADR_PREL_PG_HI21_NC:
         {
             void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
             int64 X, A, initial_addend;
@@ -184,12 +283,9 @@ apply_relocation(AOTModule *module,
             X = Page((int64)S + A) - Page((int64)P);
 
             /* Check overflow: +-4GB */
-            if (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)) {
-                set_error_buf(error_buf, error_buf_size,
-                              "AOT module load failed: "
-                              "target address out of range.");
-                return false;
-            }
+            if (reloc_type == R_AARCH64_ADR_PREL_PG_HI21
+                && (X > ((int64)4 * BH_GB) || X < ((int64)-4 * BH_GB)))
+                goto overflow_check_fail;
 
             /* write the imm21 back to instruction */
             immhi19 = (int32)(((X >> 12) >> 2) & 0x7FFFF);
@@ -224,6 +320,54 @@ apply_relocation(AOTModule *module,
             break;
         }
 
+        case R_AARCH64_LDST8_ABS_LO12_NC:
+        case R_AARCH64_LDST16_ABS_LO12_NC:
+        case R_AARCH64_LDST32_ABS_LO12_NC:
+        case R_AARCH64_LDST64_ABS_LO12_NC:
+        case R_AARCH64_LDST128_ABS_LO12_NC:
+        {
+            void *S = symbol_addr, *P = (void*)(target_section_addr + reloc_offset);
+            int64 X, A, initial_addend;
+            int32 insn, imm12;
+
+            CHECK_RELOC_OFFSET(sizeof(int32));
+
+            insn = *(int32*)P;
+            imm12 = (insn >> 10) & 0xFFF;
+
+            SIGN_EXTEND_TO_INT64(imm12, 12, initial_addend);
+            A = initial_addend;
+            A += (int64)reloc_addend;
+
+            /* S + A */
+            X = (int64)S + A;
+
+            /* No need to check overflow for this reloction type */
+
+            /* write the imm12 back to instruction */
+            switch (reloc_type) {
+                case R_AARCH64_LDST8_ABS_LO12_NC:
+                    *(int32*)P = (insn & 0xFFC003FF) | ((int32)((X & 0xFFF) << 10));
+                    break;
+                case R_AARCH64_LDST16_ABS_LO12_NC:
+                    *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 1) << 10));
+                    break;
+                case R_AARCH64_LDST32_ABS_LO12_NC:
+                    *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 2) << 10));
+                    break;
+                case R_AARCH64_LDST64_ABS_LO12_NC:
+                    *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 3) << 10));
+                    break;
+                case R_AARCH64_LDST128_ABS_LO12_NC:
+                    *(int32*)P = (insn & 0xFFC003FF) | ((int32)(((X & 0xFFF) >> 4) << 10));
+                    break;
+                default:
+                    bh_assert(0);
+                    break;
+            }
+            break;
+        }
+
         default:
             if (error_buf != NULL)
                 snprintf(error_buf, error_buf_size,
@@ -234,5 +378,10 @@ apply_relocation(AOTModule *module,
     }
 
     return true;
-}
 
+overflow_check_fail:
+    set_error_buf(error_buf, error_buf_size,
+                  "AOT module load failed: "
+                  "target address out of range.");
+    return false;
+}

+ 21 - 11
core/iwasm/aot/arch/aot_reloc_arm.c

@@ -56,7 +56,7 @@ void __aeabi_f2iz();
 void __aeabi_f2d();
 
 static SymbolMap target_sym_map[] = {
-    REG_COMMON_SYMBOLS,
+    REG_COMMON_SYMBOLS
     /* compiler-rt symbols that come from compiler(e.g. gcc) */
     REG_SYM(__divdi3),
     REG_SYM(__udivdi3),
@@ -118,22 +118,32 @@ get_target_symbol_map(uint32 *sym_num)
     return target_sym_map;
 }
 
+#define BUILD_TARGET_ARM_DEFAULT "armv4"
 void
 get_current_target(char *target_buf, uint32 target_buf_size)
 {
-    char *build_target = BUILD_TARGET;
-    char *p = target_buf, *p_end;
-    snprintf(target_buf, target_buf_size, "%s", build_target);
-    p_end = p + strlen(target_buf);
-    while (p < p_end) {
-        if (*p >= 'A' && *p <= 'Z')
-            *p++ += 'a' - 'A';
+    const char * s =  BUILD_TARGET;
+    size_t s_size = sizeof(BUILD_TARGET);
+    char *d = target_buf;
+
+    /* Set to "armv4" by default if sub version isn't specified */
+    if (strcmp(s, "ARM") == 0) {
+        s = BUILD_TARGET_ARM_DEFAULT;
+        s_size = sizeof(BUILD_TARGET_ARM_DEFAULT);
+    }
+    if(target_buf_size < s_size){
+        s_size = target_buf_size;
+    }
+    while (--s_size) {
+        if (*s >= 'A' && *s <= 'Z')
+            *d++ = *s++ + 'a' - 'A';
         else
-            p++;
+            *d++ = *s++ ;
     }
-    if (!strcmp(target_buf, "arm"))
-        snprintf(target_buf, target_buf_size, "armv4");
+    /* Ensure the string is null byte ('\0') terminated */
+    *d = '\0';
 }
+#undef BUILD_TARGET_ARM_DEFAULT
 
 uint32
 get_plt_item_size()

+ 47 - 11
core/iwasm/aot/arch/aot_reloc_thumb.c

@@ -8,6 +8,19 @@
 #define R_ARM_THM_CALL  10  /* PC relative (Thumb BL and ARMv5 Thumb BLX). */
 #define R_ARM_THM_JMP24 30  /* B.W */
 
+void __ltdf2();
+void __adddf3();
+void __eqdf2();
+void __unorddf2();
+void __muldf3();
+void __subdf3();
+void __gedf2();
+void __ledf2();
+void __fixunsdfsi();
+void __floatunsidf();
+void __fixdfsi();
+void __nedf2();
+void __floatsidf();
 void __divdi3();
 void __udivdi3();
 void __moddi3();
@@ -55,8 +68,21 @@ void __aeabi_f2iz();
 void __aeabi_f2d();
 
 static SymbolMap target_sym_map[] = {
-    REG_COMMON_SYMBOLS,
+    REG_COMMON_SYMBOLS
     /* compiler-rt symbols that come from compiler(e.g. gcc) */
+    REG_SYM(__ltdf2),
+    REG_SYM(__adddf3),
+    REG_SYM(__eqdf2),
+    REG_SYM(__unorddf2),
+    REG_SYM(__muldf3),
+    REG_SYM(__subdf3),
+    REG_SYM(__gedf2),
+    REG_SYM(__ledf2),
+    REG_SYM(__fixunsdfsi),
+    REG_SYM(__floatunsidf),
+    REG_SYM(__fixdfsi),
+    REG_SYM(__nedf2),
+    REG_SYM(__floatsidf),
     REG_SYM(__divdi3),
     REG_SYM(__udivdi3),
     REG_SYM(__umoddi3),
@@ -117,22 +143,32 @@ get_target_symbol_map(uint32 *sym_num)
     return target_sym_map;
 }
 
+#define BUILD_TARGET_THUMB_V4T "thumbv4t"
 void
 get_current_target(char *target_buf, uint32 target_buf_size)
 {
-    char *build_target = BUILD_TARGET;
-    char *p = target_buf, *p_end;
-    snprintf(target_buf, target_buf_size, "%s", build_target);
-    p_end = p + strlen(target_buf);
-    while (p < p_end) {
-        if (*p >= 'A' && *p <= 'Z')
-            *p++ += 'a' - 'A';
+    const char * s =  BUILD_TARGET;
+    size_t s_size = sizeof(BUILD_TARGET);
+    char *d = target_buf;
+
+    /* Set to "thumbv4t" by default if sub version isn't specified */
+    if (strcmp(s, "THUMB") == 0) {
+        s = BUILD_TARGET_THUMB_V4T;
+        s_size = sizeof(BUILD_TARGET_THUMB_V4T);
+    }
+    if(target_buf_size < s_size){
+        s_size = target_buf_size;
+    }
+    while (--s_size) {
+        if (*s >= 'A' && *s <= 'Z')
+            *d++ = *s++ + 'a' - 'A';
         else
-            p++;
+            *d++ = *s++ ;
     }
-    if (!strcmp(target_buf, "thumb"))
-        snprintf(target_buf, target_buf_size, "thumbv4t");
+    /* Ensure the string is null byte ('\0') terminated */
+    *d = '\0';
 }
+#undef BUILD_TARGET_THUMB_V4T
 
 uint32
 get_plt_item_size()

+ 30 - 1
core/iwasm/aot/arch/aot_reloc_x86_32.c

@@ -8,13 +8,42 @@
 #define R_386_32        1   /* Direct 32 bit  */
 #define R_386_PC32      2   /* PC relative 32 bit */
 
+#if !defined(_WIN32) && !defined(_WIN32_)
 void __divdi3();
 void __udivdi3();
 void __moddi3();
 void __umoddi3();
+#else
+#pragma function (floor)
+#pragma function (ceil)
+
+static int64
+__divdi3(int64 a, int64 b)
+{
+    return a / b;
+}
+
+static uint64
+__udivdi3(uint64 a, uint64 b)
+{
+    return a / b;
+}
+
+static int64
+__moddi3(int64 a, int64 b)
+{
+    return a % b;
+}
+
+static uint64
+__umoddi3(uint64 a, uint64 b)
+{
+    return a % b;
+}
+#endif
 
 static SymbolMap target_sym_map[] = {
-    REG_COMMON_SYMBOLS,
+    REG_COMMON_SYMBOLS
     /* compiler-rt symbols that come from compiler(e.g. gcc) */
     REG_SYM(__divdi3),
     REG_SYM(__udivdi3),

+ 82 - 13
core/iwasm/aot/arch/aot_reloc_x86_64.c

@@ -5,16 +5,27 @@
 
 #include "aot_reloc.h"
 
-#define R_X86_64_64     1   /* Direct 64 bit  */
-#define R_X86_64_PC32   2   /* PC relative 32 bit signed */
-#define R_X86_64_PLT32  4   /* 32 bit PLT address */
-#define R_X86_64_32     10  /* Direct 32 bit zero extended */
-#define R_X86_64_32S    11  /* Direct 32 bit sign extended */
+#if !defined(BH_PLATFORM_WINDOWS)
+#define R_X86_64_64    1  /* Direct 64 bit  */
+#define R_X86_64_PC32  2  /* PC relative 32 bit signed */
+#define R_X86_64_PLT32 4  /* 32 bit PLT address */
+#define R_X86_64_32    10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S   11 /* Direct 32 bit sign extended */
+#else
+#ifndef IMAGE_REL_AMD64_ADDR64
+#define IMAGE_REL_AMD64_ADDR64 1 /* The 64-bit VA of the relocation target */
+#define IMAGE_REL_AMD64_ADDR32 2 /* The 32-bit VA of the relocation target */
+#define IMAGE_REL_AMD64_REL32  4 /* The 32-bit relative address from
+                                    the byte following the relocation*/
+#endif
+#endif
 
-void __divdi3();
-void __udivdi3();
-void __moddi3();
-void __umoddi3();
+#if defined(BH_PLATFORM_WINDOWS)
+#pragma function (floor)
+#pragma function (ceil)
+#pragma function (floorf)
+#pragma function (ceilf)
+#endif
 
 static SymbolMap target_sym_map[] = {
     REG_COMMON_SYMBOLS
@@ -50,15 +61,22 @@ get_plt_item_size()
 uint32
 get_plt_table_size()
 {
-    return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
+    uint32 size = get_plt_item_size()
+                  * (sizeof(target_sym_map) / sizeof(SymbolMap));
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    size += get_plt_item_size() + sizeof(AOTUnwindInfo);
+#endif
+    return size;
 }
 
 void
 init_plt_table(uint8 *plt)
 {
     uint32 i, num = sizeof(target_sym_map) / sizeof(SymbolMap);
+    uint8 *p;
+
     for (i = 0; i < num; i++) {
-        uint8 *p = plt;
+        p = plt;
         /* mov symbol_addr, rax */
         *p++ = 0x48;
         *p++ = 0xB8;
@@ -69,6 +87,18 @@ init_plt_table(uint8 *plt)
         *p++ = 0xE0;
         plt += get_plt_item_size();
     }
+
+#if defined(OS_ENABLE_HW_BOUND_CHECK) && defined(BH_PLATFORM_WINDOWS)
+    p = plt;
+    /* mov exception_handler, rax */
+    *p++ = 0x48;
+	*p++ = 0xB8;
+    *(uint64*)p = 0;/*(uint64)(uintptr_t)aot_exception_handler;*/
+    p += sizeof(uint64);
+    /* jmp rax */
+	*p++ = 0xFF;
+	*p++ = 0xE0;
+#endif
 }
 
 static bool
@@ -93,7 +123,11 @@ apply_relocation(AOTModule *module,
                  char *error_buf, uint32 error_buf_size)
 {
     switch (reloc_type) {
+#if !defined(BH_PLATFORM_WINDOWS)
         case R_X86_64_64:
+#else
+        case IMAGE_REL_AMD64_ADDR64:
+#endif
         {
             intptr_t value;
 
@@ -103,6 +137,29 @@ apply_relocation(AOTModule *module,
                 = (uint8*)symbol_addr + reloc_addend + value;   /* S + A */
             break;
         }
+#if defined(BH_PLATFORM_WINDOWS)
+        case IMAGE_REL_AMD64_ADDR32:
+        {
+            int32 value;
+            uintptr_t target_addr;
+
+            CHECK_RELOC_OFFSET(sizeof(void *));
+            value = *(int32*)(target_section_addr + (uint32)reloc_offset);
+            target_addr = (uintptr_t)symbol_addr + reloc_addend + value;
+            if ((int32)target_addr != target_addr) {
+                set_error_buf(
+                  error_buf, error_buf_size,
+                  "AOT module load failed: "
+                  "relocation truncated to fit IMAGE_REL_AMD64_ADDR32 failed. "
+                  "Try using wamrc with --size-level=1 option.");
+                return false;
+            }
+
+            *(int32 *)(target_section_addr + reloc_offset) = (int32)target_addr;
+            break;
+        }
+#endif
+#if !defined(BH_PLATFORM_WINDOWS)
         case R_X86_64_PC32:
         {
             intptr_t target_addr = (intptr_t)   /* S + A - P */
@@ -147,7 +204,12 @@ apply_relocation(AOTModule *module,
             *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr;
             break;
         }
+#endif
+#if !defined(BH_PLATFORM_WINDOWS)
         case R_X86_64_PLT32:
+#else
+        case IMAGE_REL_AMD64_REL32:
+#endif
         {
             uint8 *plt;
             intptr_t target_addr = 0;
@@ -167,14 +229,21 @@ apply_relocation(AOTModule *module,
                                - (target_section_addr + reloc_offset));
             }
 
+#if defined(BH_PLATFORM_WINDOWS)
+            target_addr -= sizeof(int32);
+#endif
             if ((int32)target_addr != target_addr) {
                 set_error_buf(error_buf, error_buf_size,
                               "AOT module load failed: "
-                              "relocation truncated to fit R_X86_64_PC32 failed. "
+                              "relocation truncated to fit "
+#if !defined(BH_PLATFORM_WINDOWS)
+                              "R_X86_64_PLT32 failed. "
+#else
+                              "IMAGE_REL_AMD64_32 failed."
+#endif
                               "Try using wamrc with --size-level=1 option.");
                 return false;
             }
-
             *(int32*)(target_section_addr + reloc_offset) = (int32)target_addr;
             break;
         }

+ 1 - 1
core/iwasm/aot/arch/aot_reloc_xtensa.c

@@ -22,7 +22,7 @@ void __modsi3();
 void __divdi3();
 
 static SymbolMap target_sym_map[] = {
-    REG_COMMON_SYMBOLS,
+    REG_COMMON_SYMBOLS
 
     /* API's for soft-float */
     /* TODO: only register these symbols when Floating-Point Coprocessor

+ 26 - 0
core/iwasm/common/SConscript

@@ -0,0 +1,26 @@
+#
+# Copyright (c) 2021, RT-Thread Development Team
+#
+# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+#
+
+from building import *
+import re
+
+Import('rtconfig')
+
+cwd     = GetCurrentDir()
+
+src = Glob('*.c')
+
+if rtconfig.ARCH == 'arm':
+    if re.match('^cortex-m.*', rtconfig.CPU):
+        src += ['arch/invokeNative_thumb.s']
+    elif re.match('^cortex-a.*', rtconfig.CPU):
+        src += ['arch/invokeNative_arm.s']
+
+CPPPATH = [cwd, cwd + '/../include']
+
+group = DefineGroup('iwasm_common', src, depend = [''], CPPPATH = CPPPATH)
+
+Return('group')

+ 10 - 5
core/iwasm/common/arch/invokeNative_aarch64.s

@@ -4,8 +4,14 @@
  */
         .text
         .align  2
-        .global invokeNative
-        .type   invokeNative,function
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
 
 /*
  * Arguments passed in:
@@ -15,7 +21,6 @@
  * x2 nstacks
  */
 
-invokeNative:
         sub     sp, sp, #0x30
         stp     x19, x20, [sp, #0x20] /* save the registers */
         stp     x21, x22, [sp, #0x10]
@@ -32,7 +37,7 @@ invokeNative:
         ldp     d4, d5, [x20], #16 /* d4 = argv[4], d5 = argv[5] */
         ldp     d6, d7, [x20], #16 /* d6 = argv[6], d7 = argv[7] */
 
-        /* Fill inteter registers */
+        /* Fill integer registers */
         ldp     x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
         ldp     x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
         ldp     x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
@@ -44,7 +49,7 @@ invokeNative:
         cmp     x21, #0
         beq     call_func
 
-        /* Fill all stack args: reserve stack space and fill ony by one */
+        /* Fill all stack args: reserve stack space and fill one by one */
         mov     x23, sp
         bic     sp,  x23, #15    /* Ensure stack is 16 bytes aligned */
         lsl     x23, x21, #3     /* x23 = nstacks * 8 */

+ 79 - 0
core/iwasm/common/arch/invokeNative_aarch64_simd.s

@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2020 Intel Corporation Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * x0 function ptr
+ * x1 argv
+ * x2 nstacks
+ */
+
+        sub     sp, sp, #0x30
+        stp     x19, x20, [sp, #0x20] /* save the registers */
+        stp     x21, x22, [sp, #0x10]
+        stp     x23, x24, [sp, #0x0]
+
+        mov     x19, x0          /* x19 = function ptr */
+        mov     x20, x1          /* x20 = argv */
+        mov     x21, x2          /* x21 = nstacks */
+        mov     x22, sp          /* save the sp before call function */
+
+        /* Fill in float-point registers */
+        ld1    {v0.2D, v1.2D, v2.2D, v3.2D}, [x20], #64 /* v0 = argv[0], v1 = argv[1], v2 = argv[2], v3 = argv[3]*/
+        ld1    {v4.2D, v5.2D, v6.2D, v7.2D}, [x20], #64 /* v4 = argv[4], v5 = argv[5], v6 = argv[6], v7 = argv[7]*/
+
+        /* Fill inteter registers */
+        ldp     x0, x1, [x20], #16 /* x0 = argv[8] = exec_env, x1 = argv[9] */
+        ldp     x2, x3, [x20], #16 /* x2 = argv[10], x3 = argv[11] */
+        ldp     x4, x5, [x20], #16 /* x4 = argv[12], x5 = argv[13] */
+        ldp     x6, x7, [x20], #16 /* x6 = argv[14], x7 = argv[15] */
+
+        /* Now x20 points to stack args */
+
+        /* Directly call the fucntion if no args in stack */
+        cmp     x21, #0
+        beq     call_func
+
+        /* Fill all stack args: reserve stack space and fill one by one */
+        mov     x23, sp
+        bic     sp,  x23, #15    /* Ensure stack is 16 bytes aligned */
+        lsl     x23, x21, #3     /* x23 = nstacks * 8 */
+        add     x23, x23, #15    /* x23 = (x23 + 15) & ~15 */
+        bic     x23, x23, #15
+        sub     sp, sp, x23      /* reserved stack space for stack arguments */
+        mov     x23, sp
+
+loop_stack_args:                 /* copy stack arguments to stack */
+        cmp     x21, #0
+        beq     call_func
+        ldr     x24, [x20], #8
+        str     x24, [x23], #8
+        sub     x21, x21, #1
+        b       loop_stack_args
+
+call_func:
+        mov     x20, x30         /* save x30(lr) */
+        blr     x19
+        mov     sp, x22          /* restore sp which is saved before calling fuction*/
+
+return:
+        mov     x30,  x20              /* restore x30(lr) */
+        ldp     x19, x20, [sp, #0x20]  /* restore the registers in stack */
+        ldp     x21, x22, [sp, #0x10]
+        ldp     x23, x24, [sp, #0x0]
+        add     sp, sp, #0x30          /* restore sp */
+        ret
+

+ 10 - 4
core/iwasm/common/arch/invokeNative_arm.s

@@ -4,8 +4,14 @@
  */
         .text
         .align  2
-        .global invokeNative
-        .type   invokeNative,function
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
 
 /*
  * Arguments passed in:
@@ -15,8 +21,8 @@
  * r2 argc
  */
 
-invokeNative:
         stmfd   sp!, {r4, r5, r6, r7, lr}
+        sub     sp, sp, #4      /* make sp 8 byte aligned */
         mov     ip, r0          /* ip = function ptr */
         mov     r4, r1          /* r4 = argv */
         mov     r5, r2          /* r5 = argc */
@@ -48,7 +54,6 @@ invokeNative:
         mov     r6, r5, lsl#2   /* r6 = argc * 4 */
         add     r6, r6, #7      /* r6 = (r6 + 7) & ~7 */
         bic     r6, r6, #7
-        add     r6, r6, #4      /* +4 because odd(5) registers are in stack */
         sub     sp, sp, r6      /* reserved stack space for left arguments */
         mov     r7, sp
 
@@ -65,5 +70,6 @@ call_func:
         add     sp, sp, r6       /* restore sp */
 
 return:
+        add     sp, sp, #4
         ldmfd   sp!, {r4, r5, r6, r7, lr}
         bx      lr

+ 9 - 4
core/iwasm/common/arch/invokeNative_arm_vfp.s

@@ -4,8 +4,14 @@
  */
         .text
         .align  2
-        .global invokeNative
-        .type   invokeNative,function
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
 
 /*
  * Arguments passed in:
@@ -15,7 +21,6 @@
  * r2 nstacks
  */
 
-invokeNative:
         stmfd   sp!, {r4, r5, r6, r7, lr}
         mov     ip, r0          /* ip = function ptr */
         mov     r4, r1          /* r4 = argv */
@@ -52,7 +57,7 @@ invokeNative:
         beq     call_func
 
 
-        /* Fill all stack args: reserve stack space and fill ony by one */
+        /* Fill all stack args: reserve stack space and fill one by one */
         add     r4, r4, #64     /* r4 points to stack args */
         bic     sp, sp, #7      /* Ensure stack is 8 byte aligned */
         mov     r7, r5, lsl#2   /* r7 = nstacks * 4 */

+ 62 - 0
core/iwasm/common/arch/invokeNative_em64.asm

@@ -0,0 +1,62 @@
+;
+; Copyright (C) 2019 Intel Corporation.  All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+_TEXT  SEGMENT
+    ; rcx func_ptr
+    ; rdx argv
+    ; r8 n_stacks
+
+invokeNative PROC
+    push rbp
+    mov rbp, rsp
+
+    mov r10, rcx    ; func_ptr
+    mov rax, rdx    ; argv
+    mov rcx, r8     ; n_stacks
+
+; fill all fp args
+    movsd xmm0, qword ptr [rax + 0]
+    movsd xmm1, qword ptr [rax + 8]
+    movsd xmm2, qword ptr [rax + 16]
+    movsd xmm3, qword ptr [rax + 24]
+
+; check for stack args
+    cmp rcx, 0
+    jz cycle_end
+
+    mov rdx, rsp
+    and rdx, 15
+    jz no_abort
+    int 3
+no_abort:
+    mov rdx, rcx
+    and rdx, 1
+    shl rdx, 3
+    sub rsp, rdx
+
+; store stack args
+    lea r9, qword ptr [rax + rcx * 8 + 56]
+    sub r9, rsp ; offset
+cycle:
+    push qword ptr [rsp + r9]
+    loop cycle
+
+cycle_end:
+    mov rcx, [rax + 32]
+    mov rdx, [rax + 40]
+    mov r8,  [rax + 48]
+    mov r9,  [rax + 56]
+
+    sub rsp, 32 ; shadow space
+
+    call r10
+    leave
+    ret
+
+invokeNative ENDP
+
+_TEXT   ENDS
+
+END

+ 62 - 0
core/iwasm/common/arch/invokeNative_em64_simd.asm

@@ -0,0 +1,62 @@
+;
+; Copyright (C) 2019 Intel Corporation.  All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+_TEXT  SEGMENT
+    ; rcx func_ptr
+    ; rdx argv
+    ; r8 n_stacks
+
+invokeNative PROC
+    push rbp
+    mov rbp, rsp
+
+    mov r10, rcx    ; func_ptr
+    mov rax, rdx    ; argv
+    mov rcx, r8     ; n_stacks
+
+; fill all fp args
+    movdqu xmm0, xmmword ptr [rax + 0]
+    movdqu xmm1, xmmword ptr [rax + 16]
+    movdqu xmm2, xmmword ptr [rax + 32]
+    movdqu xmm3, xmmword ptr [rax + 48]
+
+; check for stack args
+    cmp rcx, 0
+    jz cycle_end
+
+    mov rdx, rsp
+    and rdx, 15
+    jz no_abort
+    int 3
+no_abort:
+    mov rdx, rcx
+    and rdx, 1
+    shl rdx, 3
+    sub rsp, rdx
+
+; store stack args
+    lea r9, qword ptr [rax + rcx * 8 + 88]
+    sub r9, rsp ; offset
+cycle:
+    push qword ptr [rsp + r9]
+    loop cycle
+
+cycle_end:
+    mov rcx, [rax + 64]
+    mov rdx, [rax + 72]
+    mov r8,  [rax + 80]
+    mov r9,  [rax + 88]
+
+    sub rsp, 32 ; shadow space
+
+    call r10
+    leave
+    ret
+
+invokeNative ENDP
+
+_TEXT   ENDS
+
+END

+ 64 - 0
core/iwasm/common/arch/invokeNative_em64_simd.s

@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+    .text
+    .align 2
+#ifndef BH_PLATFORM_DARWIN
+.globl invokeNative
+    .type    invokeNative, @function
+invokeNative:
+#else
+.globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+    /*  rdi - function ptr */
+    /*  rsi - argv */
+    /*  rdx - n_stacks */
+
+    push %rbp
+    mov %rsp, %rbp
+
+    mov %rdx, %r10
+    mov %rsp, %r11      /* Check that stack is aligned on */
+    and $8, %r11        /* 16 bytes. This code may be removed */
+    je check_stack_succ /* when we are sure that compiler always */
+    int3                /* calls us with aligned stack */
+check_stack_succ:
+    mov %r10, %r11      /* Align stack on 16 bytes before pushing */
+    and $1, %r11        /* stack arguments in case we have an odd */
+    shl $3, %r11        /* number of stack arguments */
+    sub %r11, %rsp
+    /* store memory args */
+    movq %rdi, %r11     /* func ptr */
+    movq %r10, %rcx     /* counter */
+    lea 128+48-8(%rsi,%rcx,8), %r10
+    sub %rsp, %r10
+    cmpq $0, %rcx
+    je push_args_end
+push_args:
+    push 0(%rsp,%r10)
+    loop push_args
+push_args_end:
+    /* fill all fp args */
+    movdqu 0x00(%rsi), %xmm0
+    movdqu 0x10(%rsi), %xmm1
+    movdqu 0x20(%rsi), %xmm2
+    movdqu 0x30(%rsi), %xmm3
+    movdqu 0x40(%rsi), %xmm4
+    movdqu 0x50(%rsi), %xmm5
+    movdqu 0x60(%rsi), %xmm6
+    movdqu 0x70(%rsi), %xmm7
+
+    /* fill all int args */
+    movq 0x80(%rsi), %rdi
+    movq 0x90(%rsi), %rdx
+    movq 0x98(%rsi), %rcx
+    movq 0xa0(%rsi), %r8
+    movq 0xa8(%rsi), %r9
+    movq 0x88(%rsi), %rsi
+
+    call *%r11
+    leave
+    ret
+

+ 27 - 0
core/iwasm/common/arch/invokeNative_ia32.asm

@@ -0,0 +1,27 @@
+;
+; Copyright (C) 2019 Intel Corporation.  All rights reserved.
+; SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+;
+
+    .386
+    .model flat
+    .code
+_invokeNative PROC
+    push    ebp
+    mov     ebp,esp
+    mov     ecx, [ebp+16]          ; ecx = argc */
+    mov     edx, [ebp+12]          ; edx = argv */
+    test    ecx, ecx
+    jz      skip_push_args          ; if ecx == 0, skip pushing arguments */
+    lea     edx, [edx+ecx*4-4]   ; edx = edx + ecx * 4 - 4 */
+    sub     edx,esp              ; edx = edx - esp */
+loop_push:
+    push    [esp+edx]
+    loop    loop_push                      ; loop ecx counts */
+skip_push_args:
+    mov     edx, [ebp+8]           ; edx = func_ptr */
+    call    edx
+    leave
+    ret
+_invokeNative ENDP
+END

+ 95 - 0
core/iwasm/common/arch/invokeNative_riscv32_ilp32.s

@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+
+/*
+ * Arguments passed in:
+ *
+ * a0 function ptr
+ * a1 argv
+ * a2 nstacks
+ */
+
+/*
+ * sp (stack pointer)
+ *    |- sw to store 32-bit values from register to memory
+ *    |- lw to load from stack to register
+ * fp/s0 (frame pointer)
+ * a0-a7 (8 integer arguments)
+ *    |- sw to store
+ *    |- lw to load
+ * t0-t6 (temporaries regisgers)
+ *    |- caller saved
+ */
+
+        /* reserve space on stack to save return address and frame pointer */
+        addi      sp, sp, -8
+        sw        fp, 0(sp)            /* save frame pointer */
+        sw        ra, 4(sp)            /* save return address */
+
+        mv        fp, sp               /* set frame pointer to bottom of fixed frame */
+
+        /* save function ptr, argv & nstacks */
+        mv        t0, a0               /* t0 = function ptr */
+        mv        t1, a1               /* t1 = argv array address */
+        mv        t2, a2               /* t2 = nstack */
+
+        /* fill in a0-7 integer-registers */
+        lw        a0, 0(t1)            /* a0 = argv[0] */
+        lw        a1, 4(t1)            /* a1 = argv[1] */
+        lw        a2, 8(t1)            /* a2 = argv[2] */
+        lw        a3, 12(t1)           /* a3 = argv[3] */
+        lw        a4, 16(t1)           /* a4 = argv[4] */
+        lw        a5, 20(t1)           /* a5 = argv[5] */
+        lw        a6, 24(t1)           /* a6 = argv[6] */
+        lw        a7, 28(t1)           /* a7 = argv[7] */
+
+        addi      t1, t1, 32           /* t1 points to stack args */
+
+        /* directly call the function if no args in stack,
+           x0 always holds 0 */
+        beq       t2, x0, call_func
+
+        /* reserve enough stack space for function arguments */
+        sll       t3, t2, 2             /* shift left 2 bits. t3 = n_stacks * 4 */
+        sub       sp, sp, t3
+
+        /* make 16-byte aligned */
+        and       sp, sp, ~15
+
+        /* save sp in t4 register */
+        mv        t4, sp
+
+        /* copy left arguments from caller stack to own frame stack */
+loop_stack_args:
+        beq       t2, x0, call_func
+        lw        t5, 0(t1)             /* load stack argument, t5 = argv[i] */
+        sw        t5, 0(t4)             /* store t5 to reseved stack, sp[j] = t5 */
+        addi      t1, t1, 4             /* move to next stack argument */
+        addi      t4, t4, 4             /* move to next stack pointer */
+        addi      t2, t2, -1            /* decrease t2 every loop, nstacks = nstacks -1 */
+        j loop_stack_args
+
+call_func:
+        jalr      t0
+
+        /* restore registers pushed in stack or saved in another register */
+return:
+        mv        sp, fp                /* restore sp saved in fp before function call */
+        lw        fp, 0(sp)             /* load previous frame poniter to fp register */
+        lw        ra, 4(sp)             /* load previous return address to ra register */
+        addi      sp, sp, 8             /* pop frame, restore sp */
+        jr        ra
+

+ 104 - 0
core/iwasm/common/arch/invokeNative_riscv32_ilp32d.s

@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+
+/*
+ * Arguments passed in:
+ *
+ * a0 function ptr
+ * a1 argv
+ * a2 nstacks
+ */
+
+/*
+ * sp (stack pointer)
+ *    |- sw to store 32-bit values from register to memory
+ *    |- lw to load from stack to register
+ * fp/s0 (frame pointer)
+ * a0-a7 (8 integer arguments)
+ *    |- sw to store
+ *    |- lw to load
+ * t0-t6 (temporaries regisgers)
+ *    |- caller saved
+ */
+
+        /* reserve space on stack to save return address and frame pointer */
+        addi      sp, sp, -8
+        sw        fp, 0(sp)            /* save frame pointer */
+        sw        ra, 4(sp)            /* save return address */
+
+        mv        fp, sp               /* set frame pointer to bottom of fixed frame */
+
+        /* save function ptr, argv & nstacks */
+        mv        t0, a0               /* t0 = function ptr */
+        mv        t1, a1               /* t1 = argv array address */
+        mv        t2, a2               /* t2 = nstack */
+
+        /* fill in a0-7 integer-registers */
+        lw        a0, 0(t1)            /* a0 = argv[0] */
+        lw        a1, 4(t1)            /* a1 = argv[1] */
+        lw        a2, 8(t1)            /* a2 = argv[2] */
+        lw        a3, 12(t1)           /* a3 = argv[3] */
+        lw        a4, 16(t1)           /* a4 = argv[4] */
+        lw        a5, 20(t1)           /* a5 = argv[5] */
+        lw        a6, 24(t1)           /* a6 = argv[6] */
+        lw        a7, 28(t1)           /* a7 = argv[7] */
+
+        /* fill in fa0-7 float-registers*/
+        fld       fa0, 32(t1)          /* fa0 = argv[8] */
+        fld       fa1, 40(t1)          /* fa1 = argv[9] */
+        fld       fa2, 48(t1)          /* fa2 = argv[10] */
+        fld       fa3, 56(t1)          /* fa3 = argv[11] */
+        fld       fa4, 64(t1)          /* fa4 = argv[12] */
+        fld       fa5, 72(t1)          /* fa5 = argv[13] */
+        fld       fa6, 80(t1)          /* fa6 = argv[14] */
+        fld       fa7, 88(t1)          /* fa7 = argv[15] */
+
+        addi      t1, t1, 96           /* t1 points to stack args */
+
+        /* directly call the function if no args in stack,
+           x0 always holds 0 */
+        beq       t2, x0, call_func
+
+        /* reserve enough stack space for function arguments */
+        sll       t3, t2, 2             /* shift left 2 bits. t3 = n_stacks * 4 */
+        sub       sp, sp, t3
+
+        /* make 16-byte aligned */
+        and       sp, sp, ~15
+
+        /* save sp in t4 register */
+        mv        t4, sp
+
+        /* copy left arguments from caller stack to own frame stack */
+loop_stack_args:
+        beq       t2, x0, call_func
+        lw        t5, 0(t1)             /* load stack argument, t5 = argv[i] */
+        sw        t5, 0(t4)             /* store t5 to reseved stack, sp[j] = t5 */
+        addi      t1, t1, 4             /* move to next stack argument */
+        addi      t4, t4, 4             /* move to next stack pointer */
+        addi      t2, t2, -1            /* decrease t2 every loop, nstacks = nstacks -1 */
+        j loop_stack_args
+
+call_func:
+        jalr      t0
+
+        /* restore registers pushed in stack or saved in another register */
+return:
+        mv        sp, fp                /* restore sp saved in fp before function call */
+        lw        fp, 0(sp)             /* load previous frame poniter to fp register */
+        lw        ra, 4(sp)             /* load previous return address to ra register */
+        addi      sp, sp, 8             /* pop frame, restore sp */
+        jr        ra

+ 95 - 0
core/iwasm/common/arch/invokeNative_riscv64_lp64.s

@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+
+/*
+ * Arguments passed in:
+ *
+ * a0 function ptr
+ * a1 argv
+ * a2 nstacks
+ */
+
+/*
+ * sp (stack pointer)
+ *    |- sd to store 64-bit values from register to memory
+ *    |- ld to load from stack to register
+ * fp/s0 (frame pointer)
+ * a0-a7 (8 integer arguments)
+ *    |- sd to store
+ *    |- ld to load
+ * t0-t6 (temporaries regisgers)
+ *    |- caller saved
+ */
+
+        /* reserve space on stack to save return address and frame pointer */
+        addi      sp, sp, -16
+        sd        fp, 0(sp)            /* save frame pointer */
+        sd        ra, 8(sp)            /* save return address */
+
+        mv        fp, sp               /* set frame pointer to bottom of fixed frame */
+
+        /* save function ptr, argv & nstacks */
+        mv        t0, a0               /* t0 = function ptr */
+        mv        t1, a1               /* t1 = argv array address */
+        mv        t2, a2               /* t2 = nstack */
+
+        /* fill in a0-7 integer-registers*/
+        ld        a0, 0(t1)            /* a0 = argv[0] */
+        ld        a1, 8(t1)            /* a1 = argv[1] */
+        ld        a2, 16(t1)           /* a2 = argv[2] */
+        ld        a3, 24(t1)           /* a3 = argv[3] */
+        ld        a4, 32(t1)           /* a4 = argv[4] */
+        ld        a5, 40(t1)           /* a5 = argv[5] */
+        ld        a6, 48(t1)           /* a6 = argv[6] */
+        ld        a7, 56(t1)           /* a7 = argv[7] */
+
+        addi      t1, t1, 64           /* t1 points to stack args */
+
+        /* directly call the function if no args in stack,
+           x0 always holds 0 */
+        beq       t2, x0, call_func
+
+        /* reserve enough stack space for function arguments */
+        sll       t3, t2, 3             /* shift left 3 bits. t3 = n_stacks * 8 */
+        sub       sp, sp, t3
+
+        /* make 16-byte aligned */
+        and       sp, sp, ~(15LL)
+
+        /* save sp in t4 register */
+        mv        t4, sp
+
+        /* copy left arguments from caller stack to own frame stack */
+loop_stack_args:
+        beq       t2, x0, call_func
+        ld        t5, 0(t1)             /* load stack argument, t5 = argv[i] */
+        sd        t5, 0(t4)             /* store t5 to reseved stack, sp[j] = t5 */
+        addi      t1, t1, 8             /* move to next stack argument */
+        addi      t4, t4, 8             /* move to next stack pointer */
+        addi      t2, t2, -1            /* decrease t2 every loop, nstacks = nstacks -1 */
+        j loop_stack_args
+
+call_func:
+        jalr      t0
+
+        /* restore registers pushed in stack or saved in another register */
+return:
+        mv        sp, fp                /* restore sp saved in fp before function call */
+        ld        fp, 0(sp)             /* load previous frame poniter to fp register */
+        ld        ra, 8(sp)             /* load previous return address to ra register */
+        addi      sp, sp, 16            /* pop frame, restore sp */
+        jr        ra
+

+ 108 - 0
core/iwasm/common/arch/invokeNative_riscv64_lp64d.s

@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+        .text
+        .align  2
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
+
+/*
+ * Arguments passed in:
+ *
+ * a0 function ptr
+ * a1 argv
+ * a2 nstacks
+ */
+
+/*
+ * sp (stack pointer)
+ *    |- sd to store 64-bit values from register to memory
+ *    |- ld to load from stack to register
+ * fp/s0 (frame pointer)
+ * a0-a7 (8 integer arguments)
+ *    |- sd to store
+ *    |- ld to load
+ * fa0-a7 (8 float arguments)
+ *    |- fsd to store
+ *    |- fld to load
+ * t0-t6 (temporaries regisgers)
+ *    |- caller saved
+ */
+
+        /* reserve space on stack to save return address and frame pointer */
+        addi      sp, sp, -16
+        sd        fp, 0(sp)             /* save frame pointer */
+        sd        ra, 8(sp)             /* save return address */
+
+        mv        fp, sp                /* set frame pointer to bottom of fixed frame */
+
+        /* save function ptr, argv & nstacks */
+        mv        t0, a0                /* t0 = function ptr */
+        mv        t1, a1                /* t1 = argv array address */
+        mv        t2, a2                /* t2 = nstack */
+
+        /* fill in fa0-7 float-registers*/
+        fld       fa0, 0(t1)            /* fa0 = argv[0] */
+        fld       fa1, 8(t1)            /* fa1 = argv[1] */
+        fld       fa2, 16(t1)           /* fa2 = argv[2] */
+        fld       fa3, 24(t1)           /* fa3 = argv[3] */
+        fld       fa4, 32(t1)           /* fa4 = argv[4] */
+        fld       fa5, 40(t1)           /* fa5 = argv[5] */
+        fld       fa6, 48(t1)           /* fa6 = argv[6] */
+        fld       fa7, 56(t1)           /* fa7 = argv[7] */
+
+        /* fill in a0-7 integer-registers*/
+        ld        a0, 64(t1)            /* a0 = argv[8] */
+        ld        a1, 72(t1)            /* a1 = argv[9] */
+        ld        a2, 80(t1)            /* a2 = argv[10] */
+        ld        a3, 88(t1)            /* a3 = argv[11] */
+        ld        a4, 96(t1)            /* a4 = argv[12] */
+        ld        a5, 104(t1)           /* a5 = argv[13] */
+        ld        a6, 112(t1)           /* a6 = argv[14] */
+        ld        a7, 120(t1)           /* a7 = argv[15] */
+
+        addi      t1, t1, 128           /* t1 points to stack args */
+
+        /* directly call the function if no args in stack,
+           x0 always holds 0 */
+        beq       t2, x0, call_func
+
+        /* reserve enough stack space for function arguments */
+        sll       t3, t2, 3             /* shift left 3 bits. t3 = n_stacks * 8 */
+        sub       sp, sp, t3
+
+        /* make 16-byte aligned */
+        and       sp, sp, ~(15LL)
+
+        /* save sp in t4 register */
+        mv        t4, sp
+
+        /* copy left arguments from caller stack to own frame stack */
+loop_stack_args:
+        beq       t2, x0, call_func
+        ld        t5, 0(t1)             /* load stack argument, t5 = argv[i] */
+        sd        t5, 0(t4)             /* store t5 to reseved stack, sp[j] = t5 */
+        addi      t1, t1, 8             /* move to next stack argument */
+        addi      t4, t4, 8             /* move to next stack pointer */
+        addi      t2, t2, -1            /* decrease t2 every loop, nstacks = nstacks -1 */
+        j loop_stack_args
+
+call_func:
+        jalr      t0
+
+        /* restore registers pushed in stack or saved in another register */
+return:
+        mv        sp, fp                /* restore sp saved in fp before function call */
+        ld        fp, 0(sp)             /* load previous frame poniter to fp register */
+        ld        ra, 8(sp)             /* load previous return address to ra register */
+        addi      sp, sp, 16            /* pop frame, restore sp */
+        jr        ra
+
+

+ 8 - 3
core/iwasm/common/arch/invokeNative_thumb.s

@@ -4,8 +4,14 @@
  */
         .text
         .align  2
-        .global invokeNative
-        .type   invokeNative,function
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
 
 /*
  * Arguments passed in:
@@ -15,7 +21,6 @@
  * r2 argc
  */
 
-invokeNative:
         push    {r4, r5, r6, r7}
         push    {lr}
         mov     ip, r0          /* ip = function ptr */

+ 8 - 3
core/iwasm/common/arch/invokeNative_thumb_vfp.s

@@ -4,8 +4,14 @@
  */
         .text
         .align  2
-        .global invokeNative
-        .type   invokeNative,function
+#ifndef BH_PLATFORM_DARWIN
+        .globl invokeNative
+        .type  invokeNative, function
+invokeNative:
+#else
+        .globl _invokeNative
+_invokeNative:
+#endif /* end of BH_PLATFORM_DARWIN */
 
 /*
  * Arguments passed in:
@@ -15,7 +21,6 @@
  * r2 nstacks
  */
 
-invokeNative:
         push    {r4, r5, r6, r7}
         push    {lr}
         mov     ip, r0          /* ip = function ptr */

+ 46 - 12
core/iwasm/common/iwasm_common.cmake

@@ -10,10 +10,40 @@ add_definitions(-DBH_FREE=wasm_runtime_free)
 
 file (GLOB c_source_all ${IWASM_COMMON_DIR}/*.c)
 
-if (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
-  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
+if (WAMR_DISABLE_APP_ENTRY EQUAL 1)
+  list(REMOVE_ITEM c_source_all "${IWASM_COMMON_DIR}/wasm_application.c")
+endif ()
+
+if (WAMR_BUILD_INVOKE_NATIVE_GENERAL EQUAL 1)
+  # Use invokeNative C version instead of asm code version
+  # if WAMR_BUILD_INVOKE_NATIVE_GENERAL is explicitly set.
+  # Note:
+  #   the maximum number of native arguments is limited to 20,
+  #   and there are possible issues when passing arguments to
+  #   native function for some cpus, e.g. int64 and double arguments
+  #   in arm and mips need to be 8-bytes aligned, and some arguments
+  #   of x86_64 are passed by registers but not stack
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "X86_64" OR WAMR_BUILD_TARGET STREQUAL "AMD_64")
+  if (NOT WAMR_BUILD_SIMD EQUAL 1)
+    if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+      set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.asm)
+    else ()
+      set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64.s)
+    endif ()
+  else ()
+    if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+      set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.asm)
+    else()
+      set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_em64_simd.s)
+    endif()
+  endif ()
 elseif (WAMR_BUILD_TARGET STREQUAL "X86_32")
-  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
+  if (WAMR_BUILD_PLATFORM STREQUAL "windows")
+    set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.asm)
+  else ()
+    set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_ia32.s)
+  endif ()
 elseif (WAMR_BUILD_TARGET MATCHES "ARM.*")
   if (WAMR_BUILD_TARGET MATCHES "ARM.*_VFP")
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_arm_vfp.s)
@@ -27,19 +57,23 @@ elseif (WAMR_BUILD_TARGET MATCHES "THUMB.*")
     set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_thumb.s)
   endif ()
 elseif (WAMR_BUILD_TARGET MATCHES "AARCH64.*")
-  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
+  if (NOT WAMR_BUILD_SIMD EQUAL 1)
+    set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64.s)
+  else()
+    set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_aarch64_simd.s)
+  endif()
 elseif (WAMR_BUILD_TARGET STREQUAL "MIPS")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_mips.s)
 elseif (WAMR_BUILD_TARGET STREQUAL "XTENSA")
   set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_xtensa.s)
-elseif (WAMR_BUILD_TARGET STREQUAL "GENERAL")
-  # Use invokeNative_general.c instead of assembly code,
-  # but the maximum number of native arguments is limited to 20,
-  # and there are possible issues when passing arguments to
-  # native function for some cpus, e.g. int64 and double arguments
-  # in arm and mips need to be 8-bytes aligned, and some arguments
-  # of x86_64 are passed by registers but not stack
-  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_general.c)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64" OR WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64D")
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64d.s)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV64_LP64")
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv64_lp64.s)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32" OR WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32D")
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32d.s)
+elseif (WAMR_BUILD_TARGET STREQUAL "RISCV32_ILP32")
+  set (source_all ${c_source_all} ${IWASM_COMMON_DIR}/arch/invokeNative_riscv32_ilp32.s)
 else ()
   message (FATAL_ERROR "Build target isn't set")
 endif ()

+ 676 - 0
core/iwasm/common/wasm_application.c

@@ -0,0 +1,676 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_platform.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+static void
+set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
+{
+    if (error_buf != NULL)
+        snprintf(error_buf, error_buf_size, "%s", string);
+}
+
+static void *
+runtime_malloc(uint64 size, WASMModuleInstanceCommon *module_inst,
+               char *error_buf, uint32 error_buf_size)
+{
+    void *mem;
+
+    if (size >= UINT32_MAX
+        || !(mem = wasm_runtime_malloc((uint32)size))) {
+        if (module_inst != NULL) {
+            wasm_runtime_set_exception(module_inst,
+                                       "allocate memory failed");
+        }
+        else if (error_buf != NULL) {
+            set_error_buf(error_buf, error_buf_size,
+                          "allocate memory failed");
+        }
+        return NULL;
+    }
+
+    memset(mem, 0, (uint32)size);
+    return mem;
+}
+
+static union {
+    int a;
+    char b;
+} __ue = { .a = 1 };
+
+#define is_little_endian() (__ue.b == 1)
+
+/**
+ * Implementation of wasm_application_execute_main()
+ */
+
+static WASMFunctionInstanceCommon*
+resolve_function(const WASMModuleInstanceCommon *module_inst,
+                 const char *name);
+
+static bool
+check_main_func_type(const WASMType *type)
+{
+    if (!(type->param_count == 0 || type->param_count == 2)
+        ||type->result_count > 1) {
+        LOG_ERROR("WASM execute application failed: invalid main function type.\n");
+        return false;
+    }
+
+    if (type->param_count == 2
+        && !(type->types[0] == VALUE_TYPE_I32
+        && type->types[1] == VALUE_TYPE_I32)) {
+        LOG_ERROR("WASM execute application failed: invalid main function type.\n");
+        return false;
+    }
+
+    if (type->result_count
+        && type->types[type->param_count] != VALUE_TYPE_I32) {
+        LOG_ERROR("WASM execute application failed: invalid main function type.\n");
+        return false;
+    }
+
+    return true;
+}
+
+bool
+wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
+                              int32 argc, char *argv[])
+{
+    WASMFunctionInstanceCommon *func;
+    WASMType *func_type = NULL;
+    uint32 argc1 = 0, argv1[2] = { 0 };
+    uint32 total_argv_size = 0;
+    uint64 total_size;
+    uint32 argv_buf_offset = 0;
+    int32 i;
+    char *argv_buf, *p, *p_end;
+    uint32 *argv_offsets, module_type;
+    bool ret, is_import_func = true;
+
+#if WASM_ENABLE_LIBC_WASI != 0
+    if (wasm_runtime_is_wasi_mode(module_inst)) {
+        /* In wasi mode, we should call function named "_start"
+           which initializes the wasi envrionment and then calls
+           the actual main function. Directly call main function
+           may cause exception thrown. */
+        if ((func = wasm_runtime_lookup_wasi_start_function(module_inst)))
+            return wasm_runtime_create_exec_env_and_call_wasm(
+                                            module_inst, func, 0, NULL);
+        /* if no start function is found, we execute
+           the main function as normal */
+    }
+#endif /* end of WASM_ENABLE_LIBC_WASI */
+
+    if (!(func = resolve_function(module_inst, "main"))
+        && !(func = resolve_function(module_inst, "__main_argc_argv"))
+        && !(func = resolve_function(module_inst, "_main"))) {
+        wasm_runtime_set_exception(module_inst,
+                                   "lookup main function failed");
+        return false;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        is_import_func = ((WASMFunctionInstance*)func)->is_import_func;
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        is_import_func = ((AOTFunctionInstance*)func)->is_import_func;
+    }
+#endif
+
+    if (is_import_func) {
+        wasm_runtime_set_exception(module_inst,
+                                   "lookup main function failed");
+        return false;
+    }
+
+    module_type = module_inst->module_type;
+    func_type = wasm_runtime_get_function_type(func, module_type);
+
+    if (!func_type) {
+        LOG_ERROR("invalid module instance type");
+        return false;
+    }
+
+    if (!check_main_func_type(func_type)) {
+        wasm_runtime_set_exception(module_inst,
+                                   "invalid function type of main function");
+        return false;
+    }
+
+    if (func_type->param_count) {
+        for (i = 0; i < argc; i++)
+            total_argv_size += (uint32)(strlen(argv[i]) + 1);
+        total_argv_size = align_uint(total_argv_size, 4);
+
+        total_size = (uint64)total_argv_size + sizeof(int32) * (uint64)argc;
+
+        if (total_size >= UINT32_MAX
+            || !(argv_buf_offset =
+                    wasm_runtime_module_malloc(module_inst, (uint32)total_size,
+                                               (void**)&argv_buf))) {
+            wasm_runtime_set_exception(module_inst,
+                                       "allocate memory failed");
+            return false;
+        }
+
+        p = argv_buf;
+        argv_offsets = (uint32*)(p + total_argv_size);
+        p_end = p + total_size;
+
+        for (i = 0; i < argc; i++) {
+            bh_memcpy_s(p, (uint32)(p_end - p), argv[i], (uint32)(strlen(argv[i]) + 1));
+            argv_offsets[i] = argv_buf_offset + (uint32)(p - argv_buf);
+            p += strlen(argv[i]) + 1;
+        }
+
+        argc1 = 2;
+        argv1[0] = (uint32)argc;
+        argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
+    }
+
+    ret = wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
+                                                     argc1, argv1);
+    if (ret && func_type->result_count > 0 && argc > 0 && argv)
+        /* copy the return value */
+        *(int*)argv = (int)argv1[0];
+
+    if (argv_buf_offset)
+        wasm_runtime_module_free(module_inst, argv_buf_offset);
+    return ret;
+}
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+static WASMModuleInstance *
+get_sub_module_inst(const WASMModuleInstance *parent_module_inst,
+                    const char *sub_module_name)
+{
+    WASMSubModInstNode *node =
+      bh_list_first_elem(parent_module_inst->sub_module_inst_list);
+
+    while (node && strcmp(node->module_name, sub_module_name)) {
+        node = bh_list_elem_next(node);
+    }
+    return node ? node->module_inst : NULL;
+}
+
+static bool
+parse_function_name(char *orig_function_name, char **p_module_name,
+                    char **p_function_name)
+{
+    if (orig_function_name[0] != '$') {
+        *p_module_name = NULL;
+        *p_function_name = orig_function_name;
+        return true;
+    }
+
+    /**
+     * $module_name$function_name\0
+     *  ===>
+     * module_name\0function_name\0
+     *  ===>
+     * module_name
+     * function_name
+     */
+    char *p1 = orig_function_name;
+    char *p2 = strchr(p1 + 1, '$');
+    if (!p2) {
+        LOG_DEBUG("can not parse the incoming function name");
+        return false;
+    }
+
+    *p_module_name = p1 + 1;
+    *p2 = '\0';
+    *p_function_name = p2 + 1;
+    return strlen(*p_module_name) && strlen(*p_function_name);
+}
+#endif
+
+/**
+ * Implementation of wasm_application_execute_func()
+ */
+
+static WASMFunctionInstanceCommon*
+resolve_function(const WASMModuleInstanceCommon *module_inst,
+                 const char *name)
+{
+    uint32 i = 0;
+    WASMFunctionInstanceCommon *ret = NULL;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    WASMModuleInstance *sub_module_inst = NULL;
+    char *orig_name = NULL;
+    char *sub_module_name = NULL;
+    char *function_name = NULL;
+    uint32 length = (uint32)(strlen(name) + 1);
+
+    orig_name = runtime_malloc(sizeof(char) * length, NULL, NULL, 0);
+    if (!orig_name) {
+        return NULL;
+    }
+
+    strncpy(orig_name, name, length);
+
+    if (!parse_function_name(orig_name, &sub_module_name, &function_name)) {
+        goto LEAVE;
+    }
+
+    LOG_DEBUG("%s -> %s and %s", name, sub_module_name, function_name);
+
+    if (sub_module_name) {
+        sub_module_inst = get_sub_module_inst(
+          (WASMModuleInstance *)module_inst, sub_module_name);
+        if (!sub_module_inst) {
+            LOG_DEBUG("can not find a sub module named %s", sub_module_name);
+            goto LEAVE;
+        }
+    }
+#else
+    const char *function_name = name;
+#endif
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMModuleInstance *wasm_inst = (WASMModuleInstance*)module_inst;
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+        wasm_inst = sub_module_inst ? sub_module_inst : wasm_inst;
+#endif /* WASM_ENABLE_MULTI_MODULE */
+
+        for (i = 0; i < wasm_inst->export_func_count; i++) {
+           if (!strcmp(wasm_inst->export_functions[i].name, function_name)) {
+                ret = wasm_inst->export_functions[i].function;
+                break;
+           }
+        }
+    }
+#endif /* WASM_ENABLE_INTERP */
+
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *aot_inst = (AOTModuleInstance*)module_inst;
+        AOTFunctionInstance *export_funcs = (AOTFunctionInstance *)
+                                            aot_inst->export_funcs.ptr;
+        for (i = 0; i < aot_inst->export_func_count; i++) {
+            if (!strcmp(export_funcs[i].func_name, function_name)) {
+                ret = &export_funcs[i];
+                break;
+            }
+        }
+    }
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+LEAVE:
+    wasm_runtime_free(orig_name);
+#endif
+    return ret;
+}
+
+union ieee754_float {
+    float f;
+
+    /* This is the IEEE 754 single-precision format.  */
+    union {
+        struct {
+            unsigned int negative:1;
+            unsigned int exponent:8;
+            unsigned int mantissa:23;
+        } ieee_big_endian;
+        struct {
+            unsigned int mantissa:23;
+            unsigned int exponent:8;
+            unsigned int negative:1;
+        } ieee_little_endian;
+    } ieee;
+};
+
+union ieee754_double {
+    double d;
+
+    /* This is the IEEE 754 double-precision format.  */
+    union {
+        struct {
+            unsigned int negative:1;
+            unsigned int exponent:11;
+            /* Together these comprise the mantissa.  */
+            unsigned int mantissa0:20;
+            unsigned int mantissa1:32;
+        } ieee_big_endian;
+
+        struct {
+            /* Together these comprise the mantissa.  */
+            unsigned int mantissa1:32;
+            unsigned int mantissa0:20;
+            unsigned int exponent:11;
+            unsigned int negative:1;
+        } ieee_little_endian;
+    } ieee;
+};
+
+bool
+wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
+                              const char *name, int32 argc, char *argv[])
+{
+    WASMFunctionInstanceCommon *func;
+    WASMType *type = NULL;
+    uint32 argc1, *argv1 = NULL, cell_num = 0, j, k = 0;
+    int32 i, p, module_type;
+    uint64 total_size;
+    const char *exception;
+    char buf[128];
+
+    bh_assert(argc >= 0);
+    LOG_DEBUG("call a function \"%s\" with %d arguments", name, argc);
+    func = resolve_function(module_inst, name);
+
+    if (!func) {
+        snprintf(buf, sizeof(buf), "lookup function %s failed", name);
+        wasm_runtime_set_exception(module_inst, buf);
+        goto fail;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMFunctionInstance *wasm_func = (WASMFunctionInstance*)func;
+        if (wasm_func->is_import_func
+#if WASM_ENABLE_MULTI_MODULE != 0
+            && !wasm_func->import_func_inst
+#endif
+        ) {
+            snprintf(buf, sizeof(buf), "lookup function %s failed", name);
+            wasm_runtime_set_exception(module_inst, buf);
+            goto fail;
+        }
+    }
+#endif
+
+    module_type = module_inst->module_type;
+    type = wasm_runtime_get_function_type(func, module_type);
+
+    if (!type) {
+        LOG_ERROR("invalid module instance type");
+        return false;
+    }
+
+    if (type->param_count != (uint32)argc) {
+        wasm_runtime_set_exception(module_inst,
+                                   "invalid input argument count");
+        goto fail;
+    }
+
+    argc1 = type->param_cell_num;
+    cell_num = (argc1 > type->ret_cell_num) ? argc1 : type->ret_cell_num;
+
+    total_size = sizeof(uint32) * (uint64)(cell_num > 2 ? cell_num : 2);
+    if ((!(argv1 = runtime_malloc((uint32)total_size, module_inst,
+                                  NULL, 0)))) {
+        goto fail;
+    }
+
+    /* Parse arguments */
+    for (i = 0, p = 0; i < argc; i++) {
+        char *endptr = NULL;
+        bh_assert(argv[i] != NULL);
+        if (argv[i][0] == '\0') {
+            snprintf(buf, sizeof(buf), "invalid input argument %d", i);
+            wasm_runtime_set_exception(module_inst, buf);
+            goto fail;
+        }
+        switch (type->types[i]) {
+            case VALUE_TYPE_I32:
+                argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
+                break;
+            case VALUE_TYPE_I64:
+            {
+                union { uint64 val; uint32 parts[2]; } u;
+                u.val = strtoull(argv[i], &endptr, 0);
+                argv1[p++] = u.parts[0];
+                argv1[p++] = u.parts[1];
+                break;
+            }
+            case VALUE_TYPE_F32:
+            {
+                float32 f32 = strtof(argv[i], &endptr);
+                if (isnan(f32)) {
+                    if (argv[i][0] == '-') {
+                        union ieee754_float u;
+                        u.f = f32;
+                        if (is_little_endian())
+                            u.ieee.ieee_little_endian.negative = 1;
+                        else
+                            u.ieee.ieee_big_endian.negative = 1;
+                        memcpy(&f32, &u.f, sizeof(float));
+                    }
+                    if (endptr[0] == ':') {
+                        uint32 sig;
+                        union ieee754_float u;
+                        sig = (uint32)strtoul(endptr + 1, &endptr, 0);
+                        u.f = f32;
+                        if (is_little_endian())
+                            u.ieee.ieee_little_endian.mantissa = sig;
+                        else
+                            u.ieee.ieee_big_endian.mantissa = sig;
+                        memcpy(&f32, &u.f, sizeof(float));
+                    }
+                }
+                memcpy(&argv1[p++], &f32, sizeof(float));
+                break;
+            }
+            case VALUE_TYPE_F64:
+            {
+                union { float64 val; uint32 parts[2]; } u;
+                u.val = strtod(argv[i], &endptr);
+                if (isnan(u.val)) {
+                    if (argv[i][0] == '-') {
+                        union ieee754_double ud;
+                        ud.d = u.val;
+                        if (is_little_endian())
+                            ud.ieee.ieee_little_endian.negative = 1;
+                        else
+                            ud.ieee.ieee_big_endian.negative = 1;
+                        memcpy(&u.val, &ud.d, sizeof(double));
+                    }
+                    if (endptr[0] == ':') {
+                        uint64 sig;
+                        union ieee754_double ud;
+                        sig = strtoull(endptr + 1, &endptr, 0);
+                        ud.d = u.val;
+                        if (is_little_endian()) {
+                            ud.ieee.ieee_little_endian.mantissa0 = sig >> 32;
+                            ud.ieee.ieee_little_endian.mantissa1 = (uint32)sig;
+                        }
+                        else {
+                            ud.ieee.ieee_big_endian.mantissa0 = sig >> 32;
+                            ud.ieee.ieee_big_endian.mantissa1 = (uint32)sig;
+                        }
+                        memcpy(&u.val, &ud.d, sizeof(double));
+                    }
+                }
+                argv1[p++] = u.parts[0];
+                argv1[p++] = u.parts[1];
+                break;
+            }
+#if WASM_ENABLE_SIMD != 0
+            case VALUE_TYPE_V128:
+            {
+                /* it likes 0x123\0x234 or 123\234 */
+                /* retrive first i64 */
+                *(uint64*)(argv1 + p) = strtoull(argv[i], &endptr, 0);
+                /* skip \ */
+                endptr++;
+                /* retrive second i64 */
+                *(uint64*)(argv1 + p + 2) = strtoull(endptr, &endptr, 0);
+                p += 4;
+                break;
+            }
+#endif /* WASM_ENABLE_SIMD != 0 */
+#if WASM_ENABLE_REF_TYPES != 0
+            case VALUE_TYPE_FUNCREF:
+            {
+                if (strncmp(argv[i], "null", 4) == 0
+                    || strncmp(argv[i], "NULL", 4) == 0) {
+                    argv1[p++] = NULL_REF;
+                }
+                else {
+                    argv1[p++] = (uint32)strtoul(argv[i], &endptr, 0);
+                }
+                break;
+            }
+            case VALUE_TYPE_EXTERNREF:
+            {
+                if (strncmp(argv[i], "null", 4) == 0
+                    || strncmp(argv[i], "NULL", 4) == 0) {
+                    argv1[p++] = NULL_REF;
+                }
+                else {
+                    uint64 val = strtoull(argv[i], &endptr, 0);
+                    void *extern_obj = (void *)(uintptr_t)val;
+                    uint32 externref_idx;
+
+                    if (!wasm_externref_obj2ref(module_inst, extern_obj,
+                                                &externref_idx)) {
+                        wasm_runtime_set_exception(
+                          module_inst, "map extern object to ref failed");
+                        goto fail;
+                    }
+                    argv1[p++] = externref_idx;
+                }
+                break;
+            }
+#endif /* WASM_ENABLE_REF_TYPES */
+            default:
+                bh_assert(0);
+                break;
+        }
+        if (endptr && *endptr != '\0' && *endptr != '_') {
+            snprintf(buf, sizeof(buf), "invalid input argument %d: %s",
+                     i, argv[i]);
+            wasm_runtime_set_exception(module_inst, buf);
+            goto fail;
+        }
+    }
+    bh_assert(p == (int32)argc1);
+
+    wasm_runtime_set_exception(module_inst, NULL);
+    if (!wasm_runtime_create_exec_env_and_call_wasm(module_inst, func,
+                                                    argc1, argv1)) {
+        goto fail;
+    }
+
+    /* print return value */
+    for (j = 0; j < type->result_count; j++) {
+        switch (type->types[type->param_count + j]) {
+            case VALUE_TYPE_I32:
+            {
+                os_printf("0x%x:i32", argv1[k]);
+                k++;
+                break;
+            }
+            case VALUE_TYPE_I64:
+            {
+                union { uint64 val; uint32 parts[2]; } u;
+                u.parts[0] = argv1[k];
+                u.parts[1] = argv1[k + 1];
+                k += 2;
+#ifdef PRIx64
+                os_printf("0x%"PRIx64":i64", u.val);
+#else
+                char buf[16];
+                if (sizeof(long) == 4)
+                    snprintf(buf, sizeof(buf), "%s", "0x%llx:i64");
+                else
+                    snprintf(buf, sizeof(buf), "%s", "0x%lx:i64");
+                os_printf(buf, u.val);
+#endif
+                break;
+            }
+            case VALUE_TYPE_F32:
+            {
+                os_printf("%.7g:f32", *(float32*)(argv1 + k));
+                k++;
+                break;
+            }
+            case VALUE_TYPE_F64:
+            {
+                union { float64 val; uint32 parts[2]; } u;
+                u.parts[0] = argv1[k];
+                u.parts[1] = argv1[k + 1];
+                k += 2;
+                os_printf("%.7g:f64", u.val);
+                break;
+            }
+#if WASM_ENABLE_REF_TYPES
+            case VALUE_TYPE_FUNCREF:
+            {
+                if (argv1[k] != NULL_REF)
+                    os_printf("%u:ref.func", argv1[k]);
+                else
+                    os_printf("func:ref.null");
+                k++;
+                break;
+            }
+            case VALUE_TYPE_EXTERNREF:
+            {
+                if (argv1[k] != NULL_REF) {
+                    void *extern_obj = NULL;
+                    bool ret = wasm_externref_ref2obj(argv1[k], &extern_obj);
+                    bh_assert(ret);
+                    (void)ret;
+                    os_printf("%p:ref.extern", extern_obj);
+                }
+                else
+                    os_printf("extern:ref.null");
+                k++;
+                break;
+            }
+#endif
+#if WASM_ENABLE_SIMD != 0
+            case VALUE_TYPE_V128:
+            {
+                uint64 *v = (uint64*)(argv1 + k);
+#if defined(PRIx64)
+                os_printf("<0x%016"PRIx64" 0x%016"PRIx64">:v128", *v, *(v + 1));
+#else
+                if (4 == sizeof(long)) {
+                    os_printf("<0x%016llx 0x%016llx>:v128", *v, *(v + 1));
+                }
+                else {
+                    os_printf("<0x%016lx 0x%016lx>:v128", *v, *(v + 1));
+                }
+#endif /* PRIx64 */
+                k += 4;
+                break;
+            }
+#endif /*  WASM_ENABLE_SIMD != 0 */
+            default:
+                bh_assert(0);
+                break;
+        }
+        if (j < (uint32)(type->result_count - 1))
+            os_printf(",");
+    }
+    os_printf("\n");
+
+    wasm_runtime_free(argv1);
+    return true;
+
+fail:
+    if (argv1)
+        wasm_runtime_free(argv1);
+
+    exception = wasm_runtime_get_exception(module_inst);
+    bh_assert(exception);
+    os_printf("%s\n", exception);
+    return false;
+}

+ 3784 - 0
core/iwasm/common/wasm_c_api.c

@@ -0,0 +1,3784 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "wasm_c_api_internal.h"
+#include "wasm_memory.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#define ASSERT_NOT_IMPLEMENTED() bh_assert(!"not implemented")
+
+typedef struct wasm_module_ex_t wasm_module_ex_t;
+
+static void
+wasm_module_delete_internal(wasm_module_t *);
+
+static void
+wasm_instance_delete_internal(wasm_instance_t *);
+
+/* temporarily put stubs here */
+static wasm_store_t *
+wasm_store_copy(const wasm_store_t *src)
+{
+    (void)src;
+    LOG_WARNING("in the stub of %s", __FUNCTION__);
+    return NULL;
+}
+
+wasm_module_t *
+wasm_module_copy(const wasm_module_t *src)
+{
+    (void)src;
+    LOG_WARNING("in the stub of %s", __FUNCTION__);
+    return NULL;
+}
+
+wasm_instance_t *
+wasm_instance_copy(const wasm_instance_t *src)
+{
+    (void)src;
+    LOG_WARNING("in the stub of %s", __FUNCTION__);
+    return NULL;
+}
+
+static void *
+malloc_internal(uint64 size)
+{
+    void *mem = NULL;
+
+    if (size < UINT32_MAX && (mem = wasm_runtime_malloc((uint32)size))) {
+        memset(mem, 0, size);
+    }
+
+    return mem;
+}
+
+#define FREEIF(p)                                                             \
+    if (p) {                                                                  \
+        wasm_runtime_free(p);                                                 \
+    }
+
+/* clang-format off */
+#define RETURN_OBJ(obj, obj_del_func)                                         \
+    return obj;                                                               \
+failed:                                                                       \
+    obj_del_func(obj);                                                        \
+    return NULL;
+
+#define RETURN_VOID(obj, obj_del_func)                                        \
+    return;                                                                   \
+failed:                                                                       \
+    obj_del_func(obj);                                                        \
+    return;
+/* clang-format on */
+
+/* Vectors */
+#define INIT_VEC(vector_p, init_func, ...)                                    \
+    do {                                                                      \
+        if (!(vector_p = malloc_internal(sizeof(*(vector_p))))) {             \
+            goto failed;                                                      \
+        }                                                                     \
+                                                                              \
+        init_func(vector_p, ##__VA_ARGS__);                                   \
+        if (vector_p->size && !vector_p->data) {                              \
+            LOG_DEBUG("%s failed", #init_func);                               \
+            goto failed;                                                      \
+        }                                                                     \
+    } while (false)
+
+#define DEINIT_VEC(vector_p, deinit_func)                                     \
+    if ((vector_p)) {                                                         \
+        deinit_func(vector_p);                                                \
+        wasm_runtime_free(vector_p);                                          \
+        vector_p = NULL;                                                      \
+    }
+
+#define WASM_DEFINE_VEC(name)                                                 \
+    void wasm_##name##_vec_new_empty(own wasm_##name##_vec_t *out)            \
+    {                                                                         \
+        wasm_##name##_vec_new_uninitialized(out, 0);                          \
+    }                                                                         \
+    void wasm_##name##_vec_new_uninitialized(own wasm_##name##_vec_t *out,    \
+                                             size_t size)                     \
+    {                                                                         \
+        wasm_##name##_vec_new(out, size, NULL);                               \
+    }
+
+/* vectors with no ownership management of elements */
+#define WASM_DEFINE_VEC_PLAIN(name)                                           \
+    WASM_DEFINE_VEC(name)                                                     \
+    void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size,     \
+                               own wasm_##name##_t const data[])              \
+    {                                                                         \
+        if (!out) {                                                           \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        memset(out, 0, sizeof(wasm_##name##_vec_t));                          \
+                                                                              \
+        if (!size) {                                                          \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        if (!bh_vector_init((Vector *)out, size, sizeof(wasm_##name##_t))) {  \
+            LOG_DEBUG("bh_vector_init failed");                               \
+            goto failed;                                                      \
+        }                                                                     \
+                                                                              \
+        if (data) {                                                           \
+            unsigned int size_in_bytes = 0;                                   \
+            size_in_bytes = size * sizeof(wasm_##name##_t);                   \
+            bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes);       \
+            out->num_elems = size;                                            \
+        }                                                                     \
+                                                                              \
+        RETURN_VOID(out, wasm_##name##_vec_delete)                            \
+    }                                                                         \
+    void wasm_##name##_vec_copy(wasm_##name##_vec_t *out,                     \
+                                const wasm_##name##_vec_t *src)               \
+    {                                                                         \
+        wasm_##name##_vec_new(out, src->size, src->data);                     \
+    }                                                                         \
+    void wasm_##name##_vec_delete(wasm_##name##_vec_t *v)                     \
+    {                                                                         \
+        if (v) {                                                              \
+            bh_vector_destroy((Vector *)v);                                   \
+        }                                                                     \
+    }
+
+/* vectors that own their elements */
+#define WASM_DEFINE_VEC_OWN(name, elem_destroy_func)                          \
+    WASM_DEFINE_VEC(name)                                                     \
+    void wasm_##name##_vec_new(own wasm_##name##_vec_t *out, size_t size,     \
+                               own wasm_##name##_t *const data[])             \
+    {                                                                         \
+        if (!out) {                                                           \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        memset(out, 0, sizeof(wasm_##name##_vec_t));                          \
+                                                                              \
+        if (!size) {                                                          \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        if (!bh_vector_init((Vector *)out, size,                              \
+                            sizeof(wasm_##name##_t *))) {                     \
+            LOG_DEBUG("bh_vector_init failed");                               \
+            goto failed;                                                      \
+        }                                                                     \
+                                                                              \
+        if (data) {                                                           \
+            unsigned int size_in_bytes = 0;                                   \
+            size_in_bytes = size * sizeof(wasm_##name##_t *);                 \
+            bh_memcpy_s(out->data, size_in_bytes, data, size_in_bytes);       \
+            out->num_elems = size;                                            \
+        }                                                                     \
+                                                                              \
+        RETURN_VOID(out, wasm_##name##_vec_delete)                            \
+    }                                                                         \
+    void wasm_##name##_vec_copy(own wasm_##name##_vec_t *out,                 \
+                                const wasm_##name##_vec_t *src)               \
+    {                                                                         \
+        size_t i = 0;                                                         \
+        memset(out, 0, sizeof(Vector));                                       \
+                                                                              \
+        if (!src->size) {                                                     \
+            return;                                                           \
+        }                                                                     \
+                                                                              \
+        if (!bh_vector_init((Vector *)out, src->size,                         \
+                            sizeof(wasm_##name##_t *))) {                     \
+            LOG_DEBUG("bh_vector_init failed");                               \
+            goto failed;                                                      \
+        }                                                                     \
+                                                                              \
+        for (i = 0; i != src->num_elems; ++i) {                               \
+            if (!(out->data[i] = wasm_##name##_copy(src->data[i]))) {         \
+                LOG_DEBUG("wasm_%s_copy failed", #name);                      \
+                goto failed;                                                  \
+            }                                                                 \
+        }                                                                     \
+        out->num_elems = src->num_elems;                                      \
+                                                                              \
+        RETURN_VOID(out, wasm_##name##_vec_delete)                            \
+    }                                                                         \
+    void wasm_##name##_vec_delete(wasm_##name##_vec_t *v)                     \
+    {                                                                         \
+        size_t i = 0;                                                         \
+        if (!v) {                                                             \
+            return;                                                           \
+        }                                                                     \
+        for (i = 0; i != v->num_elems; ++i) {                                 \
+            elem_destroy_func(*(v->data + i));                                \
+        }                                                                     \
+        bh_vector_destroy((Vector *)v);                                       \
+    }
+
+WASM_DEFINE_VEC_PLAIN(byte)
+WASM_DEFINE_VEC_PLAIN(val)
+
+WASM_DEFINE_VEC_OWN(valtype, wasm_valtype_delete)
+WASM_DEFINE_VEC_OWN(functype, wasm_functype_delete)
+WASM_DEFINE_VEC_OWN(exporttype, wasm_exporttype_delete)
+WASM_DEFINE_VEC_OWN(importtype, wasm_importtype_delete)
+WASM_DEFINE_VEC_OWN(store, wasm_store_delete)
+WASM_DEFINE_VEC_OWN(module, wasm_module_delete_internal)
+WASM_DEFINE_VEC_OWN(instance, wasm_instance_delete_internal)
+WASM_DEFINE_VEC_OWN(extern, wasm_extern_delete)
+
+static inline bool
+valid_module_type(uint32 module_type)
+{
+    bool result = false;
+
+#if WASM_ENABLE_INTERP != 0
+    result = result || (module_type == Wasm_Module_Bytecode);
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    result = result || (module_type == Wasm_Module_AoT);
+#endif
+
+    if (!result) {
+        LOG_VERBOSE(
+          "current building isn't compatiable with the module, may need "
+          "recompile");
+    }
+
+    return result;
+}
+
+/* Runtime Environment */
+static void
+wasm_engine_delete_internal(wasm_engine_t *engine)
+{
+    if (engine) {
+        DEINIT_VEC(engine->stores, wasm_store_vec_delete);
+        wasm_runtime_free(engine);
+    }
+
+    wasm_runtime_destroy();
+}
+
+static wasm_engine_t *
+wasm_engine_new_internal(mem_alloc_type_t type, const MemAllocOption *opts)
+{
+    wasm_engine_t *engine = NULL;
+    /* init runtime */
+    RuntimeInitArgs init_args = { 0 };
+    init_args.mem_alloc_type = type;
+
+    if (type == Alloc_With_Pool) {
+        if (!opts) {
+            return NULL;
+        }
+
+        init_args.mem_alloc_option.pool.heap_buf = opts->pool.heap_buf;
+        init_args.mem_alloc_option.pool.heap_size = opts->pool.heap_size;
+    }
+    else if (type == Alloc_With_Allocator) {
+        if (!opts) {
+            return NULL;
+        }
+
+        init_args.mem_alloc_option.allocator.malloc_func =
+          opts->allocator.malloc_func;
+        init_args.mem_alloc_option.allocator.free_func =
+          opts->allocator.free_func;
+        init_args.mem_alloc_option.allocator.realloc_func =
+          opts->allocator.realloc_func;
+    }
+    else {
+        init_args.mem_alloc_option.pool.heap_buf = NULL;
+        init_args.mem_alloc_option.pool.heap_size = 0;
+    }
+
+    if (!wasm_runtime_full_init(&init_args)) {
+        LOG_DEBUG("wasm_runtime_full_init failed");
+        goto failed;
+    }
+
+#if BH_DEBUG != 0
+    bh_log_set_verbose_level(5);
+#else
+    bh_log_set_verbose_level(3);
+#endif
+
+    /* create wasm_engine_t */
+    if (!(engine = malloc_internal(sizeof(wasm_engine_t)))) {
+        goto failed;
+    }
+
+    /* create wasm_store_vec_t */
+    INIT_VEC(engine->stores, wasm_store_vec_new_uninitialized, 1);
+
+    RETURN_OBJ(engine, wasm_engine_delete_internal)
+}
+
+/* global engine instance */
+static wasm_engine_t *singleton_engine = NULL;
+
+wasm_engine_t *
+wasm_engine_new()
+{
+    if (!singleton_engine) {
+        singleton_engine =
+          wasm_engine_new_internal(Alloc_With_System_Allocator, NULL);
+    }
+    return singleton_engine;
+}
+
+wasm_engine_t *
+wasm_engine_new_with_args(mem_alloc_type_t type, const MemAllocOption *opts)
+{
+    if (!singleton_engine) {
+        singleton_engine = wasm_engine_new_internal(type, opts);
+    }
+    return singleton_engine;
+}
+
+/* BE AWARE: will RESET the singleton */
+void
+wasm_engine_delete(wasm_engine_t *engine)
+{
+    if (engine) {
+        wasm_engine_delete_internal(engine);
+        singleton_engine = NULL;
+    }
+}
+
+wasm_store_t *
+wasm_store_new(wasm_engine_t *engine)
+{
+    wasm_store_t *store = NULL;
+
+    if (!engine || singleton_engine != engine) {
+        return NULL;
+    }
+
+    if (!wasm_runtime_init_thread_env()) {
+        LOG_ERROR("init thread environment failed");
+        return NULL;
+    }
+
+    if (!(store = malloc_internal(sizeof(wasm_store_t)))) {
+        wasm_runtime_destroy_thread_env();
+        return NULL;
+    }
+
+    /* new a vector, and new its data */
+    INIT_VEC(store->modules, wasm_module_vec_new_uninitialized,
+             DEFAULT_VECTOR_INIT_LENGTH);
+    INIT_VEC(store->instances, wasm_instance_vec_new_uninitialized,
+             DEFAULT_VECTOR_INIT_LENGTH);
+
+    /* append to a store list of engine */
+    if (!bh_vector_append((Vector *)singleton_engine->stores, &store)) {
+        LOG_DEBUG("bh_vector_append failed");
+        goto failed;
+    }
+
+    return store;
+failed:
+    wasm_store_delete(store);
+    return NULL;
+}
+
+void
+wasm_store_delete(wasm_store_t *store)
+{
+    size_t i, store_count;
+
+    if (!store) {
+        return;
+    }
+
+    /* remove it from the list in the engine */
+    store_count = bh_vector_size((Vector *)singleton_engine->stores);
+    for (i = 0; i != store_count; ++i) {
+        wasm_store_t *tmp;
+
+        if (!bh_vector_get((Vector *)singleton_engine->stores, i, &tmp)) {
+            break;
+        }
+
+        if (tmp == store) {
+            bh_vector_remove((Vector *)singleton_engine->stores, i, NULL);
+            break;
+        }
+    }
+
+    DEINIT_VEC(store->modules, wasm_module_vec_delete);
+    DEINIT_VEC(store->instances, wasm_instance_vec_delete);
+    wasm_runtime_free(store);
+
+    wasm_runtime_destroy_thread_env();
+}
+
+/* Type Representations */
+static wasm_valkind_t
+val_type_rt_2_valkind(uint8 val_type_rt)
+{
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            return WASM_I32;
+        case VALUE_TYPE_I64:
+            return WASM_I64;
+        case VALUE_TYPE_F32:
+            return WASM_F32;
+        case VALUE_TYPE_F64:
+            return WASM_F64;
+        case VALUE_TYPE_ANY:
+            return WASM_ANYREF;
+        case VALUE_TYPE_FUNCREF:
+            return WASM_FUNCREF;
+        default:
+            LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
+                        val_type_rt);
+            return WASM_ANYREF;
+    }
+}
+
+static wasm_valtype_t *
+wasm_valtype_new_internal(uint8 val_type_rt)
+{
+    return wasm_valtype_new(val_type_rt_2_valkind(val_type_rt));
+}
+
+wasm_valtype_t *
+wasm_valtype_new(wasm_valkind_t kind)
+{
+    wasm_valtype_t *val_type;
+
+    if (!(val_type = malloc_internal(sizeof(wasm_valtype_t)))) {
+        return NULL;
+    }
+
+    val_type->kind = kind;
+
+    return val_type;
+}
+
+void
+wasm_valtype_delete(wasm_valtype_t *val_type)
+{
+    FREEIF(val_type);
+}
+
+wasm_valtype_t *
+wasm_valtype_copy(const wasm_valtype_t *src)
+{
+    if (!src) {
+        return NULL;
+    }
+
+    return wasm_valtype_new(src->kind);
+}
+
+wasm_valkind_t
+wasm_valtype_kind(const wasm_valtype_t *val_type)
+{
+    if (!val_type) {
+        return WASM_ANYREF;
+    }
+
+    return val_type->kind;
+}
+
+bool
+wasm_valtype_same(const wasm_valtype_t *vt1, const wasm_valtype_t *vt2)
+{
+    if (!vt1 && !vt2) {
+        return true;
+    }
+
+    if (!vt1 || !vt2) {
+        return false;
+    }
+
+    return vt1->kind == vt2->kind;
+}
+
+static wasm_functype_t *
+wasm_functype_new_internal(WASMType *type_rt)
+{
+    wasm_functype_t *type = NULL;
+    wasm_valtype_t *param_type = NULL, *result_type = NULL;
+    uint32 i = 0;
+
+    if (!type_rt) {
+        return NULL;
+    }
+
+    if (!(type = malloc_internal(sizeof(wasm_functype_t)))) {
+        return NULL;
+    }
+
+    type->extern_kind = WASM_EXTERN_FUNC;
+
+    /* WASMType->types[0 : type_rt->param_count) -> type->params */
+    INIT_VEC(type->params, wasm_valtype_vec_new_uninitialized,
+             type_rt->param_count);
+    for (i = 0; i < type_rt->param_count; ++i) {
+        if (!(param_type = wasm_valtype_new_internal(*(type_rt->types + i)))) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)type->params, &param_type)) {
+            LOG_DEBUG("bh_vector_append failed");
+            goto failed;
+        }
+    }
+
+    /* WASMType->types[type_rt->param_count : type_rt->result_count) -> type->results */
+    INIT_VEC(type->results, wasm_valtype_vec_new_uninitialized,
+             type_rt->result_count);
+    for (i = 0; i < type_rt->result_count; ++i) {
+        if (!(result_type = wasm_valtype_new_internal(
+                *(type_rt->types + type_rt->param_count + i)))) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)type->results, &result_type)) {
+            LOG_DEBUG("bh_vector_append failed");
+            goto failed;
+        }
+    }
+
+    return type;
+
+failed:
+    wasm_valtype_delete(param_type);
+    wasm_valtype_delete(result_type);
+    wasm_functype_delete(type);
+    return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_new(own wasm_valtype_vec_t *params,
+                  own wasm_valtype_vec_t *results)
+{
+    wasm_functype_t *type = NULL;
+
+    if (!params) {
+        return NULL;
+    }
+
+    if (!results) {
+        return NULL;
+    }
+
+    if (!(type = malloc_internal(sizeof(wasm_functype_t)))) {
+        goto failed;
+    }
+
+    type->extern_kind = WASM_EXTERN_FUNC;
+
+    /* take ownership */
+    if (!(type->params = malloc_internal(sizeof(wasm_valtype_vec_t)))) {
+        goto failed;
+    }
+    bh_memcpy_s(type->params, sizeof(wasm_valtype_vec_t), params,
+                sizeof(wasm_valtype_vec_t));
+
+    if (!(type->results = malloc_internal(sizeof(wasm_valtype_vec_t)))) {
+        goto failed;
+    }
+    bh_memcpy_s(type->results, sizeof(wasm_valtype_vec_t), results,
+                sizeof(wasm_valtype_vec_t));
+
+    return type;
+
+failed:
+    wasm_functype_delete(type);
+    return NULL;
+}
+
+wasm_functype_t *
+wasm_functype_copy(const wasm_functype_t *src)
+{
+    wasm_functype_t *functype;
+    wasm_valtype_vec_t params = { 0 }, results = { 0 };
+
+    if (!src) {
+        return NULL;
+    }
+
+    wasm_valtype_vec_copy(&params, src->params);
+    if (src->params->size && !params.data) {
+        goto failed;
+    }
+
+    wasm_valtype_vec_copy(&results, src->results);
+    if (src->results->size && !results.data) {
+        goto failed;
+    }
+
+    if (!(functype = wasm_functype_new(&params, &results))) {
+        goto failed;
+    }
+
+    return functype;
+
+failed:
+    wasm_valtype_vec_delete(&params);
+    wasm_valtype_vec_delete(&results);
+    return NULL;
+}
+
+void
+wasm_functype_delete(wasm_functype_t *func_type)
+{
+    if (!func_type) {
+        return;
+    }
+
+    DEINIT_VEC(func_type->params, wasm_valtype_vec_delete);
+    DEINIT_VEC(func_type->results, wasm_valtype_vec_delete);
+
+    wasm_runtime_free(func_type);
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_params(const wasm_functype_t *func_type)
+{
+    if (!func_type) {
+        return NULL;
+    }
+
+    return func_type->params;
+}
+
+const wasm_valtype_vec_t *
+wasm_functype_results(const wasm_functype_t *func_type)
+{
+    if (!func_type) {
+        return NULL;
+    }
+
+    return func_type->results;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new(own wasm_valtype_t *val_type, wasm_mutability_t mut)
+{
+    wasm_globaltype_t *global_type = NULL;
+
+    if (!val_type) {
+        return NULL;
+    }
+
+    if (!(global_type = malloc_internal(sizeof(wasm_globaltype_t)))) {
+        return NULL;
+    }
+
+    global_type->extern_kind = WASM_EXTERN_GLOBAL;
+    global_type->val_type = val_type;
+    global_type->mutability = mut;
+
+    return global_type;
+}
+
+wasm_globaltype_t *
+wasm_globaltype_new_internal(uint8 val_type_rt, bool is_mutable)
+{
+    wasm_globaltype_t *globaltype;
+    wasm_valtype_t *val_type;
+
+    if (!(val_type = wasm_valtype_new(val_type_rt_2_valkind(val_type_rt)))) {
+        return NULL;
+    }
+
+    if (!(globaltype = wasm_globaltype_new(
+            val_type, is_mutable ? WASM_VAR : WASM_CONST))) {
+        wasm_valtype_delete(val_type);
+    }
+
+    return globaltype;
+}
+
+void
+wasm_globaltype_delete(wasm_globaltype_t *global_type)
+{
+    if (!global_type) {
+        return;
+    }
+
+    if (global_type->val_type) {
+        wasm_valtype_delete(global_type->val_type);
+        global_type->val_type = NULL;
+    }
+
+    wasm_runtime_free(global_type);
+}
+
+wasm_globaltype_t *
+wasm_globaltype_copy(const wasm_globaltype_t *src)
+{
+    wasm_globaltype_t *global_type;
+    wasm_valtype_t *val_type;
+
+    if (!src) {
+        return NULL;
+    }
+
+    if (!(val_type = wasm_valtype_copy(src->val_type))) {
+        return NULL;
+    }
+
+    if (!(global_type = wasm_globaltype_new(val_type, src->mutability))) {
+        wasm_valtype_delete(val_type);
+    }
+
+    return global_type;
+}
+
+const wasm_valtype_t *
+wasm_globaltype_content(const wasm_globaltype_t *global_type)
+{
+    if (!global_type) {
+        return NULL;
+    }
+
+    return global_type->val_type;
+}
+
+wasm_mutability_t
+wasm_globaltype_mutability(const wasm_globaltype_t *global_type)
+{
+    if (!global_type) {
+        return false;
+    }
+
+    return global_type->mutability;
+}
+
+bool
+wasm_globaltype_same(const wasm_globaltype_t *gt1,
+                     const wasm_globaltype_t *gt2)
+{
+    if (!gt1 && !gt2) {
+        return true;
+    }
+
+    if (!gt1 || !gt2) {
+        return false;
+    }
+
+    return wasm_valtype_same(gt1->val_type, gt2->val_type)
+           || gt1->mutability == gt2->mutability;
+}
+
+static wasm_tabletype_t *
+wasm_tabletype_new_internal(uint8 val_type_rt,
+                            uint32 init_size,
+                            uint32 max_size)
+{
+    wasm_tabletype_t *table_type;
+    wasm_limits_t limits = { init_size, max_size };
+    wasm_valtype_t *val_type;
+
+    if (!(val_type = wasm_valtype_new_internal(val_type_rt))) {
+        return NULL;
+    }
+
+    if (!(table_type = wasm_tabletype_new(val_type, &limits))) {
+        wasm_valtype_delete(val_type);
+    }
+
+    return table_type;
+}
+
+wasm_tabletype_t *
+wasm_tabletype_new(own wasm_valtype_t *val_type, const wasm_limits_t *limits)
+{
+    wasm_tabletype_t *table_type = NULL;
+
+    if (!val_type) {
+        return NULL;
+    }
+
+    if (!(table_type = malloc_internal(sizeof(wasm_tabletype_t)))) {
+        return NULL;
+    }
+
+    table_type->extern_kind = WASM_EXTERN_TABLE;
+    table_type->val_type = val_type;
+    table_type->limits.min = limits->min;
+    table_type->limits.max = limits->max;
+
+    return table_type;
+}
+
+wasm_tabletype_t *
+wasm_tabletype_copy(const wasm_tabletype_t *src)
+{
+    wasm_tabletype_t *table_type;
+    wasm_valtype_t *val_type;
+
+    if (!src) {
+        return NULL;
+    }
+
+    if (!(val_type = wasm_valtype_copy(src->val_type))) {
+        return NULL;
+    }
+
+    if (!(table_type = wasm_tabletype_new(val_type, &src->limits))) {
+        wasm_valtype_delete(val_type);
+    }
+
+    return table_type;
+}
+
+void
+wasm_tabletype_delete(wasm_tabletype_t *table_type)
+{
+    if (!table_type) {
+        return;
+    }
+
+    if (table_type->val_type) {
+        wasm_valtype_delete(table_type->val_type);
+        table_type->val_type = NULL;
+    }
+
+    wasm_runtime_free(table_type);
+}
+
+const wasm_valtype_t *
+wasm_tabletype_element(const wasm_tabletype_t *table_type)
+{
+    if (!table_type) {
+        return NULL;
+    }
+
+    return table_type->val_type;
+}
+
+const wasm_limits_t *
+wasm_tabletype_limits(const wasm_tabletype_t *table_type)
+{
+    if (!table_type) {
+        return NULL;
+    }
+
+    return &(table_type->limits);
+}
+
+static wasm_memorytype_t *
+wasm_memorytype_new_internal(uint32 min_pages, uint32 max_pages)
+{
+    wasm_limits_t limits = { min_pages, max_pages };
+    return wasm_memorytype_new(&limits);
+}
+
+wasm_memorytype_t *
+wasm_memorytype_new(const wasm_limits_t *limits)
+{
+    wasm_memorytype_t *memory_type = NULL;
+
+    if (!limits) {
+        return NULL;
+    }
+
+    if (!(memory_type = malloc_internal(sizeof(wasm_memorytype_t)))) {
+        return NULL;
+    }
+
+    memory_type->extern_kind = WASM_EXTERN_MEMORY;
+    memory_type->limits.min = limits->min;
+    memory_type->limits.max = limits->max;
+
+    return memory_type;
+}
+
+wasm_memorytype_t *
+wasm_memorytype_copy(const wasm_memorytype_t *src)
+{
+    if (!src) {
+        return NULL;
+    }
+
+    return wasm_memorytype_new(&src->limits);
+}
+
+void
+wasm_memorytype_delete(wasm_memorytype_t *memory_type)
+{
+    FREEIF(memory_type);
+}
+
+const wasm_limits_t *
+wasm_memorytype_limits(const wasm_memorytype_t *memory_type)
+{
+    if (!memory_type) {
+        return NULL;
+    }
+
+    return &(memory_type->limits);
+}
+
+wasm_externkind_t
+wasm_externtype_kind(const wasm_externtype_t *extern_type)
+{
+    if (!extern_type) {
+        return WASM_EXTERN_FUNC;
+    }
+
+    return extern_type->extern_kind;
+}
+
+#define BASIC_FOUR_TYPE_LIST(V)                                               \
+    V(functype)                                                               \
+    V(globaltype)                                                             \
+    V(memorytype)                                                             \
+    V(tabletype)
+
+#define WASM_EXTERNTYPE_AS_OTHERTYPE(name)                                    \
+    wasm_##name##_t *wasm_externtype_as_##name(                               \
+      wasm_externtype_t *extern_type)                                         \
+    {                                                                         \
+        return (wasm_##name##_t *)extern_type;                                \
+    }
+
+BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE)
+#undef WASM_EXTERNTYPE_AS_OTHERTYPE
+
+#define WASM_OTHERTYPE_AS_EXTERNTYPE(name)                                    \
+    wasm_externtype_t *wasm_##name##_as_externtype(wasm_##name##_t *other)    \
+    {                                                                         \
+        return (wasm_externtype_t *)other;                                    \
+    }
+
+BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE)
+#undef WASM_OTHERTYPE_AS_EXTERNTYPE
+
+#define WASM_EXTERNTYPE_AS_OTHERTYPE_CONST(name)                              \
+    const wasm_##name##_t *wasm_externtype_as_##name##_const(                 \
+      const wasm_externtype_t *extern_type)                                   \
+    {                                                                         \
+        return (const wasm_##name##_t *)extern_type;                          \
+    }
+
+BASIC_FOUR_TYPE_LIST(WASM_EXTERNTYPE_AS_OTHERTYPE_CONST)
+#undef WASM_EXTERNTYPE_AS_OTHERTYPE_CONST
+
+#define WASM_OTHERTYPE_AS_EXTERNTYPE_CONST(name)                              \
+    const wasm_externtype_t *wasm_##name##_as_externtype_const(               \
+      const wasm_##name##_t *other)                                           \
+    {                                                                         \
+        return (const wasm_externtype_t *)other;                              \
+    }
+
+BASIC_FOUR_TYPE_LIST(WASM_OTHERTYPE_AS_EXTERNTYPE_CONST)
+#undef WASM_OTHERTYPE_AS_EXTERNTYPE_CONST
+
+wasm_externtype_t *
+wasm_externtype_copy(const wasm_externtype_t *src)
+{
+    wasm_externtype_t *extern_type = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    switch (src->extern_kind) {
+#define COPY_EXTERNTYPE(NAME, name)                                           \
+    case WASM_EXTERN_##NAME:                                                  \
+    {                                                                         \
+        extern_type = wasm_##name##_as_externtype(                            \
+          wasm_##name##_copy(wasm_externtype_as_##name##_const(src)));        \
+        break;                                                                \
+    }
+        COPY_EXTERNTYPE(FUNC, functype)
+        COPY_EXTERNTYPE(GLOBAL, globaltype)
+        COPY_EXTERNTYPE(MEMORY, memorytype)
+        COPY_EXTERNTYPE(TABLE, tabletype)
+#undef COPY_EXTERNTYPE
+        default:
+            LOG_WARNING("%s meets unsupported kind", __FUNCTION__,
+                        src->extern_kind);
+            break;
+    }
+    return extern_type;
+}
+
+void
+wasm_externtype_delete(wasm_externtype_t *extern_type)
+{
+    if (!extern_type) {
+        return;
+    }
+
+    switch (wasm_externtype_kind(extern_type)) {
+        case WASM_EXTERN_FUNC:
+            wasm_functype_delete(wasm_externtype_as_functype(extern_type));
+            break;
+        case WASM_EXTERN_GLOBAL:
+            wasm_globaltype_delete(wasm_externtype_as_globaltype(extern_type));
+            break;
+        case WASM_EXTERN_MEMORY:
+            wasm_memorytype_delete(wasm_externtype_as_memorytype(extern_type));
+            break;
+        case WASM_EXTERN_TABLE:
+            wasm_tabletype_delete(wasm_externtype_as_tabletype(extern_type));
+            break;
+        default:
+            LOG_WARNING("%s meets unsupported type", __FUNCTION__,
+                        extern_type);
+            break;
+    }
+}
+
+own wasm_importtype_t *
+wasm_importtype_new(own wasm_byte_vec_t *module_name,
+                    own wasm_byte_vec_t *field_name,
+                    own wasm_externtype_t *extern_type)
+{
+    wasm_importtype_t *import_type = NULL;
+
+    if (!(import_type = malloc_internal(sizeof(wasm_importtype_t)))) {
+        return NULL;
+    }
+
+    /* take ownership */
+    if (!(import_type->module_name =
+            malloc_internal(sizeof(wasm_byte_vec_t)))) {
+        goto failed;
+    }
+    bh_memcpy_s(import_type->module_name, sizeof(wasm_byte_vec_t), module_name,
+                sizeof(wasm_byte_vec_t));
+
+    if (!(import_type->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+        goto failed;
+    }
+    bh_memcpy_s(import_type->name, sizeof(wasm_byte_vec_t), field_name,
+                sizeof(wasm_byte_vec_t));
+
+    import_type->extern_type = extern_type;
+
+    return import_type;
+failed:
+    wasm_importtype_delete(import_type);
+    return NULL;
+}
+
+void
+wasm_importtype_delete(own wasm_importtype_t *import_type)
+{
+    if (!import_type) {
+        return;
+    }
+
+    DEINIT_VEC(import_type->module_name, wasm_byte_vec_delete);
+    DEINIT_VEC(import_type->name, wasm_byte_vec_delete);
+    wasm_externtype_delete(import_type->extern_type);
+    wasm_runtime_free(import_type);
+}
+
+own wasm_importtype_t *
+wasm_importtype_copy(const wasm_importtype_t *src)
+{
+    wasm_byte_vec_t module_name = { 0 }, name = { 0 };
+    wasm_externtype_t *extern_type = NULL;
+    wasm_importtype_t *import_type = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    wasm_byte_vec_copy(&module_name, src->module_name);
+    if (src->module_name->size && !module_name.data) {
+        goto failed;
+    }
+
+    wasm_byte_vec_copy(&name, src->name);
+    if (src->name->size && !name.data) {
+        goto failed;
+    }
+
+    if (!(extern_type = wasm_externtype_copy(src->extern_type))) {
+        goto failed;
+    }
+
+    if (!(import_type =
+            wasm_importtype_new(&module_name, &name, extern_type))) {
+        goto failed;
+    }
+
+    return import_type;
+
+failed:
+    wasm_byte_vec_delete(&module_name);
+    wasm_byte_vec_delete(&name);
+    wasm_externtype_delete(extern_type);
+    wasm_importtype_delete(import_type);
+    return NULL;
+}
+
+const wasm_byte_vec_t *
+wasm_importtype_module(const wasm_importtype_t *import_type)
+{
+    if (!import_type) {
+        return NULL;
+    }
+
+    return import_type->module_name;
+}
+
+const wasm_byte_vec_t *
+wasm_importtype_name(const wasm_importtype_t *import_type)
+{
+    if (!import_type) {
+        return NULL;
+    }
+
+    return import_type->name;
+}
+
+const wasm_externtype_t *
+wasm_importtype_type(const wasm_importtype_t *import_type)
+{
+    if (!import_type) {
+        return NULL;
+    }
+
+    return import_type->extern_type;
+}
+
+own wasm_exporttype_t *
+wasm_exporttype_new(own wasm_byte_vec_t *name,
+                    own wasm_externtype_t *extern_type)
+{
+    wasm_exporttype_t *export_type = NULL;
+
+    if (!(export_type = malloc_internal(sizeof(wasm_exporttype_t)))) {
+        return NULL;
+    }
+
+    if (!(export_type->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+        wasm_exporttype_delete(export_type);
+        return NULL;
+    }
+    bh_memcpy_s(export_type->name, sizeof(wasm_byte_vec_t), name,
+                sizeof(wasm_byte_vec_t));
+
+    export_type->extern_type = extern_type;
+
+    return export_type;
+}
+
+wasm_exporttype_t *
+wasm_exporttype_copy(const wasm_exporttype_t *src)
+{
+    wasm_exporttype_t *export_type;
+    wasm_byte_vec_t name = { 0 };
+    wasm_externtype_t *extern_type = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    wasm_byte_vec_copy(&name, src->name);
+    if (src->name->size && !name.data) {
+        goto failed;
+    }
+
+    if (!(extern_type = wasm_externtype_copy(src->extern_type))) {
+        goto failed;
+    }
+
+    if (!(export_type = wasm_exporttype_new(&name, extern_type))) {
+        goto failed;
+    }
+
+    return export_type;
+failed:
+    wasm_byte_vec_delete(&name);
+    wasm_externtype_delete(extern_type);
+    return NULL;
+}
+
+void
+wasm_exporttype_delete(wasm_exporttype_t *export_type)
+{
+    if (!export_type) {
+        return;
+    }
+
+    DEINIT_VEC(export_type->name, wasm_byte_vec_delete);
+
+    wasm_externtype_delete(export_type->extern_type);
+
+    wasm_runtime_free(export_type);
+}
+
+const wasm_byte_vec_t *
+wasm_exporttype_name(const wasm_exporttype_t *export_type)
+{
+    if (!export_type) {
+        return NULL;
+    }
+    return export_type->name;
+}
+
+const wasm_externtype_t *
+wasm_exporttype_type(const wasm_exporttype_t *export_type)
+{
+    if (!export_type) {
+        return NULL;
+    }
+    return export_type->extern_type;
+}
+
+/* Runtime Objects */
+
+void
+wasm_val_delete(wasm_val_t *v)
+{
+    FREEIF(v);
+}
+
+void
+wasm_val_copy(wasm_val_t *out, const wasm_val_t *src)
+{
+    if (!out || !src) {
+        return;
+    }
+
+    bh_memcpy_s(out, sizeof(wasm_val_t), src, sizeof(wasm_val_t));
+}
+
+bool
+wasm_val_same(const wasm_val_t *v1, const wasm_val_t *v2)
+{
+    if (!v1 && !v2) {
+        return true;
+    }
+
+    if (!v1 || !v2) {
+        return false;
+    }
+
+    if (v1->kind != v2->kind) {
+        return false;
+    }
+
+    switch (v1->kind) {
+        case WASM_I32:
+            return v1->of.i32 == v2->of.i32;
+        case WASM_I64:
+            return v1->of.i64 == v2->of.i64;
+        case WASM_F32:
+            return v1->of.f32 == v2->of.f32;
+        case WASM_F64:
+            return v1->of.f64 == v2->of.f64;
+        case WASM_FUNCREF:
+            return v1->of.ref == v2->of.ref;
+        default:
+            break;
+    }
+    return false;
+}
+
+static wasm_trap_t *
+wasm_trap_new_internal(const char *string)
+{
+    wasm_trap_t *trap;
+
+    if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
+        return NULL;
+    }
+
+    if (!(trap->message = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+        goto failed;
+    }
+
+    wasm_name_new_from_string(trap->message, string);
+    if (strlen(string) && !trap->message->data) {
+        goto failed;
+    }
+
+    return trap;
+failed:
+    wasm_trap_delete(trap);
+    return NULL;
+}
+
+wasm_trap_t *
+wasm_trap_new(wasm_store_t *store, const wasm_message_t *message)
+{
+    wasm_trap_t *trap;
+
+    if (!store || !message) {
+        return NULL;
+    }
+
+    if (!(trap = malloc_internal(sizeof(wasm_trap_t)))) {
+        return NULL;
+    }
+
+    INIT_VEC(trap->message, wasm_byte_vec_new, message->size, message->data);
+
+    return trap;
+failed:
+    wasm_trap_delete(trap);
+    return NULL;
+}
+
+void
+wasm_trap_delete(wasm_trap_t *trap)
+{
+    if (!trap) {
+        return;
+    }
+
+    DEINIT_VEC(trap->message, wasm_byte_vec_delete);
+
+    wasm_runtime_free(trap);
+}
+
+void
+wasm_trap_message(const wasm_trap_t *trap, own wasm_message_t *out)
+{
+    if (!trap || !out) {
+        return;
+    }
+
+    wasm_byte_vec_copy(out, trap->message);
+}
+
+struct wasm_module_ex_t {
+    struct WASMModuleCommon *module_comm_rt;
+    wasm_byte_vec_t *binary;
+};
+
+static inline wasm_module_t *
+module_ext_to_module(wasm_module_ex_t *module_ex)
+{
+    return (wasm_module_t *)module_ex;
+}
+
+static inline wasm_module_ex_t *
+module_to_module_ext(wasm_module_t *module)
+{
+    return (wasm_module_ex_t *)module;
+}
+
+#if WASM_ENABLE_INTERP != 0
+#define MODULE_INTERP(module) ((WASMModule *)(*module))
+#endif
+
+#if WASM_ENABLE_AOT != 0
+#define MODULE_AOT(module) ((AOTModule *)(*module))
+#endif
+
+wasm_module_t *
+wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
+{
+    char error_buf[128] = { 0 };
+    wasm_module_ex_t *module_ex = NULL;
+
+    bh_assert(singleton_engine);
+
+    if (!store || !binary || binary->size > UINT32_MAX) {
+        LOG_ERROR("%s failed", __FUNCTION__);
+        return NULL;
+    }
+
+    module_ex = malloc_internal(sizeof(wasm_module_ex_t));
+    if (!module_ex) {
+        goto failed;
+    }
+
+    INIT_VEC(module_ex->binary, wasm_byte_vec_new, binary->size, binary->data);
+
+    module_ex->module_comm_rt = wasm_runtime_load(
+      (uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
+      error_buf, (uint32)sizeof(error_buf));
+    if (!(module_ex->module_comm_rt)) {
+        LOG_ERROR(error_buf);
+        goto failed;
+    }
+
+    /* add it to a watching list in store */
+    if (!bh_vector_append((Vector *)store->modules, &module_ex)) {
+        goto failed;
+    }
+
+    return module_ext_to_module(module_ex);
+
+failed:
+    LOG_ERROR("%s failed", __FUNCTION__);
+    wasm_module_delete_internal(module_ext_to_module(module_ex));
+    return NULL;
+}
+
+static void
+wasm_module_delete_internal(wasm_module_t *module)
+{
+    wasm_module_ex_t *module_ex;
+
+    if (!module) {
+        return;
+    }
+
+    module_ex = module_to_module_ext(module);
+    DEINIT_VEC(module_ex->binary, wasm_byte_vec_delete);
+
+    if (module_ex->module_comm_rt) {
+        wasm_runtime_unload(module_ex->module_comm_rt);
+        module_ex->module_comm_rt = NULL;
+    }
+
+    wasm_runtime_free(module_ex);
+}
+
+void
+wasm_module_delete(wasm_module_t *module)
+{
+    /* the module will be released when releasing the store */
+}
+
+void
+wasm_module_imports(const wasm_module_t *module,
+                    own wasm_importtype_vec_t *out)
+{
+    uint32 i, import_func_count = 0, import_memory_count = 0,
+              import_global_count = 0, import_table_count = 0,
+              import_count = 0;
+    wasm_byte_vec_t module_name = { 0 }, name = { 0 };
+    wasm_externtype_t *extern_type = NULL;
+    wasm_importtype_t *import_type = NULL;
+
+    if (!module || !out || !valid_module_type((*module)->module_type)) {
+        return;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if ((*module)->module_type == Wasm_Module_Bytecode) {
+        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) {
+        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
+
+    import_count = import_func_count + import_global_count + import_table_count
+                   + import_memory_count;
+    wasm_importtype_vec_new_uninitialized(out, import_count);
+    if (import_count && !out->data) {
+        return;
+    }
+
+    for (i = 0; i != import_count; ++i) {
+        char *module_name_rt = NULL, *field_name_rt = NULL;
+
+        if (i < import_func_count) {
+            wasm_functype_t *type = NULL;
+            WASMType *type_rt = NULL;
+
+#if WASM_ENABLE_INTERP != 0
+            if ((*module)->module_type == Wasm_Module_Bytecode) {
+                WASMImport *import =
+                  MODULE_INTERP(module)->import_functions + i;
+                module_name_rt = import->u.names.module_name;
+                field_name_rt = import->u.names.field_name;
+                type_rt = import->u.function.func_type;
+            }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+            if ((*module)->module_type == Wasm_Module_AoT) {
+                AOTImportFunc *import = MODULE_AOT(module)->import_funcs + i;
+                module_name_rt = import->module_name;
+                field_name_rt = import->func_name;
+                type_rt = import->func_type;
+            }
+#endif
+
+            if (!module_name_rt || !field_name_rt || !type_rt) {
+                continue;
+            }
+
+            wasm_name_new_from_string(&module_name, module_name_rt);
+            if (strlen(module_name_rt) && !module_name.data) {
+                goto failed;
+            }
+
+            wasm_name_new_from_string(&name, field_name_rt);
+            if (strlen(field_name_rt) && !name.data) {
+                goto failed;
+            }
+
+            if (!(type = wasm_functype_new_internal(type_rt))) {
+                goto failed;
+            }
+
+            extern_type = wasm_functype_as_externtype(type);
+        }
+        else if (i < import_func_count + import_global_count) {
+            wasm_globaltype_t *type = NULL;
+            uint8 val_type_rt = 0;
+            bool mutability_rt = 0;
+
+#if WASM_ENABLE_INTERP != 0
+            if ((*module)->module_type == Wasm_Module_Bytecode) {
+                WASMImport *import = MODULE_INTERP(module)->import_globals
+                                     + (i - import_func_count);
+                module_name_rt = import->u.names.module_name;
+                field_name_rt = import->u.names.field_name;
+                val_type_rt = import->u.global.type;
+                mutability_rt = import->u.global.is_mutable;
+            }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+            if ((*module)->module_type == Wasm_Module_AoT) {
+                AOTImportGlobal *import =
+                  MODULE_AOT(module)->import_globals + (i - import_func_count);
+                module_name_rt = import->module_name;
+                field_name_rt = import->global_name;
+                val_type_rt = import->type;
+                mutability_rt = import->is_mutable;
+            }
+#endif
+
+            if (!module_name_rt || !field_name_rt) {
+                continue;
+            }
+
+            if (!(type = wasm_globaltype_new_internal(val_type_rt,
+                                                      mutability_rt))) {
+                goto failed;
+            }
+
+            extern_type = wasm_globaltype_as_externtype(type);
+        }
+        else if (i < import_func_count + import_global_count
+                       + import_memory_count) {
+            wasm_memorytype_t *type = NULL;
+            uint32 min_page = 0, max_page = 0;
+
+#if WASM_ENABLE_INTERP != 0
+            if ((*module)->module_type == Wasm_Module_Bytecode) {
+                WASMImport *import =
+                  MODULE_INTERP(module)->import_memories
+                  + (i - import_func_count - import_global_count);
+                module_name_rt = import->u.names.module_name;
+                field_name_rt = import->u.names.field_name;
+                min_page = import->u.memory.init_page_count;
+                max_page = import->u.memory.max_page_count;
+            }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+            if ((*module)->module_type == Wasm_Module_AoT) {
+                AOTImportMemory *import =
+                  MODULE_AOT(module)->import_memories
+                  + (i - import_func_count - import_global_count);
+                module_name_rt = import->module_name;
+                field_name_rt = import->memory_name;
+                min_page = import->mem_init_page_count;
+                max_page = import->mem_max_page_count;
+            }
+#endif
+
+            if (!module_name_rt || !field_name_rt) {
+                continue;
+            }
+
+            wasm_name_new_from_string(&module_name, module_name_rt);
+            if (strlen(module_name_rt) && !module_name.data) {
+                goto failed;
+            }
+
+            wasm_name_new_from_string(&name, field_name_rt);
+            if (strlen(field_name_rt) && !name.data) {
+                goto failed;
+            }
+
+            if (!(type = wasm_memorytype_new_internal(min_page, max_page))) {
+                goto failed;
+            }
+
+            extern_type = wasm_memorytype_as_externtype(type);
+        }
+        else {
+            wasm_tabletype_t *type = NULL;
+            uint8 elem_type_rt = 0;
+            uint32 min_size = 0, max_size = 0;
+
+#if WASM_ENABLE_INTERP != 0
+            if ((*module)->module_type == Wasm_Module_Bytecode) {
+                WASMImport *import =
+                  MODULE_INTERP(module)->import_tables
+                  + (i - import_func_count - import_global_count
+                     - import_memory_count);
+                module_name_rt = import->u.names.module_name;
+                field_name_rt = import->u.names.field_name;
+                elem_type_rt = import->u.table.elem_type;
+                min_size = import->u.table.init_size;
+                max_size = import->u.table.max_size;
+            }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+            if ((*module)->module_type == Wasm_Module_AoT) {
+                AOTImportTable *import =
+                  MODULE_AOT(module)->import_tables
+                  + (i - import_func_count - import_global_count
+                     - import_memory_count);
+                module_name_rt = import->module_name;
+                field_name_rt = import->table_name;
+                elem_type_rt = VALUE_TYPE_FUNCREF;
+                min_size = import->table_init_size;
+                max_size = import->table_max_size;
+            }
+#endif
+
+            if (!module_name_rt || !field_name_rt) {
+                continue;
+            }
+
+            if (!(type = wasm_tabletype_new_internal(elem_type_rt, min_size,
+                                                     max_size))) {
+                goto failed;
+            }
+
+            extern_type = wasm_tabletype_as_externtype(type);
+        }
+
+        if (!extern_type) {
+            continue;
+        }
+
+        if (!(import_type =
+                wasm_importtype_new(&module_name, &name, extern_type))) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)out, &import_type)) {
+            goto failed_importtype_new;
+        }
+    }
+
+    return;
+
+failed:
+    wasm_byte_vec_delete(&module_name);
+    wasm_byte_vec_delete(&name);
+    wasm_externtype_delete(extern_type);
+failed_importtype_new:
+    wasm_importtype_delete(import_type);
+    wasm_importtype_vec_delete(out);
+}
+
+void
+wasm_module_exports(const wasm_module_t *module, wasm_exporttype_vec_t *out)
+{
+    uint32 i, export_count = 0;
+    wasm_byte_vec_t name = { 0 };
+    wasm_externtype_t *extern_type = NULL;
+    wasm_exporttype_t *export_type = NULL;
+
+    if (!module || !out || !valid_module_type((*module)->module_type)) {
+        return;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if ((*module)->module_type == Wasm_Module_Bytecode) {
+        export_count = MODULE_INTERP(module)->export_count;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if ((*module)->module_type == Wasm_Module_AoT) {
+        export_count = MODULE_AOT(module)->export_count;
+    }
+#endif
+
+    wasm_exporttype_vec_new_uninitialized(out, export_count);
+    if (export_count && !out->data) {
+        return;
+    }
+
+    for (i = 0; i != export_count; i++) {
+        WASMExport *export = NULL;
+#if WASM_ENABLE_INTERP != 0
+        if ((*module)->module_type == Wasm_Module_Bytecode) {
+            export = MODULE_INTERP(module)->exports + i;
+        }
+#endif
+#if WASM_ENABLE_AOT != 0
+        if ((*module)->module_type == Wasm_Module_AoT) {
+            export = MODULE_AOT(module)->exports + i;
+        }
+#endif
+
+        if (!export) {
+            continue;
+        }
+
+        /* byte* -> wasm_byte_vec_t */
+        wasm_name_new_from_string(&name, export->name);
+        if (strlen(export->name) && !name.data) {
+            goto failed;
+        }
+
+        /* WASMExport -> (WASMType, (uint8, bool)) -> (wasm_functype_t, wasm_globaltype_t) -> wasm_externtype_t*/
+        switch (export->kind) {
+            case EXPORT_KIND_FUNC:
+            {
+                wasm_functype_t *type = NULL;
+                WASMType *type_rt;
+
+                if (!wasm_runtime_get_export_func_type(*module, export,
+                                                       &type_rt)) {
+                    goto failed;
+                }
+
+                if (!(type = wasm_functype_new_internal(type_rt))) {
+                    goto failed;
+                }
+
+                extern_type = wasm_functype_as_externtype(type);
+                break;
+            }
+            case EXPORT_KIND_GLOBAL:
+            {
+                wasm_globaltype_t *type = NULL;
+                uint8 val_type_rt = 0;
+                bool mutability_rt = 0;
+
+                if (!wasm_runtime_get_export_global_type(
+                      *module, export, &val_type_rt, &mutability_rt)) {
+                    goto failed;
+                }
+
+                if (!(type = wasm_globaltype_new_internal(val_type_rt,
+                                                          mutability_rt))) {
+                    goto failed;
+                }
+
+                extern_type = wasm_globaltype_as_externtype(type);
+                break;
+            }
+            case EXPORT_KIND_MEMORY:
+            {
+                wasm_memorytype_t *type = NULL;
+                uint32 min_page = 0, max_page = 0;
+
+                if (!wasm_runtime_get_export_memory_type(
+                      *module, export, &min_page, &max_page)) {
+                    goto failed;
+                }
+
+                if (!(type =
+                        wasm_memorytype_new_internal(min_page, max_page))) {
+                    goto failed;
+                }
+
+                extern_type = wasm_memorytype_as_externtype(type);
+                break;
+            }
+            case EXPORT_KIND_TABLE:
+            {
+                wasm_tabletype_t *type = NULL;
+                uint8 elem_type_rt = 0;
+                uint32 min_size = 0, max_size = 0;
+
+                if (!wasm_runtime_get_export_table_type(
+                      *module, export, &elem_type_rt, &min_size, &max_size)) {
+                    goto failed;
+                }
+
+                if (!(type = wasm_tabletype_new_internal(
+                        elem_type_rt, min_size, max_size))) {
+                    goto failed;
+                }
+
+                extern_type = wasm_tabletype_as_externtype(type);
+                break;
+            }
+            default:
+            {
+                LOG_WARNING("%s meets unsupported type", __FUNCTION__,
+                            export->kind);
+                break;
+            }
+        }
+
+        if (!(export_type = wasm_exporttype_new(&name, extern_type))) {
+            goto failed;
+        }
+
+        if (!(bh_vector_append((Vector *)out, &export_type))) {
+            goto failed_exporttype_new;
+        }
+    }
+
+    return;
+
+failed:
+    wasm_byte_vec_delete(&name);
+    wasm_externtype_delete(extern_type);
+failed_exporttype_new:
+    wasm_exporttype_delete(export_type);
+    wasm_exporttype_vec_delete(out);
+}
+
+static wasm_func_t *
+wasm_func_new_basic(const wasm_functype_t *type,
+                    wasm_func_callback_t func_callback)
+{
+    wasm_func_t *func = NULL;
+
+    if (!(func = malloc_internal(sizeof(wasm_func_t)))) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+    func->with_env = false;
+    func->u.cb = func_callback;
+
+    if (!(func->type = wasm_functype_copy(type))) {
+        goto failed;
+    }
+
+    RETURN_OBJ(func, wasm_func_delete)
+}
+
+static wasm_func_t *
+wasm_func_new_with_env_basic(const wasm_functype_t *type,
+                             wasm_func_callback_with_env_t callback,
+                             void *env,
+                             void (*finalizer)(void *))
+{
+    wasm_func_t *func = NULL;
+
+    if (!(func = malloc_internal(sizeof(wasm_func_t)))) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+    func->with_env = true;
+    func->u.cb_env.cb = callback;
+    func->u.cb_env.env = env;
+    func->u.cb_env.finalizer = finalizer;
+
+    if (!(func->type = wasm_functype_copy(type))) {
+        goto failed;
+    }
+
+    RETURN_OBJ(func, wasm_func_delete)
+}
+
+wasm_func_t *
+wasm_func_new(wasm_store_t *store,
+              const wasm_functype_t *type,
+              wasm_func_callback_t callback)
+{
+    bh_assert(singleton_engine);
+    return wasm_func_new_basic(type, callback);
+}
+
+wasm_func_t *
+wasm_func_new_with_env(wasm_store_t *store,
+                       const wasm_functype_t *type,
+                       wasm_func_callback_with_env_t callback,
+                       void *env,
+                       void (*finalizer)(void *))
+{
+    bh_assert(singleton_engine);
+    return wasm_func_new_with_env_basic(type, callback, env, finalizer);
+}
+
+static wasm_func_t *
+wasm_func_new_internal(wasm_store_t *store,
+                       uint16 func_idx_rt,
+                       WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_func_t *func = NULL;
+    WASMType *type_rt = NULL;
+
+    bh_assert(singleton_engine);
+
+    if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) {
+        return NULL;
+    }
+
+    func = malloc_internal(sizeof(wasm_func_t));
+    if (!func) {
+        goto failed;
+    }
+
+    func->kind = WASM_EXTERN_FUNC;
+
+#if WASM_ENABLE_INTERP != 0
+    if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        bh_assert(func_idx_rt
+                  < ((WASMModuleInstance *)inst_comm_rt)->function_count);
+        WASMFunctionInstance *func_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->functions + func_idx_rt;
+        type_rt = func_interp->is_import_func
+                    ? func_interp->u.func_import->func_type
+                    : func_interp->u.func->func_type;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+        /* use same index to trace the function type in AOTFuncType **func_types */
+        AOTModule *module_aot =
+          ((AOTModuleInstance *)inst_comm_rt)->aot_module.ptr;
+        if (func_idx_rt < module_aot->import_func_count) {
+            type_rt = (module_aot->import_funcs + func_idx_rt)->func_type;
+        }
+        else {
+            type_rt =
+              module_aot
+                ->func_types[module_aot->func_type_indexes
+                               [func_idx_rt - module_aot->import_func_count]];
+        }
+    }
+#endif
+
+    if (!type_rt) {
+        goto failed;
+    }
+
+    func->type = wasm_functype_new_internal(type_rt);
+    if (!func->type) {
+        goto failed;
+    }
+
+    /* will add name information when processing "exports" */
+    func->module_name = NULL;
+    func->name = NULL;
+    func->func_idx_rt = func_idx_rt;
+    func->inst_comm_rt = inst_comm_rt;
+    return func;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_func_delete(func);
+    return NULL;
+}
+
+void
+wasm_func_delete(wasm_func_t *func)
+{
+    if (!func) {
+        return;
+    }
+
+    if (func->type) {
+        wasm_functype_delete(func->type);
+        func->type = NULL;
+    }
+
+    if (func->with_env) {
+        if (func->u.cb_env.finalizer) {
+            func->u.cb_env.finalizer(func->u.cb_env.env);
+            func->u.cb_env.finalizer = NULL;
+            func->u.cb_env.env = NULL;
+        }
+    }
+
+    wasm_runtime_free(func);
+}
+
+own wasm_func_t *
+wasm_func_copy(const wasm_func_t *func)
+{
+    wasm_func_t *cloned = NULL;
+
+    if (!func) {
+        return NULL;
+    }
+
+    if (!(cloned = func->with_env
+                     ? wasm_func_new_with_env_basic(
+                       func->type, func->u.cb_env.cb, func->u.cb_env.env,
+                       func->u.cb_env.finalizer)
+                     : wasm_func_new_basic(func->type, func->u.cb))) {
+        goto failed;
+    }
+
+    cloned->func_idx_rt = func->func_idx_rt;
+    cloned->inst_comm_rt = func->inst_comm_rt;
+
+    RETURN_OBJ(cloned, wasm_func_delete)
+}
+
+own wasm_functype_t *
+wasm_func_type(const wasm_func_t *func)
+{
+    if (!func) {
+        return NULL;
+    }
+    return wasm_functype_copy(func->type);
+}
+
+static uint32
+params_to_argv(const wasm_val_t *params,
+               const wasm_valtype_vec_t *param_defs,
+               size_t param_arity,
+               uint32 *out)
+{
+    size_t i = 0;
+    uint32 argc = 0;
+    const wasm_val_t *param = NULL;
+
+    if (!param_arity) {
+        return 0;
+    }
+
+    bh_assert(params && param_defs && out);
+    bh_assert(param_defs->num_elems == param_arity);
+
+    for (i = 0; out && i < param_arity; ++i) {
+        param = params + i;
+        bh_assert((*(param_defs->data + i))->kind == param->kind);
+
+        switch (param->kind) {
+            case WASM_I32:
+                *(int32 *)out = param->of.i32;
+                out += 1;
+                argc += 1;
+                break;
+            case WASM_I64:
+                *(int64 *)out = param->of.i64;
+                out += 2;
+                argc += 2;
+                break;
+            case WASM_F32:
+                *(float32 *)out = param->of.f32;
+                out += 1;
+                argc += 1;
+                break;
+            case WASM_F64:
+                *(float64 *)out = param->of.f64;
+                out += 2;
+                argc += 2;
+                break;
+            default:
+                LOG_DEBUG("unexpected parameter val type %d", param->kind);
+                goto failed;
+        }
+    }
+
+    return argc;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return 0;
+}
+
+static uint32
+argv_to_results(const uint32 *results,
+                const wasm_valtype_vec_t *result_defs,
+                size_t result_arity,
+                wasm_val_t *out)
+{
+    size_t i = 0;
+    uint32 argc = 0;
+    const uint32 *result = results;
+    const wasm_valtype_t *def = NULL;
+
+    if (!result_arity) {
+        return 0;
+    }
+
+    bh_assert(results && result_defs && out);
+    bh_assert(result_arity == result_defs->num_elems);
+
+    for (i = 0; out && i < result_arity; i++) {
+        def = *(result_defs->data + i);
+
+        switch (def->kind) {
+            case WASM_I32:
+            {
+                out->kind = WASM_I32;
+                out->of.i32 = *(int32 *)result;
+                result += 1;
+                break;
+            }
+            case WASM_I64:
+            {
+                out->kind = WASM_I64;
+                out->of.i64 = *(int64 *)result;
+                result += 2;
+                break;
+            }
+            case WASM_F32:
+            {
+                out->kind = WASM_F32;
+                out->of.f32 = *(float32 *)result;
+                result += 1;
+                break;
+            }
+            case WASM_F64:
+            {
+                out->kind = WASM_F64;
+                out->of.f64 = *(float64 *)result;
+                result += 2;
+                break;
+            }
+            default:
+                LOG_WARNING("%s meets unsupported type: %d", __FUNCTION__,
+                            def->kind);
+                goto failed;
+        }
+        out++;
+        argc++;
+    }
+
+    return argc;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return 0;
+}
+
+wasm_trap_t *
+wasm_func_call(const wasm_func_t *func,
+               const wasm_val_t params[],
+               wasm_val_t results[])
+{
+    /* parameters count as if all are uint32 */
+    /* a int64 or float64 parameter means 2 */
+    uint32 argc = 0;
+    /* a parameter list and a return value list */
+    uint32 argv_buf[32], *argv = argv_buf;
+    WASMFunctionInstanceCommon *func_comm_rt = NULL;
+    WASMExecEnv *exec_env = NULL;
+    size_t param_count, result_count, alloc_count;
+
+    bh_assert(func && func->type && func->inst_comm_rt);
+
+#if WASM_ENABLE_INTERP != 0
+    if (func->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        func_comm_rt = ((WASMModuleInstance *)func->inst_comm_rt)->functions
+                       + func->func_idx_rt;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (func->inst_comm_rt->module_type == Wasm_Module_AoT) {
+        if (!(func_comm_rt = func->func_comm_rt)) {
+            AOTModuleInstance *inst_aot =
+              (AOTModuleInstance *)func->inst_comm_rt;
+            AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
+            uint32 export_i = 0, export_func_j = 0;
+
+            for (; export_i < module_aot->export_count; ++export_i) {
+                AOTExport *export = module_aot->exports + export_i;
+                if (export->kind == EXPORT_KIND_FUNC) {
+                    if (export->index == func->func_idx_rt) {
+                        func_comm_rt =
+                          (AOTFunctionInstance *)inst_aot->export_funcs.ptr
+                          + export_func_j;
+                        ((wasm_func_t *)func)->func_comm_rt = func_comm_rt;
+                        break;
+                    }
+                    export_func_j++;
+                }
+            }
+        }
+    }
+#endif
+
+    if (!func_comm_rt) {
+        goto failed;
+    }
+
+    param_count = wasm_func_param_arity(func);
+    result_count = wasm_func_result_arity(func);
+    alloc_count = (param_count > result_count) ? param_count : result_count;
+    if (alloc_count > sizeof(argv_buf) / sizeof(uint64)) {
+        if (!(argv = malloc_internal(sizeof(uint64) * alloc_count))) {
+            goto failed;
+        }
+    }
+
+    /* copy parametes */
+    if (param_count
+        && !(argc = params_to_argv(params, wasm_functype_params(func->type),
+                                   param_count, argv))) {
+        goto failed;
+    }
+
+    exec_env = wasm_runtime_get_exec_env_singleton(func->inst_comm_rt);
+    if (!exec_env) {
+        goto failed;
+    }
+
+    if (!wasm_runtime_call_wasm(exec_env, func_comm_rt, argc, argv)) {
+        if (wasm_runtime_get_exception(func->inst_comm_rt)) {
+            LOG_DEBUG(wasm_runtime_get_exception(func->inst_comm_rt));
+            goto failed;
+        }
+    }
+
+    /* copy results */
+    if (result_count) {
+        if (!(argc = argv_to_results(argv, wasm_functype_results(func->type),
+                                     result_count, results))) {
+            goto failed;
+        }
+    }
+
+    if (argv != argv_buf)
+        wasm_runtime_free(argv);
+    return NULL;
+
+failed:
+    if (argv != argv_buf)
+        wasm_runtime_free(argv);
+
+    if (wasm_runtime_get_exception(func->inst_comm_rt)) {
+        return wasm_trap_new_internal(
+          wasm_runtime_get_exception(func->inst_comm_rt));
+    }
+    else {
+        return wasm_trap_new_internal("wasm_func_call failed");
+    }
+}
+
+size_t
+wasm_func_param_arity(const wasm_func_t *func)
+{
+    if (!func || !func->type || !func->type->params) {
+        return 0;
+    }
+    return func->type->params->num_elems;
+}
+
+size_t
+wasm_func_result_arity(const wasm_func_t *func)
+{
+    if (!func || !func->type || !func->type->results) {
+        return 0;
+    }
+    return func->type->results->num_elems;
+}
+
+wasm_global_t *
+wasm_global_new(wasm_store_t *store,
+                const wasm_globaltype_t *global_type,
+                const wasm_val_t *init)
+{
+    wasm_global_t *global = NULL;
+
+    bh_assert(singleton_engine);
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    global->kind = WASM_EXTERN_GLOBAL;
+    global->type = wasm_globaltype_copy(global_type);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+    wasm_val_copy(global->init, init);
+    /* TODO: how to check if above is failed */
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+/* almost same with wasm_global_new */
+wasm_global_t *
+wasm_global_copy(const wasm_global_t *src)
+{
+    wasm_global_t *global = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    global->kind = WASM_EXTERN_GLOBAL;
+    global->type = wasm_globaltype_copy(src->type);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+    wasm_val_copy(global->init, src->init);
+
+    global->global_idx_rt = src->global_idx_rt;
+    global->inst_comm_rt = src->inst_comm_rt;
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+void
+wasm_global_delete(wasm_global_t *global)
+{
+    if (!global) {
+        return;
+    }
+
+    if (global->init) {
+        wasm_val_delete(global->init);
+        global->init = NULL;
+    }
+
+    if (global->type) {
+        wasm_globaltype_delete(global->type);
+        global->type = NULL;
+    }
+
+    wasm_runtime_free(global);
+}
+
+bool
+wasm_global_same(const wasm_global_t *g1, const wasm_global_t *g2)
+{
+    if (!g1 && !g2) {
+        return true;
+    }
+
+    if (!g1 || !g2) {
+        return false;
+    }
+
+    return g1->kind == g2->kind && wasm_globaltype_same(g1->type, g2->type)
+           && wasm_val_same(g1->init, g2->init);
+}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_global_set(const WASMModuleInstance *inst_interp,
+                  uint16 global_idx_rt,
+                  const wasm_val_t *v)
+{
+    const WASMGlobalInstance *global_interp =
+      inst_interp->globals + global_idx_rt;
+    uint8 val_type_rt = global_interp->type;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    uint8 *data = global_interp->import_global_inst
+                    ? global_interp->import_module_inst->global_data
+                        + global_interp->import_global_inst->data_offset
+                    : inst_interp->global_data + global_interp->data_offset;
+#else
+    uint8 *data = inst_interp->global_data + global_interp->data_offset;
+#endif
+    bool ret = true;
+
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            bh_assert(WASM_I32 == v->kind);
+            *((int32 *)data) = v->of.i32;
+            break;
+        case VALUE_TYPE_F32:
+            bh_assert(WASM_F32 == v->kind);
+            *((float32 *)data) = v->of.f32;
+            break;
+        case VALUE_TYPE_I64:
+            bh_assert(WASM_I64 == v->kind);
+            *((int64 *)data) = v->of.i64;
+            break;
+        case VALUE_TYPE_F64:
+            bh_assert(WASM_F64 == v->kind);
+            *((float64 *)data) = v->of.f64;
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+            break;
+    }
+
+    return ret;
+}
+
+static bool
+interp_global_get(const WASMModuleInstance *inst_interp,
+                  uint16 global_idx_rt,
+                  wasm_val_t *out)
+{
+    WASMGlobalInstance *global_interp = inst_interp->globals + global_idx_rt;
+    uint8 val_type_rt = global_interp->type;
+#if WASM_ENABLE_MULTI_MODULE != 0
+    uint8 *data = global_interp->import_global_inst
+                    ? global_interp->import_module_inst->global_data
+                        + global_interp->import_global_inst->data_offset
+                    : inst_interp->global_data + global_interp->data_offset;
+#else
+    uint8 *data = inst_interp->global_data + global_interp->data_offset;
+#endif
+    bool ret = true;
+
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            out->kind = WASM_I32;
+            out->of.i32 = *((int32 *)data);
+            break;
+        case VALUE_TYPE_F32:
+            out->kind = WASM_F32;
+            out->of.f32 = *((float32 *)data);
+            break;
+        case VALUE_TYPE_I64:
+            out->kind = WASM_I64;
+            out->of.i64 = *((int64 *)data);
+            break;
+        case VALUE_TYPE_F64:
+            out->kind = WASM_F64;
+            out->of.f64 = *((float64 *)data);
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+#endif
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_global_set(const AOTModuleInstance *inst_aot,
+               uint16 global_idx_rt,
+               const wasm_val_t *v)
+{
+    AOTModule *module_aot = inst_aot->aot_module.ptr;
+    uint8 val_type_rt = 0;
+    uint32 data_offset = 0;
+    void *data = NULL;
+    bool ret = true;
+
+    if (global_idx_rt < module_aot->import_global_count) {
+        data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+        val_type_rt = module_aot->import_globals[global_idx_rt].type;
+    }
+    else {
+        data_offset =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .data_offset;
+        val_type_rt =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .type;
+    }
+
+    data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset);
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            bh_assert(WASM_I32 == v->kind);
+            *((int32 *)data) = v->of.i32;
+            break;
+        case VALUE_TYPE_F32:
+            bh_assert(WASM_F32 == v->kind);
+            *((float32 *)data) = v->of.f32;
+            break;
+        case VALUE_TYPE_I64:
+            bh_assert(WASM_I64 == v->kind);
+            *((int64 *)data) = v->of.i64;
+            break;
+        case VALUE_TYPE_F64:
+            bh_assert(WASM_F64 == v->kind);
+            *((float64 *)data) = v->of.f64;
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+
+static bool
+aot_global_get(const AOTModuleInstance *inst_aot,
+               uint16 global_idx_rt,
+               wasm_val_t *out)
+{
+    AOTModule *module_aot = inst_aot->aot_module.ptr;
+    uint8 val_type_rt = 0;
+    uint32 data_offset = 0;
+    void *data = NULL;
+    bool ret = true;
+
+    if (global_idx_rt < module_aot->import_global_count) {
+        data_offset = module_aot->import_globals[global_idx_rt].data_offset;
+        val_type_rt = module_aot->import_globals[global_idx_rt].type;
+    }
+    else {
+        data_offset =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .data_offset;
+        val_type_rt =
+          module_aot->globals[global_idx_rt - module_aot->import_global_count]
+            .type;
+    }
+
+    data = (void *)((uint8 *)inst_aot->global_data.ptr + data_offset);
+    switch (val_type_rt) {
+        case VALUE_TYPE_I32:
+            out->kind = WASM_I32;
+            out->of.i32 = *((int32 *)data);
+            break;
+        case VALUE_TYPE_F32:
+            out->kind = WASM_F32;
+            out->of.f32 = *((float32 *)data);
+            break;
+        case VALUE_TYPE_I64:
+            out->kind = WASM_I64;
+            out->of.i64 = *((int64 *)data);
+            break;
+        case VALUE_TYPE_F64:
+            out->kind = WASM_F64;
+            out->of.f64 = *((float64 *)data);
+            break;
+        default:
+            LOG_DEBUG("unexpected value type %d", val_type_rt);
+            ret = false;
+    }
+    return ret;
+}
+#endif
+
+void
+wasm_global_set(wasm_global_t *global, const wasm_val_t *v)
+{
+    if (!global || !v
+        || !valid_module_type(global->inst_comm_rt->module_type)) {
+        return;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        (void)interp_global_set((WASMModuleInstance *)global->inst_comm_rt,
+                                global->global_idx_rt, v);
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (global->inst_comm_rt->module_type == Wasm_Module_AoT) {
+        (void)aot_global_set((AOTModuleInstance *)global->inst_comm_rt,
+                             global->global_idx_rt, v);
+    }
+#endif
+}
+
+void
+wasm_global_get(const wasm_global_t *global, wasm_val_t *out)
+{
+    if (!global || !out
+        || !valid_module_type(global->inst_comm_rt->module_type)) {
+        return;
+    }
+
+    memset(out, 0, sizeof(wasm_val_t));
+
+#if WASM_ENABLE_INTERP != 0
+    if (global->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        (void)interp_global_get((WASMModuleInstance *)global->inst_comm_rt,
+                                global->global_idx_rt, out);
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (global->inst_comm_rt->module_type == Wasm_Module_AoT) {
+        (void)aot_global_get((AOTModuleInstance *)global->inst_comm_rt,
+                             global->global_idx_rt, out);
+    }
+#endif
+
+    bh_assert(global->init->kind == out->kind);
+}
+
+static wasm_global_t *
+wasm_global_new_internal(wasm_store_t *store,
+                         uint16 global_idx_rt,
+                         WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_global_t *global = NULL;
+    uint8 val_type_rt = 0;
+    bool is_mutable = 0;
+
+    bh_assert(singleton_engine);
+
+    if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) {
+        return NULL;
+    }
+
+    global = malloc_internal(sizeof(wasm_global_t));
+    if (!global) {
+        goto failed;
+    }
+
+    /*
+     * global->module_name = NULL;
+     * global->name = NULL;
+     */
+    global->kind = WASM_EXTERN_GLOBAL;
+
+#if WASM_ENABLE_INTERP != 0
+    if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        WASMGlobalInstance *global_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->globals + global_idx_rt;
+        val_type_rt = global_interp->type;
+        is_mutable = global_interp->is_mutable;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+        AOTModule *module_aot = inst_aot->aot_module.ptr;
+        if (global_idx_rt < module_aot->import_global_count) {
+            AOTImportGlobal *global_import_aot =
+              module_aot->import_globals + global_idx_rt;
+            val_type_rt = global_import_aot->type;
+            is_mutable = global_import_aot->is_mutable;
+        }
+        else {
+            AOTGlobal *global_aot =
+              module_aot->globals
+              + (global_idx_rt - module_aot->import_global_count);
+            val_type_rt = global_aot->type;
+            is_mutable = global_aot->is_mutable;
+        }
+    }
+#endif
+
+    global->type = wasm_globaltype_new_internal(val_type_rt, is_mutable);
+    if (!global->type) {
+        goto failed;
+    }
+
+    global->init = malloc_internal(sizeof(wasm_val_t));
+    if (!global->init) {
+        goto failed;
+    }
+
+#if WASM_ENABLE_INTERP != 0
+    if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        interp_global_get((WASMModuleInstance *)inst_comm_rt, global_idx_rt,
+                          global->init);
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+        aot_global_get((AOTModuleInstance *)inst_comm_rt, global_idx_rt,
+                       global->init);
+    }
+#endif
+
+    global->inst_comm_rt = inst_comm_rt;
+    global->global_idx_rt = global_idx_rt;
+
+    return global;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_global_delete(global);
+    return NULL;
+}
+
+wasm_globaltype_t *
+wasm_global_type(const wasm_global_t *global)
+{
+    if (!global) {
+        return NULL;
+    }
+    return wasm_globaltype_copy(global->type);
+}
+
+static wasm_table_t *
+wasm_table_new_basic(const wasm_tabletype_t *type)
+{
+    wasm_table_t *table = NULL;
+
+    if (!(table = malloc_internal(sizeof(wasm_table_t)))) {
+        goto failed;
+    }
+
+    table->kind = WASM_EXTERN_TABLE;
+
+    if (!(table->type = wasm_tabletype_copy(type))) {
+        goto failed;
+    }
+
+    RETURN_OBJ(table, wasm_table_delete);
+}
+
+static wasm_table_t *
+wasm_table_new_internal(wasm_store_t *store,
+                        uint16 table_idx_rt,
+                        WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_table_t *table = NULL;
+    uint8 val_type_rt = 0;
+    uint32 init_size = 0, max_size = 0;
+
+    bh_assert(singleton_engine);
+
+    if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) {
+        return NULL;
+    }
+
+    if (!(table = malloc_internal(sizeof(wasm_table_t)))) {
+        goto failed;
+    }
+
+    table->kind = WASM_EXTERN_TABLE;
+
+#if WASM_ENABLE_INTERP != 0
+    if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        WASMTableInstance *table_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->tables[table_idx_rt];
+        val_type_rt = table_interp->elem_type;
+        init_size = table_interp->cur_size;
+        max_size = table_interp->max_size;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+        AOTModule *module_aot = (AOTModule *)inst_aot->aot_module.ptr;
+
+        if (table_idx_rt < module_aot->import_table_count) {
+            AOTImportTable *table_aot =
+              module_aot->import_tables + table_idx_rt;
+            val_type_rt = VALUE_TYPE_FUNCREF;
+            init_size = table_aot->table_init_size;
+            max_size = table_aot->table_max_size;
+        }
+        else {
+            AOTTable *table_aot =
+              module_aot->tables
+              + (table_idx_rt - module_aot->import_table_count);
+            val_type_rt = VALUE_TYPE_FUNCREF;
+            init_size = table_aot->table_init_size;
+            max_size = table_aot->table_max_size;
+        }
+    }
+#endif
+
+    if (!(table->type =
+            wasm_tabletype_new_internal(val_type_rt, init_size, max_size))) {
+        goto failed;
+    }
+
+    table->inst_comm_rt = inst_comm_rt;
+    table->table_idx_rt = table_idx_rt;
+
+    RETURN_OBJ(table, wasm_table_delete);
+}
+
+wasm_table_t *
+wasm_table_new(wasm_store_t *store,
+               const wasm_tabletype_t *table_type,
+               wasm_ref_t *init)
+{
+    (void)init;
+    bh_assert(singleton_engine);
+    return wasm_table_new_basic(table_type);
+}
+
+wasm_table_t *
+wasm_table_copy(const wasm_table_t *src)
+{
+    return wasm_table_new_basic(src->type);
+}
+
+void
+wasm_table_delete(wasm_table_t *table)
+{
+    if (!table) {
+        return;
+    }
+
+    if (table->type) {
+        wasm_tabletype_delete(table->type);
+        table->type = NULL;
+    }
+
+    wasm_runtime_free(table);
+}
+
+wasm_tabletype_t *
+wasm_table_type(const wasm_table_t *table)
+{
+    if (!table) {
+        return NULL;
+    }
+    return wasm_tabletype_copy(table->type);
+}
+
+static wasm_memory_t *
+wasm_memory_new_basic(const wasm_memorytype_t *type)
+{
+    wasm_memory_t *memory = NULL;
+
+    if (!(memory = malloc_internal(sizeof(wasm_memory_t)))) {
+        goto failed;
+    }
+
+    memory->kind = WASM_EXTERN_MEMORY;
+    memory->type = wasm_memorytype_copy(type);
+
+    RETURN_OBJ(memory, wasm_memory_delete)
+}
+
+wasm_memory_t *
+wasm_memory_new(wasm_store_t *store, const wasm_memorytype_t *type)
+{
+    bh_assert(singleton_engine);
+    return wasm_memory_new_basic(type);
+}
+
+wasm_memory_t *
+wasm_memory_copy(const wasm_memory_t *src)
+{
+    wasm_memory_t *dst = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    if (!(dst = wasm_memory_new_basic(src->type))) {
+        goto failed;
+    }
+
+    dst->memory_idx_rt = src->memory_idx_rt;
+    dst->inst_comm_rt = src->inst_comm_rt;
+
+    RETURN_OBJ(dst, wasm_memory_delete)
+}
+
+static wasm_memory_t *
+wasm_memory_new_internal(wasm_store_t *store,
+                         uint16 memory_idx_rt,
+                         WASMModuleInstanceCommon *inst_comm_rt)
+{
+    wasm_memory_t *memory = NULL;
+    uint32 min_pages = 0, max_pages = 0;
+
+    bh_assert(singleton_engine);
+
+    if (!inst_comm_rt || !valid_module_type(inst_comm_rt->module_type)) {
+        return NULL;
+    }
+
+    if (!(memory = malloc_internal(sizeof(wasm_memory_t)))) {
+        goto failed;
+    }
+
+    memory->kind = WASM_EXTERN_MEMORY;
+
+#if WASM_ENABLE_INTERP != 0
+    if (inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        WASMMemoryInstance *memory_interp =
+          ((WASMModuleInstance *)inst_comm_rt)->memories[memory_idx_rt];
+        min_pages = memory_interp->cur_page_count;
+        max_pages = memory_interp->max_page_count;
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (inst_comm_rt->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *inst_aot = (AOTModuleInstance *)inst_comm_rt;
+        AOTModule *module_aot = (AOTModule *)(inst_aot->aot_module.ptr);
+
+        if (memory_idx_rt < module_aot->import_memory_count) {
+            min_pages = module_aot->import_memories->mem_init_page_count;
+            max_pages = module_aot->import_memories->mem_max_page_count;
+        }
+        else {
+            min_pages = module_aot->memories->mem_init_page_count;
+            max_pages = module_aot->memories->mem_max_page_count;
+        }
+    }
+#endif
+
+    if (!(memory->type = wasm_memorytype_new_internal(min_pages, max_pages))) {
+        goto failed;
+    }
+
+    memory->inst_comm_rt = inst_comm_rt;
+    memory->memory_idx_rt = memory_idx_rt;
+
+    RETURN_OBJ(memory, wasm_memory_delete);
+}
+
+void
+wasm_memory_delete(wasm_memory_t *memory)
+{
+    if (!memory) {
+        return;
+    }
+
+    if (memory->type) {
+        wasm_memorytype_delete(memory->type);
+        memory->type = NULL;
+    }
+
+    wasm_runtime_free(memory);
+}
+
+wasm_memorytype_t *
+wasm_memory_type(const wasm_memory_t *memory)
+{
+    if (!memory) {
+        return NULL;
+    }
+
+    return wasm_memorytype_copy(memory->type);
+}
+
+byte_t *
+wasm_memory_data(wasm_memory_t *memory)
+{
+    return (byte_t *)wasm_runtime_get_memory_data(memory->inst_comm_rt,
+                                                  memory->memory_idx_rt);
+}
+
+size_t
+wasm_memory_data_size(const wasm_memory_t *memory)
+{
+    return wasm_runtime_get_memory_data_size(memory->inst_comm_rt,
+                                             memory->memory_idx_rt);
+}
+
+#if WASM_ENABLE_INTERP != 0
+static bool
+interp_link_func(const wasm_instance_t *inst,
+                 const WASMModule *module_interp,
+                 uint16 func_idx_rt,
+                 wasm_func_t *import)
+{
+    WASMImport *imported_func_interp = NULL;
+    wasm_func_t *cloned = NULL;
+
+    bh_assert(inst && module_interp && import);
+    bh_assert(func_idx_rt < module_interp->import_function_count);
+    bh_assert(WASM_EXTERN_FUNC == import->kind);
+
+    imported_func_interp = module_interp->import_functions + func_idx_rt;
+    bh_assert(imported_func_interp);
+
+    if (!(cloned = wasm_func_copy(import))) {
+        return false;
+    }
+
+    if (!bh_vector_append((Vector *)inst->imports, &cloned)) {
+        wasm_func_delete(cloned);
+        return false;
+    }
+
+    imported_func_interp->u.function.call_conv_wasm_c_api = true;
+    imported_func_interp->u.function.wasm_c_api_with_env = import->with_env;
+    if (import->with_env) {
+        imported_func_interp->u.function.func_ptr_linked = import->u.cb_env.cb;
+        imported_func_interp->u.function.attachment = import->u.cb_env.env;
+    }
+    else {
+        imported_func_interp->u.function.func_ptr_linked = import->u.cb;
+        imported_func_interp->u.function.attachment = NULL;
+    }
+    import->func_idx_rt = func_idx_rt;
+
+    return true;
+}
+
+static bool
+interp_link_global(const WASMModule *module_interp,
+                   uint16 global_idx_rt,
+                   wasm_global_t *import)
+{
+    WASMImport *imported_global_interp = NULL;
+
+    bh_assert(module_interp && import);
+    bh_assert(global_idx_rt < module_interp->import_global_count);
+    bh_assert(WASM_EXTERN_GLOBAL == import->kind);
+
+    imported_global_interp = module_interp->import_globals + global_idx_rt;
+    bh_assert(imported_global_interp);
+
+    /* set init value */
+    switch (wasm_valtype_kind(import->type->val_type)) {
+        case WASM_I32:
+            bh_assert(VALUE_TYPE_I32 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.i32 =
+              import->init->of.i32;
+            break;
+        case WASM_I64:
+            bh_assert(VALUE_TYPE_I64 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.i64 =
+              import->init->of.i64;
+            break;
+        case WASM_F32:
+            bh_assert(VALUE_TYPE_F32 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.f32 =
+              import->init->of.f32;
+            break;
+        case WASM_F64:
+            bh_assert(VALUE_TYPE_F64 == imported_global_interp->u.global.type);
+            imported_global_interp->u.global.global_data_linked.f64 =
+              import->init->of.f64;
+            break;
+        default:
+            return false;
+    }
+
+    import->global_idx_rt = global_idx_rt;
+    imported_global_interp->u.global.is_linked = true;
+    return true;
+}
+
+static uint32
+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))) {
+                    goto failed;
+                }
+
+                break;
+            }
+            case IMPORT_KIND_GLOBAL:
+            {
+                if (!interp_link_global(module_interp, import_global_i++,
+                                        wasm_extern_as_global(import))) {
+                    goto failed;
+                }
+
+                break;
+            }
+            case IMPORT_KIND_MEMORY:
+            case IMPORT_KIND_TABLE:
+                ASSERT_NOT_IMPLEMENTED();
+                break;
+            default:
+                LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                            import_rt->kind);
+                goto failed;
+        }
+    }
+
+    return i;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return (uint32)-1;
+}
+
+static bool
+interp_process_export(wasm_store_t *store,
+                      const WASMModuleInstance *inst_interp,
+                      wasm_extern_vec_t *externals)
+{
+    WASMExport *exports = NULL;
+    WASMExport *export = NULL;
+    wasm_extern_t *external = NULL;
+    uint32 export_cnt = 0;
+    uint32 i = 0;
+
+    bh_assert(store && inst_interp && inst_interp->module && externals);
+
+    exports = inst_interp->module->exports;
+    export_cnt = inst_interp->module->export_count;
+
+    for (i = 0; i < export_cnt; ++i) {
+        export = exports + i;
+
+        switch (export->kind) {
+            case EXPORT_KIND_FUNC:
+            {
+                wasm_func_t *func;
+                if (!(func = wasm_func_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_interp))) {
+                    goto failed;
+                }
+
+                external = wasm_func_as_extern(func);
+                break;
+            }
+            case EXPORT_KIND_GLOBAL:
+            {
+                wasm_global_t *global;
+                if (!(global = wasm_global_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_interp))) {
+                    goto failed;
+                }
+
+                external = wasm_global_as_extern(global);
+                break;
+            }
+            case EXPORT_KIND_TABLE:
+            {
+                wasm_table_t *table;
+                if (!(table = wasm_table_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_interp))) {
+                    goto failed;
+                }
+
+                external = wasm_table_as_extern(table);
+                break;
+            }
+            case EXPORT_KIND_MEMORY:
+            {
+                wasm_memory_t *memory;
+                if (!(memory = wasm_memory_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_interp))) {
+                    goto failed;
+                }
+
+                external = wasm_memory_as_extern(memory);
+                break;
+            }
+            default:
+                LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                            export->kind);
+                goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)externals, &external)) {
+            goto failed;
+        }
+    }
+
+    return true;
+
+failed:
+    wasm_extern_delete(external);
+    return false;
+}
+#endif /* WASM_ENABLE_INTERP */
+
+#if WASM_ENABLE_AOT != 0
+static bool
+aot_link_func(const wasm_instance_t *inst,
+              const AOTModule *module_aot,
+              uint32 import_func_idx_rt,
+              wasm_func_t *import)
+{
+    AOTImportFunc *import_aot_func = NULL;
+    wasm_func_t *cloned = NULL;
+
+    bh_assert(inst && module_aot && import);
+
+    import_aot_func = module_aot->import_funcs + import_func_idx_rt;
+    bh_assert(import_aot_func);
+
+    if (!(cloned = wasm_func_copy(import))) {
+        return false;
+    }
+
+    if (!bh_vector_append((Vector *)inst->imports, &cloned)) {
+        wasm_func_delete(cloned);
+        return false;
+    }
+
+    import_aot_func->call_conv_wasm_c_api = true;
+    import_aot_func->wasm_c_api_with_env = import->with_env;
+    if (import->with_env) {
+        import_aot_func->func_ptr_linked = import->u.cb_env.cb;
+        import_aot_func->attachment = import->u.cb_env.env;
+    }
+    else
+        import_aot_func->func_ptr_linked = import->u.cb;
+    import->func_idx_rt = import_func_idx_rt;
+
+    return true;
+}
+
+static bool
+aot_link_global(const AOTModule *module_aot,
+                uint16 global_idx_rt,
+                wasm_global_t *import)
+{
+    AOTImportGlobal *import_aot_global = NULL;
+    const wasm_valtype_t *val_type = NULL;
+
+    bh_assert(module_aot && import);
+
+    import_aot_global = module_aot->import_globals + global_idx_rt;
+    bh_assert(import_aot_global);
+
+    //TODO: import->type ?
+    val_type = wasm_globaltype_content(import->type);
+    bh_assert(val_type);
+
+    switch (wasm_valtype_kind(val_type)) {
+        case WASM_I32:
+            bh_assert(VALUE_TYPE_I32 == import_aot_global->type);
+            import_aot_global->global_data_linked.i32 = import->init->of.i32;
+            break;
+        case WASM_I64:
+            bh_assert(VALUE_TYPE_I64 == import_aot_global->type);
+            import_aot_global->global_data_linked.i64 = import->init->of.i64;
+            break;
+        case WASM_F32:
+            bh_assert(VALUE_TYPE_F32 == import_aot_global->type);
+            import_aot_global->global_data_linked.f32 = import->init->of.f32;
+            break;
+        case WASM_F64:
+            bh_assert(VALUE_TYPE_F64 == import_aot_global->type);
+            import_aot_global->global_data_linked.f64 = import->init->of.f64;
+            break;
+        default:
+            goto failed;
+    }
+
+    import->global_idx_rt = global_idx_rt;
+    return true;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return false;
+}
+
+static uint32
+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)) {
+                    goto failed;
+                }
+
+                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)) {
+                    goto failed;
+                }
+
+                break;
+            case WASM_EXTERN_MEMORY:
+            case WASM_EXTERN_TABLE:
+                ASSERT_NOT_IMPLEMENTED();
+                break;
+            default:
+                goto failed;
+        }
+    }
+
+    return i;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    return (uint32)-1;
+}
+
+static bool
+aot_process_export(wasm_store_t *store,
+                   const AOTModuleInstance *inst_aot,
+                   wasm_extern_vec_t *externals)
+{
+    uint32 i;
+    wasm_extern_t *external = NULL;
+    AOTModule *module_aot = NULL;
+
+    bh_assert(store && inst_aot && externals);
+
+    module_aot = (AOTModule *)inst_aot->aot_module.ptr;
+    bh_assert(module_aot);
+
+    for (i = 0; i < module_aot->export_count; ++i) {
+        AOTExport *export = module_aot->exports + i;
+
+        switch (export->kind) {
+            case EXPORT_KIND_FUNC:
+            {
+                wasm_func_t *func = NULL;
+                if (!(func = wasm_func_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_aot))) {
+                    goto failed;
+                }
+
+                external = wasm_func_as_extern(func);
+                break;
+            }
+            case EXPORT_KIND_GLOBAL:
+            {
+                wasm_global_t *global = NULL;
+                if (!(global = wasm_global_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_aot))) {
+                    goto failed;
+                }
+
+                external = wasm_global_as_extern(global);
+                break;
+            }
+            case EXPORT_KIND_TABLE:
+            {
+                wasm_table_t *table;
+                if (!(table = wasm_table_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_aot))) {
+                    goto failed;
+                }
+
+                external = wasm_table_as_extern(table);
+                break;
+            }
+            case EXPORT_KIND_MEMORY:
+            {
+                wasm_memory_t *memory;
+                if (!(memory = wasm_memory_new_internal(
+                        store, export->index,
+                        (WASMModuleInstanceCommon *)inst_aot))) {
+                    goto failed;
+                }
+
+                external = wasm_memory_as_extern(memory);
+                break;
+            }
+            default:
+                LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                            export->kind);
+                goto failed;
+        }
+
+        if (!(external->name = malloc_internal(sizeof(wasm_byte_vec_t)))) {
+            goto failed;
+        }
+
+        wasm_name_new_from_string(external->name, export->name);
+        if (strlen(export->name) && !external->name->data) {
+            goto failed;
+        }
+
+        if (!bh_vector_append((Vector *)externals, &external)) {
+            goto failed;
+        }
+    }
+
+    return true;
+
+failed:
+    wasm_extern_delete(external);
+    return false;
+}
+#endif /* WASM_ENABLE_AOT */
+
+wasm_instance_t *
+wasm_instance_new(wasm_store_t *store,
+                  const wasm_module_t *module,
+                  const wasm_extern_t *const imports[],
+                  own wasm_trap_t **traps)
+{
+    char error_buf[128] = { 0 };
+    const uint32 stack_size = 16 * 1024;
+    const uint32 heap_size = 16 * 1024;
+    uint32 import_count = 0;
+    wasm_instance_t *instance = NULL;
+    uint32 i = 0;
+    (void)traps;
+
+    bh_assert(singleton_engine);
+
+    if (!module || !valid_module_type((*module)->module_type)) {
+        return NULL;
+    }
+
+    instance = malloc_internal(sizeof(wasm_instance_t));
+    if (!instance) {
+        goto failed;
+    }
+
+    /* link module and imports */
+    if (imports) {
+#if WASM_ENABLE_INTERP != 0
+        if ((*module)->module_type == Wasm_Module_Bytecode) {
+            import_count = MODULE_INTERP(module)->import_count;
+
+            INIT_VEC(instance->imports, wasm_extern_vec_new_uninitialized,
+                     import_count);
+
+            if (import_count) {
+                uint32 actual_link_import_count = interp_link(
+                  instance, MODULE_INTERP(module), (wasm_extern_t **)imports);
+                /* make sure a complete import list */
+                if ((int32)import_count < 0
+                    || import_count != actual_link_import_count) {
+                    goto failed;
+                }
+            }
+        }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+        if ((*module)->module_type == Wasm_Module_AoT) {
+            import_count = MODULE_AOT(module)->import_func_count
+                           + MODULE_AOT(module)->import_global_count
+                           + MODULE_AOT(module)->import_memory_count
+                           + MODULE_AOT(module)->import_table_count;
+
+            INIT_VEC(instance->imports, wasm_extern_vec_new_uninitialized,
+                     import_count);
+
+            if (import_count) {
+                import_count = aot_link(instance, MODULE_AOT(module),
+                                        (wasm_extern_t **)imports);
+                if ((int32)import_count < 0) {
+                    goto failed;
+                }
+            }
+        }
+#endif
+    }
+
+    instance->inst_comm_rt = wasm_runtime_instantiate(
+      *module, stack_size, heap_size, error_buf, sizeof(error_buf));
+    if (!instance->inst_comm_rt) {
+        LOG_ERROR(error_buf);
+        goto failed;
+    }
+
+    if (!wasm_runtime_create_exec_env_singleton(instance->inst_comm_rt)) {
+        goto failed;
+    }
+
+    /* fill with inst */
+    for (i = 0; imports && i < (uint32)import_count; ++i) {
+        wasm_extern_t *import = (wasm_extern_t *)imports[i];
+        switch (import->kind) {
+            case WASM_EXTERN_FUNC:
+                wasm_extern_as_func(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_GLOBAL:
+                wasm_extern_as_global(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_MEMORY:
+                wasm_extern_as_memory(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            case WASM_EXTERN_TABLE:
+                wasm_extern_as_table(import)->inst_comm_rt =
+                  instance->inst_comm_rt;
+                break;
+            default:
+                goto failed;
+        }
+    }
+
+    /* build the exports list */
+#if WASM_ENABLE_INTERP != 0
+    if (instance->inst_comm_rt->module_type == Wasm_Module_Bytecode) {
+        uint32 export_cnt =
+          ((WASMModuleInstance *)instance->inst_comm_rt)->module->export_count;
+
+        INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized,
+                 export_cnt);
+
+        if (!interp_process_export(
+              store, (WASMModuleInstance *)instance->inst_comm_rt,
+              instance->exports)) {
+            goto failed;
+        }
+    }
+#endif
+
+#if WASM_ENABLE_AOT != 0
+    if (instance->inst_comm_rt->module_type == Wasm_Module_AoT) {
+        uint32 export_cnt =
+          ((AOTModuleInstance *)instance->inst_comm_rt)->export_func_count
+          + ((AOTModuleInstance *)instance->inst_comm_rt)->export_global_count
+          + ((AOTModuleInstance *)instance->inst_comm_rt)->export_tab_count
+          + ((AOTModuleInstance *)instance->inst_comm_rt)->export_mem_count;
+
+        INIT_VEC(instance->exports, wasm_extern_vec_new_uninitialized,
+                 export_cnt);
+
+        if (!aot_process_export(store,
+                                (AOTModuleInstance *)instance->inst_comm_rt,
+                                instance->exports)) {
+            goto failed;
+        }
+    }
+#endif
+
+    /* add it to a watching list in store */
+    if (!bh_vector_append((Vector *)store->instances, &instance)) {
+        goto failed;
+    }
+
+    return instance;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_instance_delete_internal(instance);
+    return NULL;
+}
+
+static void
+wasm_instance_delete_internal(wasm_instance_t *instance)
+{
+    if (!instance) {
+        return;
+    }
+
+    DEINIT_VEC(instance->imports, wasm_extern_vec_delete);
+    DEINIT_VEC(instance->exports, wasm_extern_vec_delete);
+
+    if (instance->inst_comm_rt) {
+        wasm_runtime_deinstantiate(instance->inst_comm_rt);
+        instance->inst_comm_rt = NULL;
+    }
+    wasm_runtime_free(instance);
+}
+
+void
+wasm_instance_delete(wasm_instance_t *module)
+{
+    /* will release instance when releasing the store */
+}
+
+void
+wasm_instance_exports(const wasm_instance_t *instance,
+                      own wasm_extern_vec_t *out)
+{
+    if (!instance || !out) {
+        return;
+    }
+    wasm_extern_vec_copy(out, instance->exports);
+}
+
+wasm_extern_t *
+wasm_extern_copy(const wasm_extern_t *src)
+{
+    wasm_extern_t *dst = NULL;
+
+    if (!src) {
+        return NULL;
+    }
+
+    switch (wasm_extern_kind(src)) {
+        case WASM_EXTERN_FUNC:
+            dst = wasm_func_as_extern(
+              wasm_func_copy(wasm_extern_as_func_const(src)));
+            break;
+        case WASM_EXTERN_GLOBAL:
+            dst = wasm_global_as_extern(
+              wasm_global_copy(wasm_extern_as_global_const(src)));
+            break;
+        case WASM_EXTERN_MEMORY:
+            dst = wasm_memory_as_extern(
+              wasm_memory_copy(wasm_extern_as_memory_const(src)));
+            break;
+        case WASM_EXTERN_TABLE:
+            dst = wasm_table_as_extern(
+              wasm_table_copy(wasm_extern_as_table_const(src)));
+            break;
+        default:
+            LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                        src->kind);
+            break;
+    }
+
+    if (!dst) {
+        goto failed;
+    }
+
+    return dst;
+
+failed:
+    LOG_DEBUG("%s failed", __FUNCTION__);
+    wasm_extern_delete(dst);
+    return NULL;
+}
+
+void
+wasm_extern_delete(wasm_extern_t *external)
+{
+    if (!external) {
+        return;
+    }
+
+    if (external->name) {
+        wasm_byte_vec_delete(external->name);
+        wasm_runtime_free(external->name);
+        external->name = NULL;
+    }
+
+    switch (wasm_extern_kind(external)) {
+        case WASM_EXTERN_FUNC:
+            wasm_func_delete(wasm_extern_as_func(external));
+            break;
+        case WASM_EXTERN_GLOBAL:
+            wasm_global_delete(wasm_extern_as_global(external));
+            break;
+        case WASM_EXTERN_MEMORY:
+            wasm_memory_delete(wasm_extern_as_memory(external));
+            break;
+        case WASM_EXTERN_TABLE:
+            wasm_table_delete(wasm_extern_as_table(external));
+            break;
+        default:
+            LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                        external->kind);
+            break;
+    }
+}
+
+wasm_externkind_t
+wasm_extern_kind(const wasm_extern_t *external)
+{
+    if (!external) {
+        return WASM_ANYREF;
+    }
+
+    return external->kind;
+}
+
+own wasm_externtype_t *
+wasm_extern_type(const wasm_extern_t *external)
+{
+    if (!external) {
+        return NULL;
+    }
+
+    switch (wasm_extern_kind(external)) {
+        case WASM_EXTERN_FUNC:
+            return wasm_functype_as_externtype(
+              wasm_func_type(wasm_extern_as_func_const(external)));
+        case WASM_EXTERN_GLOBAL:
+            return wasm_globaltype_as_externtype(
+              wasm_global_type(wasm_extern_as_global_const(external)));
+        case WASM_EXTERN_MEMORY:
+            return wasm_memorytype_as_externtype(
+              wasm_memory_type(wasm_extern_as_memory_const(external)));
+        case WASM_EXTERN_TABLE:
+            return wasm_tabletype_as_externtype(
+              wasm_table_type(wasm_extern_as_table_const(external)));
+        default:
+            LOG_WARNING("%s meets unsupported kind: %d", __FUNCTION__,
+                        external->kind);
+            break;
+    }
+    return NULL;
+}
+
+#define BASIC_FOUR_LIST(V)                                                    \
+    V(func)                                                                   \
+    V(global)                                                                 \
+    V(memory)                                                                 \
+    V(table)
+
+#define WASM_EXTERN_AS_OTHER(name)                                            \
+    wasm_##name##_t *wasm_extern_as_##name(wasm_extern_t *external)           \
+    {                                                                         \
+        return (wasm_##name##_t *)external;                                   \
+    }
+
+BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER)
+#undef WASM_EXTERN_AS_OTHER
+
+#define WASM_OTHER_AS_EXTERN(name)                                            \
+    wasm_extern_t *wasm_##name##_as_extern(wasm_##name##_t *other)            \
+    {                                                                         \
+        return (wasm_extern_t *)other;                                        \
+    }
+
+BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN)
+#undef WASM_OTHER_AS_EXTERN
+
+#define WASM_EXTERN_AS_OTHER_CONST(name)                                      \
+    const wasm_##name##_t *wasm_extern_as_##name##_const(                     \
+      const wasm_extern_t *external)                                          \
+    {                                                                         \
+        return (const wasm_##name##_t *)external;                             \
+    }
+
+BASIC_FOUR_LIST(WASM_EXTERN_AS_OTHER_CONST)
+#undef WASM_EXTERN_AS_OTHER_CONST
+
+#define WASM_OTHER_AS_EXTERN_CONST(name)                                      \
+    const wasm_extern_t *wasm_##name##_as_extern_const(                       \
+      const wasm_##name##_t *other)                                           \
+    {                                                                         \
+        return (const wasm_extern_t *)other;                                  \
+    }
+
+BASIC_FOUR_LIST(WASM_OTHER_AS_EXTERN_CONST)
+#undef WASM_OTHER_AS_EXTERN_CONST

+ 174 - 0
core/iwasm/common/wasm_c_api_internal.h

@@ -0,0 +1,174 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_C_API_INTERNAL_H
+#define _WASM_C_API_INTERNAL_H
+
+#include "wasm_c_api.h"
+#include "wasm_runtime_common.h"
+
+#ifndef own
+#define own
+#endif
+
+/* Vectors */
+/* we will malloc resource for the vector's data field */
+/* we will release resource of data */
+/* caller needs to take care resource for the vector itself */
+#define DEFAULT_VECTOR_INIT_LENGTH (64)
+
+WASM_DECLARE_VEC(store, *)
+WASM_DECLARE_VEC(module, *)
+WASM_DECLARE_VEC(instance, *)
+
+/* Runtime Environment */
+struct wasm_engine_t {
+    /* support one store for now */
+    wasm_store_vec_t *stores;
+};
+
+struct wasm_store_t {
+    wasm_module_vec_t *modules;
+    wasm_instance_vec_t *instances;
+};
+
+/* Type Representations */
+struct wasm_valtype_t {
+    wasm_valkind_t kind;
+};
+
+struct wasm_functype_t {
+    uint32 extern_kind;
+    /* gona to new and delete own */
+    wasm_valtype_vec_t *params;
+    wasm_valtype_vec_t *results;
+};
+
+struct wasm_globaltype_t {
+    uint32 extern_kind;
+    /* gona to new and delete own */
+    wasm_valtype_t *val_type;
+    wasm_mutability_t mutability;
+};
+
+struct wasm_tabletype_t {
+    uint32 extern_kind;
+    /* always be WASM_FUNCREF */
+    wasm_valtype_t *val_type;
+    wasm_limits_t limits;
+};
+
+struct wasm_memorytype_t {
+    uint32 extern_kind;
+    wasm_limits_t limits;
+};
+
+struct wasm_externtype_t {
+    uint32 extern_kind;
+    uint8 data[1];
+};
+
+struct wasm_importtype_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    wasm_externtype_t *extern_type;
+};
+
+struct wasm_exporttype_t {
+    wasm_name_t *name;
+    wasm_externtype_t *extern_type;
+};
+
+/* Runtime Objects */
+struct wasm_ref_t {
+    uint32 obj;
+};
+
+struct wasm_trap_t {
+    wasm_byte_vec_t *message;
+};
+
+struct wasm_func_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_functype_t *type;
+
+    bool with_env;
+    union {
+        wasm_func_callback_t cb;
+        struct callback_ext {
+            void *env;
+            wasm_func_callback_with_env_t cb;
+            void (*finalizer)(void *);
+        } cb_env;
+    } u;
+    /*
+     * an index in both functions runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 func_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+    WASMFunctionInstanceCommon *func_comm_rt;
+};
+
+struct wasm_global_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_globaltype_t *type;
+    wasm_val_t *init;
+    /*
+     * an index in both global runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 global_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_memory_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_memorytype_t *type;
+    /*
+     * an index in both memory runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 memory_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_table_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    uint16 kind;
+
+    wasm_tabletype_t *type;
+    /*
+     * an index in both table runtime instance lists
+     * of interpreter mode and aot mode
+     */
+    uint16 table_idx_rt;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+struct wasm_extern_t {
+    wasm_name_t *module_name;
+    wasm_name_t *name;
+    wasm_externkind_t kind;
+    uint8 data[1];
+};
+
+struct wasm_instance_t {
+    wasm_extern_vec_t *imports;
+    wasm_extern_vec_t *exports;
+    WASMModuleInstanceCommon *inst_comm_rt;
+};
+
+#endif /* _WASM_C_API_INTERNAL_H */

+ 142 - 5
core/iwasm/common/wasm_exec_env.c

@@ -5,10 +5,20 @@
 
 #include "wasm_exec_env.h"
 #include "wasm_runtime_common.h"
+#if WASM_ENABLE_INTERP != 0
+#include "../interpreter/wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "../aot/aot_runtime.h"
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+#include "../libraries/thread-mgr/thread_manager.h"
+#endif
 
 WASMExecEnv *
-wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
-                     uint32 stack_size)
+wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
+                              uint32 stack_size)
 {
     uint64 total_size = offsetof(WASMExecEnv, wasm_stack.s.bottom)
                         + (uint64)stack_size;
@@ -22,31 +32,158 @@ wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
 
 #if WASM_ENABLE_AOT != 0
     if (!(exec_env->argv_buf = wasm_runtime_malloc(sizeof(uint32) * 64))) {
-        wasm_runtime_free(exec_env);
-        return NULL;
+        goto fail1;
     }
 #endif
 
+#if WASM_ENABLE_THREAD_MGR != 0
+    if (os_mutex_init(&exec_env->wait_lock) != 0)
+        goto fail2;
+
+    if (os_cond_init(&exec_env->wait_cond) != 0)
+        goto fail3;
+#endif
+
     exec_env->module_inst = module_inst;
     exec_env->wasm_stack_size = stack_size;
     exec_env->wasm_stack.s.top_boundary =
         exec_env->wasm_stack.s.bottom + stack_size;
     exec_env->wasm_stack.s.top = exec_env->wasm_stack.s.bottom;
+
+#if WASM_ENABLE_MEMORY_TRACING != 0
+    wasm_runtime_dump_exec_env_mem_consumption(exec_env);
+#endif
     return exec_env;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+fail3:
+    os_mutex_destroy(&exec_env->wait_lock);
+fail2:
+#endif
+#if WASM_ENABLE_AOT != 0
+    wasm_runtime_free(exec_env->argv_buf);
+fail1:
+#endif
+    wasm_runtime_free(exec_env);
+    return NULL;
 }
 
 void
-wasm_exec_env_destroy(WASMExecEnv *exec_env)
+wasm_exec_env_destroy_internal(WASMExecEnv *exec_env)
 {
+#if WASM_ENABLE_THREAD_MGR != 0
+    os_mutex_destroy(&exec_env->wait_lock);
+    os_cond_destroy(&exec_env->wait_cond);
+#endif
 #if WASM_ENABLE_AOT != 0
     wasm_runtime_free(exec_env->argv_buf);
 #endif
     wasm_runtime_free(exec_env);
 }
 
+WASMExecEnv *
+wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
+                     uint32 stack_size)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+    WASMCluster *cluster;
+#endif
+    WASMExecEnv *exec_env =
+        wasm_exec_env_create_internal(module_inst, stack_size);
+
+    if (!exec_env)
+        return NULL;
+
+    /* Set the aux_stack_boundary and aux_stack_bottom */
+#if WASM_ENABLE_INTERP != 0
+    if (module_inst->module_type == Wasm_Module_Bytecode) {
+        WASMModule *module = ((WASMModuleInstance *)module_inst)->module;
+        exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
+        exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom
+                                                - module->aux_stack_size;
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module_inst->module_type == Wasm_Module_AoT) {
+        AOTModule *module =
+            (AOTModule *)(((AOTModuleInstance *)module_inst)->aot_module.ptr);
+        exec_env->aux_stack_bottom.bottom = module->aux_stack_bottom;
+        exec_env->aux_stack_boundary.boundary = module->aux_stack_bottom
+                                                - module->aux_stack_size;
+    }
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* Create a new cluster for this exec_env */
+    if (!(cluster = wasm_cluster_create(exec_env))) {
+        wasm_exec_env_destroy_internal(exec_env);
+        return NULL;
+    }
+#endif
+    return exec_env;
+}
+
+void
+wasm_exec_env_destroy(WASMExecEnv *exec_env)
+{
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* Terminate all sub-threads */
+    WASMCluster *cluster = wasm_exec_env_get_cluster(exec_env);
+    if (cluster) {
+        wasm_cluster_terminate_all_except_self(cluster, exec_env);
+        wasm_cluster_del_exec_env(cluster, exec_env);
+    }
+#endif
+    wasm_exec_env_destroy_internal(exec_env);
+}
+
 WASMModuleInstanceCommon *
 wasm_exec_env_get_module_inst(WASMExecEnv *exec_env)
 {
     return exec_env->module_inst;
 }
 
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env)
+{
+    exec_env->handle = os_self_thread();
+    exec_env->native_stack_boundary = os_thread_get_stack_boundary()
+                                      + RESERVED_BYTES_TO_NATIVE_STACK_BOUNDARY;
+}
+
+#if WASM_ENABLE_THREAD_MGR != 0
+void *
+wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env)
+{
+    return exec_env->thread_arg;
+}
+
+void
+wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg)
+{
+    exec_env->thread_arg = thread_arg;
+}
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+void
+wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf)
+{
+    jmpbuf->prev = exec_env->jmpbuf_stack_top;
+    exec_env->jmpbuf_stack_top = jmpbuf;
+}
+
+WASMJmpBuf *
+wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env)
+{
+    WASMJmpBuf *stack_top = exec_env->jmpbuf_stack_top;
+
+    if (stack_top) {
+        exec_env->jmpbuf_stack_top = stack_top->prev;
+        return stack_top;
+    }
+
+    return NULL;
+}
+#endif
+

+ 116 - 12
core/iwasm/common/wasm_exec_env.h

@@ -18,14 +18,30 @@ extern "C" {
 struct WASMModuleInstanceCommon;
 struct WASMInterpFrame;
 
+#if WASM_ENABLE_THREAD_MGR != 0
+typedef struct WASMCluster WASMCluster;
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+typedef struct WASMJmpBuf {
+    struct WASMJmpBuf *prev;
+    korp_jmpbuf jmpbuf;
+} WASMJmpBuf;
+#endif
+
 /* Execution environment */
 typedef struct WASMExecEnv {
-    /* Next thread's exec env of a WASM module instance.  */
+    /* Next thread's exec env of a WASM module instance. */
     struct WASMExecEnv *next;
 
-    /* Previous thread's exec env of a WASM module instance.  */
+    /* Previous thread's exec env of a WASM module instance. */
     struct WASMExecEnv *prev;
 
+    /* Note: field module_inst, argv_buf, native_stack_boundary,
+       suspend_flags, aux_stack_boundary, aux_stack_bottom, and
+       native_symbol are used by AOTed code, don't change the
+       places of them */
+
     /* The WASM module instance of current thread */
     struct WASMModuleInstanceCommon *module_inst;
 
@@ -33,6 +49,54 @@ typedef struct WASMExecEnv {
     uint32 *argv_buf;
 #endif
 
+    /* The boundary of native stack. When runtime detects that native
+       frame may overrun this boundary, it throws stack overflow
+       exception. */
+    uint8 *native_stack_boundary;
+
+    /* Used to terminate or suspend current thread
+        bit 0: need to terminate
+        bit 1: need to suspend
+        bit 2: need to go into breakpoint
+        bit 3: return from pthread_exit */
+    union {
+        uint32 flags;
+        uintptr_t __padding__;
+    } suspend_flags;
+
+    /* Auxiliary stack boundary */
+    union {
+        uint32 boundary;
+        uintptr_t __padding__;
+    } aux_stack_boundary;
+
+    /* Auxiliary stack bottom */
+    union {
+        uint32 bottom;
+        uintptr_t __padding__;
+    } aux_stack_bottom;
+
+#if WASM_ENABLE_AOT != 0
+    /* Native symbol list, reserved */
+    void **native_symbol;
+#endif
+
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* thread return value */
+    void *thread_ret_value;
+
+    /* Must be provided by thread library */
+    void* (*thread_start_routine)(void *);
+    void *thread_arg;
+
+    /* pointer to the cluster */
+    WASMCluster *cluster;
+
+    /* used to support debugger */
+    korp_mutex wait_lock;
+    korp_cond wait_cond;
+#endif
+
     /* attachment for native function */
     void *attachment;
 
@@ -44,14 +108,21 @@ typedef struct WASMExecEnv {
     /* The native thread handle of current thread */
     korp_tid handle;
 
-#if WASM_ENABLE_INTERP != 0
+#if WASM_ENABLE_INTERP != 0 && WASM_ENABLE_FAST_INTERP == 0
     BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
 #endif
 
-    /* The boundary of native stack. When interpreter detects that native
-       frame may overrun this boundary, it throws a stack overflow
-       exception. */
-    void *native_stack_boundary;
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+    WASMJmpBuf *jmpbuf_stack_top;
+#endif
+
+#if WASM_ENABLE_REF_TYPES != 0
+    uint16 nested_calling_depth;
+#endif
+
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    uint32 max_wasm_stack_used;
+#endif
 
     /* The WASM stack size */
     uint32 wasm_stack_size;
@@ -61,18 +132,25 @@ typedef struct WASMExecEnv {
         uint64 __make_it_8_byte_aligned_;
 
         struct {
-            /* The top boundary of the stack.  */
+            /* The top boundary of the stack. */
             uint8 *top_boundary;
 
-            /* Top cell index which is free.  */
+            /* Top cell index which is free. */
             uint8 *top;
 
-            /* The Java stack.  */
+            /* The WASM stack. */
             uint8 bottom[1];
         } s;
     } wasm_stack;
 } WASMExecEnv;
 
+WASMExecEnv *
+wasm_exec_env_create_internal(struct WASMModuleInstanceCommon *module_inst,
+                              uint32 stack_size);
+
+void
+wasm_exec_env_destroy_internal(WASMExecEnv *exec_env);
+
 WASMExecEnv *
 wasm_exec_env_create(struct WASMModuleInstanceCommon *module_inst,
                      uint32 stack_size);
@@ -100,13 +178,19 @@ wasm_exec_env_alloc_wasm_frame(WASMExecEnv *exec_env, unsigned size)
        multiplying by 2 is enough. */
     if (addr + size * 2 > exec_env->wasm_stack.s.top_boundary) {
         /* WASM stack overflow. */
-        /* When throwing SOE, the preserved space must be enough. */
-        /* bh_assert(!exec_env->throwing_soe);*/
         return NULL;
     }
 
     exec_env->wasm_stack.s.top += size;
 
+#if WASM_ENABLE_MEMORY_PROFILING != 0
+    {
+        uint32 wasm_stack_used = exec_env->wasm_stack.s.top
+                                 - exec_env->wasm_stack.s.bottom;
+        if (wasm_stack_used > exec_env->max_wasm_stack_used)
+            exec_env->max_wasm_stack_used = wasm_stack_used;
+    }
+#endif
     return addr;
 }
 
@@ -159,6 +243,26 @@ wasm_exec_env_get_cur_frame(WASMExecEnv *exec_env)
 struct WASMModuleInstanceCommon *
 wasm_exec_env_get_module_inst(WASMExecEnv *exec_env);
 
+void
+wasm_exec_env_set_thread_info(WASMExecEnv *exec_env);
+
+
+#if WASM_ENABLE_THREAD_MGR != 0
+void *
+wasm_exec_env_get_thread_arg(WASMExecEnv *exec_env);
+
+void
+wasm_exec_env_set_thread_arg(WASMExecEnv *exec_env, void *thread_arg);
+#endif
+
+#ifdef OS_ENABLE_HW_BOUND_CHECK
+void
+wasm_exec_env_push_jmpbuf(WASMExecEnv *exec_env, WASMJmpBuf *jmpbuf);
+
+WASMJmpBuf *
+wasm_exec_env_pop_jmpbuf(WASMExecEnv *exec_env);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 33 - 238
core/iwasm/common/wasm_memory.c

@@ -7,33 +7,6 @@
 #include "bh_platform.h"
 #include "mem_alloc.h"
 
-#if BH_ENABLE_MEMORY_PROFILING != 0
-
-/* Memory profile data of a function */
-typedef struct memory_profile {
-    struct memory_profile *next;
-    const char *function_name;
-    const char *file_name;
-    int line_in_file;
-    int malloc_num;
-    int free_num;
-    int total_malloc;
-    int total_free;
-} memory_profile_t;
-
-/* Memory in use which grows when BH_MALLOC was called
- * and decreases when bh_free was called */
-static unsigned int memory_in_use = 0;
-
-/* Memory profile data list */
-static memory_profile_t *memory_profiles_list = NULL;
-
-/* Lock of the memory profile list */
-static korp_mutex profile_lock;
-#endif /* end of BH_ENABLE_MEMORY_PROFILING */
-
-#ifndef MALLOC_MEMORY_FROM_SYSTEM
-
 typedef enum Memory_Mode {
     MEMORY_MODE_UNKNOWN = 0,
     MEMORY_MODE_POOL,
@@ -58,9 +31,6 @@ wasm_memory_init_with_pool(void *mem, unsigned int bytes)
     if (_allocator) {
         memory_mode = MEMORY_MODE_POOL;
         pool_allocator = _allocator;
-#if BH_ENABLE_MEMORY_PROFILING != 0
-        os_mutex_init(&profile_lock);
-#endif
         global_pool_size = bytes;
         return true;
     }
@@ -78,9 +48,6 @@ wasm_memory_init_with_allocator(void *_malloc_func,
         malloc_func = _malloc_func;
         realloc_func = _realloc_func;
         free_func = _free_func;
-#if BH_ENABLE_MEMORY_PROFILING != 0
-        os_mutex_init(&profile_lock);
-#endif
         return true;
     }
     LOG_ERROR("Init memory with allocator (%p, %p, %p) failed.\n",
@@ -108,9 +75,6 @@ wasm_runtime_memory_init(mem_alloc_type_t mem_alloc_type,
 void
 wasm_runtime_memory_destroy()
 {
-#if BH_ENABLE_MEMORY_PROFILING != 0
-    os_mutex_destroy(&profile_lock);
-#endif
     if (memory_mode == MEMORY_MODE_POOL)
         mem_allocator_destroy(pool_allocator);
     memory_mode = MEMORY_MODE_UNKNOWN;
@@ -125,28 +89,32 @@ wasm_runtime_memory_pool_size()
         return 1 * BH_GB;
 }
 
-void *
-wasm_runtime_malloc(unsigned int size)
+static inline void *
+wasm_runtime_malloc_internal(unsigned int size)
 {
     if (memory_mode == MEMORY_MODE_UNKNOWN) {
         LOG_WARNING("wasm_runtime_malloc failed: memory hasn't been initialize.\n");
         return NULL;
-    } else if (memory_mode == MEMORY_MODE_POOL) {
+    }
+    else if (memory_mode == MEMORY_MODE_POOL) {
         return mem_allocator_malloc(pool_allocator, size);
-    } else {
+    }
+    else {
         return malloc_func(size);
     }
 }
 
-void *
-wasm_runtime_realloc(void *ptr, unsigned int size)
+static inline void *
+wasm_runtime_realloc_internal(void *ptr, unsigned int size)
 {
     if (memory_mode == MEMORY_MODE_UNKNOWN) {
         LOG_WARNING("wasm_runtime_realloc failed: memory hasn't been initialize.\n");
         return NULL;
-    } else if (memory_mode == MEMORY_MODE_POOL) {
+    }
+    else if (memory_mode == MEMORY_MODE_POOL) {
         return mem_allocator_realloc(pool_allocator, ptr, size);
-    } else {
+    }
+    else {
         if (realloc_func)
             return realloc_func(ptr, size);
         else
@@ -154,219 +122,46 @@ wasm_runtime_realloc(void *ptr, unsigned int size)
     }
 }
 
-void
-wasm_runtime_free(void *ptr)
+static inline void
+wasm_runtime_free_internal(void *ptr)
 {
-    if (memory_mode == MEMORY_MODE_UNKNOWN) {
-        LOG_WARNING("wasm_runtime_free failed: memory hasn't been initialize.\n");
-    } else if (memory_mode == MEMORY_MODE_POOL) {
-        mem_allocator_free(pool_allocator, ptr);
-    } else {
-        free_func(ptr);
+    if (!ptr) {
+        LOG_WARNING("warning: wasm_runtime_free with NULL pointer\n");
+        return;
     }
-}
-
-#if BH_ENABLE_MEMORY_PROFILING != 0
-
-void
-memory_profile_print(const char *file, int line,
-                     const char *func, int alloc)
-{
-    os_printf("location:%s@%d:used:%d:contribution:%d\n",
-              func, line, memory_in_use, alloc);
-}
-
-void *
-wasm_runtime_malloc_profile(const char *file, int line,
-                            const char *func, unsigned int size)
-{
-    void *p = wasm_runtime_malloc(size + 8);
-
-    if (p) {
-        memory_profile_t *profile;
-
-        os_mutex_lock(&profile_lock);
-
-        profile = memory_profiles_list;
-        while (profile) {
-            if (strcmp(profile->function_name, func) == 0
-                && strcmp(profile->file_name, file) == 0) {
-                break;
-            }
-            profile = profile->next;
-        }
-
-        if (profile) {
-            profile->total_malloc += size;/* TODO: overflow check */
-            profile->malloc_num++;
-        } else {
-            profile = wasm_runtime_malloc(sizeof(memory_profile_t));
-            if (!profile) {
-              os_mutex_unlock(&profile_lock);
-              bh_memcpy_s(p, size + 8, &size, sizeof(size));
-              return (char *)p + 8;
-            }
-
-            memset(profile, 0, sizeof(memory_profile_t));
-            profile->file_name = file;
-            profile->line_in_file = line;
-            profile->function_name = func;
-            profile->malloc_num = 1;
-            profile->total_malloc = size;
-            profile->next = memory_profiles_list;
-            memory_profiles_list = profile;
-        }
-
-        os_mutex_unlock(&profile_lock);
-
-        bh_memcpy_s(p, size + 8, &size, sizeof(size));
-        memory_in_use += size;
-
-        memory_profile_print(file, line, func, size);
-
-        return (char *)p + 8;
-    }
-
-    return NULL;
-}
-
-void
-wasm_runtime_free_profile(const char *file, int line,
-                          const char *func, void *ptr)
-{
-    unsigned int size = *(unsigned int *)((char *)ptr - 8);
-    memory_profile_t *profile;
-
-    wasm_runtime_free((char *)ptr - 8);
 
-    if (memory_in_use >= size)
-        memory_in_use -= size;
-
-    os_mutex_lock(&profile_lock);
-
-    profile = memory_profiles_list;
-    while (profile) {
-        if (strcmp(profile->function_name, func) == 0
-            && strcmp(profile->file_name, file) == 0) {
-            break;
-        }
-        profile = profile->next;
+    if (memory_mode == MEMORY_MODE_UNKNOWN) {
+        LOG_WARNING("warning: wasm_runtime_free failed: "
+                    "memory hasn't been initialize.\n");
     }
-
-    if (profile) {
-        profile->total_free += size;/* TODO: overflow check */
-        profile->free_num++;
-    } else {
-        profile = wasm_runtime_malloc(sizeof(memory_profile_t));
-        if (!profile) {
-            os_mutex_unlock(&profile_lock);
-            return;
-        }
-
-        memset(profile, 0, sizeof(memory_profile_t));
-        profile->file_name = file;
-        profile->line_in_file = line;
-        profile->function_name = func;
-        profile->free_num = 1;
-        profile->total_free = size;
-        profile->next = memory_profiles_list;
-        memory_profiles_list = profile;
+    else if (memory_mode == MEMORY_MODE_POOL) {
+        mem_allocator_free(pool_allocator, ptr);
     }
-
-    os_mutex_unlock(&profile_lock);
-}
-
-/**
- * Summarize memory usage and print it out
- * Can use awk to analyze the output like below:
- * awk -F: '{print $2,$4,$6,$8,$9}' OFS="\t" ./out.txt | sort -n -r -k 1
- */
-void memory_usage_summarize()
-{
-    memory_profile_t *profile;
-
-    os_mutex_lock(&profile_lock);
-
-    profile = memory_profiles_list;
-    while (profile) {
-        os_printf("malloc:%d:malloc_num:%d:free:%d:free_num:%d:%s\n",
-                  profile->total_malloc,
-                  profile->malloc_num,
-                  profile->total_free,
-                  profile->free_num,
-                  profile->function_name);
-        profile = profile->next;
+    else {
+        free_func(ptr);
     }
-
-    os_mutex_unlock(&profile_lock);
 }
 
-#endif /* end of BH_ENABLE_MEMORY_PROFILING */
-
-#else /* else of MALLOC_MEMORY_FROM_SYSTEM */
-
-
 void *
 wasm_runtime_malloc(unsigned int size)
 {
-    return malloc(size);
+    if (size == 0) {
+        LOG_WARNING("warning: wasm_runtime_malloc with size zero\n");
+        /* At lease alloc 1 byte to avoid malloc failed */
+        size = 1;
+    }
+
+    return wasm_runtime_malloc_internal(size);
 }
 
 void *
 wasm_runtime_realloc(void *ptr, unsigned int size)
 {
-    return realloc(ptr, size);
+    return wasm_runtime_realloc_internal(ptr, size);
 }
 
 void
 wasm_runtime_free(void *ptr)
 {
-    if (ptr)
-        free(ptr);
-}
-
-#if BH_ENABLE_MEMORY_PROFILING != 0
-void *
-wasm_runtime_malloc_profile(const char *file, int line,
-                            const char *func, unsigned int size)
-{
-    (void)file;
-    (void)line;
-    (void)func;
-
-    (void)memory_profiles_list;
-    (void)profile_lock;
-    (void)memory_in_use;
-
-    return malloc(size);
-}
-
-void *
-wasm_runtime_realloc_profile(const char *file, int line,
-                             const char *func, void *ptr, unsigned int size)
-{
-    (void)file;
-    (void)line;
-    (void)func;
-
-    (void)memory_profiles_list;
-    (void)profile_lock;
-    (void)memory_in_use;
-
-    return realloc(ptr, size);
-}
-
-void
-wasm_runtime_free_profile(const char *file, int line,
-                          const char *func, void *ptr)
-{
-    (void)file;
-    (void)line;
-    (void)func;
-
-    if (ptr)
-        free(ptr);
+    wasm_runtime_free_internal(ptr);
 }
-#endif /* end of BH_ENABLE_MEMORY_PROFILING */
-#endif /* end of MALLOC_MEMORY_FROM_SYSTEM*/
-

+ 144 - 17
core/iwasm/common/wasm_native.c

@@ -7,15 +7,28 @@
 #include "wasm_runtime_common.h"
 #include "bh_log.h"
 
+#if !defined(BH_PLATFORM_ZEPHYR) && !defined(BH_PLATFORM_ALIOS_THINGS) \
+    && !defined(BH_PLATFORM_OPENRTOS) && !defined(BH_PLATFORM_ESP_IDF)
+#define ENABLE_QUICKSORT 1
+#else
+#define ENABLE_QUICKSORT 0
+#endif
+
+#define ENABLE_SORT_DEBUG 0
+
+#if ENABLE_SORT_DEBUG != 0
+#include<sys/time.h>
+#endif
 
 static NativeSymbolsList g_native_symbols_list = NULL;
-static NativeSymbolsList g_native_symbols_list_end = NULL;
 
 uint32
 get_libc_builtin_export_apis(NativeSymbol **p_libc_builtin_apis);
 
+#if WASM_ENABLE_SPEC_TEST != 0
 uint32
 get_spectest_export_apis(NativeSymbol **p_libc_builtin_apis);
+#endif
 
 uint32
 get_libc_wasi_export_apis(NativeSymbol **p_libc_wasi_apis);
@@ -26,6 +39,20 @@ get_base_lib_export_apis(NativeSymbol **p_base_lib_apis);
 uint32
 get_ext_lib_export_apis(NativeSymbol **p_ext_lib_apis);
 
+#if WASM_ENABLE_LIB_PTHREAD != 0
+bool
+lib_pthread_init();
+
+void
+lib_pthread_destroy();
+
+uint32
+get_lib_pthread_export_apis(NativeSymbol **p_lib_pthread_apis);
+#endif
+
+uint32
+get_libc_emcc_export_apis(NativeSymbol **p_libc_emcc_apis);
+
 static bool
 check_symbol_signature(const WASMType *type, const char *signature)
 {
@@ -41,13 +68,19 @@ check_symbol_signature(const WASMType *type, const char *signature)
     if (*p++ != '(')
         return false;
 
-    if ((uint32)(p_end - p) < type->param_count + 1)
+    if ((uint32)(p_end - p) < (uint32)(type->param_count + 1))
         /* signatures of parameters, and ')' */
         return false;
 
     for (i = 0; i < type->param_count; i++) {
         sig = *p++;
-        if (sig == sig_map[type->types[i] - VALUE_TYPE_F64])
+        if ((type->types[i] >= VALUE_TYPE_F64
+             && type->types[i] <= VALUE_TYPE_I32
+             && sig == sig_map[type->types[i] - VALUE_TYPE_F64])
+#if WASM_ENABLE_REF_TYPES != 0
+            || (sig == 'i' && type->types[i] == VALUE_TYPE_EXTERNREF)
+#endif
+           )
             /* normal parameter */
             continue;
 
@@ -90,6 +123,7 @@ check_symbol_signature(const WASMType *type, const char *signature)
     return true;
 }
 
+#if ENABLE_QUICKSORT == 0
 static void
 sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
 {
@@ -107,13 +141,63 @@ sort_symbol_ptr(NativeSymbol *native_symbols, uint32 n_native_symbols)
         }
     }
 }
+#else
+static void
+swap_symbol(NativeSymbol* left, NativeSymbol* right)
+{
+    NativeSymbol temp = *left;
+    *left = *right;
+    *right = temp;
+}
+
+static void
+quick_sort_symbols(NativeSymbol* native_symbols, int left, int right)
+{
+    NativeSymbol base_symbol;
+    int pin_left = left;
+    int pin_right = right;
+
+    if (left >= right) {
+        return;
+    }
+
+    base_symbol = native_symbols[left];
+    while (left < right) {
+        while (left < right
+               && strcmp(native_symbols[right].symbol,
+                         base_symbol.symbol) > 0) {
+            right--;
+        }
+
+        if (left < right) {
+            swap_symbol(&native_symbols[left], &native_symbols[right]);
+            left++;
+        }
+
+        while (left < right
+               && strcmp(native_symbols[left].symbol,
+                         base_symbol.symbol) < 0) {
+            left++;
+        }
+
+        if (left < right) {
+            swap_symbol(&native_symbols[left], &native_symbols[right]);
+            right--;
+        }
+    }
+    native_symbols[left] = base_symbol;
+
+    quick_sort_symbols(native_symbols, pin_left, left - 1);
+    quick_sort_symbols(native_symbols, left + 1, pin_right);
+}
+#endif /* end of ENABLE_QUICKSORT */
 
 static void *
 lookup_symbol(NativeSymbol *native_symbols, uint32 n_native_symbols,
               const char *symbol, const char **p_signature, void **p_attachment)
 {
     int low = 0, mid, ret;
-    int high = n_native_symbols - 1;
+    int high = (int32)n_native_symbols - 1;
 
     while (low <= high) {
         mid = (low + high) / 2;
@@ -192,25 +276,44 @@ register_natives(const char *module_name,
                  bool call_conv_raw)
 {
     NativeSymbolsNode *node;
+#if ENABLE_SORT_DEBUG != 0
+    struct timeval start;
+    struct timeval end;
+    unsigned long timer;
+#endif
 
     if (!(node = wasm_runtime_malloc(sizeof(NativeSymbolsNode))))
         return false;
+#if WASM_ENABLE_MEMORY_TRACING != 0
+    os_printf("Register native, size: %u\n", sizeof(NativeSymbolsNode));
+#endif
 
     node->module_name = module_name;
     node->native_symbols = native_symbols;
     node->n_native_symbols = n_native_symbols;
     node->call_conv_raw = call_conv_raw;
-    node->next = NULL;
 
-    if (g_native_symbols_list_end) {
-        g_native_symbols_list_end->next = node;
-        g_native_symbols_list_end = node;
-    }
-    else {
-        g_native_symbols_list = g_native_symbols_list_end = node;
-    }
+    /* Add to list head */
+    node->next = g_native_symbols_list;
+    g_native_symbols_list = node;
+
+#if ENABLE_SORT_DEBUG != 0
+    gettimeofday(&start, NULL);
+#endif
 
+#if ENABLE_QUICKSORT == 0
     sort_symbol_ptr(native_symbols, n_native_symbols);
+#else
+    quick_sort_symbols(native_symbols, 0, (int)(n_native_symbols - 1));
+#endif
+
+#if ENABLE_SORT_DEBUG != 0
+    gettimeofday(&end, NULL);
+    timer = 1000000 * (end.tv_sec - start.tv_sec)
+            + (end.tv_usec - start.tv_usec);
+    LOG_ERROR("module_name: %s, nums: %d, sorted used: %ld us",
+              module_name, n_native_symbols, timer);
+#endif
     return true;
 }
 
@@ -239,14 +342,16 @@ wasm_native_init()
 #if WASM_ENABLE_LIBC_BUILTIN != 0
     n_native_symbols = get_libc_builtin_export_apis(&native_symbols);
     if (!wasm_native_register_natives("env",
-                                       native_symbols, n_native_symbols))
+                                      native_symbols, n_native_symbols))
         return false;
+#endif /* WASM_ENABLE_LIBC_BUILTIN */
 
+#if WASM_ENABLE_SPEC_TEST
     n_native_symbols = get_spectest_export_apis(&native_symbols);
     if (!wasm_native_register_natives("spectest",
-                                       native_symbols, n_native_symbols))
+                                      native_symbols, n_native_symbols))
         return false;
-#endif
+#endif /* WASM_ENABLE_SPEC_TEST */
 
 #if WASM_ENABLE_LIBC_WASI != 0
     n_native_symbols = get_libc_wasi_export_apis(&native_symbols);
@@ -274,6 +379,25 @@ wasm_native_init()
         return false;
 #endif
 
+#if WASM_ENABLE_LIB_PTHREAD != 0
+    if (!lib_pthread_init())
+        return false;
+
+    n_native_symbols = get_lib_pthread_export_apis(&native_symbols);
+    if (n_native_symbols > 0
+        && !wasm_native_register_natives("env",
+                                         native_symbols, n_native_symbols))
+        return false;
+#endif
+
+#if WASM_ENABLE_LIBC_EMCC != 0
+    n_native_symbols = get_libc_emcc_export_apis(&native_symbols);
+    if (n_native_symbols > 0
+        && !wasm_native_register_natives("env",
+                                         native_symbols, n_native_symbols))
+        return false;
+#endif /* WASM_ENABLE_LIBC_EMCC */
+
     return true;
 }
 
@@ -282,6 +406,10 @@ wasm_native_destroy()
 {
     NativeSymbolsNode *node, *node_next;
 
+#if WASM_ENABLE_LIB_PTHREAD != 0
+    lib_pthread_destroy();
+#endif
+
     node = g_native_symbols_list;
     while (node) {
         node_next = node->next;
@@ -289,6 +417,5 @@ wasm_native_destroy()
         node = node_next;
     }
 
-    g_native_symbols_list = g_native_symbols_list_end = NULL;
+    g_native_symbols_list = NULL;
 }
-

File diff suppressed because it is too large
+ 837 - 29
core/iwasm/common/wasm_runtime_common.c


+ 535 - 65
core/iwasm/common/wasm_runtime_common.h

@@ -13,14 +13,241 @@
 #include "../include/wasm_export.h"
 #include "../interpreter/wasm.h"
 #if WASM_ENABLE_LIBC_WASI != 0
+#if WASM_ENABLE_UVWASI == 0
 #include "wasmtime_ssp.h"
 #include "posix.h"
+#else
+#include "uvwasi.h"
+#endif
 #endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0
+
+#define PUT_I64_TO_ADDR(addr, value) do {       \
+    *(int64*)(addr) = (int64)(value);           \
+  } while (0)
+#define PUT_F64_TO_ADDR(addr, value) do {       \
+    *(float64*)(addr) = (float64)(value);       \
+  } while (0)
+
+#define GET_I64_FROM_ADDR(addr) (*(int64*)(addr))
+#define GET_F64_FROM_ADDR(addr) (*(float64*)(addr))
+
+/* For STORE opcodes */
+#define STORE_I64 PUT_I64_TO_ADDR
+#define STORE_U32(addr, value) do {             \
+    *(uint32*)(addr) = (uint32)(value);         \
+  } while (0)
+#define STORE_U16(addr, value) do {             \
+    *(uint16*)(addr) = (uint16)(value);         \
+  } while (0)
+
+/* For LOAD opcodes */
+#define LOAD_I64(addr) (*(int64*)(addr))
+#define LOAD_F64(addr) (*(float64*)(addr))
+#define LOAD_I32(addr) (*(int32*)(addr))
+#define LOAD_U32(addr) (*(uint32*)(addr))
+#define LOAD_I16(addr) (*(int16*)(addr))
+#define LOAD_U16(addr) (*(uint16*)(addr))
+
+#define STORE_PTR(addr, ptr) do {               \
+    *(void**)addr = (void*)ptr;                 \
+  } while (0)
+#define LOAD_PTR(addr) (*(void**)(addr))
+
+#else  /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
+
+#define PUT_I64_TO_ADDR(addr, value) do {       \
+    uint32 *addr_u32 = (uint32*)(addr);         \
+    union { int64 val; uint32 parts[2]; } u;    \
+    u.val = (int64)(value);                     \
+    addr_u32[0] = u.parts[0];                   \
+    addr_u32[1] = u.parts[1];                   \
+  } while (0)
+#define PUT_F64_TO_ADDR(addr, value) do {       \
+    uint32 *addr_u32 = (uint32*)(addr);         \
+    union { float64 val; uint32 parts[2]; } u;  \
+    u.val = (value);                            \
+    addr_u32[0] = u.parts[0];                   \
+    addr_u32[1] = u.parts[1];                   \
+  } while (0)
+
+static inline int64
+GET_I64_FROM_ADDR(uint32 *addr)
+{
+    union { int64 val; uint32 parts[2]; } u;
+    u.parts[0] = addr[0];
+    u.parts[1] = addr[1];
+    return u.val;
+}
+
+static inline float64
+GET_F64_FROM_ADDR (uint32 *addr)
+{
+    union { float64 val; uint32 parts[2]; } u;
+    u.parts[0] = addr[0];
+    u.parts[1] = addr[1];
+    return u.val;
+}
+
+/* For STORE opcodes */
+#define STORE_I64(addr, value) do {             \
+    uintptr_t addr1 = (uintptr_t)(addr);        \
+    union { int64 val; uint32 u32[2];           \
+            uint16 u16[4]; uint8 u8[8]; } u;    \
+    if ((addr1 & (uintptr_t)7) == 0)            \
+      *(int64*)(addr) = (int64)(value);         \
+    else {                                      \
+        u.val = (int64)(value);                 \
+        if ((addr1 & (uintptr_t)3) == 0) {      \
+            ((uint32*)(addr))[0] = u.u32[0];    \
+            ((uint32*)(addr))[1] = u.u32[1];    \
+        }                                       \
+        else if ((addr1 & (uintptr_t)1) == 0) { \
+            ((uint16*)(addr))[0] = u.u16[0];    \
+            ((uint16*)(addr))[1] = u.u16[1];    \
+            ((uint16*)(addr))[2] = u.u16[2];    \
+            ((uint16*)(addr))[3] = u.u16[3];    \
+        }                                       \
+        else {                                  \
+            int32 t;                            \
+            for (t = 0; t < 8; t++)             \
+                ((uint8*)(addr))[t] = u.u8[t];  \
+        }                                       \
+    }                                           \
+  } while (0)
+
+#define STORE_U32(addr, value) do {             \
+    uintptr_t addr1 = (uintptr_t)(addr);        \
+    union { uint32 val;                         \
+            uint16 u16[2]; uint8 u8[4]; } u;    \
+    if ((addr1 & (uintptr_t)3) == 0)            \
+      *(uint32*)(addr) = (uint32)(value);       \
+    else {                                      \
+        u.val = (uint32)(value);                \
+        if ((addr1 & (uintptr_t)1) == 0) {      \
+            ((uint16*)(addr))[0] = u.u16[0];    \
+            ((uint16*)(addr))[1] = u.u16[1];    \
+        }                                       \
+        else {                                  \
+            ((uint8*)(addr))[0] = u.u8[0];      \
+            ((uint8*)(addr))[1] = u.u8[1];      \
+            ((uint8*)(addr))[2] = u.u8[2];      \
+            ((uint8*)(addr))[3] = u.u8[3];      \
+        }                                       \
+    }                                           \
+  } while (0)
+
+#define STORE_U16(addr, value) do {             \
+    union { uint16 val; uint8 u8[2]; } u;       \
+    u.val = (uint16)(value);                    \
+    ((uint8*)(addr))[0] = u.u8[0];              \
+    ((uint8*)(addr))[1] = u.u8[1];              \
+  } while (0)
+
+/* For LOAD opcodes */
+static inline int64
+LOAD_I64(void *addr)
+{
+    uintptr_t addr1 = (uintptr_t)addr;
+    union { int64 val; uint32 u32[2];
+            uint16 u16[4]; uint8 u8[8]; } u;
+    if ((addr1 & (uintptr_t)7) == 0)
+        return *(int64*)addr;
+
+    if ((addr1 & (uintptr_t)3) == 0) {
+        u.u32[0] = ((uint32*)addr)[0];
+        u.u32[1] = ((uint32*)addr)[1];
+    }
+    else if ((addr1 & (uintptr_t)1) == 0) {
+        u.u16[0] = ((uint16*)addr)[0];
+        u.u16[1] = ((uint16*)addr)[1];
+        u.u16[2] = ((uint16*)addr)[2];
+        u.u16[3] = ((uint16*)addr)[3];
+    }
+    else {
+        int32 t;
+        for (t = 0; t < 8; t++)
+            u.u8[t] = ((uint8*)addr)[t];
+    }
+    return u.val;
+}
+
+static inline float64
+LOAD_F64(void *addr)
+{
+    uintptr_t addr1 = (uintptr_t)addr;
+    union { float64 val; uint32 u32[2];
+            uint16 u16[4]; uint8 u8[8]; } u;
+    if ((addr1 & (uintptr_t)7) == 0)
+        return *(float64*)addr;
+
+    if ((addr1 & (uintptr_t)3) == 0) {
+        u.u32[0] = ((uint32*)addr)[0];
+        u.u32[1] = ((uint32*)addr)[1];
+    }
+    else if ((addr1 & (uintptr_t)1) == 0) {
+        u.u16[0] = ((uint16*)addr)[0];
+        u.u16[1] = ((uint16*)addr)[1];
+        u.u16[2] = ((uint16*)addr)[2];
+        u.u16[3] = ((uint16*)addr)[3];
+    }
+    else {
+        int32 t;
+        for (t = 0; t < 8; t++)
+            u.u8[t] = ((uint8*)addr)[t];
+    }
+    return u.val;
+}
+
+static inline int32
+LOAD_I32(void *addr)
+{
+    uintptr_t addr1 = (uintptr_t)addr;
+    union { int32 val; uint16 u16[2]; uint8 u8[4]; } u;
+    if ((addr1 & (uintptr_t)3) == 0)
+        return *(int32*)addr;
+
+    if ((addr1 & (uintptr_t)1) == 0) {
+        u.u16[0] = ((uint16*)addr)[0];
+        u.u16[1] = ((uint16*)addr)[1];
+    }
+    else {
+        u.u8[0] = ((uint8*)addr)[0];
+        u.u8[1] = ((uint8*)addr)[1];
+        u.u8[2] = ((uint8*)addr)[2];
+        u.u8[3] = ((uint8*)addr)[3];
+    }
+    return u.val;
+}
+
+static inline int16
+LOAD_I16(void *addr)
+{
+    uintptr_t addr1 = (uintptr_t)addr;
+    union { int16 val; uint8 u8[2]; } u;
+    if ((addr1 & (uintptr_t)1)) {
+        u.u8[0] = ((uint8*)addr)[0];
+        u.u8[1] = ((uint8*)addr)[1];
+        return u.val;
+    }
+    return *(int16*)addr;
+}
+
+#define LOAD_U32(addr) ((uint32)LOAD_I32(addr))
+#define LOAD_U16(addr) ((uint16)LOAD_I16(addr))
+
+#if UINTPTR_MAX == UINT32_MAX
+#define STORE_PTR(addr, ptr) STORE_U32(addr, (uintptr_t)ptr)
+#elif UINTPTR_MAX == UINT64_MAX
+#define STORE_PTR(addr, ptr) STORE_I64(addr, (uintptr_t)ptr)
+#endif
+
+#endif  /* WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS != 0 */
 
 typedef struct WASMModuleCommon {
     /* Module type, for module loaded from WASM bytecode binary,
@@ -44,96 +271,174 @@ typedef struct WASMModuleInstanceCommon {
     uint8 module_inst_data[1];
 } WASMModuleInstanceCommon;
 
+typedef struct WASMModuleMemConsumption {
+    uint32 total_size;
+    uint32 module_struct_size;
+    uint32 types_size;
+    uint32 imports_size;
+    uint32 functions_size;
+    uint32 tables_size;
+    uint32 memories_size;
+    uint32 globals_size;
+    uint32 exports_size;
+    uint32 table_segs_size;
+    uint32 data_segs_size;
+    uint32 const_strs_size;
+#if WASM_ENABLE_AOT != 0
+    uint32 aot_code_size;
+#endif
+} WASMModuleMemConsumption;
+
+typedef struct WASMModuleInstMemConsumption {
+    uint32 total_size;
+    uint32 module_inst_struct_size;
+    uint32 memories_size;
+    uint32 app_heap_size;
+    uint32 tables_size;
+    uint32 globals_size;
+    uint32 functions_size;
+    uint32 exports_size;
+} WASMModuleInstMemConsumption;
+
 #if WASM_ENABLE_LIBC_WASI != 0
+#if WASM_ENABLE_UVWASI == 0
 typedef struct WASIContext {
-    /* Use offset but not native address, since these fields are
-       allocated from app's heap, and the heap space may be re-allocated
-       after memory.grow opcode is executed, the original native address
-       cannot be accessed again. */
-    int32 curfds_offset;
-    int32 prestats_offset;
-    int32 argv_environ_offset;
+    struct fd_table *curfds;
+    struct fd_prestats *prestats;
+    struct argv_environ_values *argv_environ;
+    char *argv_buf;
+    char **argv_list;
+    char *env_buf;
+    char **env_list;
 } WASIContext;
+#else
+typedef uvwasi_t WASIContext;
+#endif
+#endif
+
+#if WASM_ENABLE_MULTI_MODULE != 0
+typedef struct WASMRegisteredModule {
+    bh_list_link l;
+    /* point to a string pool */
+    const char *module_name;
+    WASMModuleCommon *module;
+    /* to store the original module file buffer address */
+    uint8 *orig_file_buf;
+    uint32 orig_file_buf_size;
+} WASMRegisteredModule;
 #endif
 
+typedef struct WASMMemoryInstanceCommon {
+    uint32 module_type;
+    uint8 memory_inst_data[1];
+} WASMMemoryInstanceCommon;
+
 typedef package_type_t PackageType;
 typedef wasm_section_t WASMSection, AOTSection;
 
 /* See wasm_export.h for description */
-bool
-wasm_runtime_init();
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_init(void);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_full_init(RuntimeInitArgs *init_args);
 
 /* See wasm_export.h for description */
-void
-wasm_runtime_destroy();
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_destroy(void);
 
 /* See wasm_export.h for description */
-PackageType
+WASM_RUNTIME_API_EXTERN PackageType
 get_package_type(const uint8 *buf, uint32 size);
 
 /* See wasm_export.h for description */
-WASMModuleCommon *
+WASM_RUNTIME_API_EXTERN WASMModuleCommon *
 wasm_runtime_load(const uint8 *buf, uint32 size,
                   char *error_buf, uint32 error_buf_size);
 
 /* See wasm_export.h for description */
-WASMModuleCommon *
+WASM_RUNTIME_API_EXTERN WASMModuleCommon *
 wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
-                                char *error_buf, uint32_t error_buf_size);
+                                char *error_buf, uint32 error_buf_size);
 
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_unload(WASMModuleCommon *module);
 
-/* See wasm_export.h for description */
+/* Internal API */
 WASMModuleInstanceCommon *
+wasm_runtime_instantiate_internal(WASMModuleCommon *module, bool is_sub_inst,
+                                  uint32 stack_size, uint32 heap_size,
+                                  char *error_buf, uint32 error_buf_size);
+
+/* Internal API */
+void
+wasm_runtime_deinstantiate_internal(WASMModuleInstanceCommon *module_inst,
+                                    bool is_sub_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
 wasm_runtime_instantiate(WASMModuleCommon *module,
                          uint32 stack_size, uint32 heap_size,
                          char *error_buf, uint32 error_buf_size);
 
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_deinstantiate(WASMModuleInstanceCommon *module_inst);
 
 /* See wasm_export.h for description */
-WASMFunctionInstanceCommon *
+WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
 wasm_runtime_lookup_function(WASMModuleInstanceCommon * const module_inst,
                              const char *name, const char *signature);
 
+/* Internal API */
+WASMType *
+wasm_runtime_get_function_type(const WASMFunctionInstanceCommon *function,
+                               uint32 module_type);
+
 /* See wasm_export.h for description */
-WASMExecEnv *
+WASM_RUNTIME_API_EXTERN WASMExecEnv *
 wasm_runtime_create_exec_env(WASMModuleInstanceCommon *module_inst,
                              uint32 stack_size);
 
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_destroy_exec_env(WASMExecEnv *exec_env);
 
 /* See wasm_export.h for description */
-WASMModuleInstanceCommon *
+WASM_RUNTIME_API_EXTERN WASMModuleInstanceCommon *
 wasm_runtime_get_module_inst(WASMExecEnv *exec_env);
 
 /* See wasm_export.h for description */
-void *
-wasm_runtime_get_function_attachment(wasm_exec_env_t exec_env);
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_function_attachment(WASMExecEnv *exec_env);
 
 /* See wasm_export.h for description */
-void
-wasm_runtime_set_user_data(wasm_exec_env_t exec_env, void *user_data);
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_user_data(WASMExecEnv *exec_env, void *user_data);
 
 /* See wasm_export.h for description */
-void *
-wasm_runtime_get_user_data(wasm_exec_env_t exec_env);
+WASM_RUNTIME_API_EXTERN void *
+wasm_runtime_get_user_data(WASMExecEnv *exec_env);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_call_wasm(WASMExecEnv *exec_env,
                        WASMFunctionInstanceCommon *function,
-                       unsigned argc, uint32 argv[]);
+                       uint32 argc, uint32 argv[]);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_a(WASMExecEnv *exec_env,
+                         WASMFunctionInstanceCommon *function,
+                         uint32 num_results, wasm_val_t *results,
+                         uint32 num_args, wasm_val_t *args);
+
+WASM_RUNTIME_API_EXTERN bool
+wasm_runtime_call_wasm_v(WASMExecEnv *exec_env,
+                         WASMFunctionInstanceCommon *function,
+                         uint32 num_results, wasm_val_t *results,
+                         uint32 num_args, ...);
 
 /**
  * Call a function reference of a given WASM runtime instance with
@@ -154,94 +459,105 @@ wasm_runtime_call_wasm(WASMExecEnv *exec_env,
  */
 bool
 wasm_runtime_call_indirect(WASMExecEnv *exec_env,
-                           uint32_t element_indices,
-                           uint32_t argc, uint32_t argv[]);
+                           uint32 element_indices,
+                           uint32 argc, uint32 argv[]);
 
 bool
 wasm_runtime_create_exec_env_and_call_wasm(WASMModuleInstanceCommon *module_inst,
                                            WASMFunctionInstanceCommon *function,
-                                           unsigned argc, uint32 argv[]);
+                                           uint32 argc, uint32 argv[]);
 
-/* See wasm_export.h for description */
 bool
+wasm_runtime_create_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
+WASMExecEnv *
+wasm_runtime_get_exec_env_singleton(WASMModuleInstanceCommon *module_inst);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
 wasm_application_execute_main(WASMModuleInstanceCommon *module_inst,
-                              int argc, char *argv[]);
+                              int32 argc, char *argv[]);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_application_execute_func(WASMModuleInstanceCommon *module_inst,
-                              const char *name, int argc, char *argv[]);
+                              const char *name, int32 argc, char *argv[]);
 
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_set_exception(WASMModuleInstanceCommon *module,
                            const char *exception);
 
 /* See wasm_export.h for description */
-const char *
+WASM_RUNTIME_API_EXTERN const char *
 wasm_runtime_get_exception(WASMModuleInstanceCommon *module);
 
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_clear_exception(WASMModuleInstanceCommon *module_inst);
 
-/* See wasm_export.h for description */
+/* Internal API */
 void
+wasm_runtime_set_custom_data_internal(WASMModuleInstanceCommon *module_inst,
+                                      void *custom_data);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_set_custom_data(WASMModuleInstanceCommon *module_inst,
                              void *custom_data);
 
 /* See wasm_export.h for description */
-void *
+WASM_RUNTIME_API_EXTERN void *
 wasm_runtime_get_custom_data(WASMModuleInstanceCommon *module_inst);
 
 /* See wasm_export.h for description */
-int32
+WASM_RUNTIME_API_EXTERN uint32
 wasm_runtime_module_malloc(WASMModuleInstanceCommon *module_inst, uint32 size,
                            void **p_native_addr);
 
 /* See wasm_export.h for description */
-void
-wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, int32 ptr);
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_module_free(WASMModuleInstanceCommon *module_inst, uint32 ptr);
 
 /* See wasm_export.h for description */
-int32
+WASM_RUNTIME_API_EXTERN uint32
 wasm_runtime_module_dup_data(WASMModuleInstanceCommon *module_inst,
                              const char *src, uint32 size);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst,
-                               int32 app_offset, uint32 size);
+                               uint32 app_offset, uint32 size);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst,
-                                   int32 app_str_offset);
+                                   uint32 app_str_offset);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst,
                                   void *native_ptr, uint32 size);
 
 /* See wasm_export.h for description */
-void *
+WASM_RUNTIME_API_EXTERN void *
 wasm_runtime_addr_app_to_native(WASMModuleInstanceCommon *module_inst,
-                                int32 app_offset);
+                                uint32 app_offset);
 
 /* See wasm_export.h for description */
-int32
+WASM_RUNTIME_API_EXTERN uint32
 wasm_runtime_addr_native_to_app(WASMModuleInstanceCommon *module_inst,
                                 void *native_ptr);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_get_app_addr_range(WASMModuleInstanceCommon *module_inst,
-                                int32 app_offset,
-                                int32 *p_app_start_offset,
-                                int32 *p_app_end_offset);
+                                uint32 app_offset,
+                                uint32 *p_app_start_offset,
+                                uint32 *p_app_end_offset);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_get_native_addr_range(WASMModuleInstanceCommon *module_inst,
                                    uint8 *native_ptr,
                                    uint8 **p_native_start_addr,
@@ -261,9 +577,69 @@ void
 wasm_runtime_set_llvm_stack(WASMModuleInstanceCommon *module_inst,
                             uint32 llvm_stack);
 
+#if WASM_ENABLE_MULTI_MODULE != 0
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_module_reader(const module_reader reader,
+                               const module_destroyer destroyer);
+
+module_reader
+wasm_runtime_get_module_reader();
+
+module_destroyer
+wasm_runtime_get_module_destroyer();
+
+bool
+wasm_runtime_register_module_internal(const char *module_name,
+                                      WASMModuleCommon *module,
+                                      uint8 *orig_file_buf,
+                                      uint32 orig_file_buf_size,
+                                      char *error_buf,
+                                      uint32 error_buf_size);
+
+void
+wasm_runtime_unregister_module(const WASMModuleCommon *module);
+
+bool
+wasm_runtime_is_module_registered(const char *module_name);
+
+bool
+wasm_runtime_add_loading_module(const char *module_name,
+                                char *error_buf, uint32 error_buf_size);
+
+void
+wasm_runtime_delete_loading_module(const char *module_name);
+
+bool
+wasm_runtime_is_loading_module(const char *module_name);
+
+void
+wasm_runtime_destroy_loading_module_list();
+#endif /* WASM_ENALBE_MULTI_MODULE */
+
+bool
+wasm_runtime_is_built_in_module(const char *module_name);
+
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+wasm_exec_env_get_aux_stack(WASMExecEnv *exec_env,
+                            uint32 *start_offset, uint32 *size);
+
+bool
+wasm_exec_env_set_aux_stack(WASMExecEnv *exec_env,
+                            uint32 start_offset, uint32 size);
+#endif
+
 #if WASM_ENABLE_LIBC_WASI != 0
+WASM_RUNTIME_API_EXTERN void
+wasm_runtime_set_wasi_args_ex(WASMModuleCommon *module,
+                           const char *dir_list[], uint32 dir_count,
+                           const char *map_dir_list[], uint32 map_dir_count,
+                           const char *env_list[], uint32 env_count,
+                           char *argv[], int argc,
+                           int stdinfd, int stdoutfd, int stderrfd);
+
 /* See wasm_export.h for description */
-void
+WASM_RUNTIME_API_EXTERN void
 wasm_runtime_set_wasi_args(WASMModuleCommon *module,
                            const char *dir_list[], uint32 dir_count,
                            const char *map_dir_list[], uint32 map_dir_count,
@@ -271,11 +647,11 @@ wasm_runtime_set_wasi_args(WASMModuleCommon *module,
                            char *argv[], int argc);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_is_wasi_mode(WASMModuleInstanceCommon *module_inst);
 
 /* See wasm_export.h for description */
-WASMFunctionInstanceCommon *
+WASM_RUNTIME_API_EXTERN WASMFunctionInstanceCommon *
 wasm_runtime_lookup_wasi_start_function(WASMModuleInstanceCommon *module_inst);
 
 bool
@@ -284,6 +660,7 @@ wasm_runtime_init_wasi(WASMModuleInstanceCommon *module_inst,
                        const char *map_dir_list[], uint32 map_dir_count,
                        const char *env[], uint32 env_count,
                        char *argv[], uint32 argc,
+                       int stdinfd, int stdoutfd, int stderrfd,
                        char *error_buf, uint32 error_buf_size);
 
 void
@@ -298,6 +675,38 @@ wasm_runtime_get_wasi_ctx(WASMModuleInstanceCommon *module_inst);
 
 #endif /* end of WASM_ENABLE_LIBC_WASI */
 
+#if WASM_ENABLE_REF_TYPES != 0
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_obj2ref(WASMModuleInstanceCommon *module_inst,
+                       void *extern_obj, uint32 *p_externref_idx);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_ref2obj(uint32 externref_idx, void **p_extern_obj);
+
+/* See wasm_export.h for description */
+WASM_RUNTIME_API_EXTERN bool
+wasm_externref_retain(uint32 externref_idx);
+
+/**
+ * Reclaim the externref objects/indexes which are not used by
+ * module instance
+ */
+void
+wasm_externref_reclaim(WASMModuleInstanceCommon *module_inst);
+
+/**
+ * Cleanup the externref objects/indexes of the module instance
+ */
+void
+wasm_externref_cleanup(WASMModuleInstanceCommon *module_inst);
+#endif /* end of WASM_ENABLE_REF_TYPES */
+
+/* Get module of the current exec_env */
+WASMModuleCommon*
+wasm_exec_env_get_module(WASMExecEnv *exec_env);
+
 /**
  * Enlarge wasm memory data space.
  *
@@ -309,13 +718,13 @@ bool
 wasm_runtime_enlarge_memory(WASMModuleInstanceCommon *module, uint32 inc_page_count);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_register_natives(const char *module_name,
                               NativeSymbol *native_symbols,
                               uint32 n_native_symbols);
 
 /* See wasm_export.h for description */
-bool
+WASM_RUNTIME_API_EXTERN bool
 wasm_runtime_register_natives_raw(const char *module_name,
                                   NativeSymbol *native_symbols,
                                   uint32 n_native_symbols);
@@ -332,6 +741,67 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
                                void *attachment,
                                uint32 *argv, uint32 argc, uint32 *ret);
 
+void
+wasm_runtime_read_v128(const uint8 *bytes, uint64 *ret1, uint64 *ret2);
+
+void
+wasm_runtime_dump_module_mem_consumption(const WASMModuleCommon *module);
+
+void
+wasm_runtime_dump_module_inst_mem_consumption(const WASMModuleInstanceCommon
+                                              *module_inst);
+
+void
+wasm_runtime_dump_exec_env_mem_consumption(const WASMExecEnv *exec_env);
+
+#if WASM_ENABLE_REF_TYPES != 0
+void
+wasm_runtime_prepare_call_function(WASMExecEnv *exec_env,
+                                   WASMFunctionInstanceCommon *function);
+void
+wasm_runtime_finalize_call_function(WASMExecEnv *exec_env,
+                                    WASMFunctionInstanceCommon *function,
+                                    bool ret, uint32 *argv);
+#endif
+
+bool
+wasm_runtime_get_export_func_type(const WASMModuleCommon *module_comm,
+                                  const WASMExport *export,
+                                  WASMType **out);
+
+bool
+wasm_runtime_get_export_global_type(const WASMModuleCommon *module_comm,
+                                    const WASMExport *export,
+                                    uint8 *out_val_type,
+                                    bool *out_mutability);
+
+bool
+wasm_runtime_get_export_memory_type(const WASMModuleCommon *module_comm,
+                                    const WASMExport *export,
+                                    uint32 *out_min_page,
+                                    uint32 *out_max_page);
+
+bool
+wasm_runtime_get_export_table_type(const WASMModuleCommon *module_comm,
+                                   const WASMExport *export,
+                                   uint8 *out_elem_type,
+                                   uint32 *out_min_size,
+                                   uint32 *out_max_size);
+
+uint8 *
+wasm_runtime_get_memory_data(const WASMModuleInstanceCommon *module_inst_comm,
+                             uint32 memory_inst_idx);
+
+uint32
+wasm_runtime_get_memory_data_size(const WASMModuleInstanceCommon *module_inst_comm,
+                                  uint32 memory_inst_idx);
+
+bool
+wasm_runtime_invoke_c_api_native(WASMModuleInstanceCommon *module_inst,
+                                 void *func_ptr, WASMType *func_type,
+                                 uint32 argc, uint32 *argv,
+                                 bool with_env, void *wasm_c_api_env);
+
 #ifdef __cplusplus
 }
 #endif

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

@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "bh_log.h"
+#include "wasm_shared_memory.h"
+
+static bh_list shared_memory_list_head;
+static bh_list *const shared_memory_list = &shared_memory_list_head;
+static korp_mutex shared_memory_list_lock;
+
+enum {
+    S_WAITING, S_NOTIFIED
+};
+
+typedef struct AtomicWaitInfo {
+    korp_mutex wait_list_lock;
+    bh_list wait_list_head;
+    bh_list *wait_list;
+} AtomicWaitInfo;
+
+typedef struct AtomicWaitNode {
+    bh_list_link l;
+    uint8 status;
+    korp_mutex wait_lock;
+    korp_cond wait_cond;
+} AtomicWaitNode;
+
+/* Atomic wait map */
+static HashMap *wait_map;
+
+static uint32
+wait_address_hash(void *address);
+
+static bool
+wait_address_equal(void *h1, void *h2);
+
+static void
+destroy_wait_info(void *wait_info);
+
+bool
+wasm_shared_memory_init()
+{
+    if (os_mutex_init(&shared_memory_list_lock) != 0)
+        return false;
+    /* wait map not exists, create new map */
+    if (!(wait_map =
+        bh_hash_map_create(32, true,
+                           (HashFunc)wait_address_hash,
+                           (KeyEqualFunc)wait_address_equal,
+                           NULL, destroy_wait_info))) {
+        os_mutex_destroy(&shared_memory_list_lock);
+        return false;
+    }
+
+    return true;
+}
+
+void
+wasm_shared_memory_destroy()
+{
+    os_mutex_destroy(&shared_memory_list_lock);
+    if (wait_map) {
+        bh_hash_map_destroy(wait_map);
+    }
+}
+
+static WASMSharedMemNode*
+search_module(WASMModuleCommon *module)
+{
+    WASMSharedMemNode *node;
+
+    os_mutex_lock(&shared_memory_list_lock);
+    node = bh_list_first_elem(shared_memory_list);
+
+    while (node) {
+        if (module == node->module) {
+            os_mutex_unlock(&shared_memory_list_lock);
+            return node;
+        }
+        node = bh_list_elem_next(node);
+    }
+
+    os_mutex_unlock(&shared_memory_list_lock);
+    return NULL;
+}
+
+WASMSharedMemNode*
+wasm_module_get_shared_memory(WASMModuleCommon *module)
+{
+    return search_module(module);
+}
+
+int32
+shared_memory_inc_reference(WASMModuleCommon *module)
+{
+    WASMSharedMemNode *node = search_module(module);
+    if (node) {
+        os_mutex_lock(&node->lock);
+        node->ref_count++;
+        os_mutex_unlock(&node->lock);
+        return node->ref_count;
+    }
+    return -1;
+}
+
+int32
+shared_memory_dec_reference(WASMModuleCommon *module)
+{
+    WASMSharedMemNode *node = search_module(module);
+    uint32 ref_count = 0;
+    if (node) {
+        os_mutex_lock(&node->lock);
+        ref_count = --node->ref_count;
+        os_mutex_unlock(&node->lock);
+        if (ref_count == 0) {
+            os_mutex_lock(&shared_memory_list_lock);
+            bh_list_remove(shared_memory_list, node);
+            os_mutex_unlock(&shared_memory_list_lock);
+
+            os_mutex_destroy(&node->lock);
+            wasm_runtime_free(node);
+        }
+        return ref_count;
+    }
+
+    return -1;
+}
+
+WASMMemoryInstanceCommon*
+shared_memory_get_memory_inst(WASMSharedMemNode *node)
+{
+    return node->memory_inst;
+}
+
+WASMSharedMemNode*
+shared_memory_set_memory_inst(WASMModuleCommon *module,
+                              WASMMemoryInstanceCommon *memory)
+{
+    WASMSharedMemNode *node;
+    bh_list_status ret;
+
+    if (!(node = wasm_runtime_malloc(sizeof(WASMSharedMemNode))))
+        return NULL;
+
+    node->module = module;
+    node->memory_inst = memory;
+    node->ref_count = 1;
+    if (os_mutex_init(&node->lock) != 0) {
+        wasm_runtime_free(node);
+        return NULL;
+    }
+
+    os_mutex_lock(&shared_memory_list_lock);
+    ret = bh_list_insert(shared_memory_list, node);
+    bh_assert(ret == BH_LIST_SUCCESS);
+    os_mutex_unlock(&shared_memory_list_lock);
+
+    (void)ret;
+    return node;
+}
+
+/* Atomics wait && notify APIs */
+static uint32
+wait_address_hash(void *address)
+{
+    return (uint32)(uintptr_t)address;
+}
+
+static bool
+wait_address_equal(void *h1, void *h2)
+{
+    return h1 == h2 ? true : false;
+}
+
+static bool
+is_wait_node_exists(bh_list *wait_list, AtomicWaitNode *node)
+{
+    AtomicWaitNode *curr;
+    curr = bh_list_first_elem(wait_list);
+
+    while (curr) {
+        if (curr == node) {
+            return true;
+        }
+        curr = bh_list_elem_next(curr);
+    }
+
+    return false;
+}
+
+static uint32
+notify_wait_list(bh_list *wait_list, uint32 count)
+{
+    AtomicWaitNode *node, *next;
+    uint32 i, notify_count = count;
+
+    if ((count == UINT32_MAX) || (count > wait_list->len))
+        notify_count = wait_list->len;
+
+    node = bh_list_first_elem(wait_list);
+    if (!node)
+        return 0;
+
+    for (i = 0; i < notify_count; i++) {
+        bh_assert(node);
+        next = bh_list_elem_next(node);
+
+        node->status = S_NOTIFIED;
+        /* wakeup */
+        os_cond_signal(&node->wait_cond);
+
+        node = next;
+    }
+
+    return notify_count;
+}
+
+static AtomicWaitInfo *
+acquire_wait_info(void *address, bool create)
+{
+    AtomicWaitInfo *wait_info = NULL;
+    bh_list_status ret;
+
+    wait_info = (AtomicWaitInfo *)
+                    bh_hash_map_find(wait_map, address);
+
+    if (!create)
+        return wait_info;
+
+    /* No wait info on this address, create new info */
+    if (!wait_info) {
+        if (!(wait_info =
+                (AtomicWaitInfo *)wasm_runtime_malloc(sizeof(AtomicWaitInfo))))
+            return NULL;
+        memset(wait_info, 0, sizeof(AtomicWaitInfo));
+
+        /* init wait list */
+        wait_info->wait_list = &wait_info->wait_list_head;
+        ret = bh_list_init(wait_info->wait_list);
+        bh_assert(ret == BH_LIST_SUCCESS);
+
+        /* init wait list lock */
+        if (0 != os_mutex_init(&wait_info->wait_list_lock)) {
+            wasm_runtime_free(wait_info);
+            return NULL;
+        }
+
+        if (!bh_hash_map_insert(wait_map, address,
+                                (void *)wait_info)) {
+            os_mutex_destroy(&wait_info->wait_list_lock);
+            wasm_runtime_free(wait_info);
+            return NULL;
+        }
+    }
+
+    bh_assert(wait_info);
+    (void)ret;
+    return wait_info;
+}
+
+static void
+destroy_wait_info(void *wait_info)
+{
+    AtomicWaitNode *node, *next;
+
+    if (wait_info) {
+
+        node = bh_list_first_elem(((AtomicWaitInfo *)wait_info)->wait_list);
+
+        while (node) {
+            next = bh_list_elem_next(node);
+            os_mutex_destroy(&node->wait_lock);
+            os_cond_destroy(&node->wait_cond);
+            wasm_runtime_free(node);
+            node = next;
+        }
+
+        os_mutex_destroy(&((AtomicWaitInfo *)wait_info)->wait_list_lock);
+        wasm_runtime_free(wait_info);
+    }
+}
+
+static void
+release_wait_info(HashMap *wait_map,
+                  AtomicWaitInfo *wait_info, void *address)
+{
+    if (wait_info->wait_list->len == 0) {
+        bh_hash_map_remove(wait_map, address, NULL, NULL);
+        destroy_wait_info(wait_info);
+    }
+}
+
+uint32
+wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
+                         uint64 expect, int64 timeout, bool wait64)
+{
+    AtomicWaitInfo *wait_info;
+    AtomicWaitNode *wait_node;
+    bool check_ret, is_timeout;
+
+#if WASM_ENABLE_INTERP != 0
+    if (module->module_type == Wasm_Module_Bytecode) {
+        WASMModuleInstance *module_inst = (WASMModuleInstance *)module;
+        /* Currently we have only one memory instance */
+        if (!module_inst->memories[0]->is_shared) {
+            wasm_runtime_set_exception(module, "wait on unshared memory");
+            return -1;
+        }
+    }
+#endif
+#if WASM_ENABLE_AOT != 0
+    if (module->module_type == Wasm_Module_AoT) {
+        AOTModuleInstance *aot_inst = (AOTModuleInstance *)module;
+        AOTMemoryInstance *aot_memory =
+            ((AOTMemoryInstance **)aot_inst->memories.ptr)[0];
+        /* Currently we have only one memory instance */
+        if (!aot_memory->is_shared) {
+            wasm_runtime_set_exception(module, "wait on unshared memory");
+            return -1;
+        }
+    }
+#endif
+
+    /* acquire the wait info, create new one if not exists */
+    wait_info = acquire_wait_info(address, true);
+
+    if (!wait_info) {
+        wasm_runtime_set_exception(module, "failed to acquire wait_info");
+        return -1;
+    }
+
+    os_mutex_lock(&wait_info->wait_list_lock);
+
+    if ((!wait64 && *(uint32*)address != (uint32)expect)
+        || (wait64 && *(uint64*)address != expect)) {
+        os_mutex_unlock(&wait_info->wait_list_lock);
+        return 1;
+    }
+    else {
+        bh_list_status ret;
+
+        if (!(wait_node = wasm_runtime_malloc(sizeof(AtomicWaitNode)))) {
+            wasm_runtime_set_exception(module, "failed to create wait node");
+            os_mutex_unlock(&wait_info->wait_list_lock);
+            return -1;
+        }
+        memset(wait_node, 0, sizeof(AtomicWaitNode));
+
+        if (0 != os_mutex_init(&wait_node->wait_lock)) {
+            wasm_runtime_free(wait_node);
+            os_mutex_unlock(&wait_info->wait_list_lock);
+            return -1;
+        }
+
+        if (0 != os_cond_init(&wait_node->wait_cond)) {
+            os_mutex_destroy(&wait_node->wait_lock);
+            wasm_runtime_free(wait_node);
+            os_mutex_unlock(&wait_info->wait_list_lock);
+            return -1;
+        }
+
+        wait_node->status = S_WAITING;
+
+        ret = bh_list_insert(wait_info->wait_list, wait_node);
+        bh_assert(ret == BH_LIST_SUCCESS);
+        (void)ret;
+    }
+
+    os_mutex_unlock(&wait_info->wait_list_lock);
+
+    /* condition wait start */
+    os_mutex_lock(&wait_node->wait_lock);
+
+    if (timeout < 0)
+        timeout = BHT_WAIT_FOREVER;
+    os_cond_reltimedwait(&wait_node->wait_cond,
+                         &wait_node->wait_lock, timeout);
+
+    os_mutex_unlock(&wait_node->wait_lock);
+
+    /* Check the wait node status */
+    os_mutex_lock(&wait_info->wait_list_lock);
+    check_ret = is_wait_node_exists(wait_info->wait_list, wait_node);
+    bh_assert(check_ret);
+
+    is_timeout = wait_node->status == S_WAITING ? true : false;
+
+    bh_list_remove(wait_info->wait_list, wait_node);
+    os_mutex_destroy(&wait_node->wait_lock);
+    os_cond_destroy(&wait_node->wait_cond);
+    wasm_runtime_free(wait_node);
+    os_mutex_unlock(&wait_info->wait_list_lock);
+
+    release_wait_info(wait_map, wait_info, address);
+
+    (void)check_ret;
+    return is_timeout ? 2 : 0;
+}
+
+uint32
+wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module,
+                           void *address, uint32 count)
+{
+    uint32 notify_result;
+    AtomicWaitInfo *wait_info;
+
+    /* Nobody wait on this address */
+    wait_info = acquire_wait_info(address, false);
+    if (!wait_info)
+        return 0;
+
+    os_mutex_lock(&wait_info->wait_list_lock);
+    notify_result = notify_wait_list(wait_info->wait_list, count);
+    os_mutex_unlock(&wait_info->wait_list_lock);
+
+    release_wait_info(wait_map, wait_info, address);
+
+    return notify_result;
+}

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

@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2019 Intel Corporation.  All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _WASM_SHARED_MEMORY_H
+#define _WASM_SHARED_MEMORY_H
+
+#include "bh_common.h"
+#if WASM_ENABLE_INTERP != 0
+#include "wasm_runtime.h"
+#endif
+#if WASM_ENABLE_AOT != 0
+#include "aot_runtime.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct WASMSharedMemNode {
+    bh_list_link l;
+    /* Lock */
+    korp_mutex lock;
+    /* The module reference */
+    WASMModuleCommon *module;
+    /* The memory information */
+    WASMMemoryInstanceCommon *memory_inst;
+
+    /* reference count */
+    uint32 ref_count;
+} WASMSharedMemNode;
+
+bool
+wasm_shared_memory_init();
+
+void
+wasm_shared_memory_destroy();
+
+WASMSharedMemNode*
+wasm_module_get_shared_memory(WASMModuleCommon *module);
+
+int32
+shared_memory_inc_reference(WASMModuleCommon *module);
+
+int32
+shared_memory_dec_reference(WASMModuleCommon *module);
+
+WASMMemoryInstanceCommon*
+shared_memory_get_memory_inst(WASMSharedMemNode *node);
+
+WASMSharedMemNode*
+shared_memory_set_memory_inst(WASMModuleCommon *module,
+                              WASMMemoryInstanceCommon *memory);
+
+uint32
+wasm_runtime_atomic_wait(WASMModuleInstanceCommon *module, void *address,
+                         uint64 expect, int64 timeout, bool wait64);
+
+uint32
+wasm_runtime_atomic_notify(WASMModuleInstanceCommon *module,
+                           void *address, uint32 count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* end of _WASM_SHARED_MEMORY_H */

+ 134 - 67
core/iwasm/compilation/aot.c

@@ -14,6 +14,15 @@ aot_get_last_error()
   return aot_error[0] == '\0' ? "" : aot_error;
 }
 
+void
+aot_set_last_error_v(const char *format, ...)
+{
+    va_list args;
+    va_start(args, format);
+    vsnprintf(aot_error, sizeof(aot_error), format, args);
+    va_end(args);
+}
+
 void
 aot_set_last_error(const char *error)
 {
@@ -60,6 +69,10 @@ aot_create_mem_init_data_list(const WASMModule *module)
       goto fail;
     }
 
+#if WASM_ENABLE_BULK_MEMORY != 0
+    data_list[i]->is_passive = module->data_segments[i]->is_passive;
+    data_list[i]->memory_index = module->data_segments[i]->memory_index;
+#endif
     data_list[i]->offset = module->data_segments[i]->base_offset;
     data_list[i]->byte_count = module->data_segments[i]->data_length;
     memcpy(data_list[i]->bytes, module->data_segments[i]->data,
@@ -112,8 +125,18 @@ aot_create_table_init_data_list(const WASMModule *module)
 
     data_list[i]->offset = module->table_segments[i].base_offset;
     data_list[i]->func_index_count = module->table_segments[i].function_count;
-    memcpy(data_list[i]->func_indexes, module->table_segments[i].func_indexes,
-           sizeof(uint32) * module->table_segments[i].function_count);
+    data_list[i]->mode = module->table_segments[i].mode;
+    data_list[i]->elem_type = module->table_segments[i].elem_type;
+    /* runtime control it */
+    data_list[i]->is_dropped = false;
+    data_list[i]->table_index = module->table_segments[i].table_index;
+    bh_memcpy_s(&data_list[i]->offset, sizeof(AOTInitExpr),
+                &module->table_segments[i].base_offset, sizeof(AOTInitExpr));
+    data_list[i]->func_index_count = module->table_segments[i].function_count;
+    bh_memcpy_s(data_list[i]->func_indexes,
+                sizeof(uint32) * module->table_segments[i].function_count,
+                module->table_segments[i].func_indexes,
+                sizeof(uint32) * module->table_segments[i].function_count);
   }
 
   return data_list;
@@ -267,6 +290,7 @@ aot_create_import_funcs(const WASMModule *module)
     import_funcs[i].signature = import_func->signature;
     import_funcs[i].attachment = import_func->attachment;
     import_funcs[i].call_conv_raw = import_func->call_conv_raw;
+    import_funcs[i].call_conv_wasm_c_api = false;
     /* Resolve function type index */
     for (j = 0; j < module->type_count; j++)
       if (import_func->func_type == module->types[j]) {
@@ -327,6 +351,8 @@ aot_create_funcs(const WASMModule *module)
     /* Resolve local variable info and code info */
     funcs[i]->local_count = func->local_count;
     funcs[i]->local_types = func->local_types;
+    funcs[i]->param_cell_num = func->param_cell_num;
+    funcs[i]->local_cell_num = func->local_cell_num;
     funcs[i]->code = func->code;
     funcs[i]->code_size = func->code_size;
   }
@@ -338,43 +364,12 @@ fail:
   return NULL;
 }
 
-static AOTExportFunc *
-aot_create_export_funcs(const WASMModule *module,
-                        uint32 export_func_count)
-{
-  AOTExportFunc *export_funcs;
-  uint64 size;
-  uint32 i, j = 0;
-
-  /* Allocate memory */
-  size = sizeof(AOTExportFunc) * (uint64)export_func_count;
-  if (size >= UINT32_MAX
-      || !(export_funcs = wasm_runtime_malloc((uint32)size))) {
-    aot_set_last_error("allocate memory failed.");
-    return NULL;
-  }
-
-  /* Create each export function */
-  for (i = 0; i < module->export_count; i++) {
-    if (module->exports[i].kind == EXPORT_KIND_FUNC) {
-      export_funcs[j].func_name = module->exports[i].name;
-      export_funcs[j].func_index = module->exports[i].index;
-      export_funcs[j].func_type =
-          module->functions[module->exports[i].index
-                            - module->import_function_count]->func_type;
-      /* Function pointer to be linked in JIT mode */
-      export_funcs[j].func_ptr = NULL;
-      j++;
-    }
-  }
-  return export_funcs;
-}
-
 AOTCompData*
 aot_create_comp_data(WASMModule *module)
 {
   AOTCompData *comp_data;
-  uint32 import_global_data_size = 0, global_data_size = 0, i;
+  uint32 import_global_data_size = 0, global_data_size = 0, i, j;
+  uint64 size;
 
   /* Allocate memory */
   if (!(comp_data = wasm_runtime_malloc(sizeof(AOTCompData)))) {
@@ -384,22 +379,53 @@ aot_create_comp_data(WASMModule *module)
 
   memset(comp_data, 0, sizeof(AOTCompData));
 
-  /* Set memory page count */
-  if (module->import_memory_count) {
-    comp_data->num_bytes_per_page =
-      module->import_memories[0].u.memory.num_bytes_per_page;
-    comp_data->mem_init_page_count =
-      module->import_memories[0].u.memory.init_page_count;
-    comp_data->mem_max_page_count =
-      module->import_memories[0].u.memory.max_page_count;
+  comp_data->memory_count = module->import_memory_count + module->memory_count;
+
+  /* TODO: create import memories */
+
+  /* Allocate memory for memory array, reserve one AOTMemory space at least */
+  if (!comp_data->memory_count)
+    comp_data->memory_count = 1;
+
+  size = (uint64)comp_data->memory_count * sizeof(AOTMemory);
+  if (size >= UINT32_MAX
+      || !(comp_data->memories = wasm_runtime_malloc((uint32)size))) {
+    aot_set_last_error("create memories array failed.\n");
+    goto fail;
+  }
+  memset(comp_data->memories, 0, size);
+
+  if (!(module->import_memory_count + module->memory_count)) {
+      comp_data->memories[0].num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
   }
-  else if (module->memory_count) {
-    comp_data->num_bytes_per_page =
-      module->memories[0].num_bytes_per_page;
-    comp_data->mem_init_page_count =
-      module->memories[0].init_page_count;
-    comp_data->mem_max_page_count =
-      module->memories[0].max_page_count;
+
+  /* Set memory page count */
+  for (i = 0; i < module->import_memory_count + module->memory_count; i++) {
+    if (i < module->import_memory_count) {
+      comp_data->memories[i].memory_flags =
+        module->import_memories[i].u.memory.flags;
+      comp_data->memories[i].num_bytes_per_page =
+        module->import_memories[i].u.memory.num_bytes_per_page;
+      comp_data->memories[i].mem_init_page_count =
+        module->import_memories[i].u.memory.init_page_count;
+      comp_data->memories[i].mem_max_page_count =
+        module->import_memories[i].u.memory.max_page_count;
+      comp_data->memories[i].num_bytes_per_page =
+        module->import_memories[i].u.memory.num_bytes_per_page;
+    }
+    else {
+      j = i - module->import_memory_count;
+      comp_data->memories[i].memory_flags =
+                    module->memories[j].flags;
+      comp_data->memories[i].num_bytes_per_page =
+                    module->memories[j].num_bytes_per_page;
+      comp_data->memories[i].mem_init_page_count =
+                    module->memories[j].init_page_count;
+      comp_data->memories[i].mem_max_page_count =
+                    module->memories[j].max_page_count;
+      comp_data->memories[i].num_bytes_per_page =
+                    module->memories[j].num_bytes_per_page;
+    }
   }
 
   /* Create memory data segments */
@@ -409,11 +435,40 @@ aot_create_comp_data(WASMModule *module)
             aot_create_mem_init_data_list(module)))
     goto fail;
 
-  /* Set table size */
-  if (module->import_table_count)
-    comp_data->table_size = module->import_tables[0].u.table.init_size;
-  else if (module->table_count)
-    comp_data->table_size = module->tables[0].init_size;
+  /* Create tables */
+  comp_data->table_count = module->import_table_count + module->table_count;
+
+  if (comp_data->table_count > 0) {
+    size = sizeof(AOTTable) * (uint64)comp_data->table_count;
+    if (size >= UINT32_MAX
+        || !(comp_data->tables = wasm_runtime_malloc((uint32)size))) {
+      aot_set_last_error("create memories array failed.\n");
+      goto fail;
+    }
+    memset(comp_data->tables, 0, size);
+    for (i = 0; i < comp_data->table_count; i++) {
+      if (i < module->import_table_count) {
+        comp_data->tables[i].elem_type =
+            module->import_tables[i].u.table.elem_type;
+        comp_data->tables[i].table_flags =
+            module->import_tables[i].u.table.flags;
+        comp_data->tables[i].table_init_size =
+            module->import_tables[i].u.table.init_size;
+        comp_data->tables[i].table_max_size =
+            module->import_tables[i].u.table.max_size;
+        comp_data->tables[i].possible_grow =
+            module->import_tables[i].u.table.possible_grow;
+      }
+      else {
+        j = i - module->import_table_count;
+        comp_data->tables[i].elem_type = module->tables[i].elem_type;
+        comp_data->tables[i].table_flags = module->tables[i].flags;
+        comp_data->tables[i].table_init_size = module->tables[i].init_size;
+        comp_data->tables[i].table_max_size = module->tables[i].max_size;
+        comp_data->tables[i].possible_grow = module->tables[i].possible_grow;
+      }
+    }
+  }
 
   /* Create table data segments */
   comp_data->table_init_data_count = module->table_seg_count;
@@ -457,17 +512,20 @@ aot_create_comp_data(WASMModule *module)
       && !(comp_data->funcs = aot_create_funcs(module)))
     goto fail;
 
-  /* Create export functions */
-  for (i = 0; i < module->export_count; i++)
-    if (module->exports[i].kind == EXPORT_KIND_FUNC)
-      comp_data->export_func_count++;
-
-  if (comp_data->export_func_count
-      && !(comp_data->export_funcs = aot_create_export_funcs
-            (module, comp_data->export_func_count)))
-    goto fail;
+  /* Create aux data/heap/stack information */
+  comp_data->aux_data_end_global_index = module->aux_data_end_global_index;
+  comp_data->aux_data_end = module->aux_data_end;
+  comp_data->aux_heap_base_global_index = module->aux_heap_base_global_index;
+  comp_data->aux_heap_base = module->aux_heap_base;
+  comp_data->aux_stack_top_global_index = module->aux_stack_top_global_index;
+  comp_data->aux_stack_bottom = module->aux_stack_bottom;
+  comp_data->aux_stack_size = module->aux_stack_size;
 
   comp_data->start_func_index = module->start_function;
+  comp_data->malloc_func_index = module->malloc_function;
+  comp_data->free_func_index = module->free_function;
+  comp_data->retain_func_index = module->retain_function;
+
   comp_data->wasm_module = module;
 
   return comp_data;
@@ -484,10 +542,22 @@ aot_destroy_comp_data(AOTCompData *comp_data)
   if (!comp_data)
     return;
 
+  if (comp_data->import_memories)
+    wasm_runtime_free(comp_data->import_memories);
+
+  if (comp_data->memories)
+    wasm_runtime_free(comp_data->memories);
+
   if (comp_data->mem_init_data_list)
     aot_destroy_mem_init_data_list(comp_data->mem_init_data_list,
                                    comp_data->mem_init_data_count);
 
+  if (comp_data->import_tables)
+    wasm_runtime_free(comp_data->import_tables);
+
+  if (comp_data->tables)
+    wasm_runtime_free(comp_data->tables);
+
   if (comp_data->table_init_data_list)
     aot_destroy_table_init_data_list(comp_data->table_init_data_list,
                                      comp_data->table_init_data_count);
@@ -508,9 +578,6 @@ aot_destroy_comp_data(AOTCompData *comp_data)
   if (comp_data->funcs)
     aot_destroy_funcs(comp_data->funcs, comp_data->func_count);
 
-  if (comp_data->export_funcs)
-    wasm_runtime_free(comp_data->export_funcs);
-
   wasm_runtime_free(comp_data);
 }
 

+ 130 - 31
core/iwasm/compilation/aot.h

@@ -19,11 +19,41 @@ extern "C" {
 
 typedef InitializerExpression AOTInitExpr;
 typedef WASMType AOTFuncType;
+typedef WASMExport AOTExport;
+
+/**
+ * Import memory
+ */
+typedef struct AOTImportMemory {
+  char *module_name;
+  char *memory_name;
+  uint32 memory_flags;
+  uint32 num_bytes_per_page;
+  uint32 mem_init_page_count;
+  uint32 mem_max_page_count;
+} AOTImportMemory;
+
+/**
+ * Memory information
+ */
+typedef struct AOTMemory {
+  /* memory info */
+  uint32 memory_flags;
+  uint32 num_bytes_per_page;
+  uint32 mem_init_page_count;
+  uint32 mem_max_page_count;
+} AOTMemory;
 
 /**
  * A segment of memory init data
  */
 typedef struct AOTMemInitData {
+#if WASM_ENABLE_BULK_MEMORY != 0
+  /* Passive flag */
+  bool is_passive;
+  /* memory index */
+  uint32 memory_index;
+#endif
   /* Start address of init data */
   AOTInitExpr offset;
   /* Byte count */
@@ -32,10 +62,40 @@ typedef struct AOTMemInitData {
   uint8 bytes[1];
 } AOTMemInitData;
 
+/**
+ * Import table
+ */
+typedef struct AOTImportTable {
+  char *module_name;
+  char *table_name;
+  uint32 table_flags;
+  uint32 table_init_size;
+  uint32 table_max_size;
+  bool possible_grow;
+} AOTImportTable;
+
+/**
+ * Table
+ */
+typedef struct AOTTable {
+  uint32 elem_type;
+  uint32 table_flags;
+  uint32 table_init_size;
+  uint32 table_max_size;
+  bool possible_grow;
+} AOTTable;
+
 /**
  * A segment of table init data
  */
 typedef struct AOTTableInitData {
+  /* 0 to 7 */
+  uint32 mode;
+  /* funcref or externref, elemkind will be considered as funcref */
+  uint32 elem_type;
+  bool is_dropped;
+  /* optional, only for active */
+  uint32 table_index;
   /* Start address of init data */
   AOTInitExpr offset;
   /* Function index count */
@@ -88,6 +148,8 @@ typedef struct AOTImportFunc {
   /* attachment */
   void *attachment;
   bool call_conv_raw;
+  bool call_conv_wasm_c_api;
+  bool wasm_c_api_with_env;
 } AOTImportFunc;
 
 /**
@@ -98,60 +160,71 @@ typedef struct AOTFunc {
   uint32 func_type_index;
   uint32 local_count;
   uint8 *local_types;
+  uint16 param_cell_num;
+  uint16 local_cell_num;
   uint32 code_size;
   uint8 *code;
 } AOTFunc;
 
-/**
- * Export function
- */
-typedef struct AOTExportFunc {
-  char *func_name;
-  AOTFuncType *func_type;
-  /* function pointer linked */
-  void *func_ptr;
-  uint32 func_index;
-} AOTExportFunc;
-
 typedef struct AOTCompData {
-  /* Memory and memory init data info */
-  uint32 num_bytes_per_page;
-  uint32 mem_init_page_count;
-  uint32 mem_max_page_count;
+  /* Import memories */
+  uint32 import_memory_count;
+  AOTImportMemory *import_memories;
+
+  /* Memories */
+  uint32 memory_count;
+  AOTMemory *memories;
+
+  /* Memory init data info */
   uint32 mem_init_data_count;
   AOTMemInitData **mem_init_data_list;
 
-  /* Table and table init data info */
-  uint32 table_size;
-  AOTTableInitData **table_init_data_list;
+  /* Import tables */
+  uint32 import_table_count;
+  AOTImportTable *import_tables;
+
+  /* Tables */
+  uint32 table_count;
+  AOTTable *tables;
+
+  /* Table init data info */
   uint32 table_init_data_count;
+  AOTTableInitData **table_init_data_list;
 
-  AOTImportGlobal *import_globals;
+  /* Import globals */
   uint32 import_global_count;
+  AOTImportGlobal *import_globals;
 
-  AOTGlobal *globals;
+  /* Globals */
   uint32 global_count;
+  AOTGlobal *globals;
 
-  AOTFuncType **func_types;
+  /* Function types */
   uint32 func_type_count;
+  AOTFuncType **func_types;
 
-  AOTImportFunc *import_funcs;
+  /* Import functions */
   uint32 import_func_count;
+  AOTImportFunc *import_funcs;
 
-  AOTFunc **funcs;
+  /* Functions */
   uint32 func_count;
+  AOTFunc **funcs;
 
-  AOTExportFunc *export_funcs;
-  uint32 export_func_count;
+  uint32 global_data_size;
 
   uint32 start_func_index;
-  uint32 addr_data_size;
-  uint32 global_data_size;
+  uint32 malloc_func_index;
+  uint32 free_func_index;
+  uint32 retain_func_index;
 
-  uint32 llvm_aux_data_end;
-  uint32 llvm_aux_stack_bottom;
-  uint32 llvm_aux_stack_size;
-  uint32 llvm_aux_stack_global_index;
+  uint32 aux_data_end_global_index;
+  uint32 aux_data_end;
+  uint32 aux_heap_base_global_index;
+  uint32 aux_heap_base;
+  uint32 aux_stack_top_global_index;
+  uint32 aux_stack_bottom;
+  uint32 aux_stack_size;
 
   WASMModule *wasm_module;
 } AOTCompData;
@@ -168,6 +241,32 @@ aot_get_last_error();
 void
 aot_set_last_error(const char *error);
 
+void
+aot_set_last_error_v(const char *format, ...);
+
+#if BH_DEBUG != 0
+#define HANDLE_FAILURE(callee) do {                          \
+    aot_set_last_error_v("call %s failed in %s:%d", (callee),\
+                         __FUNCTION__, __LINE__);            \
+  } while (0)
+#else
+#define HANDLE_FAILURE(callee) do {                          \
+    aot_set_last_error_v("call %s failed", (callee));        \
+  } while (0)
+#endif
+
+static inline uint32
+aot_get_tbl_data_slots(const AOTTable *tbl)
+{
+    return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+}
+
+static inline uint32
+aot_get_imp_tbl_data_slots(const AOTImportTable *tbl)
+{
+    return tbl->possible_grow ? tbl->table_max_size : tbl->table_init_size;
+}
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

File diff suppressed because it is too large
+ 1357 - 39
core/iwasm/compilation/aot_compiler.c


+ 154 - 13
core/iwasm/compilation/aot_compiler.h

@@ -46,12 +46,35 @@ typedef enum IntArithmetic {
   INT_REM_U
 } IntArithmetic;
 
+typedef enum V128Arithmetic {
+  V128_ADD = 0,
+  V128_ADD_SATURATE_S,
+  V128_ADD_SATURATE_U,
+  V128_SUB,
+  V128_SUB_SATURATE_S,
+  V128_SUB_SATURATE_U,
+  V128_MUL,
+  V128_DIV,
+  V128_NEG,
+  V128_MIN,
+  V128_MAX,
+} V128Arithmetic;
+
 typedef enum IntBitwise {
   INT_AND = 0,
   INT_OR,
   INT_XOR,
 } IntBitwise;
 
+typedef enum V128Bitwise {
+  V128_NOT,
+  V128_AND,
+  V128_ANDNOT,
+  V128_OR,
+  V128_XOR,
+  V128_BITSELECT
+} V128Bitwise;
+
 typedef enum IntShift {
   INT_SHL = 0,
   INT_SHR_S,
@@ -79,6 +102,34 @@ typedef enum FloatArithmetic {
   FLOAT_MAX
 } FloatArithmetic;
 
+static inline bool
+check_type_compatible(uint8 src_type, uint8 dst_type)
+{
+  if (src_type == dst_type) {
+      return true;
+  }
+
+  /* ext i1 to i32 */
+  if (src_type == VALUE_TYPE_I1 && dst_type == VALUE_TYPE_I32) {
+      return true;
+  }
+
+  /* i32 <==> func.ref, i32 <==> extern.ref */
+  if (src_type == VALUE_TYPE_I32
+      && (dst_type == VALUE_TYPE_EXTERNREF
+          || dst_type == VALUE_TYPE_FUNCREF)) {
+      return true;
+  }
+
+  if (dst_type == VALUE_TYPE_I32
+      && (src_type == VALUE_TYPE_FUNCREF
+          || src_type == VALUE_TYPE_EXTERNREF)) {
+      return true;
+  }
+
+  return false;
+}
+
 #define CHECK_STACK() do {                                  \
     if (!func_ctx->block_stack.block_list_end) {            \
       aot_set_last_error("WASM block stack underflow.");    \
@@ -96,11 +147,8 @@ typedef enum FloatArithmetic {
     CHECK_STACK();                                          \
     aot_value = aot_value_stack_pop                         \
       (&func_ctx->block_stack.block_list_end->value_stack); \
-    if ((value_type != VALUE_TYPE_I32                       \
-         && aot_value->type != value_type)                  \
-        || (value_type == VALUE_TYPE_I32                    \
-            && (aot_value->type != VALUE_TYPE_I32           \
-                && aot_value->type != VALUE_TYPE_I1))) {    \
+    if (!check_type_compatible(aot_value->type,             \
+                               value_type)) {               \
       aot_set_last_error("invalid WASM stack data type.");  \
       wasm_runtime_free(aot_value);                         \
       goto fail;                                            \
@@ -108,12 +156,23 @@ typedef enum FloatArithmetic {
     if (aot_value->type == value_type)                      \
       llvm_value = aot_value->value;                        \
     else {                                                  \
-      bh_assert(aot_value->type == VALUE_TYPE_I1);          \
-      if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder,   \
-            aot_value->value, I32_TYPE, "i1toi32"))) {      \
-        aot_set_last_error("invalid WASM stack data type.");\
-        wasm_runtime_free(aot_value);                       \
-        goto fail;                                          \
+      if (aot_value->type == VALUE_TYPE_I1) {               \
+        if (!(llvm_value = LLVMBuildZExt(comp_ctx->builder, \
+              aot_value->value, I32_TYPE, "i1toi32"))) {    \
+          aot_set_last_error("invalid WASM stack "          \
+                             "data type.");                 \
+          wasm_runtime_free(aot_value);                     \
+          goto fail;                                        \
+        }                                                   \
+      }                                                     \
+      else {                                                \
+        bh_assert(aot_value->type == VALUE_TYPE_I32         \
+          || aot_value->type == VALUE_TYPE_FUNCREF          \
+          || aot_value->type == VALUE_TYPE_EXTERNREF);      \
+        bh_assert(value_type == VALUE_TYPE_I32              \
+          || value_type == VALUE_TYPE_FUNCREF               \
+          || value_type == VALUE_TYPE_EXTERNREF);           \
+        llvm_value = aot_value->value;                      \
       }                                                     \
     }                                                       \
     wasm_runtime_free(aot_value);                           \
@@ -123,6 +182,9 @@ typedef enum FloatArithmetic {
 #define POP_I64(v) POP(v, VALUE_TYPE_I64)
 #define POP_F32(v) POP(v, VALUE_TYPE_F32)
 #define POP_F64(v) POP(v, VALUE_TYPE_F64)
+#define POP_V128(v) POP(v, VALUE_TYPE_V128)
+#define POP_FUNCREF(v) POP(v, VALUE_TYPE_FUNCREF)
+#define POP_EXTERNREF(v) POP(v, VALUE_TYPE_EXTERNREF)
 
 #define POP_COND(llvm_value) do {                           \
     AOTValue *aot_value;                                    \
@@ -156,11 +218,11 @@ typedef enum FloatArithmetic {
       goto fail;                                            \
     }                                                       \
     aot_value = wasm_runtime_malloc(sizeof(AOTValue));      \
-    memset(aot_value, 0, sizeof(AOTValue));                 \
     if (!aot_value) {                                       \
       aot_set_last_error("allocate memory failed.");        \
       goto fail;                                            \
     }                                                       \
+    memset(aot_value, 0, sizeof(AOTValue));                 \
     aot_value->type = value_type;                           \
     aot_value->value = llvm_value;                          \
     aot_value_stack_push                                    \
@@ -172,7 +234,10 @@ typedef enum FloatArithmetic {
 #define PUSH_I64(v) PUSH(v, VALUE_TYPE_I64)
 #define PUSH_F32(v) PUSH(v, VALUE_TYPE_F32)
 #define PUSH_F64(v) PUSH(v, VALUE_TYPE_F64)
+#define PUSH_V128(v) PUSH(v, VALUE_TYPE_V128)
 #define PUSH_COND(v) PUSH(v, VALUE_TYPE_I1)
+#define PUSH_FUNCREF(v) PUSH(v, VALUE_TYPE_FUNCREF)
+#define PUSH_EXTERNREF(v) PUSH(v, VALUE_TYPE_EXTERNREF)
 
 #define TO_LLVM_TYPE(wasm_type) \
     wasm_type_to_llvm_type(&comp_ctx->basic_types, wasm_type)
@@ -192,7 +257,8 @@ typedef enum FloatArithmetic {
 #define INT64_PTR_TYPE comp_ctx->basic_types.int64_ptr_type
 #define F32_PTR_TYPE comp_ctx->basic_types.float32_ptr_type
 #define F64_PTR_TYPE comp_ctx->basic_types.float64_ptr_type
-#define VOID_PTR_TYPE comp_ctx->basic_types.void_ptr_type
+#define FUNC_REF_TYPE comp_ctx->basic_types.funcref_type
+#define EXTERN_REF_TYPE comp_ctx->basic_types.externref_type
 
 #define I32_CONST(v) LLVMConstInt(I32_TYPE, v, true)
 #define I64_CONST(v) LLVMConstInt(I64_TYPE, v, true)
@@ -209,6 +275,9 @@ typedef enum FloatArithmetic {
 #define I32_TWO     (comp_ctx->llvm_consts.i32_two)
 #define I32_THREE   (comp_ctx->llvm_consts.i32_three)
 #define I32_FOUR    (comp_ctx->llvm_consts.i32_four)
+#define I32_FIVE    (comp_ctx->llvm_consts.i32_five)
+#define I32_SIX     (comp_ctx->llvm_consts.i32_six)
+#define I32_SEVEN   (comp_ctx->llvm_consts.i32_seven)
 #define I32_EIGHT   (comp_ctx->llvm_consts.i32_eight)
 #define I32_NEG_ONE (comp_ctx->llvm_consts.i32_neg_one)
 #define I64_NEG_ONE (comp_ctx->llvm_consts.i64_neg_one)
@@ -219,6 +288,38 @@ typedef enum FloatArithmetic {
 #define I64_63     (comp_ctx->llvm_consts.i64_63)
 #define I64_64     (comp_ctx->llvm_consts.i64_64)
 
+#define V128_TYPE       comp_ctx->basic_types.v128_type
+#define V128_PTR_TYPE   comp_ctx->basic_types.v128_ptr_type
+#define V128_i8x16_TYPE comp_ctx->basic_types.i8x16_vec_type
+#define V128_i16x8_TYPE comp_ctx->basic_types.i16x8_vec_type
+#define V128_i32x4_TYPE comp_ctx->basic_types.i32x4_vec_type
+#define V128_i64x2_TYPE comp_ctx->basic_types.i64x2_vec_type
+#define V128_f32x4_TYPE comp_ctx->basic_types.f32x4_vec_type
+#define V128_f64x2_TYPE comp_ctx->basic_types.f64x2_vec_type
+
+#define V128_ZERO       (comp_ctx->llvm_consts.v128_zero)
+#define V128_i8x16_ZERO (comp_ctx->llvm_consts.i8x16_vec_zero)
+#define V128_i16x8_ZERO (comp_ctx->llvm_consts.i16x8_vec_zero)
+#define V128_i32x4_ZERO (comp_ctx->llvm_consts.i32x4_vec_zero)
+#define V128_i64x2_ZERO (comp_ctx->llvm_consts.i64x2_vec_zero)
+#define V128_f32x4_ZERO (comp_ctx->llvm_consts.f32x4_vec_zero)
+#define V128_f64x2_ZERO (comp_ctx->llvm_consts.f64x2_vec_zero)
+
+#define REF_NULL        (comp_ctx->llvm_consts.i32_neg_one)
+
+#define TO_V128_i8x16(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_i8x16_TYPE, "i8x16_val")
+#define TO_V128_i16x8(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_i16x8_TYPE, "i16x8_val")
+#define TO_V128_i32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_i32x4_TYPE, "i32x4_val")
+#define TO_V128_i64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_i64x2_TYPE, "i64x2_val")
+#define TO_V128_f32x4(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_f32x4_TYPE, "f32x4_val")
+#define TO_V128_f64x2(v) LLVMBuildBitCast(comp_ctx->builder, v, \
+                                          V128_f64x2_TYPE, "f64x2_val")
+
 #define CHECK_LLVM_CONST(v) do {                        \
     if (!v) {                                           \
       aot_set_last_error("create llvm const failed.");  \
@@ -226,6 +327,36 @@ typedef enum FloatArithmetic {
     }                                                   \
   } while (0)
 
+#define GET_AOT_FUNCTION(name, argc) do {                               \
+    if (!(func_type = LLVMFunctionType(ret_type, param_types,           \
+                                       argc, false))) {                 \
+        aot_set_last_error("llvm add function type failed.");           \
+        return false;                                                   \
+    }                                                                   \
+    if (comp_ctx->is_jit_mode) {                                        \
+        /* JIT mode, call the function directly */                      \
+        if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {         \
+            aot_set_last_error("llvm add pointer type failed.");        \
+            return false;                                               \
+        }                                                               \
+        if (!(value = I64_CONST((uint64)(uintptr_t)name))               \
+            || !(func = LLVMConstIntToPtr(value, func_ptr_type))) {     \
+            aot_set_last_error("create LLVM value failed.");            \
+            return false;                                               \
+        }                                                               \
+    }                                                                   \
+    else {                                                              \
+        char *func_name = #name;                                        \
+        /* AOT mode, delcare the function */                            \
+        if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name)) \
+            && !(func = LLVMAddFunction(comp_ctx->module,               \
+                                        func_name, func_type))) {       \
+            aot_set_last_error("llvm add function failed.");            \
+            return false;                                               \
+        }                                                               \
+    }                                                                   \
+  } while (0)
+
 bool
 aot_compile_wasm(AOTCompContext *comp_ctx);
 
@@ -237,9 +368,19 @@ aot_emit_aot_file(AOTCompContext *comp_ctx,
                   AOTCompData *comp_data,
                   const char *file_name);
 
+uint8_t*
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
+                      AOTCompData *comp_data,
+                      uint32_t *p_aot_file_size);
+
 bool
 aot_emit_object_file(AOTCompContext *comp_ctx, char *file_name);
 
+uint8_t*
+aot_compile_wasm_file(const uint8_t *wasm_file_buf, uint32_t wasm_file_size,
+                      uint32_t opt_level, uint32_t size_level,
+                      uint32_t *p_aot_file_size);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 402 - 92
core/iwasm/compilation/aot_emit_aot_file.c

@@ -124,8 +124,18 @@ get_mem_init_data_size(AOTMemInitData *mem_init_data)
 {
     /* init expr type (4 bytes) + init expr value (8 bytes)
        + byte count (4 bytes) + bytes */
-    return (uint32)(sizeof(uint32) + sizeof(uint64)
-                    + sizeof(uint32) + mem_init_data->byte_count);
+    uint32 total_size =
+        (uint32)(sizeof(uint32) + sizeof(uint64)
+                 + sizeof(uint32) + mem_init_data->byte_count);
+
+    /* bulk_memory enabled:
+        is_passive (4 bytes) + memory_index (4 bytes)
+       bulk memory disabled:
+        placeholder (4 bytes) + placeholder (4 bytes)
+    */
+    total_size += (sizeof(uint32) + sizeof(uint32));
+
+    return total_size;
 }
 
 static uint32
@@ -142,12 +152,30 @@ get_mem_init_data_list_size(AOTMemInitData **mem_init_data_list,
     return size;
 }
 
+static uint32
+get_import_memory_size(AOTCompData *comp_data)
+{
+    /* currently we only emit import_memory_count = 0 */
+    return sizeof(uint32);
+}
+
+static uint32
+get_memory_size(AOTCompData *comp_data)
+{
+    /* memory_count + count * (memory_flags + num_bytes_per_page +
+                               init_page_count + max_page_count) */
+    return (uint32)(sizeof(uint32)
+                    + comp_data->memory_count * sizeof(uint32) * 4);
+}
+
 static uint32
 get_mem_info_size(AOTCompData *comp_data)
 {
-    /* num bytes per page + init page count + max page count
-       + init data count + init data list */
-    return (uint32)sizeof(uint32) * 4
+    /* import_memory_size + memory_size
+       + init_data_count + init_data_list */
+    return get_import_memory_size(comp_data)
+           + get_memory_size(comp_data)
+           + (uint32)sizeof(uint32)
            + get_mem_init_data_list_size(comp_data->mem_init_data_list,
                                          comp_data->mem_init_data_count);
 }
@@ -155,9 +183,14 @@ get_mem_info_size(AOTCompData *comp_data)
 static uint32
 get_table_init_data_size(AOTTableInitData *table_init_data)
 {
-    /* init expr type (4 bytes) + init expr value (8 bytes)
-       + func index count (4 bytes) + func indexes */
-    return (uint32)(sizeof(uint32) + sizeof(uint64) + sizeof(uint32)
+    /*
+     * mode (4 bytes), elem_type (4 bytes), do not need is_dropped field
+     *
+     * table_index(4 bytes) + init expr type (4 bytes) + init expr value (8 bytes)
+     * + func index count (4 bytes) + func indexes
+     */
+    return (uint32)(sizeof(uint32) * 2 + sizeof(uint32) + sizeof(uint32)
+                    + sizeof(uint64) + sizeof(uint32)
                     + sizeof(uint32) * table_init_data->func_index_count);
 }
 
@@ -165,9 +198,24 @@ static uint32
 get_table_init_data_list_size(AOTTableInitData **table_init_data_list,
                               uint32 table_init_data_count)
 {
+    /*
+     * ------------------------------
+     * | table_init_data_count
+     * ------------------------------
+     * |                     | U32 mode
+     * | AOTTableInitData[N] | U32 elem_type
+     * |                     | U32 table_index
+     * |                     | U32 offset.init_expr_type
+     * |                     | U64 offset.u.i64
+     * |                     | U32 func_index_count
+     * |                     | U32[func_index_count]
+     * ------------------------------
+     */
     AOTTableInitData **table_init_data = table_init_data_list;
     uint32 size = 0, i;
 
+    size = (uint32)sizeof(uint32);
+
     for (i = 0; i < table_init_data_count; i++, table_init_data++) {
         size = align_uint(size, 4);
         size += get_table_init_data_size(*table_init_data);
@@ -175,11 +223,69 @@ get_table_init_data_list_size(AOTTableInitData **table_init_data_list,
     return size;
 }
 
+static uint32
+get_import_table_size(AOTCompData *comp_data)
+{
+    /*
+     * ------------------------------
+     * | import_table_count
+     * ------------------------------
+     * |                  | U32 table_init_size
+     * |                  | ----------------------
+     * | AOTImpotTable[N] | U32 table_init_size
+     * |                  | ----------------------
+     * |                  | U32 possible_grow (convenient than U8)
+     * ------------------------------
+     */
+    return (uint32)(sizeof(uint32)
+                    + comp_data->import_table_count
+                        * (sizeof(uint32) * 3));
+}
+
+static uint32
+get_table_size(AOTCompData *comp_data)
+{
+    /*
+     * ------------------------------
+     * | table_count
+     * ------------------------------
+     * |             | U32 elem_type
+     * | AOTTable[N] | U32 table_flags
+     * |             | U32 table_init_size
+     * |             | U32 table_max_size
+     * |             | U32 possible_grow (convenient than U8)
+     * ------------------------------
+     */
+    return (uint32)(sizeof(uint32)
+                    + comp_data->table_count
+                        * (sizeof(uint32) * 5));
+}
+
 static uint32
 get_table_info_size(AOTCompData *comp_data)
 {
-    /* table size + init data count + init data list */
-    return (uint32)sizeof(uint32) * 2
+    /*
+     * ------------------------------
+     * | import_table_count
+     * ------------------------------
+     * |
+     * | AOTImportTable[import_table_count]
+     * |
+     * ------------------------------
+     * | table_count
+     * ------------------------------
+     * |
+     * | AOTTable[table_count]
+     * |
+     * ------------------------------
+     * | table_init_data_count
+     * ------------------------------
+     * |
+     * | AOTTableInitData*[table_init_data_count]
+     * |
+     * ------------------------------
+     */
+    return get_import_table_size(comp_data) + get_table_size(comp_data)
            + get_table_init_data_list_size(comp_data->table_init_data_list,
                                            comp_data->table_init_data_count);
 }
@@ -251,9 +357,14 @@ get_import_global_info_size(AOTCompData *comp_data)
 static uint32
 get_global_size(AOTGlobal *global)
 {
-    /* type (1 byte) + is_mutable (1 byte)
-       + init expr type (2 byes) + init expr value (8 byes) */
-    return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64);
+    if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
+        /* type (1 byte) + is_mutable (1 byte)
+           + init expr type (2 byes) + init expr value (8 byes) */
+        return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64);
+    else
+        /* type (1 byte) + is_mutable (1 byte)
+           + init expr type (2 byes) + v128 value (16 byes) */
+        return sizeof(uint8) * 2 + sizeof(uint16) + sizeof(uint64) * 2;
 }
 
 static uint32
@@ -372,9 +483,8 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
     size = align_uint(size, 4);
     size += (uint32)sizeof(uint32) * 2;
 
-    /* llvm aux data end + llvm aux stack bottom
-       + llvm aux stack size + llvm stack global index */
-    size += sizeof(uint32) * 4;
+    /* aux data/heap/stack data */
+    size += sizeof(uint32) * 7;
 
     size += get_object_data_section_info_size(obj_data);
     return size;
@@ -402,23 +512,22 @@ get_func_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
 }
 
 static uint32
-get_export_func_size(AOTExportFunc *export_func)
+get_export_size(AOTExport *export)
 {
-    /* export func index + export func name */
-    return (uint32)sizeof(uint32)
-           + get_string_size(export_func->func_name);
+    /* export index + export kind + 1 byte padding + export name */
+    return (uint32)sizeof(uint32) + sizeof(uint8) + 1
+           + get_string_size(export->name);
 }
 
 static uint32
-get_export_funcs_size(AOTExportFunc *export_funcs,
-                      uint32 export_func_count)
+get_exports_size(AOTExport *exports, uint32 export_count)
 {
-    AOTExportFunc *export_func = export_funcs;
+    AOTExport *export = exports;
     uint32 size = 0, i;
 
-    for (i = 0; i < export_func_count; i++, export_func++) {
+    for (i = 0; i < export_count; i++, export++) {
         size = align_uint(size, 4);
-        size += get_export_func_size(export_func);
+        size += get_export_size(export);
     }
     return size;
 }
@@ -426,10 +535,10 @@ get_export_funcs_size(AOTExportFunc *export_funcs,
 static uint32
 get_export_section_size(AOTCompData *comp_data)
 {
-    /* export func count + export funcs */
+    /* export count + exports */
     return (uint32)sizeof(uint32)
-           + get_export_funcs_size(comp_data->export_funcs,
-                                   comp_data->export_func_count);
+           + get_exports_size(comp_data->wasm_module->exports,
+                              comp_data->wasm_module->export_count);
 }
 
 static uint32
@@ -682,7 +791,8 @@ get_relocation_section_size(AOTObjectData *obj_data)
 }
 
 static uint32
-get_aot_file_size(AOTCompData *comp_data, AOTObjectData *obj_data)
+get_aot_file_size(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                  AOTObjectData *obj_data)
 {
     uint32 size = 0;
 
@@ -753,10 +863,28 @@ exchange_uint32(uint8 *p_data)
 static void
 exchange_uint64(uint8 *pData)
 {
+    uint32 value;
+
+    value = *(uint32 *)pData;
+    *(uint32 *)pData = *(uint32 *)(pData + 4);
+    *(uint32 *)(pData + 4) = value;
     exchange_uint32(pData);
     exchange_uint32(pData + 4);
 }
 
+static void
+exchange_uint128(uint8 *pData)
+{
+    /* swap high 64bit and low 64bit */
+    uint64 value = *(uint64*)pData;
+    *(uint64*)pData = *(uint64*)(pData + 8);
+    *(uint64*)(pData + 8) = value;
+    /* exchange high 64bit */
+    exchange_uint64(pData);
+    /* exchange low 64bit */
+    exchange_uint64(pData + 8);
+}
+
 static union {
     int a;
     char b;
@@ -804,6 +932,17 @@ static union {
     offset += (uint32)sizeof(uint64);       \
   } while (0)
 
+#define EMIT_V128(v)  do {                  \
+    uint64 *t = (uint64*)v.i64x2;           \
+    CHECK_BUF(16);                          \
+    if (!is_little_endian())                \
+        exchange_uint128((uint8 *)t);       \
+    PUT_U64_TO_ADDR(buf + offset, t[0]);    \
+    offset += (uint32)sizeof(uint64);       \
+    PUT_U64_TO_ADDR(buf + offset, t[1]);    \
+    offset += (uint32)sizeof(uint64);       \
+  } while (0)
+
 #define EMIT_BUF(v, len)  do {              \
     CHECK_BUF(len);                         \
     memcpy(buf + offset, v, len);           \
@@ -868,20 +1007,46 @@ aot_emit_target_info_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 
 static bool
 aot_emit_mem_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
-                  AOTCompData *comp_data, AOTObjectData *obj_data)
+                  AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                  AOTObjectData *obj_data)
 {
     uint32 offset = *p_offset, i;
     AOTMemInitData **init_datas = comp_data->mem_init_data_list;
 
     *p_offset = offset = align_uint(offset, 4);
 
-    EMIT_U32(comp_data->num_bytes_per_page);
-    EMIT_U32(comp_data->mem_init_page_count);
-    EMIT_U32(comp_data->mem_max_page_count);
-    EMIT_U32(comp_data->mem_init_data_count);
+    /* Emit import memory count, only emit 0 currently.
+       TODO: emit the actual import memory count and
+             the full import memory info. */
+    EMIT_U32(0);
+
+    /* Emit memory count */
+    EMIT_U32(comp_data->memory_count);
+    /* Emit memory items */
+    for (i = 0; i < comp_data->memory_count; i++) {
+        EMIT_U32(comp_data->memories[i].memory_flags);
+        EMIT_U32(comp_data->memories[i].num_bytes_per_page);
+        EMIT_U32(comp_data->memories[i].mem_init_page_count);
+        EMIT_U32(comp_data->memories[i].mem_max_page_count);
+    }
 
+    /* Emit mem init data count */
+    EMIT_U32(comp_data->mem_init_data_count);
+    /* Emit mem init data items */
     for (i = 0; i < comp_data->mem_init_data_count; i++) {
         offset = align_uint(offset, 4);
+#if WASM_ENABLE_BULK_MEMORY != 0
+        if (comp_ctx->enable_bulk_memory) {
+            EMIT_U32(init_datas[i]->is_passive);
+            EMIT_U32(init_datas[i]->memory_index);
+        }
+        else
+#endif
+        {
+            /* emit two placeholder to keep the same size */
+            EMIT_U32(0);
+            EMIT_U32(0);
+        }
         EMIT_U32(init_datas[i]->offset.init_expr_type);
         EMIT_U64(init_datas[i]->offset.u.i64);
         EMIT_U32(init_datas[i]->byte_count);
@@ -907,11 +1072,38 @@ aot_emit_table_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 
     *p_offset = offset = align_uint(offset, 4);
 
-    EMIT_U32(comp_data->table_size);
+    /* Emit import table count */
+    EMIT_U32(comp_data->import_table_count);
+    /* Emit table items */
+    for (i = 0; i < comp_data->import_table_count; i++) {
+        /* TODO:
+         * EMIT_STR(comp_data->import_tables[i].module_name );
+         * EMIT_STR(comp_data->import_tables[i].table_name);
+         */
+        EMIT_U32(comp_data->import_tables[i].table_init_size);
+        EMIT_U32(comp_data->import_tables[i].table_max_size);
+        EMIT_U32(comp_data->import_tables[i].possible_grow & 0x000000FF);
+    }
+
+    /* Emit table count */
+    EMIT_U32(comp_data->table_count);
+    /* Emit table items */
+    for (i = 0; i < comp_data->table_count; i++) {
+        EMIT_U32(comp_data->tables[i].elem_type);
+        EMIT_U32(comp_data->tables[i].table_flags);
+        EMIT_U32(comp_data->tables[i].table_init_size);
+        EMIT_U32(comp_data->tables[i].table_max_size);
+        EMIT_U32(comp_data->tables[i].possible_grow & 0x000000FF);
+    }
+
+    /* Emit table init data count */
     EMIT_U32(comp_data->table_init_data_count);
-
+    /* Emit table init data items */
     for (i = 0; i < comp_data->table_init_data_count; i++) {
         offset = align_uint(offset, 4);
+        EMIT_U32(init_datas[i]->mode);
+        EMIT_U32(init_datas[i]->elem_type);
+        EMIT_U32(init_datas[i]->table_index);
         EMIT_U32(init_datas[i]->offset.init_expr_type);
         EMIT_U64(init_datas[i]->offset.u.i64);
         EMIT_U32(init_datas[i]->func_index_count);
@@ -1004,7 +1196,10 @@ aot_emit_global_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
         EMIT_U8(global->type);
         EMIT_U8(global->is_mutable);
         EMIT_U16(global->init_expr.init_expr_type);
-        EMIT_U64(global->init_expr.u.i64);
+        if (global->init_expr.init_expr_type != INIT_EXPR_TYPE_V128_CONST)
+            EMIT_U64(global->init_expr.u.i64);
+        else
+            EMIT_V128(global->init_expr.u.v128);
     }
 
     if (offset - *p_offset != get_global_info_size(comp_data)) {
@@ -1077,7 +1272,8 @@ aot_emit_object_data_section_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
 
 static bool
 aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
-                           AOTCompData *comp_data, AOTObjectData *obj_data)
+                           AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                           AOTObjectData *obj_data)
 {
     uint32 section_size = get_init_data_section_size(comp_data, obj_data);
     uint32 offset = *p_offset;
@@ -1087,7 +1283,7 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     EMIT_U32(AOT_SECTION_TYPE_INIT_DATA);
     EMIT_U32(section_size);
 
-    if (!aot_emit_mem_info(buf, buf_end, &offset, comp_data, obj_data)
+    if (!aot_emit_mem_info(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
         || !aot_emit_table_info(buf, buf_end, &offset, comp_data, obj_data)
         || !aot_emit_func_type_info(buf, buf_end, &offset, comp_data, obj_data)
         || !aot_emit_import_global_info(buf, buf_end, &offset, comp_data, obj_data)
@@ -1099,10 +1295,13 @@ aot_emit_init_data_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     EMIT_U32(comp_data->func_count);
     EMIT_U32(comp_data->start_func_index);
 
-    EMIT_U32(comp_data->llvm_aux_data_end);
-    EMIT_U32(comp_data->llvm_aux_stack_bottom);
-    EMIT_U32(comp_data->llvm_aux_stack_size);
-    EMIT_U32(comp_data->llvm_aux_stack_global_index);
+    EMIT_U32(comp_data->aux_data_end_global_index);
+    EMIT_U32(comp_data->aux_data_end);
+    EMIT_U32(comp_data->aux_heap_base_global_index);
+    EMIT_U32(comp_data->aux_heap_base);
+    EMIT_U32(comp_data->aux_stack_top_global_index);
+    EMIT_U32(comp_data->aux_stack_bottom);
+    EMIT_U32(comp_data->aux_stack_size);
 
     if (!aot_emit_object_data_section_info(buf, buf_end, &offset, obj_data))
         return false;
@@ -1186,19 +1385,22 @@ aot_emit_export_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
                         AOTCompData *comp_data, AOTObjectData *obj_data)
 {
     uint32 section_size = get_export_section_size(comp_data);
-    AOTExportFunc *func = comp_data->export_funcs;;
-    uint32 i, offset = *p_offset, export_func_count = comp_data->export_func_count;
+    AOTExport *export = comp_data->wasm_module->exports;
+    uint32 export_count = comp_data->wasm_module->export_count;
+    uint32 i, offset = *p_offset;
 
     *p_offset = offset = align_uint(offset, 4);
 
     EMIT_U32(AOT_SECTION_TYPE_EXPORT);
     EMIT_U32(section_size);
-    EMIT_U32(export_func_count);
+    EMIT_U32(export_count);
 
-    for (i = 0; i < export_func_count; i++, func++) {
+    for (i = 0; i < export_count; i++, export++) {
         offset = align_uint(offset, 4);
-        EMIT_U32(func->func_index);
-        EMIT_STR(func->func_name);
+        EMIT_U32(export->index);
+        EMIT_U8(export->kind);
+        EMIT_U8(0);
+        EMIT_STR(export->name);
     }
 
     if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
@@ -1303,6 +1505,27 @@ aot_emit_relocation_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
     return true;
 }
 
+typedef uint32 U32;
+typedef int32  I32;
+typedef uint16 U16;
+typedef uint8  U8;
+
+struct coff_hdr {
+    U16 u16Machine;
+    U16 u16NumSections;
+    U32 u32DateTimeStamp;
+    U32 u32SymTblPtr;
+    U32 u32NumSymbols;
+    U16 u16PeHdrSize;
+    U16 u16Characs;
+};
+
+#define IMAGE_FILE_MACHINE_AMD64  0x8664
+#define IMAGE_FILE_MACHINE_I386   0x014c
+#define IMAGE_FILE_MACHINE_IA64   0x0200
+
+#define AOT_COFF_BIN_TYPE 6
+
 #define EI_NIDENT 16
 
 typedef uint32  elf32_word;
@@ -1391,17 +1614,39 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
     const uint8 *elf_buf = (uint8 *)LLVMGetBufferStart(obj_data->mem_buf);
     uint32 elf_size = (uint32)LLVMGetBufferSize(obj_data->mem_buf);
 
-    if (bin_type != LLVMBinaryTypeELF32L
+    if (bin_type != LLVMBinaryTypeCOFF
+        && bin_type != LLVMBinaryTypeELF32L
         && bin_type != LLVMBinaryTypeELF32B
         && bin_type != LLVMBinaryTypeELF64L
-        && bin_type != LLVMBinaryTypeELF64B) {
+        && bin_type != LLVMBinaryTypeELF64B
+        && bin_type != LLVMBinaryTypeMachO32L
+        && bin_type != LLVMBinaryTypeMachO32B
+        && bin_type != LLVMBinaryTypeMachO64L
+        && bin_type != LLVMBinaryTypeMachO64B) {
         aot_set_last_error("invaid llvm binary bin_type.");
         return false;
     }
 
     obj_data->target_info.bin_type = bin_type - LLVMBinaryTypeELF32L;
 
-    if (bin_type == LLVMBinaryTypeELF32L || bin_type == LLVMBinaryTypeELF32B) {
+    if (bin_type == LLVMBinaryTypeCOFF) {
+        struct coff_hdr  * coff_header;
+
+        if (!elf_buf || elf_size < sizeof(struct coff_hdr)) {
+            aot_set_last_error("invalid coff_hdr buffer.");
+            return false;
+        }
+        coff_header = (struct coff_hdr *)elf_buf;
+        obj_data->target_info.e_type = 1;
+        obj_data->target_info.e_machine = coff_header->u16Machine;
+        obj_data->target_info.e_version = 1;
+        obj_data->target_info.e_flags = 0;
+
+        if (coff_header->u16Machine == IMAGE_FILE_MACHINE_AMD64)
+            obj_data->target_info.bin_type = AOT_COFF_BIN_TYPE;
+    }
+    else if (bin_type == LLVMBinaryTypeELF32L
+             || bin_type == LLVMBinaryTypeELF32B) {
         struct elf32_ehdr *elf_header;
         bool is_little_bin = bin_type == LLVMBinaryTypeELF32L;
 
@@ -1416,7 +1661,8 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
         SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin);
         SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin);
     }
-    else {
+    else if (bin_type == LLVMBinaryTypeELF64L
+             || bin_type == LLVMBinaryTypeELF64B) {
         struct elf64_ehdr *elf_header;
         bool is_little_bin = bin_type == LLVMBinaryTypeELF64L;
 
@@ -1431,6 +1677,19 @@ aot_resolve_target_info(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
         SET_TARGET_INFO(e_version, e_version, uint32, is_little_bin);
         SET_TARGET_INFO(e_flags, e_flags, uint32, is_little_bin);
     }
+    else if (bin_type == LLVMBinaryTypeMachO32L
+             || bin_type == LLVMBinaryTypeMachO32B) {
+        /* TODO: parse file type of Mach-O 32 */
+        aot_set_last_error("invaid llvm binary bin_type.");
+        return false;
+    }
+    else if (bin_type == LLVMBinaryTypeMachO64L
+             || bin_type == LLVMBinaryTypeMachO64B) {
+        /* TODO: parse file type of Mach-O 64 */
+        aot_set_last_error("invaid llvm binary bin_type.");
+        return false;
+    }
+
 
     strncpy(obj_data->target_info.arch, comp_ctx->target_arch,
             sizeof(obj_data->target_info.arch));
@@ -1485,16 +1744,24 @@ aot_resolve_literal(AOTObjectData *obj_data)
 }
 
 static bool
-is_data_section(char *section_name)
+get_relocations_count(LLVMSectionIteratorRef sec_itr, uint32 *p_count);
+
+static bool
+is_data_section(LLVMSectionIteratorRef sec_itr, char *section_name)
 {
+    uint32 relocation_count = 0;
+
     return (!strcmp(section_name, ".data")
             || !strcmp(section_name, ".rodata")
             /* ".rodata.cst4/8/16/.." */
-            || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst")));
+            || !strncmp(section_name, ".rodata.cst", strlen(".rodata.cst"))
+            || (!strcmp(section_name, ".rdata")
+                && get_relocations_count(sec_itr, &relocation_count)
+                && relocation_count > 0));
 }
 
-static uint32
-get_object_data_sections_count(AOTObjectData *obj_data)
+static bool
+get_object_data_sections_count(AOTObjectData *obj_data, uint32 *p_count)
 {
     LLVMSectionIteratorRef sec_itr;
     char *name;
@@ -1502,18 +1769,19 @@ get_object_data_sections_count(AOTObjectData *obj_data)
 
     if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
         aot_set_last_error("llvm get section iterator failed.");
-        return 0;
+        return false;
     }
     while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
         if ((name = (char *)LLVMGetSectionName(sec_itr))
-            && (is_data_section(name))) {
+            && (is_data_section(sec_itr, name))) {
             count++;
         }
         LLVMMoveToNextSection(sec_itr);
     }
     LLVMDisposeSectionIterator(sec_itr);
 
-    return count;
+    *p_count = count;
+    return true;
 }
 
 static bool
@@ -1522,9 +1790,13 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
     LLVMSectionIteratorRef sec_itr;
     char *name;
     AOTObjectDataSection *data_section;
-    uint32 sections_count = get_object_data_sections_count(obj_data);
+    uint32 sections_count;
     uint32 size;
 
+    if (!get_object_data_sections_count(obj_data, &sections_count)) {
+        return false;
+    }
+
     if (sections_count > 0) {
         size = (uint32)sizeof(AOTObjectDataSection) * sections_count;
         if (!(data_section = obj_data->data_sections = wasm_runtime_malloc(size))) {
@@ -1538,10 +1810,9 @@ aot_resolve_object_data_sections(AOTObjectData *obj_data)
             aot_set_last_error("llvm get section iterator failed.");
             return false;
         }
-        while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary,
-                                                     sec_itr)) {
+        while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
             if ((name = (char *)LLVMGetSectionName(sec_itr))
-                && (is_data_section(name))) {
+                && (is_data_section(sec_itr, name))) {
                 data_section->name = name;
                 data_section->data = (uint8 *)LLVMGetSectionContents(sec_itr);
                 data_section->size = (uint32)LLVMGetSectionSize(sec_itr);
@@ -1561,16 +1832,18 @@ aot_resolve_functions(AOTCompContext *comp_ctx, AOTObjectData *obj_data)
     AOTObjectFunc *func;
     LLVMSymbolIteratorRef sym_itr;
     char *name, *prefix = AOT_FUNC_PREFIX;
-    uint32 func_index;
+    uint32 func_index, total_size;
 
     /* allocate memory for aot function */
     obj_data->func_count = comp_ctx->comp_data->func_count;
-    if (!(obj_data->funcs
-                = wasm_runtime_malloc((uint32)sizeof(AOTObjectFunc) * obj_data->func_count))) {
-        aot_set_last_error("allocate memory for functions failed.");
-        return false;
+    if (obj_data->func_count) {
+        total_size = (uint32)sizeof(AOTObjectFunc) * obj_data->func_count;
+        if (!(obj_data->funcs = wasm_runtime_malloc(total_size))) {
+            aot_set_last_error("allocate memory for functions failed.");
+            return false;
+        }
+        memset(obj_data->funcs, 0, total_size);
     }
-    memset(obj_data->funcs, 0, sizeof(AOTObjectFunc) * obj_data->func_count);
 
     if (!(sym_itr = LLVMObjectFileCopySymbolIterator(obj_data->binary))) {
         aot_set_last_error("llvm get symbol iterator failed.");
@@ -1732,7 +2005,7 @@ fail:
 }
 
 static bool
-is_relocation_section(char *section_name)
+is_relocation_section_name(char *section_name)
 {
     return (!strcmp(section_name, ".rela.text")
             || !strcmp(section_name, ".rel.text")
@@ -1749,20 +2022,33 @@ is_relocation_section(char *section_name)
                         strlen(".rel.rodata.cst")));
 }
 
+static bool
+is_relocation_section(LLVMSectionIteratorRef sec_itr)
+{
+    uint32 count = 0;
+    char *name = (char *)LLVMGetSectionName(sec_itr);
+    if (name) {
+        if (is_relocation_section_name(name))
+            return true;
+        else if ((!strcmp(name, ".text") || !strcmp(name, ".rdata"))
+                 && get_relocations_count(sec_itr, &count) && count > 0)
+            return true;
+    }
+    return false;
+}
+
 static bool
 get_relocation_groups_count(AOTObjectData *obj_data, uint32 *p_count)
 {
     uint32 count = 0;
     LLVMSectionIteratorRef sec_itr;
-    char *name;
 
     if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
         aot_set_last_error("llvm get section iterator failed.");
         return false;
     }
     while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
-        if ((name = (char *)LLVMGetSectionName(sec_itr))
-            && is_relocation_section(name)) {
+        if (is_relocation_section(sec_itr)) {
             count++;
         }
         LLVMMoveToNextSection(sec_itr);
@@ -1803,8 +2089,8 @@ aot_resolve_object_relocation_groups(AOTObjectData *obj_data)
         return false;
     }
     while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
-        if ((name = (char *)LLVMGetSectionName(sec_itr))
-            && is_relocation_section(name)) {
+        if (is_relocation_section(sec_itr)) {
+            name = (char *)LLVMGetSectionName(sec_itr);
             relocation_group->section_name = name;
             if (!aot_resolve_object_relocation_group(
                     obj_data,
@@ -1922,22 +2208,19 @@ fail:
     return NULL;
 }
 
-bool
-aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
-                  const char *file_name)
+uint8*
+aot_emit_aot_file_buf(AOTCompContext *comp_ctx,
+                      AOTCompData *comp_data,
+                      uint32 *p_aot_file_size)
 {
     AOTObjectData *obj_data = aot_obj_data_create(comp_ctx);
     uint8 *aot_file_buf, *buf, *buf_end;
     uint32 aot_file_size, offset = 0;
-    bool ret = false;
-    FILE *file;
 
     if (!obj_data)
-        return false;
-
-    bh_print_time("Begin to emit AOT file");
+        return NULL;
 
-    aot_file_size = get_aot_file_size(comp_data, obj_data);
+    aot_file_size = get_aot_file_size(comp_ctx, comp_data, obj_data);
 
     if (!(buf = aot_file_buf = wasm_runtime_malloc(aot_file_size))) {
         aot_set_last_error("allocate memory failed.");
@@ -1949,7 +2232,7 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
 
     if (!aot_emit_file_header(buf, buf_end, &offset, comp_data, obj_data)
         || !aot_emit_target_info_section(buf, buf_end, &offset, comp_data, obj_data)
-        || !aot_emit_init_data_section(buf, buf_end, &offset, comp_data, obj_data)
+        || !aot_emit_init_data_section(buf, buf_end, &offset, comp_ctx, comp_data, obj_data)
         || !aot_emit_text_section(buf, buf_end, &offset, comp_data, obj_data)
         || !aot_emit_func_section(buf, buf_end, &offset, comp_data, obj_data)
         || !aot_emit_export_section(buf, buf_end, &offset, comp_data, obj_data)
@@ -1965,25 +2248,52 @@ aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
         goto fail2;
     }
 
+    *p_aot_file_size = aot_file_size;
+
+    aot_obj_data_destroy(obj_data);
+    return aot_file_buf;
+
+fail2:
+    wasm_runtime_free(aot_file_buf);
+
+fail1:
+    aot_obj_data_destroy(obj_data);
+    return NULL;
+}
+
+bool
+aot_emit_aot_file(AOTCompContext *comp_ctx, AOTCompData *comp_data,
+                  const char *file_name)
+{
+    uint8 *aot_file_buf;
+    uint32 aot_file_size;
+    bool ret = false;
+    FILE *file;
+
+    bh_print_time("Begin to emit AOT file");
+
+    if (!(aot_file_buf = aot_emit_aot_file_buf(comp_ctx, comp_data,
+                                               &aot_file_size))) {
+        return false;
+    }
+
     /* write buffer to file */
     if (!(file = fopen(file_name, "wb"))) {
         aot_set_last_error("open or create aot file failed.");
-        goto fail2;
+        goto fail1;
     }
     if (!fwrite(aot_file_buf, aot_file_size, 1, file)) {
         aot_set_last_error("write to aot file failed.");
-        goto fail3;
+        goto fail2;
     }
 
     ret = true;
 
-fail3:
+fail2:
     fclose(file);
 
-fail2:
+fail1:
     wasm_runtime_free(aot_file_buf);
 
-fail1:
-    aot_obj_data_destroy(obj_data);
     return ret;
 }

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

@@ -45,7 +45,7 @@ aot_compile_op_f32_const(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
       int32 i32_const;
       memcpy(&i32_const, &f32_const, sizeof(int32));
       if (!(alloca = LLVMBuildAlloca(comp_ctx->builder,
-                                     INT32_PTR_TYPE, "i32_ptr"))) {
+                                     I32_TYPE, "i32_ptr"))) {
           aot_set_last_error("llvm build alloca failed.");
           return false;
       }

+ 531 - 116
core/iwasm/compilation/aot_emit_control.c

@@ -19,13 +19,13 @@ enum {
 
 static void
 format_block_name(char *name, uint32 name_size,
-                  uint32 block_index, uint32 block_type,
-                  uint32 label_type)
+                  uint32 block_index, uint32 label_type,
+                  uint32 label_id)
 {
-    if (block_type != BLOCK_TYPE_FUNCTION)
+    if (label_type != LABEL_TYPE_FUNCTION)
         snprintf(name, name_size, "%s%d%s%s",
-                 block_name_prefix[block_type], block_index,
-                 "_", block_name_suffix[label_type]);
+                 block_name_prefix[label_type], block_index,
+                 "_", block_name_suffix[label_id]);
     else
         snprintf(name, name_size, "%s", "func_end");
 }
@@ -69,28 +69,58 @@ format_block_name(char *name, uint32 name_size,
 #define SET_BUILDER_POS(llvm_block) \
     LLVMPositionBuilderAtEnd(comp_ctx->builder, llvm_block)
 
-#define CREATE_RETURN_VALUE_PHI(block) do {                 \
-    if (block->return_type != VALUE_TYPE_VOID               \
-        && !block->return_value_phi) {                      \
-      LLVMBasicBlockRef block_curr = CURR_BLOCK();          \
-      SET_BUILDER_POS(block->llvm_end_block);               \
-      if (!(block->return_value_phi =                       \
-              LLVMBuildPhi(comp_ctx->builder,               \
-                           TO_LLVM_TYPE(block->return_type),\
-                           "phi"))) {                       \
-        aot_set_last_error("llvm build phi failed.");       \
-        goto fail;                                          \
-      }                                                     \
-      SET_BUILDER_POS(block_curr);                          \
-    }                                                       \
+#define CREATE_RESULT_VALUE_PHIS(block) do {                        \
+    if (block->result_count && !block->result_phis) {               \
+      uint32 i;                                                     \
+      uint64 size;                                                  \
+      LLVMBasicBlockRef block_curr = CURR_BLOCK();                  \
+      /* Allocate memory */                                         \
+      size = sizeof(LLVMValueRef) * (uint64)block->result_count;    \
+      if (size >= UINT32_MAX                                        \
+          || !(block->result_phis =                                 \
+                 wasm_runtime_malloc((uint32)size))) {              \
+        aot_set_last_error("allocate memory failed.");              \
+        goto fail;                                                  \
+      }                                                             \
+      SET_BUILDER_POS(block->llvm_end_block);                       \
+      for (i = 0; i < block->result_count; i++) {                   \
+        if (!(block->result_phis[i] =                               \
+                LLVMBuildPhi(comp_ctx->builder,                     \
+                             TO_LLVM_TYPE(block->result_types[i]),  \
+                             "phi"))) {                             \
+          aot_set_last_error("llvm build phi failed.");             \
+          goto fail;                                                \
+        }                                                           \
+      }                                                             \
+      SET_BUILDER_POS(block_curr);                                  \
+    }                                                               \
   } while (0)
 
-#define ADD_TO_RETURN_PHI(block, value) do {                \
-    LLVMBasicBlockRef block_curr = CURR_BLOCK();            \
-    LLVMAddIncoming(block->return_value_phi,                \
-                    &value, &block_curr, 1);                \
+#define ADD_TO_RESULT_PHIS(block, value, idx) do {                        \
+    LLVMBasicBlockRef block_curr = CURR_BLOCK();                          \
+    LLVMTypeRef phi_ty = LLVMTypeOf(block->result_phis[idx]);             \
+    LLVMTypeRef value_ty = LLVMTypeOf(value);                             \
+    bh_assert(LLVMGetTypeKind(phi_ty) == LLVMGetTypeKind(value_ty));      \
+    bh_assert(LLVMGetTypeContext(phi_ty)                                  \
+              == LLVMGetTypeContext(value_ty));                           \
+    LLVMAddIncoming(block->result_phis[idx], &value, &block_curr, 1);     \
+    (void)phi_ty;                                                         \
+    (void)value_ty;                                                       \
+ } while (0)
+
+#define BUILD_ICMP(op, left, right, res, name) do {     \
+    if (!(res = LLVMBuildICmp(comp_ctx->builder, op,    \
+                              left, right, name))) {    \
+        aot_set_last_error("llvm build icmp failed.");  \
+        goto fail;                                      \
+    }                                                   \
   } while (0)
 
+#define ADD_TO_PARAM_PHIS(block, value, idx) do {            \
+    LLVMBasicBlockRef block_curr = CURR_BLOCK();             \
+    LLVMAddIncoming(block->param_phis[idx],                  \
+                    &value, &block_curr, 1);                 \
+  } while (0)
 
 static LLVMBasicBlockRef
 find_next_llvm_end_block(AOTBlock *block)
@@ -125,14 +155,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
 {
     AOTBlock *block = func_ctx->block_stack.block_list_end;
     AOTBlock *block_prev;
-    uint8 *frame_ip;
+    uint8 *frame_ip = NULL;
+    uint32 i;
+    AOTFuncType *func_type;
+
+    aot_checked_addr_list_destroy(func_ctx);
 
-    if (block->block_type == BLOCK_TYPE_IF
+    bh_assert(block);
+
+    if (block->label_type == LABEL_TYPE_IF
         && block->llvm_else_block
         && !block->skip_wasm_code_else
         && *p_frame_ip <= block->wasm_code_else) {
         /* Clear value stack and start to translate else branch */
         aot_value_stack_destroy(&block->value_stack);
+        /* Recover parameters of else branch */
+        for (i = 0; i < block->param_count; i++)
+            PUSH(block->else_param_phis[i], block->param_types[i]);
         SET_BUILDER_POS(block->llvm_else_block);
         *p_frame_ip = block->wasm_code_else + 1;
         return true;
@@ -142,10 +181,23 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
         block_prev = block->prev;
         block = aot_block_stack_pop(&func_ctx->block_stack);
 
-        if (block->block_type == BLOCK_TYPE_IF
-            && block->llvm_end_block) {
-            LLVMDeleteBasicBlock(block->llvm_end_block);
-            block->llvm_end_block = NULL;
+        if (block->label_type == LABEL_TYPE_IF) {
+            if (block->llvm_else_block
+                && !block->skip_wasm_code_else
+                && *p_frame_ip <= block->wasm_code_else) {
+                /* Clear value stack and start to translate else branch */
+                aot_value_stack_destroy(&block->value_stack);
+                SET_BUILDER_POS(block->llvm_else_block);
+                *p_frame_ip = block->wasm_code_else + 1;
+                /* Push back the block */
+                aot_block_stack_push(&func_ctx->block_stack, block);
+                return true;
+            }
+            else if (block->llvm_end_block) {
+                /* Remove unreachable basic block */
+                LLVMDeleteBasicBlock(block->llvm_end_block);
+                block->llvm_end_block = NULL;
+            }
         }
 
         frame_ip = block->wasm_code_end;
@@ -163,15 +215,39 @@ handle_next_reachable_block(AOTCompContext *comp_ctx,
 
     /* Pop block, push its return value, and destroy the block */
     block = aot_block_stack_pop(&func_ctx->block_stack);
-    if (block->return_type != VALUE_TYPE_VOID) {
-        bh_assert(block->return_value_phi);
-        if (block->block_type != BLOCK_TYPE_FUNCTION)
-            PUSH(block->return_value_phi, block->return_type);
-        else
-            LLVMBuildRet(comp_ctx->builder, block->return_value_phi);
+    func_type = func_ctx->aot_func->func_type;
+    for (i = 0; i < block->result_count; i++) {
+        bh_assert(block->result_phis[i]);
+        if (block->label_type != LABEL_TYPE_FUNCTION) {
+            PUSH(block->result_phis[i], block->result_types[i]);
+        }
+        else {
+            /* Store extra return values to function parameters */
+            if (i != 0) {
+                uint32 param_index = func_type->param_count + i;
+                if (!LLVMBuildStore(comp_ctx->builder,
+                                    block->result_phis[i],
+                                    LLVMGetParam(func_ctx->func, param_index))) {
+                    aot_set_last_error("llvm build store failed.");
+                    goto fail;
+                }
+            }
+        }
     }
-    else if (block->block_type == BLOCK_TYPE_FUNCTION) {
-        LLVMBuildRetVoid(comp_ctx->builder);
+    if (block->label_type == LABEL_TYPE_FUNCTION) {
+        if (block->result_count) {
+            /* Return the first return value */
+            if (!LLVMBuildRet(comp_ctx->builder, block->result_phis[0])) {
+                aot_set_last_error("llvm build return failed.");
+                goto fail;
+            }
+        }
+        else {
+            if (!LLVMBuildRetVoid(comp_ctx->builder)) {
+                aot_set_last_error("llvm build return void failed.");
+                goto fail;
+            }
+        }
     }
     aot_block_destroy(block);
     return true;
@@ -179,10 +255,116 @@ fail:
     return false;
 }
 
+static bool
+push_aot_block_to_stack_and_pass_params(AOTCompContext *comp_ctx,
+                                        AOTFuncContext *func_ctx,
+                                        AOTBlock *block)
+{
+    uint32 i, param_index;
+    LLVMValueRef value;
+    uint64 size;
+    char name[32];
+    LLVMBasicBlockRef block_curr = CURR_BLOCK();
+
+    if (block->param_count) {
+        size = sizeof(LLVMValueRef) * (uint64)block->param_count;
+        if (size >= UINT32_MAX
+            || !(block->param_phis = wasm_runtime_malloc((uint32)size))) {
+            aot_set_last_error("allocate memory failed.");
+            return false;
+        }
+
+        if (block->label_type == LABEL_TYPE_IF
+            && !block->skip_wasm_code_else
+            && !(block->else_param_phis = wasm_runtime_malloc((uint32)size))) {
+            wasm_runtime_free(block->param_phis);
+            block->param_phis = NULL;
+            aot_set_last_error("allocate memory failed.");
+            return false;
+        }
+
+        /* Create param phis */
+        for (i = 0; i < block->param_count; i++) {
+            SET_BUILDER_POS(block->llvm_entry_block);
+            snprintf(name, sizeof(name), "%s%d_phi%d",
+                     block_name_prefix[block->label_type],
+                     block->block_index, i);
+            if (!(block->param_phis[i] =
+                    LLVMBuildPhi(comp_ctx->builder,
+                                 TO_LLVM_TYPE(block->param_types[i]),
+                                 name))) {
+                aot_set_last_error("llvm build phi failed.");
+                goto fail;
+            }
+
+            if (block->label_type == LABEL_TYPE_IF
+                && !block->skip_wasm_code_else
+                && block->llvm_else_block) {
+                /* Build else param phis */
+                SET_BUILDER_POS(block->llvm_else_block);
+                snprintf(name, sizeof(name), "else%d_phi%d",
+                         block->block_index, i);
+                if (!(block->else_param_phis[i] =
+                    LLVMBuildPhi(comp_ctx->builder,
+                                 TO_LLVM_TYPE(block->param_types[i]),
+                                 name))) {
+                    aot_set_last_error("llvm build phi failed.");
+                    goto fail;
+                }
+            }
+        }
+        SET_BUILDER_POS(block_curr);
+
+        /* Pop param values from current block's
+         * value stack and add to param phis.
+         */
+        for (i = 0; i < block->param_count; i++) {
+            param_index = block->param_count - 1 - i;
+            POP(value, block->param_types[param_index]);
+            ADD_TO_PARAM_PHIS(block, value, param_index);
+            if (block->label_type == LABEL_TYPE_IF
+                && !block->skip_wasm_code_else) {
+                if (block->llvm_else_block) {
+                    /* has else branch, add to else param phis */
+                    LLVMAddIncoming(block->else_param_phis[param_index],
+                                    &value, &block_curr, 1);
+                }
+                else {
+                    /* no else branch, add to result phis */
+                    CREATE_RESULT_VALUE_PHIS(block);
+                    ADD_TO_RESULT_PHIS(block, value, param_index);
+                }
+            }
+        }
+    }
+
+    /* Push the new block to block stack */
+    aot_block_stack_push(&func_ctx->block_stack, block);
+
+    /* Push param phis to the new block */
+    for (i = 0; i < block->param_count; i++) {
+        PUSH(block->param_phis[i], block->param_types[i]);
+    }
+
+    return true;
+
+fail:
+    if (block->param_phis) {
+        wasm_runtime_free(block->param_phis);
+        block->param_phis = NULL;
+    }
+    if (block->else_param_phis) {
+        wasm_runtime_free(block->else_param_phis);
+        block->else_param_phis = NULL;
+    }
+    return false;
+}
+
 bool
 aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                      uint8 **p_frame_ip, uint8 *frame_ip_end,
-                     uint32 block_type, uint32 block_ret_type)
+                     uint32 label_type, uint32 param_count, uint8 *param_types,
+                     uint32 result_count, uint8 *result_types)
 {
     BlockAddr block_addr_cache[BLOCK_ADDR_CACHE_SIZE][BLOCK_ADDR_CONFLICT_SIZE];
     AOTBlock *block;
@@ -200,8 +382,8 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* Get block info */
     if (!(wasm_loader_find_block_addr((BlockAddr*)block_addr_cache,
-                                      *p_frame_ip, frame_ip_end, (uint8)block_type,
-                                      &else_addr, &end_addr, NULL, 0))) {
+                                      *p_frame_ip, frame_ip_end, (uint8)label_type,
+                                      &else_addr, &end_addr))) {
         aot_set_last_error("find block end addr failed.");
         return false;
     }
@@ -211,49 +393,66 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         aot_set_last_error("allocate memory failed.");
         return false;
     }
+    memset(block, 0, sizeof(AOTBlock));
+    if (param_count
+        && !(block->param_types = wasm_runtime_malloc(param_count))) {
+        aot_set_last_error("allocate memory failed.");
+        goto fail;
+    }
+    if (result_count) {
+        if (!(block->result_types = wasm_runtime_malloc(result_count))) {
+            aot_set_last_error("allocate memory failed.");
+            goto fail;
+        }
+    }
 
     /* Init aot block data */
-    memset(block, 0, sizeof(AOTBlock));
-    block->block_type = block_type;
-    block->return_type = (uint8)block_ret_type;
+    block->label_type = label_type;
+    block->param_count = param_count;
+    memcpy(block->param_types, param_types, param_count);
+    block->result_count = result_count;
+    memcpy(block->result_types, result_types, result_count);
     block->wasm_code_else = else_addr;
     block->wasm_code_end = end_addr;
-    block->block_index = func_ctx->block_stack.block_index[block_type];
-    func_ctx->block_stack.block_index[block_type]++;
+    block->block_index = func_ctx->block_stack.block_index[label_type];
+    func_ctx->block_stack.block_index[label_type]++;
 
-    if (block_type == BLOCK_TYPE_BLOCK
-        || block_type == BLOCK_TYPE_LOOP) {
+    if (label_type == LABEL_TYPE_BLOCK
+        || label_type == LABEL_TYPE_LOOP) {
         /* Create block */
         format_block_name(name, sizeof(name),
-                          block->block_index, block_type, LABEL_BEGIN);
+                          block->block_index, label_type, LABEL_BEGIN);
         CREATE_BLOCK(block->llvm_entry_block, name);
         MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
         /* Jump to the entry block */
         BUILD_BR(block->llvm_entry_block);
+        if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
+            goto fail;
         /* Start to translate the block */
         SET_BUILDER_POS(block->llvm_entry_block);
-        aot_block_stack_push(&func_ctx->block_stack, block);
+        if (label_type == LABEL_TYPE_LOOP)
+            aot_checked_addr_list_destroy(func_ctx);
     }
-    else if (block_type == BLOCK_TYPE_IF) {
+    else if (label_type == LABEL_TYPE_IF) {
         POP_COND(value);
         if (!LLVMIsConstant(value)) {
             /* Compare value is not constant, create condition br IR */
             /* Create entry block */
             format_block_name(name, sizeof(name),
-                              block->block_index, block_type, LABEL_BEGIN);
+                              block->block_index, label_type, LABEL_BEGIN);
             CREATE_BLOCK(block->llvm_entry_block, name);
             MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
 
             /* Create end block */
             format_block_name(name, sizeof(name),
-                              block->block_index, block_type, LABEL_END);
+                              block->block_index, label_type, LABEL_END);
             CREATE_BLOCK(block->llvm_end_block, name);
             MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_entry_block);
 
             if (else_addr) {
                 /* Create else block */
                 format_block_name(name, sizeof(name),
-                                  block->block_index, block_type, LABEL_ELSE);
+                                  block->block_index, label_type, LABEL_ELSE);
                 CREATE_BLOCK(block->llvm_else_block, name);
                 MOVE_BLOCK_AFTER(block->llvm_else_block, block->llvm_entry_block);
                 /* Create condition br IR */
@@ -266,49 +465,48 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                               block->llvm_end_block);
                 block->is_reachable = true;
             }
+            if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
+                goto fail;
             /* Start to translate if branch of BLOCK if */
             SET_BUILDER_POS(block->llvm_entry_block);
-            aot_block_stack_push(&func_ctx->block_stack, block);
         }
         else {
             if ((int32)LLVMConstIntGetZExtValue(value) != 0) {
-                /* Compare value is not 0, condtion is true, else branch of
+                /* Compare value is not 0, condition is true, else branch of
                    BLOCK if cannot be reached */
                 block->skip_wasm_code_else = true;
                 /* Create entry block */
                 format_block_name(name, sizeof(name),
-                                  block->block_index, block_type, LABEL_BEGIN);
+                                  block->block_index, label_type, LABEL_BEGIN);
                 CREATE_BLOCK(block->llvm_entry_block, name);
                 MOVE_BLOCK_AFTER_CURR(block->llvm_entry_block);
                 /* Jump to the entry block */
                 BUILD_BR(block->llvm_entry_block);
+                if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
+                    goto fail;
                 /* Start to translate the if branch */
                 SET_BUILDER_POS(block->llvm_entry_block);
-                aot_block_stack_push(&func_ctx->block_stack, block);
             }
             else {
-                /* Compare value is not 0, condtion is false, if branch of
+                /* Compare value is not 0, condition is false, if branch of
                    BLOCK if cannot be reached */
                 if (else_addr) {
                     /* Create else block */
                     format_block_name(name, sizeof(name),
-                                      block->block_index, block_type, LABEL_ELSE);
+                                      block->block_index, label_type, LABEL_ELSE);
                     CREATE_BLOCK(block->llvm_else_block, name);
                     MOVE_BLOCK_AFTER_CURR(block->llvm_else_block);
                     /* Jump to the else block */
                     BUILD_BR(block->llvm_else_block);
+                    if (!push_aot_block_to_stack_and_pass_params(comp_ctx, func_ctx, block))
+                        goto fail;
                     /* Start to translate the else branch */
                     SET_BUILDER_POS(block->llvm_else_block);
                     *p_frame_ip = else_addr + 1;
-                    aot_block_stack_push(&func_ctx->block_stack, block);
                 }
                 else {
-                    if (block->return_type != VALUE_TYPE_VOID) {
-                        aot_set_last_error("WASM value stack underflow.");
-                        goto fail;
-                    }
                     /* skip the block */
-                    wasm_runtime_free(block);
+                    aot_block_destroy(block);
                     *p_frame_ip = end_addr + 1;
                 }
             }
@@ -321,7 +519,7 @@ aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     return true;
 fail:
-    wasm_runtime_free(block);
+    aot_block_destroy(block);
     return false;
 }
 
@@ -332,13 +530,14 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     AOTBlock *block = func_ctx->block_stack.block_list_end;
     LLVMValueRef value;
     char name[32];
+    uint32 i, result_index;
 
     /* Check block */
     if (!block) {
         aot_set_last_error("WASM block stack underflow.");
         return false;
     }
-    if (block->block_type != BLOCK_TYPE_IF
+    if (block->label_type != LABEL_TYPE_IF
         || (!block->skip_wasm_code_else
             && !block->llvm_else_block)) {
         aot_set_last_error("Invalid WASM block type.");
@@ -348,7 +547,7 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Create end block if needed */
     if (!block->llvm_end_block) {
         format_block_name(name, sizeof(name),
-                          block->block_index, block->block_type, LABEL_END);
+                          block->block_index, block->label_type, LABEL_END);
         CREATE_BLOCK(block->llvm_end_block, name);
         if (block->llvm_else_block)
             MOVE_BLOCK_AFTER(block->llvm_end_block, block->llvm_else_block);
@@ -359,10 +558,11 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     block->is_reachable = true;
 
     /* Comes from the if branch of BLOCK if */
-    if (block->return_type != VALUE_TYPE_VOID) {
-        POP(value, block->return_type);
-        CREATE_RETURN_VALUE_PHI(block);
-        ADD_TO_RETURN_PHI(block, value);
+    CREATE_RESULT_VALUE_PHIS(block);
+    for (i = 0; i < block->result_count; i++) {
+        result_index = block->result_count - 1 - i;
+        POP(value, block->result_types[result_index]);
+        ADD_TO_RESULT_PHIS(block, value, result_index);
     }
 
     /* Jump to end block */
@@ -370,9 +570,14 @@ aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     if (!block->skip_wasm_code_else
         && block->llvm_else_block) {
-        /* Clear value stack and start to translate else branch */
+        /* Clear value stack, recover param values
+         * and start to translate else branch.
+         */
         aot_value_stack_destroy(&block->value_stack);
+        for (i = 0; i < block->param_count; i++)
+            PUSH(block->else_param_phis[i], block->param_types[i]);
         SET_BUILDER_POS(block->llvm_else_block);
+        aot_checked_addr_list_destroy(func_ctx);
         return true;
     }
 
@@ -391,6 +596,7 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef value;
     LLVMBasicBlockRef next_llvm_end_block;
     char name[32];
+    uint32 i, result_index;
 
     /* Check block stack */
     if (!(block = func_ctx->block_stack.block_list_end)) {
@@ -401,17 +607,20 @@ aot_compile_op_end(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     /* Create the end block */
     if (!block->llvm_end_block) {
         format_block_name(name, sizeof(name),
-                          block->block_index, block->block_type, LABEL_END);
+                          block->block_index, block->label_type, LABEL_END);
         CREATE_BLOCK(block->llvm_end_block, name);
         if ((next_llvm_end_block = find_next_llvm_end_block(block)))
             MOVE_BLOCK_BEFORE(block->llvm_end_block, next_llvm_end_block);
     }
 
-    /* Handle block return value */
-    if (block->return_type != VALUE_TYPE_VOID) {
-        POP(value, block->return_type);
-        CREATE_RETURN_VALUE_PHI(block);
-        ADD_TO_RETURN_PHI(block, value);
+    /* Handle block result values */
+    CREATE_RESULT_VALUE_PHIS(block);
+    for (i = 0; i < block->result_count; i++) {
+        value = NULL;
+        result_index = block->result_count - 1 - i;
+        POP(value, block->result_types[result_index]);
+        bh_assert(value);
+        ADD_TO_RESULT_PHIS(block, value, result_index);
     }
 
     /* Jump to the end block */
@@ -423,21 +632,112 @@ fail:
     return false;
 }
 
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef terminate_addr, terminate_flags, flag, offset, res;
+    LLVMBasicBlockRef terminate_check_block, non_terminate_block;
+    AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+    LLVMBasicBlockRef terminate_block;
+
+    /* Offset of suspend_flags */
+    offset = I32_FIVE;
+
+    if (!(terminate_addr =
+                LLVMBuildInBoundsGEP(comp_ctx->builder, func_ctx->exec_env,
+                                     &offset, 1, "terminate_addr"))) {
+        aot_set_last_error("llvm build in bounds gep failed");
+        return false;
+    }
+    if (!(terminate_addr =
+                LLVMBuildBitCast(comp_ctx->builder,
+                                 terminate_addr,
+                                 INT32_PTR_TYPE, "terminate_addr_ptr"))) {
+        aot_set_last_error("llvm build bit cast failed");
+        return false;
+    }
+
+    if (!(terminate_flags =
+                LLVMBuildLoad(comp_ctx->builder,
+                              terminate_addr, "terminate_flags"))) {
+        aot_set_last_error("llvm build bit cast failed");
+        return false;
+    }
+    /* Set terminate_flags memory accecc to volatile, so that the value
+        will always be loaded from memory rather than register */
+    LLVMSetVolatile(terminate_flags, true);
+
+    CREATE_BLOCK(terminate_check_block, "terminate_check");
+    MOVE_BLOCK_AFTER_CURR(terminate_check_block);
+
+    CREATE_BLOCK(non_terminate_block, "non_terminate");
+    MOVE_BLOCK_AFTER_CURR(non_terminate_block);
+
+    BUILD_ICMP(LLVMIntSGT, terminate_flags, I32_ZERO, res, "need_terminate");
+    BUILD_COND_BR(res, terminate_check_block, non_terminate_block);
+
+    /* Move builder to terminate check block */
+    SET_BUILDER_POS(terminate_check_block);
+
+    CREATE_BLOCK(terminate_block, "terminate");
+    MOVE_BLOCK_AFTER_CURR(terminate_block);
+
+    if (!(flag =
+            LLVMBuildAnd(comp_ctx->builder, terminate_flags,
+                         I32_ONE, "termination_flag"))) {
+        aot_set_last_error("llvm build AND failed");
+        return false;
+    }
+
+    BUILD_ICMP(LLVMIntSGT, flag, I32_ZERO, res, "need_terminate");
+    BUILD_COND_BR(res, terminate_block, non_terminate_block);
+
+    /* Move builder to terminate block */
+    SET_BUILDER_POS(terminate_block);
+    if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
+        goto fail;
+    }
+
+    /* Move builder to terminate block */
+    SET_BUILDER_POS(non_terminate_block);
+    return true;
+
+fail:
+    return false;
+}
+#endif /* End of WASM_ENABLE_THREAD_MGR */
+
 bool
 aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                   uint32 br_depth, uint8 **p_frame_ip)
 {
     AOTBlock *block_dst;
-    LLVMValueRef value_ret;
+    LLVMValueRef value_ret, value_param;
     LLVMBasicBlockRef next_llvm_end_block;
     char name[32];
+    uint32 i, param_index, result_index;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* Insert suspend check point */
+    if (comp_ctx->enable_thread_mgr) {
+        if (!check_suspend_flags(comp_ctx, func_ctx))
+            return false;
+    }
+#endif
 
     if (!(block_dst = get_target_block(func_ctx, br_depth))) {
         return false;
     }
 
-    if (block_dst->block_type == BLOCK_TYPE_LOOP) {
+    if (block_dst->label_type == LABEL_TYPE_LOOP) {
         /* Dest block is Loop block */
+        /* Handle Loop parameters */
+        for (i = 0; i < block_dst->param_count; i++) {
+            param_index = block_dst->param_count - 1 - i;
+            POP(value_param, block_dst->param_types[param_index]);
+            ADD_TO_PARAM_PHIS(block_dst, value_param, param_index);
+        }
         BUILD_BR(block_dst->llvm_entry_block);
     }
     else {
@@ -445,7 +745,7 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         /* Create the end block */
         if (!block_dst->llvm_end_block) {
             format_block_name(name, sizeof(name),
-                              block_dst->block_index, block_dst->block_type,
+                              block_dst->block_index, block_dst->label_type,
                               LABEL_END);
             CREATE_BLOCK(block_dst->llvm_end_block, name);
             if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
@@ -455,13 +755,13 @@ aot_compile_op_br(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
         block_dst->is_reachable = true;
 
-        /* Handle return value */
-        if (block_dst->return_type != VALUE_TYPE_VOID) {
-            POP(value_ret, block_dst->return_type);
-            CREATE_RETURN_VALUE_PHI(block_dst);
-            ADD_TO_RETURN_PHI(block_dst, value_ret);
+        /* Handle result values */
+        CREATE_RESULT_VALUE_PHIS(block_dst);
+        for (i = 0; i < block_dst->result_count; i++) {
+            result_index = block_dst->result_count - 1 - i;
+            POP(value_ret, block_dst->result_types[result_index]);
+            ADD_TO_RESULT_PHIS(block_dst, value_ret, result_index);
         }
-
         /* Jump to the end block */
         BUILD_BR(block_dst->llvm_end_block);
     }
@@ -476,9 +776,19 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                      uint32 br_depth, uint8 **p_frame_ip)
 {
     AOTBlock *block_dst;
-    LLVMValueRef value_cmp, value_ret;
+    LLVMValueRef value_cmp, value, *values = NULL;
     LLVMBasicBlockRef llvm_else_block, next_llvm_end_block;
     char name[32];
+    uint32 i, param_index, result_index;
+    uint64 size;
+
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* Insert suspend check point */
+    if (comp_ctx->enable_thread_mgr) {
+        if (!check_suspend_flags(comp_ctx, func_ctx))
+            return false;
+    }
+#endif
 
     POP_COND(value_cmp);
     if (!LLVMIsConstant(value_cmp)) {
@@ -491,8 +801,29 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         CREATE_BLOCK(llvm_else_block, "br_if_else");
         MOVE_BLOCK_AFTER_CURR(llvm_else_block);
 
-        if (block_dst->block_type == BLOCK_TYPE_LOOP) {
+        if (block_dst->label_type == LABEL_TYPE_LOOP) {
             /* Dest block is Loop block */
+            /* Handle Loop parameters */
+            if (block_dst->param_count) {
+                size = sizeof(LLVMValueRef) * (uint64)block_dst->param_count;
+                if (size >= UINT32_MAX
+                    || !(values = wasm_runtime_malloc((uint32)size))) {
+                    aot_set_last_error("allocate memory failed.");
+                    goto fail;
+                }
+                for (i = 0; i < block_dst->param_count; i++) {
+                    param_index = block_dst->param_count - 1 - i;
+                    POP(value, block_dst->param_types[param_index]);
+                    ADD_TO_PARAM_PHIS(block_dst, value, param_index);
+                    values[param_index] = value;
+                }
+                for (i = 0; i < block_dst->param_count; i++) {
+                    PUSH(values[i], block_dst->param_types[i]);
+                }
+                wasm_runtime_free(values);
+                values = NULL;
+            }
+
             BUILD_COND_BR(value_cmp, block_dst->llvm_entry_block,
                           llvm_else_block);
 
@@ -504,7 +835,7 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             /* Create the end block */
             if (!block_dst->llvm_end_block) {
                 format_block_name(name, sizeof(name),
-                                  block_dst->block_index, block_dst->block_type,
+                                  block_dst->block_index, block_dst->label_type,
                                   LABEL_END);
                 CREATE_BLOCK(block_dst->llvm_end_block, name);
                 if ((next_llvm_end_block = find_next_llvm_end_block(block_dst)))
@@ -512,15 +843,29 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                       next_llvm_end_block);
             }
 
-            /* Set reachable flag and create condtion br IR */
+            /* Set reachable flag and create condition br IR */
             block_dst->is_reachable = true;
 
-            /* Handle return value */
-            if (block_dst->return_type != VALUE_TYPE_VOID) {
-                POP(value_ret, block_dst->return_type);
-                CREATE_RETURN_VALUE_PHI(block_dst);
-                ADD_TO_RETURN_PHI(block_dst, value_ret);
-                PUSH(value_ret, block_dst->return_type);
+            /* Handle result values */
+            if (block_dst->result_count) {
+                size = sizeof(LLVMValueRef) * (uint64)block_dst->result_count;
+                if (size >= UINT32_MAX
+                    || !(values = wasm_runtime_malloc((uint32)size))) {
+                    aot_set_last_error("allocate memory failed.");
+                    goto fail;
+                }
+                CREATE_RESULT_VALUE_PHIS(block_dst);
+                for (i = 0; i < block_dst->result_count; i++) {
+                    result_index = block_dst->result_count - 1 - i;
+                    POP(value, block_dst->result_types[result_index]);
+                    values[result_index] = value;
+                    ADD_TO_RESULT_PHIS(block_dst, value, result_index);
+                }
+                for (i = 0; i < block_dst->result_count; i++) {
+                    PUSH(values[i], block_dst->result_types[i]);
+                }
+                wasm_runtime_free(values);
+                values = NULL;
             }
 
             /* Condition jump to end block */
@@ -533,16 +878,18 @@ aot_compile_op_br_if(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
     else {
         if ((int32)LLVMConstIntGetZExtValue(value_cmp) != 0) {
-            /* Compare value is not 0, condtion is true, same as op_br */
+            /* Compare value is not 0, condition is true, same as op_br */
             return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
         }
         else {
-            /* Compare value is not 0, condtion is false, skip br_if */
+            /* Compare value is not 0, condition is false, skip br_if */
             return true;
         }
     }
     return true;
 fail:
+    if (values)
+        wasm_runtime_free(values);
     return false;
 }
 
@@ -551,14 +898,24 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                         uint32 *br_depths, uint32 br_count,
                         uint8 **p_frame_ip)
 {
-    uint32 i;
-    LLVMValueRef value_switch, value_cmp, value_case, value_ret = NULL;
+    uint32 i, j;
+    LLVMValueRef value_switch, value_cmp, value_case, value, *values = NULL;
     LLVMBasicBlockRef default_llvm_block = NULL, target_llvm_block;
     LLVMBasicBlockRef next_llvm_end_block;
     AOTBlock *target_block;
     uint32 br_depth, depth_idx;
+    uint32 param_index, result_index;
+    uint64 size;
     char name[32];
 
+#if WASM_ENABLE_THREAD_MGR != 0
+    /* Insert suspend check point */
+    if (comp_ctx->enable_thread_mgr) {
+        if (!check_suspend_flags(comp_ctx, func_ctx))
+            return false;
+    }
+#endif
+
     POP_I32(value_cmp);
     if (!LLVMIsConstant(value_cmp)) {
         /* Compare value is not constant, create switch IR */
@@ -567,13 +924,13 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             if (!target_block)
                 return false;
 
-            if (target_block->block_type != BLOCK_TYPE_LOOP) {
+            if (target_block->label_type != LABEL_TYPE_LOOP) {
                 /* Dest block is Block/If/Function block */
                 /* Create the end block */
                 if (!target_block->llvm_end_block) {
                     format_block_name(name, sizeof(name),
                                       target_block->block_index,
-                                      target_block->block_type,
+                                      target_block->label_type,
                                       LABEL_END);
                     CREATE_BLOCK(target_block->llvm_end_block, name);
                     if ((next_llvm_end_block =
@@ -581,18 +938,50 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                         MOVE_BLOCK_BEFORE(target_block->llvm_end_block,
                                           next_llvm_end_block);
                 }
-                /* Handle return value */
-                if (target_block->return_type != VALUE_TYPE_VOID) {
-                    POP(value_ret, target_block->return_type);
-                    CREATE_RETURN_VALUE_PHI(target_block);
-                    ADD_TO_RETURN_PHI(target_block, value_ret);
-                    PUSH(value_ret, target_block->return_type);
+                /* Handle result values */
+                if (target_block->result_count) {
+                    size = sizeof(LLVMValueRef) * (uint64)target_block->result_count;
+                    if (size >= UINT32_MAX
+                        || !(values = wasm_runtime_malloc((uint32)size))) {
+                        aot_set_last_error("allocate memory failed.");
+                        goto fail;
+                    }
+                    CREATE_RESULT_VALUE_PHIS(target_block);
+                    for (j = 0; j < target_block->result_count; j++) {
+                        result_index = target_block->result_count - 1 - j;
+                        POP(value, target_block->result_types[result_index]);
+                        values[result_index] = value;
+                        ADD_TO_RESULT_PHIS(target_block, value, result_index);
+                    }
+                    for (j = 0; j < target_block->result_count; j++) {
+                        PUSH(values[j], target_block->result_types[j]);
+                    }
+                    wasm_runtime_free(values);
                 }
                 target_block->is_reachable = true;
                 if (i == br_count)
                     default_llvm_block = target_block->llvm_end_block;
             }
             else {
+                /* Handle Loop parameters */
+                if (target_block->param_count) {
+                    size = sizeof(LLVMValueRef) * (uint64)target_block->param_count;
+                    if (size >= UINT32_MAX
+                        || !(values = wasm_runtime_malloc((uint32)size))) {
+                        aot_set_last_error("allocate memory failed.");
+                        goto fail;
+                    }
+                    for (j = 0; j < target_block->param_count; j++) {
+                        param_index = target_block->param_count - 1 - j;
+                        POP(value, target_block->param_types[param_index]);
+                        values[param_index] = value;
+                        ADD_TO_PARAM_PHIS(target_block, value, param_index);
+                    }
+                    for (j = 0; j < target_block->param_count; j++) {
+                        PUSH(values[j], target_block->param_types[j]);
+                    }
+                    wasm_runtime_free(values);
+                }
                 if (i == br_count)
                     default_llvm_block = target_block->llvm_entry_block;
             }
@@ -612,7 +1001,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             target_block = get_target_block(func_ctx, br_depths[i]);
             if (!target_block)
                 return false;
-            target_llvm_block = target_block->block_type != BLOCK_TYPE_LOOP
+            target_llvm_block = target_block->label_type != LABEL_TYPE_LOOP
                                 ? target_block->llvm_end_block
                                 : target_block->llvm_entry_block;
             LLVMAddCase(value_switch, value_case, target_llvm_block);
@@ -630,6 +1019,8 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return aot_compile_op_br(comp_ctx, func_ctx, br_depth, p_frame_ip);
     }
 fail:
+    if (values)
+        wasm_runtime_free(values);
     return false;
 }
 
@@ -639,14 +1030,38 @@ aot_compile_op_return(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 {
     AOTBlock *block_func = func_ctx->block_stack.block_list_head;
     LLVMValueRef value;
+    AOTFuncType *func_type;
+    uint32 i, param_index, result_index;
 
     bh_assert(block_func);
-    if (block_func->return_type != VALUE_TYPE_VOID) {
-        POP(value, block_func->return_type);
-        LLVMBuildRet(comp_ctx->builder, value);
+    func_type = func_ctx->aot_func->func_type;
+
+    if (block_func->result_count) {
+        /* Store extra result values to function parameters */
+        for (i = 0; i < block_func->result_count - 1; i++) {
+            result_index = block_func->result_count - 1 - i;
+            POP(value, block_func->result_types[result_index]);
+            param_index = func_type->param_count + result_index;
+            if (!LLVMBuildStore(comp_ctx->builder,
+                                value,
+                                LLVMGetParam(func_ctx->func, param_index))) {
+                aot_set_last_error("llvm build store failed.");
+                goto fail;
+            }
+        }
+        /* Return the first result value */
+        POP(value, block_func->result_types[0]);
+        if (!LLVMBuildRet(comp_ctx->builder, value)) {
+            aot_set_last_error("llvm build return failed.");
+            goto fail;
+        }
+    }
+    else {
+        if (!LLVMBuildRetVoid(comp_ctx->builder)) {
+            aot_set_last_error("llvm build return void failed.");
+            goto fail;
+        }
     }
-    else
-        LLVMBuildRetVoid(comp_ctx->builder);
 
     return handle_next_reachable_block(comp_ctx, func_ctx, p_frame_ip);
 fail:

+ 7 - 1
core/iwasm/compilation/aot_emit_control.h

@@ -15,7 +15,8 @@ extern "C" {
 bool
 aot_compile_op_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                      uint8 **p_frame_ip, uint8 *frame_ip_end,
-                     uint32 block_type, uint32 block_ret_type);
+                     uint32 label_type, uint32 param_count, uint8 *param_types,
+                     uint32 result_count, uint8 *result_types);
 
 bool
 aot_compile_op_else(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
@@ -52,6 +53,11 @@ aot_handle_next_reachable_block(AOTCompContext *comp_ctx,
                                 AOTFuncContext *func_ctx,
                                 uint8 **p_frame_ip);
 
+#if WASM_ENABLE_THREAD_MGR != 0
+bool
+check_suspend_flags(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+#endif
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 265 - 16
core/iwasm/compilation/aot_emit_conversion.c

@@ -89,6 +89,156 @@ fail:
     return false;
 }
 
+#define ADD_BASIC_BLOCK(block, name) do {                                  \
+    if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,         \
+                                                func_ctx->func,            \
+                                                name))) {                  \
+        aot_set_last_error("llvm add basic block failed.");                \
+        goto fail;                                                         \
+    }                                                                      \
+                                                                           \
+    LLVMMoveBasicBlockAfter(block, LLVMGetInsertBlock(comp_ctx->builder)); \
+} while (0)
+
+static bool
+trunc_sat_float_to_int(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                       LLVMValueRef operand, LLVMTypeRef dest_type,
+                       LLVMValueRef min_value, LLVMValueRef max_value,
+                       char *name, bool sign)
+{
+    LLVMBasicBlockRef check_nan_succ, check_less_succ, check_greater_succ;
+    LLVMBasicBlockRef is_nan_block, is_less_block, is_greater_block, res_block;
+    LLVMValueRef is_less, is_greater, res, phi;
+    LLVMValueRef zero = (dest_type == I32_TYPE) ? I32_ZERO : I64_ZERO;
+    LLVMValueRef vmin, vmax;
+
+    if (!(res = LLVMBuildFCmp(comp_ctx->builder, LLVMRealUNO,
+                              operand, operand, "fcmp_is_nan"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+
+    ADD_BASIC_BLOCK(check_nan_succ, "check_nan_succ");
+    ADD_BASIC_BLOCK(is_nan_block, "is_nan_block");
+    ADD_BASIC_BLOCK(check_less_succ, "check_less_succ");
+    ADD_BASIC_BLOCK(is_less_block, "is_less_block");
+    ADD_BASIC_BLOCK(check_greater_succ, "check_greater_succ");
+    ADD_BASIC_BLOCK(is_greater_block, "is_greater_block");
+    ADD_BASIC_BLOCK(res_block, "res_block");
+
+    if (!LLVMBuildCondBr(comp_ctx->builder, res,
+                         is_nan_block, check_nan_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_nan block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_nan_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_nan_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_nan_succ);
+    if (!(is_less = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOLE, operand,
+                                  min_value, "fcmp_min_value"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+    if (!LLVMBuildCondBr(comp_ctx->builder, is_less,
+                         is_less_block, check_less_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_less block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_less_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_less_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_less_succ);
+    if (!(is_greater = LLVMBuildFCmp(comp_ctx->builder, LLVMRealOGE, operand,
+                                     max_value, "fcmp_max_value"))) {
+        aot_set_last_error("llvm build fcmp failed.");
+        goto fail;
+    }
+    if (!LLVMBuildCondBr(comp_ctx->builder, is_greater,
+                         is_greater_block, check_greater_succ)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* Start to translate is_greater block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, is_greater_block);
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate check_greater_succ block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, check_greater_succ);
+    if (sign)
+        res = LLVMBuildFPToSI(comp_ctx->builder, operand, dest_type, name);
+    else
+        res = LLVMBuildFPToUI(comp_ctx->builder, operand, dest_type, name);
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+    if (!LLVMBuildBr(comp_ctx->builder, res_block)) {
+        aot_set_last_error("llvm build br failed.");
+        goto fail;
+    }
+
+    /* Start to translate res_block */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, res_block);
+    /* Create result phi */
+    if (!(phi = LLVMBuildPhi(comp_ctx->builder,
+                             dest_type,
+                             "trunc_sat_result_phi"))) {
+        aot_set_last_error("llvm build phi failed.");
+        return false;
+    }
+
+    /* Add phi incoming values */
+    if (dest_type == I32_TYPE) {
+        if (sign) {
+            vmin = I32_CONST(INT32_MIN);
+            vmax = I32_CONST(INT32_MAX);
+        }
+        else {
+            vmin = I32_CONST(0);
+            vmax = I32_CONST(UINT32_MAX);
+        }
+    }
+    else if (dest_type == I64_TYPE) {
+        if (sign) {
+            vmin = I64_CONST(INT64_MIN);
+            vmax = I64_CONST(INT64_MAX);
+        }
+        else {
+            vmin = I64_CONST(0);
+            vmax = I64_CONST(UINT64_MAX);
+        }
+    }
+    LLVMAddIncoming(phi, &zero, &is_nan_block, 1);
+    LLVMAddIncoming(phi, &vmin, &is_less_block, 1);
+    LLVMAddIncoming(phi, &vmax, &is_greater_block, 1);
+    LLVMAddIncoming(phi, &res, &check_greater_succ, 1);
+
+    if (dest_type == I32_TYPE)
+        PUSH_I32(phi);
+    else if (dest_type == I64_TYPE)
+        PUSH_I64(phi);
+    return true;
+fail:
+    return false;
+}
+
 bool
 aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
@@ -109,7 +259,7 @@ fail:
 
 bool
 aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -125,16 +275,22 @@ aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F32_CONST(4294967296.0f);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I32_TYPE, min_value, max_value,
-                              sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I32_TYPE, min_value, max_value,
+                                  sign ? "i32_trunc_f32_s" : "i32_trunc_f32_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I32_TYPE, min_value, max_value,
+                                      sign ? "i32_trunc_sat_f32_s" :
+                                      "i32_trunc_sat_f32_u", sign);
 fail:
     return false;
 }
 
 bool
 aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -150,9 +306,15 @@ aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F64_CONST(4294967296.0);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I32_TYPE, min_value, max_value,
-                              sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I32_TYPE, min_value, max_value,
+                                  sign ? "i32_trunc_f64_s" : "i32_trunc_f64_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I32_TYPE, min_value, max_value,
+                                      sign ? "i32_trunc_sat_f64_s" :
+                                      "i32_trunc_sat_f64_u", sign);
 fail:
     return false;
 }
@@ -180,9 +342,83 @@ fail:
     return false;
 }
 
+bool
+aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth)
+{
+    LLVMValueRef value, res, cast_value = NULL;
+
+    POP_I64(value);
+
+    if (bitwidth == 8) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT8_TYPE, true, "i8_intcast_i64");
+    }
+    else if (bitwidth == 16) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT16_TYPE, true, "i16_intcast_i64");
+    }
+    else if (bitwidth == 32) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       I32_TYPE, true, "i32_intcast_i64");
+    }
+
+    if (!cast_value) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    res = LLVMBuildSExt(comp_ctx->builder, cast_value, I64_TYPE, "i64_extend_i64_s");
+
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    PUSH_I64(res);
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth)
+{
+    LLVMValueRef value, res, cast_value = NULL;
+
+    POP_I32(value);
+
+    if (bitwidth == 8) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT8_TYPE, true, "i8_intcast_i32");
+    }
+    else if (bitwidth == 16) {
+        cast_value = LLVMBuildIntCast2(comp_ctx->builder, value,
+                                       INT16_TYPE, true, "i16_intcast_i32");
+    }
+
+    if (!cast_value) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    res = LLVMBuildSExt(comp_ctx->builder, cast_value, I32_TYPE, "i32_extend_i32_s");
+
+    if (!res) {
+        aot_set_last_error("llvm build conversion failed.");
+        return false;
+    }
+
+    PUSH_I32(res);
+    return true;
+fail:
+    return false;
+}
+
 bool
 aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -198,16 +434,22 @@ aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F32_CONST(18446744073709551616.0f);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I64_TYPE, min_value, max_value,
-                              sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I64_TYPE, min_value, max_value,
+                                  sign ? "i64_trunc_f32_s" : "i64_trunc_f32_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I64_TYPE, min_value, max_value,
+                                      sign ? "i64_trunc_sat_f32_s" :
+                                      "i64_trunc_sat_f32_u", sign);
 fail:
     return false;
 }
 
 bool
 aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign)
+                             bool sign, bool saturating)
 {
     LLVMValueRef value;
     LLVMValueRef min_value, max_value;
@@ -223,9 +465,16 @@ aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         max_value = F64_CONST(18446744073709551616.0);
     }
 
-    return trunc_float_to_int(comp_ctx, func_ctx, value,
-                              I64_TYPE, min_value, max_value,
-                              sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
+    if (!saturating)
+        return trunc_float_to_int(comp_ctx, func_ctx, value,
+                                  I64_TYPE, min_value, max_value,
+                                  sign ? "i64_trunc_f64_s" : "i64_trunc_f64_u", sign);
+    else
+        return trunc_sat_float_to_int(comp_ctx, func_ctx, value,
+                                      I64_TYPE, min_value, max_value,
+                                      sign ? "i64_trunc_sat_f64_s" :
+                                      "i64_trunc_sat_f64_u", sign);
+
 fail:
     return false;
 }

+ 12 - 4
core/iwasm/compilation/aot_emit_conversion.h

@@ -17,23 +17,31 @@ aot_compile_op_i32_wrap_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 
 bool
 aot_compile_op_i32_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i32_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i64_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                               bool sign);
 
+bool
+aot_compile_op_i64_extend_i64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth);
+
+bool
+aot_compile_op_i32_extend_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                              int8 bitwidth);
+
 bool
 aot_compile_op_i64_trunc_f32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_i64_trunc_f64(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             bool sign);
+                             bool sign, bool saturating);
 
 bool
 aot_compile_op_f32_convert_i32(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,

+ 8 - 65
core/iwasm/compilation/aot_emit_exception.c

@@ -6,20 +6,6 @@
 #include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
 
-static char *exce_block_names[] = {
-    "exce_unreachable",             /* EXCE_UNREACHABLE */
-    "exce_out_of_memory",           /* EXCE_OUT_OF_MEMORY */
-    "exce_out_of_bounds_mem_access",/* EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS */
-    "exce_integer_overflow",        /* EXCE_INTEGER_OVERFLOW */
-    "exce_divide_by_zero",          /* EXCE_INTEGER_DIVIDE_BY_ZERO */
-    "exce_invalid_convert_to_int",  /* EXCE_INVALID_CONVERSION_TO_INTEGER */
-    "exce_invalid_func_type_idx",   /* EXCE_INVALID_FUNCTION_TYPE_INDEX */
-    "exce_invalid_func_idx",        /* EXCE_INVALID_FUNCTION_INDEX */
-    "exce_undefined_element",       /* EXCE_UNDEFINED_ELEMENT */
-    "exce_uninit_element",          /* EXCE_UNINITIALIZED_ELEMENT */
-    "exce_call_unlinked"            /* EXCE_CALL_UNLINKED_IMPORT_FUNC */
-};
-
 bool
 aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                    int32 exception_id,
@@ -27,7 +13,6 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                    LLVMValueRef cond_br_if,
                    LLVMBasicBlockRef cond_br_else_block)
 {
-    LLVMBasicBlockRef exce_block;
     LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
     LLVMValueRef exce_id = I32_CONST((uint32)exception_id), func_const, func;
     LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
@@ -51,10 +36,8 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                                  func_ctx->got_exception_block);
 
         /* Create exection id phi */
-        if (!(func_ctx->exception_id_phi =
-                LLVMBuildPhi(comp_ctx->builder,
-                             comp_ctx->basic_types.int32_type,
-                             "exception_id_phi"))) {
+        if (!(func_ctx->exception_id_phi = LLVMBuildPhi(
+                comp_ctx->builder, I32_TYPE, "exception_id_phi"))) {
             aot_set_last_error("llvm build phi failed.");
             return false;
         }
@@ -108,60 +91,20 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
         /* Create return IR */
         AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
-        if (aot_func_type->result_count) {
-            switch (aot_func_type->types[aot_func_type->param_count]) {
-                case VALUE_TYPE_I32:
-                    LLVMBuildRet(comp_ctx->builder, I32_ZERO);
-                    break;
-                case VALUE_TYPE_I64:
-                    LLVMBuildRet(comp_ctx->builder, I64_ZERO);
-                    break;
-                case VALUE_TYPE_F32:
-                    LLVMBuildRet(comp_ctx->builder, F32_ZERO);
-                    break;
-                case VALUE_TYPE_F64:
-                    LLVMBuildRet(comp_ctx->builder, F64_ZERO);
-                    break;
-            }
-        }
-        else {
-            LLVMBuildRetVoid(comp_ctx->builder);
+        if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
+            return false;
         }
 
         /* Resume the builder position */
         LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
     }
 
-    /* Create exception block if needed */
-    if (!(exce_block = func_ctx->exception_blocks[exception_id])) {
-        if (!(func_ctx->exception_blocks[exception_id] = exce_block =
-                LLVMAppendBasicBlockInContext(comp_ctx->context,
-                                              func_ctx->func,
-                                              exce_block_names[exception_id]))) {
-            aot_set_last_error("add LLVM basic block failed.");
-            return false;
-        }
-
-        /* Move before got_exception block */
-        LLVMMoveBasicBlockBefore(exce_block, func_ctx->got_exception_block);
-
-        /* Add phi incoming value to got_exception block */
-        LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &exce_block, 1);
-
-        /* Jump to got exception block */
-        LLVMPositionBuilderAtEnd(comp_ctx->builder, exce_block);
-        if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
-            aot_set_last_error("llvm build br failed.");
-            return false;
-        }
-    }
-
-    /* Resume builder position */
-    LLVMPositionBuilderAtEnd(comp_ctx->builder, block_curr);
+    /* Add phi incoming value to got_exception block */
+    LLVMAddIncoming(func_ctx->exception_id_phi, &exce_id, &block_curr, 1);
 
     if (!is_cond_br) {
         /* not condition br, create br IR */
-        if (!LLVMBuildBr(comp_ctx->builder, exce_block)) {
+        if (!LLVMBuildBr(comp_ctx->builder, func_ctx->got_exception_block)) {
             aot_set_last_error("llvm build br failed.");
             return false;
         }
@@ -169,7 +112,7 @@ aot_emit_exception(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     else {
         /* Create condition br */
         if (!LLVMBuildCondBr(comp_ctx->builder, cond_br_if,
-                             exce_block, cond_br_else_block)) {
+                             func_ctx->got_exception_block, cond_br_else_block)) {
             aot_set_last_error("llvm build cond br failed.");
             return false;
         }

File diff suppressed because it is too large
+ 752 - 96
core/iwasm/compilation/aot_emit_function.c


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

@@ -14,12 +14,24 @@ extern "C" {
 
 bool
 aot_compile_op_call(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                    uint32 func_idx, uint8 **p_frame_ip);
+                    uint32 func_idx, bool tail_call);
 
 bool
-aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                             uint32 type_idx);
+aot_compile_op_call_indirect(AOTCompContext *comp_ctx,
+                             AOTFuncContext *func_ctx,
+                             uint32 type_idx,
+                             uint32 tbl_idx);
 
+bool
+aot_compile_op_ref_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_ref_is_null(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_ref_func(AOTCompContext *comp_ctx,
+                        AOTFuncContext *func_ctx,
+                        uint32 func_idx);
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 789 - 155
core/iwasm/compilation/aot_emit_memory.c

@@ -42,16 +42,19 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     LLVMValueRef mem_check_bound = NULL;
     switch (bytes) {
         case 1:
-            mem_check_bound = func_ctx->mem_bound_check_1byte;
+            mem_check_bound = func_ctx->mem_info[0].mem_bound_check_1byte;
             break;
         case 2:
-            mem_check_bound = func_ctx->mem_bound_check_2bytes;
+            mem_check_bound = func_ctx->mem_info[0].mem_bound_check_2bytes;
             break;
         case 4:
-            mem_check_bound = func_ctx->mem_bound_check_4bytes;
+            mem_check_bound = func_ctx->mem_info[0].mem_bound_check_4bytes;
             break;
         case 8:
-            mem_check_bound = func_ctx->mem_bound_check_8bytes;
+            mem_check_bound = func_ctx->mem_info[0].mem_bound_check_8bytes;
+            break;
+        case 16:
+            mem_check_bound = func_ctx->mem_info[0].mem_bound_check_16bytes;
             break;
         default:
             bh_assert(0);
@@ -71,51 +74,73 @@ get_memory_check_bound(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 }
 
 static LLVMValueRef
-check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                      uint32 offset, uint32 bytes)
+get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+LLVMValueRef
+aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 offset, uint32 bytes)
 {
     LLVMValueRef offset_const = I32_CONST(offset);
-    LLVMValueRef bytes_const = I32_CONST(bytes);
-    LLVMValueRef bytes64_const = I64_CONST(bytes);
-    LLVMValueRef heap_base_offset = func_ctx->heap_base_offset;
-    LLVMValueRef addr, maddr, offset1, offset2, cmp;
-    LLVMValueRef mem_base_addr, mem_check_bound, total_mem_size;
+    LLVMValueRef addr, maddr, offset1, cmp1, cmp2, cmp;
+    LLVMValueRef mem_base_addr, mem_check_bound;
     LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
-    LLVMBasicBlockRef check_succ, check_mem_space;
+    LLVMBasicBlockRef check_succ;
+    AOTValue *aot_value;
+    uint32 local_idx_of_aot_value = 0;
+    bool is_target_64bit, is_local_of_aot_value = false;
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    bool is_shared_memory =
+        comp_ctx->comp_data->memories[0].memory_flags & 0x02;
+#endif
+
+    is_target_64bit = (comp_ctx->pointer_size == sizeof(uint64))
+                      ? true : false;
 
     CHECK_LLVM_CONST(offset_const);
-    CHECK_LLVM_CONST(bytes_const);
-    CHECK_LLVM_CONST(bytes64_const);
 
     /* Get memory base address and memory data size */
-    if (func_ctx->mem_space_unchanged) {
-        mem_base_addr = func_ctx->mem_base_addr;
+    if (func_ctx->mem_space_unchanged
+#if WASM_ENABLE_SHARED_MEMORY != 0
+        || is_shared_memory
+#endif
+       ) {
+        mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
     }
     else {
-        if (!(mem_base_addr = LLVMBuildLoad(comp_ctx->builder,
-                                            func_ctx->mem_base_addr,
-                                            "mem_base"))) {
+        if (!(mem_base_addr =
+                LLVMBuildLoad(comp_ctx->builder,
+                              func_ctx->mem_info[0].mem_base_addr,
+                              "mem_base"))) {
             aot_set_last_error("llvm build load failed.");
             goto fail;
         }
     }
 
+    aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end;
+    if (aot_value) {
+        /* aot_value is freed in the following POP_I32(addr),
+           so save its fields here for further use */
+        is_local_of_aot_value = aot_value->is_local;
+        local_idx_of_aot_value = aot_value->local_idx;
+    }
+
     POP_I32(addr);
-    /* offset1 = offset + addr; */
-    BUILD_OP(Add, offset_const, addr, offset1, "offset1");
 
     /* return addres directly if constant offset and inside memory space */
-    if (LLVMIsConstant(offset1)) {
-        uint32 mem_offset = (uint32)LLVMConstIntGetZExtValue(offset1);
-        uint32 num_bytes_per_page = comp_ctx->comp_data->num_bytes_per_page;
-        uint32 init_page_count = comp_ctx->comp_data->mem_init_page_count;
-        uint32 mem_data_size = num_bytes_per_page * init_page_count;
-        if (mem_data_size > 0
-            && mem_offset <= mem_data_size - bytes) {
+    if (LLVMIsConstant(addr)) {
+        uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(addr)
+                             + (uint64)offset;
+        uint32 num_bytes_per_page =
+                comp_ctx->comp_data->memories[0].num_bytes_per_page;
+        uint32 init_page_count =
+                comp_ctx->comp_data->memories[0].mem_init_page_count;
+        uint64 mem_data_size = num_bytes_per_page * init_page_count;
+
+        if (mem_offset + bytes <= mem_data_size) {
             /* inside memory space */
-            /* maddr = mem_base_addr + moffset */
-            if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder,
-                                               mem_base_addr,
+            offset1 = I32_CONST((uint32)mem_offset);
+            CHECK_LLVM_CONST(offset1);
+            if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
                                                &offset1, 1, "maddr"))) {
                 aot_set_last_error("llvm build add failed.");
                 goto fail;
@@ -124,56 +149,78 @@ check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         }
     }
 
-    if (comp_ctx->comp_data->mem_init_page_count == 0) {
-        /* Get total memory size */
-        if (func_ctx->mem_space_unchanged) {
-            total_mem_size = func_ctx->total_mem_size;
+    if (is_target_64bit) {
+        if (!(offset_const = LLVMBuildZExt(comp_ctx->builder, offset_const,
+                                           I64_TYPE, "offset_i64"))
+            || !(addr = LLVMBuildZExt(comp_ctx->builder, addr,
+                                      I64_TYPE, "addr_i64"))) {
+            aot_set_last_error("llvm build zero extend failed.");
+            goto fail;
         }
-        else {
-            if (!(total_mem_size = LLVMBuildLoad(comp_ctx->builder,
-                                                 func_ctx->total_mem_size,
-                                                 "total_mem_size"))) {
-                aot_set_last_error("llvm build load failed.");
+    }
+
+    /* offset1 = offset + addr; */
+    BUILD_OP(Add, offset_const, addr, offset1, "offset1");
+
+    if (comp_ctx->enable_bound_check
+        && !(is_local_of_aot_value
+             && aot_checked_addr_list_find(func_ctx, local_idx_of_aot_value,
+                                           offset, bytes))) {
+        uint32 init_page_count =
+                comp_ctx->comp_data->memories[0].mem_init_page_count;
+        if (init_page_count == 0) {
+            LLVMValueRef mem_size;
+
+            if (!(mem_size = get_memory_curr_page_count(comp_ctx, func_ctx))) {
+                goto fail;
+            }
+            BUILD_ICMP(LLVMIntEQ, mem_size, I32_ZERO, cmp, "is_zero");
+            ADD_BASIC_BLOCK(check_succ, "check_mem_size_succ");
+            LLVMMoveBasicBlockAfter(check_succ, block_curr);
+            if (!aot_emit_exception(comp_ctx, func_ctx,
+                                    EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
+                                    true, cmp, check_succ)) {
                 goto fail;
             }
+
+            SET_BUILD_POS(check_succ);
+            block_curr = check_succ;
         }
 
-        ADD_BASIC_BLOCK(check_mem_space, "check_mem_space");
-        LLVMMoveBasicBlockAfter(check_mem_space, block_curr);
+        if (!(mem_check_bound =
+                    get_memory_check_bound(comp_ctx, func_ctx, bytes))) {
+            goto fail;
+        }
+
+        if (is_target_64bit) {
+            BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp, "cmp");
+        }
+        else {
+            /* Check integer overflow */
+            BUILD_ICMP(LLVMIntULT, offset1, addr, cmp1, "cmp1");
+            BUILD_ICMP(LLVMIntUGT, offset1, mem_check_bound, cmp2, "cmp2");
+            BUILD_OP(Or, cmp1, cmp2, cmp, "cmp");
+        }
+
+        /* Add basic blocks */
+        ADD_BASIC_BLOCK(check_succ, "check_succ");
+        LLVMMoveBasicBlockAfter(check_succ, block_curr);
 
-        /* if total_mem_size is zero, boundary check fail */
-        BUILD_ICMP(LLVMIntEQ, total_mem_size, I32_ZERO, cmp,
-                   "cmp_total_mem_size");
         if (!aot_emit_exception(comp_ctx, func_ctx,
                                 EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
-                                true, cmp, check_mem_space)) {
+                                true, cmp, check_succ)) {
             goto fail;
         }
-        SET_BUILD_POS(check_mem_space);
-    }
 
-    /* offset2 = offset1 - heap_base_offset; */
-    BUILD_OP(Sub, offset1, heap_base_offset, offset2, "offset2");
-
-    if (!(mem_check_bound =
-                get_memory_check_bound(comp_ctx, func_ctx, bytes))) {
-        goto fail;
-    }
-
-    /* Add basic blocks */
-    ADD_BASIC_BLOCK(check_succ, "check_succ");
-    LLVMMoveBasicBlockAfter(check_succ, block_curr);
+        SET_BUILD_POS(check_succ);
 
-    /* offset2 > bound ? */
-    BUILD_ICMP(LLVMIntUGT, offset2, mem_check_bound, cmp, "cmp");
-    if (!aot_emit_exception(comp_ctx, func_ctx,
-                            EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
-                            true, cmp, check_succ)) {
-        goto fail;
+        if (is_local_of_aot_value) {
+            if (!aot_checked_addr_list_add(func_ctx, local_idx_of_aot_value,
+                                           offset, bytes))
+                goto fail;
+        }
     }
 
-    SET_BUILD_POS(check_succ);
-
     /* maddr = mem_base_addr + offset1 */
     if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
                                        &offset1, 1, "maddr"))) {
@@ -202,7 +249,7 @@ fail:
     LLVMSetAlignment(value, 1);                             \
   } while (0)
 
-#define BUILD_TRUNC(data_type) do {                         \
+#define BUILD_TRUNC(value, data_type) do {                  \
     if (!(value = LLVMBuildTrunc(comp_ctx->builder, value,  \
                                  data_type, "val_trunc"))){ \
         aot_set_last_error("llvm build trunc failed.");     \
@@ -235,19 +282,94 @@ fail:
     }                                                       \
   } while (0)
 
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+check_memory_alignment(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                       LLVMValueRef addr, uint32 align)
+{
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef check_align_succ;
+    LLVMValueRef align_mask = I32_CONST(((uint32)1 << align) - 1);
+    LLVMValueRef res;
+
+    CHECK_LLVM_CONST(align_mask);
+
+    /* Convert pointer to int */
+    if (!(addr = LLVMBuildPtrToInt(comp_ctx->builder, addr,
+                                   I32_TYPE, "address"))) {
+        aot_set_last_error("llvm build ptr to int failed.");
+        goto fail;
+    }
+
+    /* The memory address should be aligned */
+    BUILD_OP(And, addr, align_mask, res, "and");
+    BUILD_ICMP(LLVMIntNE, res, I32_ZERO, res, "cmp");
+
+    /* Add basic blocks */
+    ADD_BASIC_BLOCK(check_align_succ, "check_align_succ");
+    LLVMMoveBasicBlockAfter(check_align_succ, block_curr);
+
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_UNALIGNED_ATOMIC,
+                            true, res, check_align_succ)) {
+        goto fail;
+    }
+
+    SET_BUILD_POS(check_align_succ);
+
+    return true;
+fail:
+    return false;
+}
+
+#define BUILD_ATOMIC_LOAD(align) do {                                   \
+    if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) {  \
+        goto fail;                                                      \
+    }                                                                   \
+    if (!(value = LLVMBuildLoad(comp_ctx->builder, maddr,               \
+                                "data"))) {                             \
+        aot_set_last_error("llvm build load failed.");                  \
+        goto fail;                                                      \
+    }                                                                   \
+    LLVMSetAlignment(value, 1 << align);                                \
+    LLVMSetVolatile(value, true);                                       \
+    LLVMSetOrdering(value, LLVMAtomicOrderingSequentiallyConsistent);   \
+  } while (0)
+
+#define BUILD_ATOMIC_STORE(align) do {                                  \
+    LLVMValueRef res;                                                   \
+    if (!(check_memory_alignment(comp_ctx, func_ctx, maddr, align))) {  \
+        goto fail;                                                      \
+    }                                                                   \
+    if (!(res = LLVMBuildStore(comp_ctx->builder, value, maddr))) {     \
+        aot_set_last_error("llvm build store failed.");                 \
+        goto fail;                                                      \
+    }                                                                   \
+    LLVMSetAlignment(res, 1 << align);                                  \
+    LLVMSetVolatile(res, true);                                         \
+    LLVMSetOrdering(res, LLVMAtomicOrderingSequentiallyConsistent);     \
+  } while (0)
+#endif
+
 bool
 aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                        uint32 align, uint32 offset, uint32 bytes, bool sign)
+                        uint32 align, uint32 offset, uint32 bytes,
+                        bool sign, bool atomic)
 {
     LLVMValueRef maddr, value = NULL;
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
         return false;
 
     switch (bytes) {
         case 4:
             BUILD_PTR_CAST(INT32_PTR_TYPE);
-            BUILD_LOAD();
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            if (atomic)
+                BUILD_ATOMIC_LOAD(align);
+            else
+#endif
+                BUILD_LOAD();
             break;
         case 2:
         case 1:
@@ -255,11 +377,20 @@ aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 BUILD_PTR_CAST(INT16_PTR_TYPE);
             else
                 BUILD_PTR_CAST(INT8_PTR_TYPE);
-            BUILD_LOAD();
-            if (sign)
-                BUILD_SIGN_EXT(I32_TYPE);
-            else
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            if (atomic) {
+                BUILD_ATOMIC_LOAD(align);
                 BUILD_ZERO_EXT(I32_TYPE);
+            }
+            else
+#endif
+            {
+                BUILD_LOAD();
+                if (sign)
+                    BUILD_SIGN_EXT(I32_TYPE);
+                else
+                    BUILD_ZERO_EXT(I32_TYPE);
+            }
             break;
         default:
             bh_assert(0);
@@ -274,17 +405,23 @@ fail:
 
 bool
 aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                        uint32 align, uint32 offset, uint32 bytes, bool sign)
+                        uint32 align, uint32 offset, uint32 bytes,
+                        bool sign, bool atomic)
 {
     LLVMValueRef maddr, value = NULL;
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
         return false;
 
     switch (bytes) {
         case 8:
             BUILD_PTR_CAST(INT64_PTR_TYPE);
-            BUILD_LOAD();
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            if (atomic)
+                BUILD_ATOMIC_LOAD(align);
+            else
+#endif
+                BUILD_LOAD();
             break;
         case 4:
         case 2:
@@ -295,11 +432,20 @@ aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 BUILD_PTR_CAST(INT16_PTR_TYPE);
             else
                 BUILD_PTR_CAST(INT8_PTR_TYPE);
-            BUILD_LOAD();
-            if (sign)
-                BUILD_SIGN_EXT(I64_TYPE);
-            else
+#if WASM_ENABLE_SHARED_MEMORY != 0
+            if (atomic) {
+                BUILD_ATOMIC_LOAD(align);
                 BUILD_ZERO_EXT(I64_TYPE);
+            }
+            else
+#endif
+            {
+                BUILD_LOAD();
+                if (sign)
+                    BUILD_SIGN_EXT(I64_TYPE);
+                else
+                    BUILD_ZERO_EXT(I64_TYPE);
+            }
             break;
         default:
             bh_assert(0);
@@ -318,7 +464,7 @@ aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 {
     LLVMValueRef maddr, value;
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
         return false;
 
     BUILD_PTR_CAST(F32_PTR_TYPE);
@@ -335,7 +481,7 @@ aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 {
     LLVMValueRef maddr, value;
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
         return false;
 
     BUILD_PTR_CAST(F64_PTR_TYPE);
@@ -348,13 +494,13 @@ fail:
 
 bool
 aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                         uint32 align, uint32 offset, uint32 bytes)
+                         uint32 align, uint32 offset, uint32 bytes, bool atomic)
 {
     LLVMValueRef maddr, value;
 
     POP_I32(value);
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
         return false;
 
     switch (bytes) {
@@ -363,18 +509,23 @@ aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             break;
         case 2:
             BUILD_PTR_CAST(INT16_PTR_TYPE);
-            BUILD_TRUNC(INT16_TYPE);
+            BUILD_TRUNC(value, INT16_TYPE);
             break;
         case 1:
             BUILD_PTR_CAST(INT8_PTR_TYPE);
-            BUILD_TRUNC(INT8_TYPE);
+            BUILD_TRUNC(value, INT8_TYPE);
             break;
         default:
             bh_assert(0);
             break;
     }
 
-    BUILD_STORE();
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    if (atomic)
+        BUILD_ATOMIC_STORE(align);
+    else
+#endif
+        BUILD_STORE();
     return true;
 fail:
     return false;
@@ -382,13 +533,13 @@ fail:
 
 bool
 aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                         uint32 align, uint32 offset, uint32 bytes)
+                         uint32 align, uint32 offset, uint32 bytes, bool atomic)
 {
     LLVMValueRef maddr, value;
 
     POP_I64(value);
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
         return false;
 
     switch (bytes) {
@@ -397,22 +548,27 @@ aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             break;
         case 4:
             BUILD_PTR_CAST(INT32_PTR_TYPE);
-            BUILD_TRUNC(I32_TYPE);
+            BUILD_TRUNC(value, I32_TYPE);
             break;
         case 2:
             BUILD_PTR_CAST(INT16_PTR_TYPE);
-            BUILD_TRUNC(INT16_TYPE);
+            BUILD_TRUNC(value, INT16_TYPE);
             break;
         case 1:
             BUILD_PTR_CAST(INT8_PTR_TYPE);
-            BUILD_TRUNC(INT8_TYPE);
+            BUILD_TRUNC(value, INT8_TYPE);
             break;
         default:
             bh_assert(0);
             break;
     }
 
-    BUILD_STORE();
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    if (atomic)
+        BUILD_ATOMIC_STORE(align);
+    else
+#endif
+        BUILD_STORE();
     return true;
 fail:
     return false;
@@ -426,7 +582,7 @@ aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     POP_F32(value);
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 4)))
         return false;
 
     BUILD_PTR_CAST(F32_PTR_TYPE);
@@ -444,7 +600,7 @@ aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     POP_F64(value);
 
-    if (!(maddr = check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, 8)))
         return false;
 
     BUILD_PTR_CAST(F64_PTR_TYPE);
@@ -455,34 +611,21 @@ fail:
 }
 
 static LLVMValueRef
-get_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+get_memory_curr_page_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
-    uint32 offset = offsetof(AOTModuleInstance, mem_cur_page_count);
-    LLVMValueRef mem_size_offset, mem_size_ptr, mem_size;
-
-    /* mem_size_offset = aot_inst + offset */
-    mem_size_offset = I32_CONST(offset);
-    CHECK_LLVM_CONST(mem_size_offset);
-    if (!(mem_size_ptr = LLVMBuildInBoundsGEP(comp_ctx->builder,
-                                              func_ctx->aot_inst,
-                                              &mem_size_offset, 1,
-                                              "mem_size_ptr_tmp"))) {
-        aot_set_last_error("llvm build inbounds gep failed.");
-        return NULL;
-    }
+    LLVMValueRef mem_size;
 
-    /* cast to int32* */
-    if (!(mem_size_ptr = LLVMBuildBitCast(comp_ctx->builder, mem_size_ptr,
-                                          INT32_PTR_TYPE, "mem_size_ptr"))) {
-        aot_set_last_error("llvm build bitcast failed.");
-        return NULL;
+    if (func_ctx->mem_space_unchanged) {
+        mem_size = func_ctx->mem_info[0].mem_cur_page_count_addr;
     }
-
-    /* load memory size, or current page count */
-    if (!(mem_size = LLVMBuildLoad(comp_ctx->builder,
-                                   mem_size_ptr, "mem_size"))) {
-        aot_set_last_error("llvm build load failed.");
-        return NULL;
+    else {
+        if (!(mem_size =
+                LLVMBuildLoad(comp_ctx->builder,
+                              func_ctx->mem_info[0].mem_cur_page_count_addr,
+                              "mem_size"))) {
+            aot_set_last_error("llvm build load failed.");
+            goto fail;
+        }
     }
 
     return mem_size;
@@ -493,7 +636,7 @@ fail:
 bool
 aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
-    LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
+    LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
 
     if (mem_size)
         PUSH_I32(mem_size);
@@ -505,7 +648,7 @@ fail:
 bool
 aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 {
-    LLVMValueRef mem_size = get_memory_size(comp_ctx, func_ctx);
+    LLVMValueRef mem_size = get_memory_curr_page_count(comp_ctx, func_ctx);
     LLVMValueRef delta, param_values[2], ret_value, func, value;
     LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
 
@@ -514,7 +657,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
 
     POP_I32(delta);
 
-    /* Function type of wasm_runtime_enlarge_memory() */
+    /* Function type of aot_enlarge_memory() */
     param_types[0] = INT8_PTR_TYPE;
     param_types[1] = I32_TYPE;
     ret_type = INT8_TYPE;
@@ -530,14 +673,14 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
             aot_set_last_error("llvm add pointer type failed.");
             return false;
         }
-        if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_enlarge_memory))
+        if (!(value = I64_CONST((uint64)(uintptr_t)aot_enlarge_memory))
             || !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
             aot_set_last_error("create LLVM value failed.");
             return false;
         }
     }
     else {
-        char *func_name = "wasm_runtime_enlarge_memory";
+        char *func_name = "aot_enlarge_memory";
         /* AOT mode, delcare the function */
         if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
             && !(func = LLVMAddFunction(comp_ctx->module,
@@ -547,7 +690,7 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
         }
     }
 
-    /* Call function wasm_runtime_enlarge_memory() */
+    /* Call function aot_enlarge_memory() */
     param_values[0] = func_ctx->aot_inst;
     param_values[1] = delta;
     if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
@@ -567,49 +710,540 @@ aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
     }
 
     PUSH_I32(ret_value);
+    return true;
+fail:
+    return false;
+}
 
-    /* To be simple, call wasm_runtime_set_exception() no matter
-       enlarge success or not */
-    param_types[1] = VOID_PTR_TYPE;
-    ret_type = VOID_TYPE;
-    if (!(func_type = LLVMFunctionType(ret_type, param_types, 2, false))) {
-        aot_set_last_error("llvm add function type failed.");
+
+#if WASM_ENABLE_BULK_MEMORY != 0
+
+static LLVMValueRef
+check_bulk_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           LLVMValueRef offset, LLVMValueRef bytes)
+{
+    LLVMValueRef maddr, max_addr, cmp;
+    LLVMValueRef mem_base_addr;
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef check_succ;
+    LLVMValueRef mem_size;
+
+    /* Get memory base address and memory data size */
+#if WASM_ENABLE_SHARED_MEMORY != 0
+    bool is_shared_memory =
+        comp_ctx->comp_data->memories[0].memory_flags & 0x02;
+
+    if (func_ctx->mem_space_unchanged || is_shared_memory) {
+#else
+    if (func_ctx->mem_space_unchanged) {
+#endif
+        mem_base_addr = func_ctx->mem_info[0].mem_base_addr;
+    }
+    else {
+        if (!(mem_base_addr =
+                LLVMBuildLoad(comp_ctx->builder,
+                              func_ctx->mem_info[0].mem_base_addr,
+                              "mem_base"))) {
+            aot_set_last_error("llvm build load failed.");
+            goto fail;
+        }
+    }
+
+    /* return addres directly if constant offset and inside memory space */
+    if (LLVMIsConstant(offset) && LLVMIsConstant(bytes)) {
+        uint64 mem_offset = (uint64)LLVMConstIntGetZExtValue(offset);
+        uint64 mem_len = (uint64)LLVMConstIntGetZExtValue(bytes);
+        uint32 num_bytes_per_page =
+                comp_ctx->comp_data->memories[0].num_bytes_per_page;
+        uint32 init_page_count =
+                comp_ctx->comp_data->memories[0].mem_init_page_count;
+        uint32 mem_data_size = num_bytes_per_page * init_page_count;
+        if (mem_data_size > 0
+            && mem_offset + mem_len <= mem_data_size) {
+            /* inside memory space */
+            /* maddr = mem_base_addr + moffset */
+            if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder,
+                                               mem_base_addr,
+                                               &offset, 1, "maddr"))) {
+                aot_set_last_error("llvm build add failed.");
+                goto fail;
+            }
+            return maddr;
+        }
+    }
+
+    if (func_ctx->mem_space_unchanged) {
+        mem_size = func_ctx->mem_info[0].mem_data_size_addr;
+    }
+    else {
+        if (!(mem_size =
+                LLVMBuildLoad(comp_ctx->builder,
+                              func_ctx->mem_info[0].mem_data_size_addr,
+                              "mem_size"))) {
+            aot_set_last_error("llvm build load failed.");
+            goto fail;
+        }
+    }
+
+    ADD_BASIC_BLOCK(check_succ, "check_succ");
+    LLVMMoveBasicBlockAfter(check_succ, block_curr);
+
+    offset = LLVMBuildZExt(comp_ctx->builder, offset, I64_TYPE, "extend_offset");
+    bytes = LLVMBuildZExt(comp_ctx->builder, bytes, I64_TYPE, "extend_len");
+    mem_size = LLVMBuildZExt(comp_ctx->builder, mem_size, I64_TYPE, "extend_size");
+
+    BUILD_OP(Add, offset, bytes, max_addr, "max_addr");
+    BUILD_ICMP(LLVMIntUGT, max_addr, mem_size, cmp,
+               "cmp_max_mem_addr");
+    if (!aot_emit_exception(comp_ctx, func_ctx,
+                            EXCE_OUT_OF_BOUNDS_MEMORY_ACCESS,
+                            true, cmp, check_succ)) {
+        goto fail;
+    }
+
+    /* maddr = mem_base_addr + offset */
+    if (!(maddr = LLVMBuildInBoundsGEP(comp_ctx->builder, mem_base_addr,
+                                       &offset, 1, "maddr"))) {
+        aot_set_last_error("llvm build add failed.");
+        goto fail;
+    }
+    return maddr;
+fail:
+    return NULL;
+}
+
+bool
+aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           uint32 seg_index)
+{
+    LLVMValueRef seg, offset, dst, len, param_values[5], ret_value, func, value;
+    LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+    AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    LLVMBasicBlockRef mem_init_fail, init_success;
+
+    seg = I32_CONST(seg_index);
+
+    POP_I32(len);
+    POP_I32(offset);
+    POP_I32(dst);
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    param_types[4] = I32_TYPE;
+    ret_type = INT8_TYPE;
+
+    GET_AOT_FUNCTION(aot_memory_init, 5);
+
+    /* Call function aot_memory_init() */
+    param_values[0] = func_ctx->aot_inst;
+    param_values[1] = seg;
+    param_values[2] = offset;
+    param_values[3] = len;
+    param_values[4] = dst;
+    if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
+                                    param_values, 5, "call"))) {
+        aot_set_last_error("llvm build call failed.");
         return false;
     }
 
-    if (comp_ctx->is_jit_mode) {
-        /* JIT mode, call the function directly */
-        if (!(func_ptr_type = LLVMPointerType(func_type, 0))) {
-            aot_set_last_error("llvm add pointer type failed.");
-            return false;
+    BUILD_ICMP(LLVMIntUGT, ret_value, I8_ZERO, ret_value, "mem_init_ret");
+
+    ADD_BASIC_BLOCK(mem_init_fail, "mem_init_fail");
+    ADD_BASIC_BLOCK(init_success, "init_success");
+
+    LLVMMoveBasicBlockAfter(mem_init_fail, block_curr);
+    LLVMMoveBasicBlockAfter(init_success, block_curr);
+
+    if (!LLVMBuildCondBr(comp_ctx->builder, ret_value,
+                         init_success, mem_init_fail)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* If memory.init failed, return this function
+        so the runtime can catch the exception */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, mem_init_fail);
+    if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
+        goto fail;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, init_success);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                         uint32 seg_index)
+{
+    LLVMValueRef seg, param_values[2], ret_value, func, value;
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+
+    seg = I32_CONST(seg_index);
+    CHECK_LLVM_CONST(seg);
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = INT8_TYPE;
+
+    GET_AOT_FUNCTION(aot_data_drop, 2);
+
+    /* Call function aot_data_drop() */
+    param_values[0] = func_ctx->aot_inst;
+    param_values[1] = seg;
+    if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
+                                    param_values, 2, "call"))) {
+        aot_set_last_error("llvm build call failed.");
+        return false;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef src, dst, src_addr, dst_addr, len, res;
+
+    POP_I32(len);
+    POP_I32(src);
+    POP_I32(dst);
+
+    if (!(src_addr =
+            check_bulk_memory_overflow(comp_ctx, func_ctx, src, len)))
+        return false;
+
+    if (!(dst_addr =
+            check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
+        return false;
+
+    if (!(res = LLVMBuildMemMove(comp_ctx->builder, dst_addr, 1,
+                                 src_addr, 1, len))) {
+        aot_set_last_error("llvm build memmove failed.");
+        return false;
+    }
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
+{
+    LLVMValueRef val, dst, dst_addr, len, res;
+
+    POP_I32(len);
+    POP_I32(val);
+    POP_I32(dst);
+
+    if (!(dst_addr =
+            check_bulk_memory_overflow(comp_ctx, func_ctx, dst, len)))
+        return false;
+
+    val = LLVMBuildIntCast2(comp_ctx->builder, val, INT8_TYPE, true, "mem_set_value");
+
+    if (!(res = LLVMBuildMemSet(comp_ctx->builder, dst_addr,
+                                val, len, 1))) {
+        aot_set_last_error("llvm build memset failed.");
+        return false;
+    }
+    return true;
+fail:
+    return false;
+}
+#endif /* end of WASM_ENABLE_BULK_MEMORY */
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint8 atomic_op, uint8 op_type,
+                          uint32 align, uint32 offset,
+                          uint32 bytes)
+{
+    LLVMValueRef maddr, value, result;
+
+    if (op_type == VALUE_TYPE_I32)
+        POP_I32(value);
+    else
+        POP_I64(value);
+
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+        return false;
+
+    if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+        return false;
+
+    switch (bytes) {
+        case 8:
+            BUILD_PTR_CAST(INT64_PTR_TYPE);
+            break;
+        case 4:
+            BUILD_PTR_CAST(INT32_PTR_TYPE);
+            if (op_type == VALUE_TYPE_I64)
+                BUILD_TRUNC(value, I32_TYPE);
+            break;
+        case 2:
+            BUILD_PTR_CAST(INT16_PTR_TYPE);
+            BUILD_TRUNC(value, INT16_TYPE);
+            break;
+        case 1:
+            BUILD_PTR_CAST(INT8_PTR_TYPE);
+            BUILD_TRUNC(value, INT8_TYPE);
+            break;
+        default:
+            bh_assert(0);
+            break;
+    }
+
+    if (!(result =
+        LLVMBuildAtomicRMW(comp_ctx->builder,
+                           atomic_op, maddr, value,
+                           LLVMAtomicOrderingSequentiallyConsistent, false))) {
+        goto fail;
+    }
+
+    LLVMSetVolatile(result, true);
+
+    if (op_type == VALUE_TYPE_I32) {
+        if (!(result = LLVMBuildZExt(comp_ctx->builder, result,
+                                     I32_TYPE, "result_i32"))) {
+            goto fail;
         }
-        if (!(value = I64_CONST((uint64)(uintptr_t)wasm_runtime_set_exception))
-            || !(func = LLVMConstIntToPtr(value, func_ptr_type))) {
-            aot_set_last_error("create LLVM value failed.");
-            return false;
+        PUSH_I32(result);
+    }
+    else {
+        if (!(result = LLVMBuildZExt(comp_ctx->builder, result,
+                                     I64_TYPE, "result_i64"))) {
+            goto fail;
         }
+        PUSH_I64(result);
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              uint8 op_type, uint32 align,
+                              uint32 offset, uint32 bytes)
+{
+    LLVMValueRef maddr, value, expect, result;
+
+    if (op_type == VALUE_TYPE_I32) {
+        POP_I32(value);
+        POP_I32(expect);
     }
     else {
-        char *func_name = "wasm_runtime_set_exception";
-        /* AOT mode, delcare the function */
-        if (!(func = LLVMGetNamedFunction(comp_ctx->module, func_name))
-            && !(func = LLVMAddFunction(comp_ctx->module,
-                                        func_name, func_type))) {
-           aot_set_last_error("llvm add function failed.");
-           return false;
-       }
+        POP_I64(value);
+        POP_I64(expect);
     }
 
-    /* Call function wasm_runtime_set_exception(aot_inst, NULL) */
-    param_values[1] = LLVMConstNull(VOID_PTR_TYPE);
-    CHECK_LLVM_CONST(param_values[1]);
-    if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+        return false;
+
+    if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+        return false;
+
+    switch (bytes) {
+        case 8:
+            BUILD_PTR_CAST(INT64_PTR_TYPE);
+            break;
+        case 4:
+            BUILD_PTR_CAST(INT32_PTR_TYPE);
+            if (op_type == VALUE_TYPE_I64) {
+                BUILD_TRUNC(value, I32_TYPE);
+                BUILD_TRUNC(expect, I32_TYPE);
+            }
+            break;
+        case 2:
+            BUILD_PTR_CAST(INT16_PTR_TYPE);
+            BUILD_TRUNC(value, INT16_TYPE);
+            BUILD_TRUNC(expect, INT16_TYPE);
+            break;
+        case 1:
+            BUILD_PTR_CAST(INT8_PTR_TYPE);
+            BUILD_TRUNC(value, INT8_TYPE);
+            BUILD_TRUNC(expect, INT8_TYPE);
+            break;
+        default:
+            bh_assert(0);
+            break;
+    }
+
+    if (!(result =
+        LLVMBuildAtomicCmpXchg(comp_ctx->builder, maddr, expect, value,
+                               LLVMAtomicOrderingSequentiallyConsistent,
+                               LLVMAtomicOrderingSequentiallyConsistent,
+                               false))) {
+        goto fail;
+    }
+
+    LLVMSetVolatile(result, true);
+
+    /* CmpXchg return {i32, i1} structure,
+        we need to extrack the previous_value from the structure */
+    if (!(result =
+        LLVMBuildExtractValue(comp_ctx->builder,
+                              result, 0, "previous_value"))) {
+        goto fail;
+    }
+
+    if (op_type == VALUE_TYPE_I32) {
+        if (!(result = LLVMBuildZExt(comp_ctx->builder, result,
+                                     I32_TYPE, "result_i32"))) {
+            goto fail;
+        }
+        PUSH_I32(result);
+    }
+    else {
+        if (!(result = LLVMBuildZExt(comp_ctx->builder, result,
+                                     I64_TYPE, "result_i64"))) {
+            goto fail;
+        }
+        PUSH_I64(result);
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           uint8 op_type, uint32 align,
+                           uint32 offset, uint32 bytes)
+{
+    LLVMValueRef maddr, value, timeout, expect, cmp;
+    LLVMValueRef param_values[5], ret_value, func, is_wait64;
+    LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+    LLVMBasicBlockRef wait_fail, wait_success;
+    LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+    AOTFuncType *aot_func_type = func_ctx->aot_func->func_type;
+
+    POP_I64(timeout);
+    if (op_type == VALUE_TYPE_I32) {
+        POP_I32(expect);
+        is_wait64 = I8_CONST(false);
+        if (!(expect =
+            LLVMBuildZExt(comp_ctx->builder, expect,
+                          I64_TYPE, "expect_i64"))) {
+            goto fail;
+        }
+    }
+    else {
+        POP_I64(expect);
+        is_wait64 = I8_CONST(true);
+    }
+
+    CHECK_LLVM_CONST(is_wait64);
+
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+        return false;
+
+    if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+        return false;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = INT8_PTR_TYPE;
+    param_types[2] = I64_TYPE;
+    param_types[3] = I64_TYPE;
+    param_types[4] = INT8_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_runtime_atomic_wait, 5);
+
+    /* Call function wasm_runtime_atomic_wait() */
+    param_values[0] = func_ctx->aot_inst;
+    param_values[1] = maddr;
+    param_values[2] = expect;
+    param_values[3] = timeout;
+    param_values[4] = is_wait64;
+    if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
+                                    param_values, 5, "call"))) {
+        aot_set_last_error("llvm build call failed.");
+        return false;
+    }
+
+    BUILD_ICMP(LLVMIntSGT, ret_value, I32_ZERO, cmp, "atomic_wait_ret");
+
+    ADD_BASIC_BLOCK(wait_fail, "atomic_wait_fail");
+    ADD_BASIC_BLOCK(wait_success, "wait_success");
+
+    LLVMMoveBasicBlockAfter(wait_fail, block_curr);
+    LLVMMoveBasicBlockAfter(wait_success, block_curr);
+
+    if (!LLVMBuildCondBr(comp_ctx->builder, cmp,
+                         wait_success, wait_fail)) {
+        aot_set_last_error("llvm build cond br failed.");
+        goto fail;
+    }
+
+    /* If atomic wait failed, return this function
+        so the runtime can catch the exception */
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_fail);
+    if (!aot_build_zero_function_ret(comp_ctx, aot_func_type)) {
+        goto fail;
+    }
+
+    LLVMPositionBuilderAtEnd(comp_ctx->builder, wait_success);
+
+    PUSH_I32(ret_value);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              uint32 align, uint32 offset, uint32 bytes)
+{
+    LLVMValueRef maddr, value, count;
+    LLVMValueRef param_values[3], ret_value, func;
+    LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
+
+    POP_I32(count);
+
+    if (!(maddr = aot_check_memory_overflow(comp_ctx, func_ctx, offset, bytes)))
+        return false;
+
+    if (!check_memory_alignment(comp_ctx, func_ctx, maddr, align))
+        return false;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = INT8_PTR_TYPE;
+    param_types[2] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(wasm_runtime_atomic_notify, 3);
+
+    /* Call function wasm_runtime_atomic_notify() */
+    param_values[0] = func_ctx->aot_inst;
+    param_values[1] = maddr;
+    param_values[2] = count;
+    if (!(ret_value = LLVMBuildCall(comp_ctx->builder, func,
+                                    param_values, 3, "call"))) {
         aot_set_last_error("llvm build call failed.");
         return false;
     }
 
+    PUSH_I32(ret_value);
+
     return true;
 fail:
     return false;
 }
 
+#endif /* end of WASM_ENABLE_SHARED_MEMORY */

+ 54 - 4
core/iwasm/compilation/aot_emit_memory.h

@@ -7,6 +7,9 @@
 #define _AOT_EMIT_MEMORY_H_
 
 #include "aot_compiler.h"
+#if WASM_ENABLE_SHARED_MEMORY != 0
+#include "wasm_shared_memory.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -14,11 +17,13 @@ extern "C" {
 
 bool
 aot_compile_op_i32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                        uint32 align, uint32 offset, uint32 bytes, bool sign);
+                        uint32 align, uint32 offset, uint32 bytes,
+                        bool sign, bool atomic);
 
 bool
 aot_compile_op_i64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                        uint32 align, uint32 offset, uint32 bytes, bool sign);
+                        uint32 align, uint32 offset, uint32 bytes,
+                        bool sign, bool atomic);
 
 bool
 aot_compile_op_f32_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
@@ -30,11 +35,11 @@ aot_compile_op_f64_load(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 bool
 aot_compile_op_i32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                         uint32 align, uint32 offset, uint32 bytes);
+                         uint32 align, uint32 offset, uint32 bytes, bool atomic);
 
 bool
 aot_compile_op_i64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                         uint32 align, uint32 offset, uint32 bytes);
+                         uint32 align, uint32 offset, uint32 bytes, bool atomic);
 
 bool
 aot_compile_op_f32_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
@@ -44,12 +49,57 @@ bool
 aot_compile_op_f64_store(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                          uint32 align, uint32 offset);
 
+LLVMValueRef
+aot_check_memory_overflow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                          uint32 offset, uint32 bytes);
+
 bool
 aot_compile_op_memory_size(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 
 bool
 aot_compile_op_memory_grow(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
 
+#if WASM_ENABLE_BULK_MEMORY != 0
+bool
+aot_compile_op_memory_init(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           uint32 seg_index);
+
+bool
+aot_compile_op_data_drop(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                         uint32 seg_index);
+
+bool
+aot_compile_op_memory_copy(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+
+bool
+aot_compile_op_memory_fill(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
+#endif
+
+#if WASM_ENABLE_SHARED_MEMORY != 0
+bool
+aot_compile_op_atomic_rmw(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint8 atomic_op, uint8 op_type,
+                          uint32 align, uint32 offset,
+                          uint32 bytes);
+
+bool
+aot_compile_op_atomic_cmpxchg(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              uint8 op_type, uint32 align,
+                              uint32 offset, uint32 bytes);
+
+bool
+aot_compile_op_atomic_wait(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
+                           uint8 op_type, uint32 align,
+                           uint32 offset, uint32 bytes);
+
+bool
+aot_compiler_op_atomic_notify(AOTCompContext *comp_ctx,
+                              AOTFuncContext *func_ctx,
+                              uint32 align, uint32 offset, uint32 bytes);
+#endif
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 63 - 183
core/iwasm/compilation/aot_emit_numberic.c

@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * Copyright (C) 2020 Intel Corporation. All rights reserved.
  * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  */
 
@@ -27,7 +27,7 @@
 #define ADD_BASIC_BLOCK(block, name) do {                                  \
     if (!(block = LLVMAppendBasicBlockInContext(comp_ctx->context,         \
                                                 func_ctx->func,            \
-                                                name))) { \
+                                                name))) {                  \
         aot_set_last_error("llvm add basic block failed.");                \
         goto fail;                                                         \
     }                                                                      \
@@ -135,116 +135,12 @@
 } while (0)
 
 
-static LLVMValueRef
-__call_llvm_intrinsic(AOTCompContext *comp_ctx,
-                      const char *name,
-                      LLVMTypeRef ret_type,
-                      LLVMTypeRef *param_types,
-                      int param_count,
-                      LLVMValueRef *param_values)
-{
-    LLVMValueRef func, ret;
-    LLVMTypeRef func_type;
-
-    /* Declare llvm intrinsic function if necessary */
-    if (!(func = LLVMGetNamedFunction(comp_ctx->module, name))) {
-        if (!(func_type =
-                LLVMFunctionType(ret_type, param_types, (uint32)param_count, false))) {
-            aot_set_last_error("create LLVM function type failed.");
-            return NULL;
-        }
-
-        if (!(func = LLVMAddFunction(comp_ctx->module, name, func_type))) {
-            aot_set_last_error("add LLVM function failed.");
-            return NULL;
-        }
-    }
-
-    /* Call the LLVM intrinsic function */
-    if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values,
-                              (uint32)param_count, "call"))) {
-        aot_set_last_error("llvm build call failed.");
-        return NULL;
-    }
-
-    return ret;
-}
-
-static LLVMValueRef
-call_llvm_intrinsic(AOTCompContext *comp_ctx,
-                    const char *name,
-                    LLVMTypeRef ret_type,
-                    LLVMTypeRef *param_types,
-                    int param_count,
-                    ...)
-{
-    LLVMValueRef *param_values, ret;
-    va_list argptr;
-    uint64 total_size;
-    int i = 0;
-
-    /* Create param values */
-    total_size = sizeof(LLVMValueRef) * (uint64)param_count;
-    if (total_size >= UINT32_MAX
-        || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
-        aot_set_last_error("allocate memory for param values failed.");
-        return false;
-    }
-
-    /* Load each param value */
-    va_start(argptr, param_count);
-    while (i < param_count)
-        param_values[i++] = va_arg(argptr, LLVMValueRef);
-    va_end(argptr);
-
-    ret = __call_llvm_intrinsic(comp_ctx, name, ret_type,
-                                param_types, param_count,
-                                param_values);
-
-    wasm_runtime_free(param_values);
-
-    return ret;
-}
-
-static LLVMValueRef
-call_llvm_intrinsic_v(AOTCompContext *comp_ctx,
-                      const char *name,
-                      LLVMTypeRef ret_type,
-                      LLVMTypeRef *param_types,
-                      int param_count,
-                      va_list param_value_list)
-{
-    LLVMValueRef *param_values, ret;
-    uint64 total_size;
-    int i = 0;
-
-    /* Create param values */
-    total_size = sizeof(LLVMValueRef) * (uint64)param_count;
-    if (total_size >= UINT32_MAX
-        || !(param_values = wasm_runtime_malloc((uint32)total_size))) {
-        aot_set_last_error("allocate memory for param values failed.");
-        return false;
-    }
-
-    /* Load each param value */
-    while (i < param_count)
-        param_values[i++] = va_arg(param_value_list, LLVMValueRef);
-
-    ret = __call_llvm_intrinsic(comp_ctx, name, ret_type,
-                                param_types, param_count,
-                                param_values);
-
-    wasm_runtime_free(param_values);
-
-    return ret;
-}
-
 /* Call llvm constrained floating-point intrinsic */
 static LLVMValueRef
-call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
-                                                  const char *intrinsic,
-                                                  bool is_f32,
-                                                  ...)
+call_llvm_float_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
+                                                   bool is_f32,
+                                                   const char *intrinsic,
+                                                   ...)
 {
     va_list param_value_list;
     LLVMValueRef ret;
@@ -253,14 +149,10 @@ call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
     param_types[0] = param_types[1] = ret_type;
     param_types[2] = param_types[3] = MD_TYPE;
 
-    va_start(param_value_list, is_f32);
+    va_start(param_value_list, intrinsic);
 
-    ret = call_llvm_intrinsic_v(comp_ctx,
-                                intrinsic,
-                                ret_type,
-                                param_types,
-                                4,
-                                param_value_list);
+    ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
+                                    4, param_value_list);
 
     va_end(param_value_list);
 
@@ -269,10 +161,10 @@ call_llvm_float_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
 
 /* Call llvm constrained libm-equivalent intrinsic */
 static LLVMValueRef
-call_llvm_libm_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
-                                                 const char *intrinsic,
-                                                 bool is_f32,
-                                                 ...)
+call_llvm_libm_experimental_constrained_intrinsic(AOTCompContext *comp_ctx,
+                                                  bool is_f32,
+                                                  const char *intrinsic,
+                                                  ...)
 {
     va_list param_value_list;
     LLVMValueRef ret;
@@ -281,14 +173,10 @@ call_llvm_libm_expermental_constrained_intrinsic(AOTCompContext *comp_ctx,
     param_types[0] = ret_type;
     param_types[1] = param_types[2] = MD_TYPE;
 
-    va_start(param_value_list, is_f32);
+    va_start(param_value_list, intrinsic);
 
-    ret = call_llvm_intrinsic_v(comp_ctx,
-                                intrinsic,
-                                ret_type,
-                                param_types,
-                                3,
-                                param_value_list);
+    ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, param_types,
+                                    3, param_value_list);
 
     va_end(param_value_list);
 
@@ -342,13 +230,8 @@ compile_op_float_min_max(AOTCompContext *comp_ctx,
         return NULL;
     }
 
-    if (!(cmp = call_llvm_intrinsic(comp_ctx,
-                                    intrinsic,
-                                    ret_type,
-                                    param_types,
-                                    2,
-                                    left,
-                                    right)))
+    if (!(cmp = aot_call_llvm_intrinsic(comp_ctx, intrinsic, ret_type,
+                                        param_types, 2, left, right)))
         return NULL;
 
     if (!(cmp = LLVMBuildSelect(comp_ctx->builder,
@@ -406,21 +289,21 @@ aot_compile_int_bit_count(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     /* Call the LLVM intrinsic function */
     if (type < POP_CNT32)
-        DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
-                                             bit_cnt_llvm_intrinsic[type],
-                                             ret_type,
-                                             param_types,
-                                             2,
-                                             operand,
-                                             zero_undef),
+        DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
+                                                 bit_cnt_llvm_intrinsic[type],
+                                                 ret_type,
+                                                 param_types,
+                                                 2,
+                                                 operand,
+                                                 zero_undef),
                          NULL);
     else
-        DEF_INT_UNARY_OP(call_llvm_intrinsic(comp_ctx,
-                                             bit_cnt_llvm_intrinsic[type],
-                                             ret_type,
-                                             param_types,
-                                             1,
-                                             operand),
+        DEF_INT_UNARY_OP(aot_call_llvm_intrinsic(comp_ctx,
+                                                 bit_cnt_llvm_intrinsic[type],
+                                                 ret_type,
+                                                 param_types,
+                                                 1,
+                                                 operand),
                          NULL);
 
     return true;
@@ -861,6 +744,7 @@ static bool
 is_target_arm(AOTCompContext *comp_ctx)
 {
     return !strncmp(comp_ctx->target_arch, "arm", 3) ||
+           !strncmp(comp_ctx->target_arch, "aarch64", 7) ||
            !strncmp(comp_ctx->target_arch, "thumb", 5);
 }
 
@@ -929,12 +813,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 DEF_FP_BINARY_OP(LLVMBuildFAdd(comp_ctx->builder, left, right, "fadd"),
                                  "llvm build fadd fail.");
             else
-                DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
+                DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
                                     comp_ctx,
+                                    is_f32,
                                     (is_f32
                                      ? "llvm.experimental.constrained.fadd.f32"
                                      : "llvm.experimental.constrained.fadd.f64"),
-                                    is_f32,
                                     left,
                                     right,
                                     comp_ctx->fp_rounding_mode,
@@ -946,12 +830,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 DEF_FP_BINARY_OP(LLVMBuildFSub(comp_ctx->builder, left, right, "fsub"),
                                  "llvm build fsub fail.");
             else
-                DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
+                DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
                                     comp_ctx,
+                                    is_f32,
                                     (is_f32
                                      ? "llvm.experimental.constrained.fsub.f32"
                                      : "llvm.experimental.constrained.fsub.f64"),
-                                    is_f32,
                                     left,
                                     right,
                                     comp_ctx->fp_rounding_mode,
@@ -963,12 +847,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 DEF_FP_BINARY_OP(LLVMBuildFMul(comp_ctx->builder, left, right, "fmul"),
                                  "llvm build fmul fail.");
             else
-                DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
+                DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
                                     comp_ctx,
+                                    is_f32,
                                     (is_f32
                                      ? "llvm.experimental.constrained.fmul.f32"
                                      : "llvm.experimental.constrained.fmul.f64"),
-                                    is_f32,
                                     left,
                                     right,
                                     comp_ctx->fp_rounding_mode,
@@ -980,12 +864,12 @@ compile_op_float_arithmetic(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                 DEF_FP_BINARY_OP(LLVMBuildFDiv(comp_ctx->builder, left, right, "fdiv"),
                                  "llvm build fdiv fail.");
             else
-                DEF_FP_BINARY_OP(call_llvm_float_expermental_constrained_intrinsic(
+                DEF_FP_BINARY_OP(call_llvm_float_experimental_constrained_intrinsic(
                                     comp_ctx,
+                                    is_f32,
                                     (is_f32
                                      ? "llvm.experimental.constrained.fdiv.f32"
                                      : "llvm.experimental.constrained.fdiv.f64"),
-                                    is_f32,
                                     left,
                                     right,
                                     comp_ctx->fp_rounding_mode,
@@ -1020,9 +904,9 @@ fail:
 
 static LLVMValueRef
 call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
-                                const char *intrinsic,
-                                bool is_f32,
-                                ...)
+                               bool is_f32,
+                               const char *intrinsic,
+                               ...)
 {
     va_list param_value_list;
     LLVMValueRef ret;
@@ -1030,14 +914,10 @@ call_llvm_float_math_intrinsic(AOTCompContext *comp_ctx,
 
     param_type = ret_type;
 
-    va_start(param_value_list, is_f32);
+    va_start(param_value_list, intrinsic);
 
-    ret = call_llvm_intrinsic_v(comp_ctx,
-                                intrinsic,
-                                ret_type,
-                                &param_type,
-                                1,
-                                param_value_list);
+    ret = aot_call_llvm_intrinsic_v(comp_ctx, intrinsic, ret_type, &param_type,
+                                    1, param_value_list);
 
     va_end(param_value_list);
 
@@ -1051,9 +931,9 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     switch (math_op) {
         case FLOAT_ABS:
             DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
+                                                   is_f32,
                                                    is_f32 ? "llvm.fabs.f32" :
                                                             "llvm.fabs.f64",
-                                                   is_f32,
                                                    operand),
                             NULL);
             return true;
@@ -1064,51 +944,51 @@ compile_op_float_math(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
         case FLOAT_CEIL:
             DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
+                                                   is_f32,
                                                    is_f32 ? "llvm.ceil.f32" :
                                                             "llvm.ceil.f64",
-                                                   is_f32,
                                                    operand),
                             NULL);
             return true;
         case FLOAT_FLOOR:
             DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
-                                                   is_f32 ? "llvm.floor.f32" :
-                                                            "llvm.floor.f64",
                                                    is_f32,
+                                                   is_f32 ? "llvm.floor.f32":
+                                                            "llvm.floor.f64",
                                                    operand),
                             NULL);
             return true;
         case FLOAT_TRUNC:
             DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
+                                                   is_f32,
                                                    is_f32 ? "llvm.trunc.f32" :
                                                             "llvm.trunc.f64",
-                                                   is_f32,
                                                    operand),
                             NULL);
             return true;
         case FLOAT_NEAREST:
             DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
+                                                   is_f32,
                                                    is_f32 ? "llvm.rint.f32" :
                                                             "llvm.rint.f64",
-                                                   is_f32,
                                                    operand),
                             NULL);
             return true;
         case FLOAT_SQRT:
             if (is_targeting_soft_float(comp_ctx, is_f32))
                 DEF_FP_UNARY_OP(call_llvm_float_math_intrinsic(comp_ctx,
+                                                   is_f32,
                                                    is_f32 ? "llvm.sqrt.f32" :
                                                             "llvm.sqrt.f64",
-                                                   is_f32,
                                                    operand),
                                 NULL);
             else
-                DEF_FP_UNARY_OP(call_llvm_libm_expermental_constrained_intrinsic(
+                DEF_FP_UNARY_OP(call_llvm_libm_experimental_constrained_intrinsic(
                                            comp_ctx,
+                                           is_f32,
                                            (is_f32
                                             ? "llvm.experimental.constrained.sqrt.f32"
                                             : "llvm.experimental.constrained.sqrt.f64"),
-                                           is_f32,
                                            operand,
                                            comp_ctx->fp_rounding_mode,
                                            comp_ctx->fp_exception_behavior),
@@ -1133,14 +1013,14 @@ compile_float_copysign(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     param_types[0] = param_types[1] = ret_type = is_f32 ? F32_TYPE : F64_TYPE;
 
-    DEF_FP_BINARY_OP(call_llvm_intrinsic(comp_ctx,
-                                         is_f32 ? "llvm.copysign.f32" :
-                                                  "llvm.copysign.f64",
-                                         ret_type,
-                                         param_types,
-                                         2,
-                                         left,
-                                         right),
+    DEF_FP_BINARY_OP(aot_call_llvm_intrinsic(comp_ctx,
+                                             is_f32 ? "llvm.copysign.f32" :
+                                                      "llvm.copysign.f64",
+                                             ret_type,
+                                             param_types,
+                                             2,
+                                             left,
+                                             right),
                     NULL);
     return true;
 

+ 12 - 4
core/iwasm/compilation/aot_emit_parametric.c

@@ -45,10 +45,18 @@ pop_value_from_wasm_stack(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     wasm_runtime_free(aot_value);
 
-    if ((is_32
-         && (type != VALUE_TYPE_I32 && type != VALUE_TYPE_F32))
-        || (!is_32
-            && (type != VALUE_TYPE_I64 && type != VALUE_TYPE_F64))) {
+    /* is_32: i32, f32, ref.func, ref.extern, v128 */
+    if (is_32
+        && !(type == VALUE_TYPE_I32 || type == VALUE_TYPE_F32
+             || type == VALUE_TYPE_FUNCREF || type == VALUE_TYPE_EXTERNREF
+             || type == VALUE_TYPE_V128)) {
+        aot_set_last_error("invalid WASM stack data type.");
+        return false;
+    }
+
+    /* !is_32: i64, f64 */
+    if (!is_32
+        && !(type == VALUE_TYPE_I64 || type == VALUE_TYPE_F64)) {
         aot_set_last_error("invalid WASM stack data type.");
         return false;
     }

+ 487 - 0
core/iwasm/compilation/aot_emit_table.c

@@ -0,0 +1,487 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include "aot_emit_table.h"
+#include "aot_emit_exception.h"
+#include "../aot/aot_runtime.h"
+
+
+uint64
+get_tbl_inst_offset(const AOTCompContext *comp_ctx,
+                    const AOTFuncContext *func_ctx,
+                    uint32 tbl_idx)
+{
+    uint64 offset = 0, i = 0;
+    AOTImportTable *imp_tbls = comp_ctx->comp_data->import_tables;
+    AOTTable *tbls = comp_ctx->comp_data->tables;
+
+    /* from the head of AOTModuleInstance */
+    offset =
+      offsetof(AOTModuleInstance, global_table_data.bytes)
+      + (uint64)comp_ctx->comp_data->memory_count * sizeof(AOTMemoryInstance)
+      + comp_ctx->comp_data->global_data_size;
+
+    while (i < tbl_idx && i < comp_ctx->comp_data->import_table_count) {
+        offset += offsetof(AOTTableInstance, data);
+        offset += sizeof(uint32) * aot_get_imp_tbl_data_slots(imp_tbls + i);
+        ++i;
+    }
+
+    if (i == tbl_idx) {
+        return offset;
+    }
+
+    tbl_idx -= comp_ctx->comp_data->import_table_count;
+    i -= comp_ctx->comp_data->import_table_count;
+    while (i < tbl_idx && i < comp_ctx->comp_data->table_count) {
+        offset += offsetof(AOTTableInstance, data);
+        offset += sizeof(uint32) * aot_get_tbl_data_slots(tbls + i);
+        ++i;
+    }
+
+    return offset;
+}
+
+#if WASM_ENABLE_REF_TYPES != 0
+
+LLVMValueRef
+aot_compile_get_tbl_inst(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx)
+{
+    LLVMValueRef offset, tbl_inst;
+
+    if (!(offset =
+            I64_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(tbl_inst = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                  &offset, 1, "tbl_inst"))) {
+        HANDLE_FAILURE("LLVMBuildGEP");
+        goto fail;
+    }
+
+    return tbl_inst;
+fail:
+    return NULL;
+}
+
+bool
+aot_compile_op_elem_drop(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_seg_idx)
+{
+    LLVMTypeRef param_types[2], ret_type, func_type, func_ptr_type;
+    LLVMValueRef param_values[2], ret_value, func, value;
+
+    /* void aot_drop_table_seg(AOTModuleInstance *, uint32 ) */
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    ret_type = VOID_TYPE;
+
+    GET_AOT_FUNCTION(aot_drop_table_seg, 2);
+
+    param_values[0] = func_ctx->aot_inst;
+    if (!(param_values[1] = I32_CONST(tbl_seg_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /* "" means return void */
+    if (!(ret_value =
+            LLVMBuildCall(comp_ctx->builder, func, param_values, 2, ""))) {
+        HANDLE_FAILURE("LLVMBuildCall");
+        goto fail;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+static bool
+aot_check_table_access(AOTCompContext *comp_ctx,
+                       AOTFuncContext *func_ctx,
+                       uint32 tbl_idx,
+                       LLVMValueRef elem_idx)
+{
+    LLVMValueRef offset, tbl_sz, cmp_elem_idx;
+    LLVMBasicBlockRef check_elem_idx_succ;
+
+    /* get the cur size of the table instance */
+    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+                             + offsetof(AOTTableInstance, cur_size)))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
+                                1, "cur_size_i8p"))) {
+        HANDLE_FAILURE("LLVMBuildGEP");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
+                                    "cur_siuze_i32p"))) {
+        HANDLE_FAILURE("LLVMBuildBitCast");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "cur_size"))) {
+        HANDLE_FAILURE("LLVMBuildLoad");
+        goto fail;
+    }
+
+    /* Check if (uint32)elem index >= table size */
+    if (!(cmp_elem_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGE, elem_idx,
+                                       tbl_sz, "cmp_elem_idx"))) {
+        aot_set_last_error("llvm build icmp failed.");
+        goto fail;
+    }
+
+    /* Throw exception if elem index >= table size */
+    if (!(check_elem_idx_succ = LLVMAppendBasicBlockInContext(
+            comp_ctx->context, func_ctx->func, "check_elem_idx_succ"))) {
+        aot_set_last_error("llvm add basic block failed.");
+        goto fail;
+    }
+
+    LLVMMoveBasicBlockAfter(check_elem_idx_succ,
+                            LLVMGetInsertBlock(comp_ctx->builder));
+
+    if (!(aot_emit_exception(comp_ctx, func_ctx,
+                             EXCE_OUT_OF_BOUNDS_TABLE_ACCESS, true,
+                             cmp_elem_idx, check_elem_idx_succ)))
+        goto fail;
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_get(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx)
+{
+    LLVMValueRef elem_idx, offset, table_elem, func_idx;
+
+    POP_I32(elem_idx);
+
+    if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
+        goto fail;
+    }
+
+    /* load data as i32* */
+    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+                             + offsetof(AOTTableInstance, data)))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                    &offset, 1, "table_elem_i8p"))) {
+        aot_set_last_error("llvm build add failed.");
+        goto fail;
+    }
+
+    if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
+                                        INT32_PTR_TYPE, "table_elem_i32p"))) {
+        HANDLE_FAILURE("LLVMBuildBitCast");
+        goto fail;
+    }
+
+    /* Load function index */
+    if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
+                                    1, "table_elem"))) {
+        HANDLE_FAILURE("LLVMBuildNUWAdd");
+        goto fail;
+    }
+
+    if (!(func_idx =
+            LLVMBuildLoad(comp_ctx->builder, table_elem, "func_idx"))) {
+        HANDLE_FAILURE("LLVMBuildLoad");
+        goto fail;
+    }
+
+    PUSH_I32(func_idx);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_set(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx)
+{
+    LLVMValueRef val, elem_idx, offset, table_elem;
+
+    POP_I32(val);
+    POP_I32(elem_idx);
+
+    if (!aot_check_table_access(comp_ctx, func_ctx, tbl_idx, elem_idx)) {
+        goto fail;
+    }
+
+    /* load data as i32* */
+    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+                             + offsetof(AOTTableInstance, data)))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst,
+                                    &offset, 1, "table_elem_i8p"))) {
+        HANDLE_FAILURE("LLVMBuildGEP");
+        goto fail;
+    }
+
+    if (!(table_elem = LLVMBuildBitCast(comp_ctx->builder, table_elem,
+                                        INT32_PTR_TYPE, "table_elem_i32p"))) {
+        HANDLE_FAILURE("LLVMBuildBitCast");
+        goto fail;
+    }
+
+    /* Load function index */
+    if (!(table_elem = LLVMBuildGEP(comp_ctx->builder, table_elem, &elem_idx,
+                                    1, "table_elem"))) {
+        HANDLE_FAILURE("LLVMBuildGEP");
+        goto fail;
+    }
+
+    if (!(LLVMBuildStore(comp_ctx->builder, val, table_elem))) {
+        HANDLE_FAILURE("LLVMBuildStore");
+        goto fail;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_init(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx,
+                          uint32 tbl_seg_idx)
+
+{
+    LLVMValueRef func, param_values[6], value;
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    param_types[4] = I32_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = VOID_TYPE;
+
+    GET_AOT_FUNCTION(aot_table_init, 6);
+
+    param_values[0] = func_ctx->aot_inst;
+
+    if (!(param_values[1] = I32_CONST(tbl_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(param_values[2] = I32_CONST(tbl_seg_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /* n */
+    POP_I32(param_values[3]);
+    /* s */
+    POP_I32(param_values[4]);
+    /* d */
+    POP_I32(param_values[5]);
+
+    /* "" means return void */
+    if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
+        HANDLE_FAILURE("LLVMBuildCall");
+        goto fail;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_copy(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 src_tbl_idx,
+                          uint32 dst_tbl_idx)
+{
+    LLVMTypeRef param_types[6], ret_type, func_type, func_ptr_type;
+    LLVMValueRef func, param_values[6], value;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    param_types[4] = I32_TYPE;
+    param_types[5] = I32_TYPE;
+    ret_type = VOID_TYPE;
+
+    GET_AOT_FUNCTION(aot_table_copy, 6);
+
+    param_values[0] = func_ctx->aot_inst;
+
+    if (!(param_values[1] = I32_CONST(src_tbl_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(param_values[2] = I32_CONST(dst_tbl_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /* n */
+    POP_I32(param_values[3]);
+    /* s */
+    POP_I32(param_values[4]);
+    /* d */
+    POP_I32(param_values[5]);
+
+    /* "" means return void */
+    if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 6, ""))) {
+        HANDLE_FAILURE("LLVMBuildCall");
+        goto fail;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_size(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx)
+{
+    LLVMValueRef offset, tbl_sz;
+
+    if (!(offset = I32_CONST(get_tbl_inst_offset(comp_ctx, func_ctx, tbl_idx)
+                             + offsetof(AOTTableInstance, cur_size)))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildGEP(comp_ctx->builder, func_ctx->aot_inst, &offset,
+                                1, "tbl_sz_ptr_i8"))) {
+        HANDLE_FAILURE("LLVMBuildGEP");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildBitCast(comp_ctx->builder, tbl_sz, INT32_PTR_TYPE,
+                                    "tbl_sz_ptr"))) {
+        HANDLE_FAILURE("LLVMBuildBitCast");
+        goto fail;
+    }
+
+    if (!(tbl_sz = LLVMBuildLoad(comp_ctx->builder, tbl_sz, "tbl_sz"))) {
+        HANDLE_FAILURE("LLVMBuildLoad");
+        goto fail;
+    }
+
+    PUSH_I32(tbl_sz);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_grow(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx)
+{
+    LLVMTypeRef param_types[4], ret_type, func_type, func_ptr_type;
+    LLVMValueRef func, param_values[4], ret, value;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    ret_type = I32_TYPE;
+
+    GET_AOT_FUNCTION(aot_table_grow, 4);
+
+    param_values[0] = func_ctx->aot_inst;
+
+    if (!(param_values[1] = I32_CONST(tbl_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /* n */
+    POP_I32(param_values[2]);
+    /* v */
+    POP_I32(param_values[3]);
+
+    if (!(ret = LLVMBuildCall(comp_ctx->builder, func, param_values, 4,
+                              "table_grow"))) {
+        HANDLE_FAILURE("LLVMBuildCall");
+        goto fail;
+    }
+
+    PUSH_I32(ret);
+
+    return true;
+fail:
+    return false;
+}
+
+bool
+aot_compile_op_table_fill(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx)
+{
+    LLVMTypeRef param_types[5], ret_type, func_type, func_ptr_type;
+    LLVMValueRef func, param_values[5], value;
+
+    param_types[0] = INT8_PTR_TYPE;
+    param_types[1] = I32_TYPE;
+    param_types[2] = I32_TYPE;
+    param_types[3] = I32_TYPE;
+    param_types[4] = I32_TYPE;
+    ret_type = VOID_TYPE;
+
+    GET_AOT_FUNCTION(aot_table_fill, 5);
+
+    param_values[0] = func_ctx->aot_inst;
+
+    if (!(param_values[1] = I32_CONST(tbl_idx))) {
+        HANDLE_FAILURE("LLVMConstInt");
+        goto fail;
+    }
+
+    /* n */
+    POP_I32(param_values[2]);
+    /* v */
+    POP_I32(param_values[3]);
+    /* i */
+    POP_I32(param_values[4]);
+
+    /* "" means return void */
+    if (!(LLVMBuildCall(comp_ctx->builder, func, param_values, 5, ""))) {
+        HANDLE_FAILURE("LLVMBuildCall");
+        goto fail;
+    }
+
+    return true;
+fail:
+    return false;
+}
+
+#endif /*  WASM_ENABLE_REF_TYPES != 0 */

+ 71 - 0
core/iwasm/compilation/aot_emit_table.h

@@ -0,0 +1,71 @@
+
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#ifndef _AOT_EMIT_TABLE_H_
+#define _AOT_EMIT_TABLE_H_
+
+#include "aot_compiler.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool
+aot_compile_op_elem_drop(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_seg_idx);
+
+bool
+aot_compile_op_table_get(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx);
+
+bool
+aot_compile_op_table_set(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx);
+
+bool
+aot_compile_op_table_init(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx,
+                          uint32 tbl_seg_idx);
+
+bool
+aot_compile_op_table_copy(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 src_tbl_idx,
+                          uint32 dst_tbl_idx);
+
+bool
+aot_compile_op_table_size(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx);
+
+bool
+aot_compile_op_table_grow(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx);
+
+bool
+aot_compile_op_table_fill(AOTCompContext *comp_ctx,
+                          AOTFuncContext *func_ctx,
+                          uint32 tbl_idx);
+
+uint64
+get_tbl_inst_offset(const AOTCompContext *comp_ctx,
+                    const AOTFuncContext *func_ctx,
+                    uint32 tbl_idx);
+
+LLVMValueRef
+aot_compile_get_tbl_inst(AOTCompContext *comp_ctx,
+                         AOTFuncContext *func_ctx,
+                         uint32 tbl_idx);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+#endif

+ 83 - 9
core/iwasm/compilation/aot_emit_variable.c

@@ -4,6 +4,7 @@
  */
 
 #include "aot_emit_variable.h"
+#include "aot_emit_exception.h"
 #include "../aot/aot_runtime.h"
 
 #define CHECK_LOCAL(idx) do {                               \
@@ -30,6 +31,7 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 {
     char name[32];
     LLVMValueRef value;
+    AOTValue *aot_value;
 
     CHECK_LOCAL(local_idx);
 
@@ -42,6 +44,10 @@ aot_compile_op_get_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     PUSH(value, get_local_type(func_ctx, local_idx));
+
+    aot_value = func_ctx->block_stack.block_list_end->value_stack.value_list_end;
+    aot_value->is_local = true;
+    aot_value->local_idx = local_idx;
     return true;
 
 fail:
@@ -65,6 +71,7 @@ aot_compile_op_set_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         return false;
     }
 
+    aot_checked_addr_list_del(func_ctx, local_idx);
     return true;
 
 fail:
@@ -92,6 +99,7 @@ aot_compile_op_tee_local(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
     }
 
     PUSH(value, type);
+    aot_checked_addr_list_del(func_ctx, local_idx);
     return true;
 
 fail:
@@ -100,15 +108,16 @@ fail:
 
 static bool
 compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-               uint32 global_idx, bool is_set)
+               uint32 global_idx, bool is_set, bool is_aux_stack)
 {
     AOTCompData *comp_data = comp_ctx->comp_data;
     uint32 import_global_count = comp_data->import_global_count;
-    uint32 global_base_offset = offsetof(AOTModuleInstance,
-                                         global_table_data.bytes);
+    uint32 global_base_offset =
+        offsetof(AOTModuleInstance, global_table_data.bytes)
+        + sizeof(AOTMemoryInstance) * comp_ctx->comp_data->memory_count;
     uint32 global_offset;
     uint8 global_type;
-    LLVMValueRef offset, global_ptr, global;
+    LLVMValueRef offset, global_ptr, global, res;
     LLVMTypeRef ptr_type = NULL;
 
     bh_assert(global_idx < import_global_count + comp_data->global_count);
@@ -134,6 +143,8 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
     switch (global_type) {
         case VALUE_TYPE_I32:
+        case VALUE_TYPE_EXTERNREF:
+        case VALUE_TYPE_FUNCREF:
             ptr_type = comp_ctx->basic_types.int32_ptr_type;
             break;
         case VALUE_TYPE_I64:
@@ -145,8 +156,11 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
         case VALUE_TYPE_F64:
             ptr_type = comp_ctx->basic_types.float64_ptr_type;
             break;
+        case VALUE_TYPE_V128:
+            ptr_type = comp_ctx->basic_types.v128_ptr_type;
+            break;
         default:
-            bh_assert(0);
+            bh_assert("unknown type");
             break;
     }
 
@@ -162,14 +176,74 @@ compile_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
             aot_set_last_error("llvm build load failed.");
             return false;
         }
+        /* All globals' data is 4-byte aligned */
+        LLVMSetAlignment(global, 4);
         PUSH(global, global_type);
     }
     else {
         POP(global, global_type);
-        if (!LLVMBuildStore(comp_ctx->builder, global, global_ptr)) {
+
+        if (is_aux_stack && comp_ctx->enable_aux_stack_check) {
+            LLVMBasicBlockRef block_curr = LLVMGetInsertBlock(comp_ctx->builder);
+            LLVMBasicBlockRef check_overflow_succ, check_underflow_succ;
+            LLVMValueRef cmp;
+
+            /* Add basic blocks */
+            if (!(check_overflow_succ =
+                        LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                      func_ctx->func,
+                                                      "check_overflow_succ"))) {
+                aot_set_last_error("llvm add basic block failed.");
+                return false;
+            }
+            LLVMMoveBasicBlockAfter(check_overflow_succ, block_curr);
+
+            if (!(check_underflow_succ =
+                        LLVMAppendBasicBlockInContext(comp_ctx->context,
+                                                      func_ctx->func,
+                                                      "check_underflow_succ"))) {
+                aot_set_last_error("llvm add basic block failed.");
+                return false;
+            }
+            LLVMMoveBasicBlockAfter(check_underflow_succ, check_overflow_succ);
+
+            /* Check aux stack overflow */
+            if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntULE,
+                                      global, func_ctx->aux_stack_bound,
+                                      "cmp"))) {
+                aot_set_last_error("llvm build icmp failed.");
+                return false;
+            }
+            if (!aot_emit_exception(comp_ctx, func_ctx,
+                                    EXCE_AUX_STACK_OVERFLOW,
+                                    true, cmp, check_overflow_succ)) {
+                return false;
+            }
+
+            /* Check aux stack underflow */
+            LLVMPositionBuilderAtEnd(comp_ctx->builder, check_overflow_succ);
+            if (!(cmp = LLVMBuildICmp(comp_ctx->builder, LLVMIntUGT,
+                                      global, func_ctx->aux_stack_bottom,
+                                      "cmp"))) {
+                aot_set_last_error("llvm build icmp failed.");
+                return false;
+            }
+            if (!aot_emit_exception(comp_ctx, func_ctx,
+                                    EXCE_AUX_STACK_UNDERFLOW,
+                                    true, cmp, check_underflow_succ)) {
+                return false;
+            }
+
+            LLVMPositionBuilderAtEnd(comp_ctx->builder, check_underflow_succ);
+        }
+
+        if (!(res = LLVMBuildStore(comp_ctx->builder,
+                                   global, global_ptr))) {
             aot_set_last_error("llvm build store failed.");
             return false;
         }
+        /* All globals' data is 4-byte aligned */
+        LLVMSetAlignment(res, 4);
     }
 
     return true;
@@ -181,13 +255,13 @@ bool
 aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
                           uint32 global_idx)
 {
-    return compile_global(comp_ctx, func_ctx, global_idx, false);
+    return compile_global(comp_ctx, func_ctx, global_idx, false, false);
 }
 
 bool
 aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                          uint32 global_idx)
+                          uint32 global_idx, bool is_aux_stack)
 {
-    return compile_global(comp_ctx, func_ctx, global_idx, true);
+    return compile_global(comp_ctx, func_ctx, global_idx, true, is_aux_stack);
 }
 

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

@@ -30,7 +30,7 @@ aot_compile_op_get_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
 
 bool
 aot_compile_op_set_global(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
-                          uint32 global_idx);
+                          uint32 global_idx, bool is_aux_stack);
 
 #ifdef __cplusplus
 } /* end of extern "C" */

File diff suppressed because it is too large
+ 506 - 187
core/iwasm/compilation/aot_llvm.c


+ 137 - 17
core/iwasm/compilation/aot_llvm.h

@@ -7,13 +7,16 @@
 #define _AOT_LLVM_H_
 
 #include "aot.h"
+#include "llvm/Config/llvm-config.h"
 #include "llvm-c/Types.h"
 #include "llvm-c/Target.h"
 #include "llvm-c/Core.h"
 #include "llvm-c/Object.h"
 #include "llvm-c/ExecutionEngine.h"
 #include "llvm-c/Analysis.h"
+#include "llvm-c/Transforms/Utils.h"
 #include "llvm-c/Transforms/Scalar.h"
+#include "llvm-c/Transforms/Vectorize.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -30,6 +33,8 @@ typedef struct AOTValue {
   LLVMValueRef value;
   /* VALUE_TYPE_I32/I64/F32/F64/VOID */
   uint8 type;
+  bool is_local;
+  uint32 local_idx;
 } AOTValue;
 
 /**
@@ -46,10 +51,8 @@ typedef struct AOTBlock {
 
   /* Block index */
   uint32 block_index;
-  /* BLOCK_TYPE_BLOCK/LOOP/IF/FUNCTION */
-  uint32 block_type;
-  /* VALUE_TYPE_I32/I64/F32/F64/VOID */
-  uint8 return_type;
+  /* LABEL_TYPE_BLOCK/LOOP/IF/FUNCTION */
+  uint32 label_type;
   /* Whether it is reachable */
   bool is_reachable;
   /* Whether skip translation of wasm else branch */
@@ -70,8 +73,16 @@ typedef struct AOTBlock {
   /* WASM operation stack */
   AOTValueStack value_stack;
 
-  /* Return value of this block, a PHI node */
-  LLVMValueRef return_value_phi;
+  /* Param count/types/PHIs of this block */
+  uint32 param_count;
+  uint8 *param_types;
+  LLVMValueRef *param_phis;
+  LLVMValueRef *else_param_phis;
+
+  /* Result count/types/PHIs of this block */
+  uint32 result_count;
+  uint8 *result_types;
+  LLVMValueRef *result_phis;
 } AOTBlock;
 
 /**
@@ -84,6 +95,24 @@ typedef struct AOTBlockStack {
   uint32 block_index[3];
 } AOTBlockStack;
 
+typedef struct AOTCheckedAddr {
+  struct AOTCheckedAddr *next;
+  uint32 local_idx;
+  uint32 offset;
+  uint32 bytes;
+} AOTCheckedAddr, *AOTCheckedAddrList;
+
+typedef struct AOTMemInfo {
+  LLVMValueRef mem_base_addr;
+  LLVMValueRef mem_data_size_addr;
+  LLVMValueRef mem_cur_page_count_addr;
+  LLVMValueRef mem_bound_check_1byte;
+  LLVMValueRef mem_bound_check_2bytes;
+  LLVMValueRef mem_bound_check_4bytes;
+  LLVMValueRef mem_bound_check_8bytes;
+  LLVMValueRef mem_bound_check_16bytes;
+} AOTMemInfo;
+
 typedef struct AOTFuncContext {
   AOTFunc *aot_func;
   LLVMValueRef func;
@@ -91,26 +120,23 @@ typedef struct AOTFuncContext {
 
   LLVMValueRef exec_env;
   LLVMValueRef aot_inst;
-  LLVMValueRef table_base;
   LLVMValueRef argv_buf;
+  LLVMValueRef native_stack_bound;
+  LLVMValueRef aux_stack_bound;
+  LLVMValueRef aux_stack_bottom;
+  LLVMValueRef last_alloca;
+  LLVMValueRef func_ptrs;
 
-  LLVMValueRef heap_base_offset;
-  LLVMValueRef mem_base_addr;
-  LLVMValueRef total_mem_size;
-  LLVMValueRef mem_bound_check_1byte;
-  LLVMValueRef mem_bound_check_2bytes;
-  LLVMValueRef mem_bound_check_4bytes;
-  LLVMValueRef mem_bound_check_8bytes;
+  AOTMemInfo *mem_info;
 
   LLVMValueRef cur_exception;
 
   bool mem_space_unchanged;
+  AOTCheckedAddrList checked_addr_list;
 
-  LLVMBasicBlockRef *exception_blocks;
   LLVMBasicBlockRef got_exception_block;
   LLVMBasicBlockRef func_return_block;
   LLVMValueRef exception_id_phi;
-  LLVMValueRef func_ptrs;
   LLVMValueRef func_type_indexes;
   LLVMValueRef locals[1];
 } AOTFuncContext;
@@ -126,14 +152,26 @@ typedef struct AOTLLVMTypes {
   LLVMTypeRef void_type;
 
   LLVMTypeRef int8_ptr_type;
+  LLVMTypeRef int8_pptr_type;
   LLVMTypeRef int16_ptr_type;
   LLVMTypeRef int32_ptr_type;
   LLVMTypeRef int64_ptr_type;
   LLVMTypeRef float32_ptr_type;
   LLVMTypeRef float64_ptr_type;
-  LLVMTypeRef void_ptr_type;
+
+  LLVMTypeRef v128_type;
+  LLVMTypeRef v128_ptr_type;
+  LLVMTypeRef i8x16_vec_type;
+  LLVMTypeRef i16x8_vec_type;
+  LLVMTypeRef i32x4_vec_type;
+  LLVMTypeRef i64x2_vec_type;
+  LLVMTypeRef f32x4_vec_type;
+  LLVMTypeRef f64x2_vec_type;
 
   LLVMTypeRef meta_data_type;
+
+  LLVMTypeRef funcref_type;
+  LLVMTypeRef externref_type;
 } AOTLLVMTypes;
 
 typedef struct AOTLLVMConsts {
@@ -142,10 +180,20 @@ typedef struct AOTLLVMConsts {
     LLVMValueRef i64_zero;
     LLVMValueRef f32_zero;
     LLVMValueRef f64_zero;
+    LLVMValueRef v128_zero;
+    LLVMValueRef i8x16_vec_zero;
+    LLVMValueRef i16x8_vec_zero;
+    LLVMValueRef i32x4_vec_zero;
+    LLVMValueRef i64x2_vec_zero;
+    LLVMValueRef f32x4_vec_zero;
+    LLVMValueRef f64x2_vec_zero;
     LLVMValueRef i32_one;
     LLVMValueRef i32_two;
     LLVMValueRef i32_three;
     LLVMValueRef i32_four;
+    LLVMValueRef i32_five;
+    LLVMValueRef i32_six;
+    LLVMValueRef i32_seven;
     LLVMValueRef i32_eight;
     LLVMValueRef i32_neg_one;
     LLVMValueRef i64_neg_one;
@@ -155,6 +203,7 @@ typedef struct AOTLLVMConsts {
     LLVMValueRef i32_32;
     LLVMValueRef i64_63;
     LLVMValueRef i64_64;
+    LLVMValueRef ref_null;
 } AOTLLVMConsts;
 
 /**
@@ -170,11 +219,36 @@ typedef struct AOTCompContext {
   LLVMTargetMachineRef target_machine;
   char *target_cpu;
   char target_arch[16];
+  unsigned pointer_size;
 
   /* LLVM execution engine required by JIT */
   LLVMExecutionEngineRef exec_engine;
   bool is_jit_mode;
 
+  /* Bulk memory feature */
+  bool enable_bulk_memory;
+
+  /* Bounday Check */
+  bool enable_bound_check;
+
+  /* 128-bit SIMD */
+  bool enable_simd;
+
+  /* Auxiliary stack overflow/underflow check */
+  bool enable_aux_stack_check;
+
+  /* Generate auxiliary stack frame */
+  bool enable_aux_stack_frame;
+
+  /* Thread Manager */
+  bool enable_thread_mgr;
+
+  /* Tail Call */
+  bool enable_tail_call;
+
+  /* Reference Types */
+  bool enable_ref_types;
+
   /* Whether optimize the JITed code */
   bool optimize;
 
@@ -213,9 +287,18 @@ typedef struct AOTCompOption{
     char *target_abi;
     char *target_cpu;
     char *cpu_features;
+    bool enable_bulk_memory;
+    bool enable_thread_mgr;
+    bool enable_tail_call;
+    bool enable_simd;
+    bool enable_ref_types;
+    bool enable_aux_stack_check;
+    bool enable_aux_stack_frame;
+    bool is_sgx_platform;
     uint32 opt_level;
     uint32 size_level;
     uint32 output_format;
+    uint32 bounds_checks;
 } AOTCompOption, *aot_comp_option_t;
 
 AOTCompContext *
@@ -258,6 +341,43 @@ aot_block_destroy(AOTBlock *block);
 LLVMTypeRef
 wasm_type_to_llvm_type(AOTLLVMTypes *llvm_types, uint8 wasm_type);
 
+bool
+aot_checked_addr_list_add(AOTFuncContext *func_ctx,
+                          uint32 local_idx, uint32 offset, uint32 bytes);
+
+void
+aot_checked_addr_list_del(AOTFuncContext *func_ctx, uint32 local_idx);
+
+bool
+aot_checked_addr_list_find(AOTFuncContext *func_ctx,
+                           uint32 local_idx, uint32 offset, uint32 bytes);
+
+void
+aot_checked_addr_list_destroy(AOTFuncContext *func_ctx);
+
+bool
+aot_build_zero_function_ret(AOTCompContext *comp_ctx,
+                            AOTFuncType *func_type);
+
+LLVMValueRef
+aot_call_llvm_intrinsic(const AOTCompContext *comp_ctx,
+                        const char *name,
+                        LLVMTypeRef ret_type,
+                        LLVMTypeRef *param_types,
+                        int param_count,
+                        ...);
+
+LLVMValueRef
+aot_call_llvm_intrinsic_v(const AOTCompContext *comp_ctx,
+                          const char *name,
+                          LLVMTypeRef ret_type,
+                          LLVMTypeRef *param_types,
+                          int param_count,
+                          va_list param_value_list);
+
+bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
+
 #ifdef __cplusplus
 } /* end of extern "C" */
 #endif

+ 148 - 0
core/iwasm/compilation/aot_llvm_extra.cpp

@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ */
+
+#include <llvm/ADT/SmallVector.h>
+#include <llvm/ADT/Twine.h>
+#include <llvm/ADT/Triple.h>
+#include <llvm/ExecutionEngine/ExecutionEngine.h>
+#include <llvm/MC/MCSubtargetInfo.h>
+#include <llvm/Support/TargetSelect.h>
+#include <llvm/Target/TargetMachine.h>
+#include <llvm-c/Core.h>
+#include <llvm-c/ExecutionEngine.h>
+#include <llvm/ExecutionEngine/GenericValue.h>
+#include <llvm/ExecutionEngine/JITEventListener.h>
+#include <llvm/ExecutionEngine/RTDyldMemoryManager.h>
+#include <llvm/IR/DerivedTypes.h>
+#include <llvm/IR/Module.h>
+#include <llvm/Support/ErrorHandling.h>
+#include <llvm/Target/CodeGenCWrappers.h>
+#include <llvm/Target/TargetOptions.h>
+#include <cstring>
+
+using namespace llvm;
+
+extern "C" LLVMBool
+WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
+                                 LLVMModuleRef M,
+                                 LLVMMCJITCompilerOptions *PassedOptions,
+                                 size_t SizeOfPassedOptions,
+                                 char **OutError);
+
+extern "C" bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str);
+
+LLVMBool
+WAMRCreateMCJITCompilerForModule(LLVMExecutionEngineRef *OutJIT,
+                                 LLVMModuleRef M,
+                                 LLVMMCJITCompilerOptions *PassedOptions,
+                                 size_t SizeOfPassedOptions,
+                                 char **OutError)
+{
+    LLVMMCJITCompilerOptions options;
+    // If the user passed a larger sized options struct, then they were compiled
+    // against a newer LLVM. Tell them that something is wrong.
+    if (SizeOfPassedOptions > sizeof(options)) {
+        *OutError = strdup(
+                "Refusing to use options struct that is larger than my own; assuming "
+                "LLVM library mismatch.");
+        return 1;
+    }
+
+    // Defend against the user having an old version of the API by ensuring that
+    // any fields they didn't see are cleared. We must defend against fields being
+    // set to the bitwise equivalent of zero, and assume that this means "do the
+    // default" as if that option hadn't been available.
+    LLVMInitializeMCJITCompilerOptions(&options, sizeof(options));
+    memcpy(&options, PassedOptions, SizeOfPassedOptions);
+
+    TargetOptions targetOptions;
+    targetOptions.EnableFastISel = options.EnableFastISel;
+    std::unique_ptr<Module> Mod(unwrap(M));
+
+    if (Mod) {
+        // Set function attribute "frame-pointer" based on
+        // NoFramePointerElim.
+        for (auto &F : *Mod) {
+            auto Attrs = F.getAttributes();
+            StringRef Value = options.NoFramePointerElim ? "all" : "none";
+            Attrs = Attrs.addAttribute(F.getContext(), AttributeList::FunctionIndex,
+                    "frame-pointer", Value);
+            F.setAttributes(Attrs);
+        }
+    }
+
+    std::string Error;
+    bool JIT;
+    char *host_cpu = LLVMGetHostCPUName();
+
+    if (!host_cpu) {
+        *OutError = NULL;
+        return false;
+    }
+
+    std::string mcpu(host_cpu);
+    LLVMDisposeMessage(host_cpu);
+
+    EngineBuilder builder(std::move(Mod));
+    builder.setEngineKind(EngineKind::JIT)
+           .setErrorStr(&Error)
+           .setMCPU(mcpu)
+           .setOptLevel((CodeGenOpt::Level)options.OptLevel)
+           .setTargetOptions(targetOptions);
+    if (Optional<CodeModel::Model> CM = unwrap(options.CodeModel, JIT))
+        builder.setCodeModel(*CM);
+    if (options.MCJMM)
+        builder.setMCJITMemoryManager(
+                std::unique_ptr<RTDyldMemoryManager>(unwrap(options.MCJMM)));
+    if (ExecutionEngine *JIT = builder.create()) {
+        *OutJIT = wrap(JIT);
+        return 0;
+    }
+    *OutError = strdup(Error.c_str());
+    return 1;
+}
+
+bool
+aot_check_simd_compatibility(const char *arch_c_str, const char *cpu_c_str)
+{
+#if WASM_ENABLE_SIMD != 0
+    if (!arch_c_str || !cpu_c_str) {
+        return false;
+    }
+
+    llvm::SmallVector<std::string, 1> targetAttributes;
+    llvm::Triple targetTriple(arch_c_str, "", "");
+    auto targetMachine =
+      std::unique_ptr<llvm::TargetMachine>(llvm::EngineBuilder().selectTarget(
+        targetTriple, "", std::string(cpu_c_str), targetAttributes));
+    if (!targetMachine) {
+        return false;
+    }
+
+    const llvm::Triple::ArchType targetArch =
+      targetMachine->getTargetTriple().getArch();
+    const llvm::MCSubtargetInfo *subTargetInfo =
+      targetMachine->getMCSubtargetInfo();
+    if (subTargetInfo == nullptr) {
+        return false;
+    }
+
+    if (targetArch == llvm::Triple::x86_64) {
+        return subTargetInfo->checkFeatures("+sse4.1");
+    }
+    else if (targetArch == llvm::Triple::aarch64) {
+        return subTargetInfo->checkFeatures("+neon");
+    }
+    else {
+        return false;
+    }
+#else
+    (void)arch_c_str;
+    (void)cpu_c_str;
+    return true;
+#endif /* WASM_ENABLE_SIMD */
+}
+

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