Merge branch 'bytecodealliance:main' into zephyr-socket-support

This commit is contained in:
Lucas Abad 2024-04-19 08:21:58 +02:00 committed by GitHub
commit 214345aa42
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
118 changed files with 6392 additions and 1819 deletions

35
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,35 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "docker"
directory: "/.devcontainer"
schedule:
interval: "weekly"
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/build-scripts"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/language-bindings/python/wasm-c-api"
schedule:
interval: "weekly"
- package-ecosystem: "pip"
directory: "/language-bindings/python/wamr-api"
schedule:
interval: "weekly"

View File

@ -1,5 +1,10 @@
#!/usr/bin/env bash
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
sudo apt update
sudo apt install -y build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ninja-build ccache
@ -101,6 +106,26 @@ if [[ $? != 0 ]]; then
exit 1;
fi
# build iwasm with exception handling enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_EXCE_HANDLING=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with exception handling enabled!"
exit 1;
fi
# build iwasm with memory64 enabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Debug -DWAMR_BUILD_MEMORY64=1
make -j
if [[ $? != 0 ]]; then
echo "Failed to build iwasm with memory64 enabled!"
exit 1;
fi
# build iwasm with hardware boundary check disabled
cd ${WAMR_DIR}/product-mini/platforms/linux
rm -rf build && mkdir build && cd build

124
.github/scripts/codeql_fail_on_error.py vendored Executable file
View File

@ -0,0 +1,124 @@
#!/usr/bin/env python3
#
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
import json
import sys
import os
import requests
def fetch_dismissed_alerts(repo_name, github_token):
headers = {
"Authorization": f"token {github_token}",
"Accept": "application/vnd.github.v3+json",
}
url = (
f"https://api.github.com/repos/{repo_name}/code-scanning/alerts?state=dismissed"
)
response = requests.get(url, headers=headers)
return response.json() # This assumes a successful API call
def parse_location(location):
path = location.get("physicalLocation", {}).get("artifactLocation", {}).get("uri")
start_line = location.get("physicalLocation", {}).get("region", {}).get("startLine")
column_range = (
location.get("physicalLocation", {}).get("region", {}).get("startColumn"),
location.get("physicalLocation", {}).get("region", {}).get("endColumn"),
)
return (path, start_line, column_range)
def is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
for alert in dismissed_alerts:
alert_rule_id = alert.get("rule", {}).get("id")
alert_path = alert.get("location", {}).get("path")
alert_start_line = alert.get("location", {}).get("start_line")
alert_column_range = (
alert.get("location", {}).get("start_column"),
alert.get("location", {}).get("end_column"),
)
if (
rule_id == alert_rule_id
and path == alert_path
and start_line == alert_start_line
and column_range == alert_column_range
):
return True
return False
# Return whether SARIF file contains error-level results
def codeql_sarif_contain_error(filename, dismissed_alerts):
has_error = False
with open(filename, "r") as f:
s = json.load(f)
for run in s.get("runs", []):
rules_metadata = run["tool"]["driver"]["rules"]
if not rules_metadata:
rules_metadata = run["tool"]["extensions"][0]["rules"]
for res in run.get("results", []):
if "ruleIndex" in res:
rule_index = res["ruleIndex"]
elif "rule" in res and "index" in res["rule"]:
rule_index = res["rule"]["index"]
else:
continue
# check whether it's dismissed before
rule_id = res["ruleId"]
path, start_line, column_range = parse_location(res["locations"][0])
# the source code is from dependencies
if "_deps" in path:
continue
if is_dismissed(rule_id, path, start_line, column_range, dismissed_alerts):
print(
f"====== Finding a dismissed entry: {rule_id} at {path}:{start_line} is dismissed.======"
)
print(res)
continue
try:
rule_level = rules_metadata[rule_index]["defaultConfiguration"]["level"]
except IndexError as e:
print(e, rule_index, len(rules_metadata))
else:
if rule_level == "error":
# very likely to be an actual error
if rules_metadata[rule_index]["properties"].get("precision") in [
"high",
"very-high",
]:
# the security severity is above medium(Common Vulnerability Scoring System (CVSS) >= 4.0)
if "security-severity" in rules_metadata[rule_index][
"properties"
] and (
float(
rules_metadata[rule_index]["properties"][
"security-severity"
]
)
> 4.0
):
print("====== Finding a likely error. ======")
print(res)
has_error = True
return has_error
if __name__ == "__main__":
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN")
GITHUB_REPOSITORY = os.getenv("GITHUB_REPOSITORY")
dismissed_alerts = fetch_dismissed_alerts(GITHUB_REPOSITORY, GITHUB_TOKEN)
if codeql_sarif_contain_error(sys.argv[1], dismissed_alerts):
sys.exit(1)

View File

@ -42,9 +42,12 @@ def fetch_version_from_code():
def fetch_latest_git_tag():
list_tag_cmd = (
'git tag --list WAMR-*.*.* --sort=committerdate --format="%(refname:short)"'
)
"""
Get the most recent tag from the HEAD,
if it's main branch, it should be the latest release tag.
if it's release/x.x.x branch, it should be the latest release tag of the branch.
"""
list_tag_cmd = "git describe --tags --abbrev=0 HEAD"
p = subprocess.run(shlex.split(list_tag_cmd), capture_output=True, check=True)
all_tags = p.stdout.decode().strip()

View File

@ -33,10 +33,16 @@ jobs:
- name: checkout
uses: actions/checkout@v4
- name: install dependencies
- name: install dependencies for non macos-14
if: inputs.os != 'macos-14'
run: /usr/bin/env python3 -m pip install -r requirements.txt
working-directory: build-scripts
- name: install dependencies for macos-14
if: inputs.os == 'macos-14'
run: /usr/bin/env python3 -m pip install -r requirements.txt --break-system-packages
working-directory: build-scripts
- name: retrive the last commit ID
id: get_last_commit
run: echo "last_commit=$(GH_TOKEN=${{ secrets.GITHUB_TOKEN }} /usr/bin/env python3 ./build_llvm.py --llvm-ver)" >> $GITHUB_OUTPUT

View File

@ -82,9 +82,7 @@ jobs:
- name: install utils macos
if: steps.lldb_build_cache.outputs.cache-hit != 'true' && contains(inputs.runner, 'macos')
run: |
brew remove swig
brew install swig@4.1 cmake ninja libedit
brew link --overwrite swig@4.1
brew install swig cmake ninja libedit
sudo rm -rf /Library/Developer/CommandLineTools
- name: install utils ubuntu

View File

@ -58,6 +58,12 @@ jobs:
sudo rm ${basename}
sudo mv wasi-sdk-* wasi-sdk
- name: download dependencies
run: |
cd ./wamr-app-framework/deps
./download.sh
working-directory: wamr-sdk
- name: generate wamr-sdk release
run: |
cd ./wamr-app-framework/wamr-sdk

View File

@ -21,7 +21,7 @@ jobs:
- uses: actions/checkout@v4
- name: Use Node.js 16.x
uses: actions/setup-node@v3
uses: actions/setup-node@v4
with:
node-version: 16.x

View File

@ -49,7 +49,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
@ -64,9 +64,9 @@ jobs:
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
- run: |
./.github/workflows/codeql_buildscript.sh
./.github/scripts/codeql_buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"
upload: false
@ -95,14 +95,14 @@ jobs:
output: ${{ steps.step1.outputs.sarif-output }}/cpp.sarif
- name: Upload CodeQL results to code scanning
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ${{ steps.step1.outputs.sarif-output }}
category: "/language:${{matrix.language}}"
- name: Upload CodeQL results as an artifact
if: success() || failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: codeql-results
path: ${{ steps.step1.outputs.sarif-output }}
@ -110,5 +110,8 @@ jobs:
- name: Fail if an error is found
run: |
./.github/workflows/codeql_fail_on_error.py \
./.github/scripts/codeql_fail_on_error.py \
${{ steps.step1.outputs.sarif-output }}/cpp.sarif
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPOSITORY: ${{ github.repository }}

View File

@ -1,34 +0,0 @@
#!/usr/bin/env python3
import json
import sys
# Return whether SARIF file contains error-level results
def codeql_sarif_contain_error(filename):
with open(filename, 'r') as f:
s = json.load(f)
for run in s.get('runs', []):
rules_metadata = run['tool']['driver']['rules']
if not rules_metadata:
rules_metadata = run['tool']['extensions'][0]['rules']
for res in run.get('results', []):
if 'ruleIndex' in res:
rule_index = res['ruleIndex']
elif 'rule' in res and 'index' in res['rule']:
rule_index = res['rule']['index']
else:
continue
try:
rule_level = rules_metadata[rule_index]['defaultConfiguration']['level']
except IndexError as e:
print(e, rule_index, len(rules_metadata))
else:
if rule_level == 'error':
return True
return False
if __name__ == "__main__":
if codeql_sarif_contain_error(sys.argv[1]):
sys.exit(1)

View File

@ -65,6 +65,7 @@ env:
WASI_TEST_OPTIONS: "-s wasi_certification -w"
WAMR_COMPILER_TEST_OPTIONS: "-s wamr_compiler -S -b -P"
GC_TEST_OPTIONS: "-s spec -G -b -P"
MEMORY64_TEST_OPTIONS: "-s spec -W -b -P"
jobs:
build_llvm_libraries_on_ubuntu_2204:
@ -144,6 +145,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
os: [ubuntu-22.04]
platform: [android, linux]
@ -202,6 +204,21 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform
- make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
platform: android
- make_options_run_mode: $AOT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android
@ -372,14 +389,14 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Get LLVM libraries
id: retrieve_llvm_libs
uses: actions/cache@v4
@ -503,6 +520,7 @@ jobs:
$THREADS_TEST_OPTIONS,
$WASI_TEST_OPTIONS,
$GC_TEST_OPTIONS,
$MEMORY64_TEST_OPTIONS,
]
wasi_sdk_release:
[
@ -541,19 +559,30 @@ jobs:
test_option: $GC_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $GC_TEST_OPTIONS
# aot, fast-interp, fast-jit, llvm-jit, multi-tier-jit don't support Memory64
- running_mode: "aot"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-interp"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "fast-jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "jit"
test_option: $MEMORY64_TEST_OPTIONS
- running_mode: "multi-tier-jit"
test_option: $MEMORY64_TEST_OPTIONS
steps:
- name: checkout
uses: actions/checkout@v4
- name: Set-up OCaml
uses: ocaml/setup-ocaml@v2
if: matrix.test_option == '$GC_TEST_OPTIONS'
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
with:
ocaml-compiler: 4.13
- name: Set-up Ocamlbuild
if: matrix.test_option == '$GC_TEST_OPTIONS'
run: opam install ocamlbuild dune
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: opam install ocamlbuild dune menhir
- name: download and install wasi-sdk
if: matrix.test_option == '$WASI_TEST_OPTIONS'
@ -617,13 +646,13 @@ jobs:
- name: run tests
timeout-minutes: 30
if: matrix.test_option != '$GC_TEST_OPTIONS'
if: matrix.test_option != '$GC_TEST_OPTIONS' && matrix.test_option != '$MEMORY64_TEST_OPTIONS'
run: ./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}
working-directory: ./tests/wamr-test-suites
- name: run gc tests
- name: run gc or memory64 tests
timeout-minutes: 20
if: matrix.test_option == '$GC_TEST_OPTIONS'
if: matrix.test_option == '$GC_TEST_OPTIONS' || matrix.test_option == '$MEMORY64_TEST_OPTIONS'
run: |
eval $(opam env)
./test_wamr.sh ${{ matrix.test_option }} -t ${{ matrix.running_mode }}

View File

@ -273,14 +273,14 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Build Sample [basic]
run: |

View File

@ -32,8 +32,22 @@ jobs:
- name: prepare
id: preparation
run: |
# show latest 3 versions
git tag --list WAMR-*.*.* --sort=committerdate --format="%(refname:short)" | tail -n 3
# show latest 3 versions on the branch that create release
# Set the initial commit to the head of the branch
commit="HEAD"
#
# Loop to get the three most recent tags
for i in {1..3}
do
# Get the most recent tag reachable from the current commit
tag=$(git describe --tags --abbrev=0 $commit)
# Print the tag
echo "$tag"
# Move to the commit before the found tag to find the next tag in the next iteration
commit=$(git rev-list -n 1 $tag^)
done
# compare latest git tag and semantic version definition
result=$(python3 ./.github/scripts/fetch_and_compare_version.py)
echo "script result is ${result}"

View File

@ -130,6 +130,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
os: [ubuntu-20.04]
platform: [android, linux]
@ -188,6 +189,21 @@ jobs:
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 only on CLASSIC INTERP mode, and only on 64-bit platform
- make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
platform: android
- make_options_run_mode: $AOT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_LAZY_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $LLVM_EAGER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $MULTI_TIER_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
# Fast-JIT and Multi-Tier-JIT mode don't support android
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
platform: android
@ -271,6 +287,7 @@ jobs:
"-DWAMR_BUILD_SIMD=1",
"-DWAMR_BUILD_TAIL_CALL=1",
"-DWAMR_DISABLE_HW_BOUND_CHECK=1",
"-DWAMR_BUILD_MEMORY64=1",
]
exclude:
# uncompatiable feature and platform
@ -299,6 +316,11 @@ jobs:
# MINI_LOADER only on INTERP mode
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MINI_LOADER=1"
# Memory64 only on CLASSIC INTERP mode
- make_options_run_mode: $FAST_INTERP_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
- make_options_run_mode: $FAST_JIT_BUILD_OPTIONS
make_options_feature: "-DWAMR_BUILD_MEMORY64=1"
steps:
- name: checkout
uses: actions/checkout@v3
@ -437,13 +459,13 @@ jobs:
cd /opt
sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz
sudo mv wasi-sdk-20.0 wasi-sdk
sudo ln -sf wasi-sdk-20.0 wasi-sdk
- name: download and install wabt
run: |
cd /opt
sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz
sudo mv wabt-1.0.31 wabt
sudo ln -sf wabt-1.0.31 wabt
- name: Get LLVM libraries
id: retrieve_llvm_libs

View File

@ -3,6 +3,11 @@
cmake_minimum_required (VERSION 3.0)
if(ESP_PLATFORM)
include (${COMPONENT_DIR}/build-scripts/esp-idf/wamr/CMakeLists.txt)
return()
endif()
project (iwasm)
set (CMAKE_VERBOSE_MAKEFILE OFF)

View File

@ -41,9 +41,8 @@ WebAssembly Micro Runtime (WAMR) is a lightweight standalone WebAssembly (Wasm)
- [wasm-c-api](https://github.com/WebAssembly/wasm-c-api), ref to [document](doc/wasm_c_api.md) and [sample](samples/wasm-c-api)
- [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)
- [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)
- [Multi-value](https://github.com/WebAssembly/multi-value), [Tail-call](https://github.com/WebAssembly/tail-call), [Shared memory](https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md#shared-linear-memory)
- [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), [Memory64](https://github.com/WebAssembly/memory64)
- [Tail-call](https://github.com/WebAssembly/tail-call), [Garbage Collection](https://github.com/WebAssembly/gc), [Exception Handling](https://github.com/WebAssembly/exception-handling)
### Supported architectures and platforms
The WAMR VMcore supports the following architectures:
@ -68,6 +67,7 @@ The following platforms are supported, click each link below for how to build iw
- [Port WAMR to a new platform](./doc/port_wamr.md)
- [VS Code development container](./doc/devcontainer.md)
- [Samples](./samples) and [Benchmarks](./tests/benchmarks)
- [End-user APIs documentation](https://bytecodealliance.github.io/wamr.dev/apis/)

View File

@ -134,7 +134,9 @@ endif ()
# Sanitizers
set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER})
if (NOT DEFINED WAMR_BUILD_SANITIZER)
set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER})
endif ()
if (NOT DEFINED WAMR_BUILD_SANITIZER)
set(WAMR_BUILD_SANITIZER "")
@ -248,6 +250,15 @@ if (WAMR_BUILD_SHARED_MEMORY EQUAL 1)
else ()
add_definitions (-DWASM_ENABLE_SHARED_MEMORY=0)
endif ()
if (WAMR_BUILD_MEMORY64 EQUAL 1)
# if native is 32-bit or cross-compiled to 32-bit
if (NOT WAMR_BUILD_TARGET MATCHES ".*64.*")
message (FATAL_ERROR "-- Memory64 is only available on the 64-bit platform/target")
endif()
add_definitions (-DWASM_ENABLE_MEMORY64=1)
set (WAMR_DISABLE_HW_BOUND_CHECK 1)
message (" Memory64 memory enabled")
endif ()
if (WAMR_BUILD_THREAD_MGR EQUAL 1)
message (" Thread manager enabled")
endif ()
@ -529,3 +540,25 @@ else ()
# Disable quick aot/jit entries for interp and fast-jit
add_definitions (-DWASM_ENABLE_QUICK_AOT_ENTRY=0)
endif ()
if (WAMR_BUILD_AOT EQUAL 1)
if (NOT DEFINED WAMR_BUILD_AOT_INTRINSICS)
# Enable aot intrinsics by default
set (WAMR_BUILD_AOT_INTRINSICS 1)
endif ()
if (WAMR_BUILD_AOT_INTRINSICS EQUAL 1)
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=1)
message (" AOT intrinsics enabled")
else ()
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
message (" AOT intrinsics disabled")
endif ()
else ()
# Disable aot intrinsics for interp, fast-jit and llvm-jit
add_definitions (-DWASM_ENABLE_AOT_INTRINSICS=0)
endif ()
if (WAMR_BUILD_ALLOC_WITH_USAGE EQUAL 1)
add_definitions(-DWASM_MEM_ALLOC_WITH_USAGE=1)
endif()
if (NOT WAMR_BUILD_SANITIZER STREQUAL "")
message (" Sanitizer ${WAMR_BUILD_SANITIZER} enabled")
endif ()

View File

@ -415,7 +415,7 @@
#else
#define DEFAULT_WASM_STACK_SIZE (12 * 1024)
#endif
/* Min auxilliary stack size of each wasm thread */
/* Min auxiliary stack size of each wasm thread */
#define WASM_THREAD_AUX_STACK_SIZE_MIN (256)
/* Default/min native stack size of each app thread */
@ -445,7 +445,29 @@
#endif
/* Reserved bytes to the native thread stack boundary, throw native
stack overflow exception if the guard boudary is reached */
* stack overflow exception if the guard boudary is reached
*
* WASM_STACK_GUARD_SIZE needs to be large enough for:
*
* - native functions
* w/o hw bound check, the overhead (aot_call_function etc) + the native
* function itself. as of writing this, the former is about 1000 bytes
* on macOS amd64.
* with hw bound check, theoretically, only needs to cover the logic to
* set up the jmp_buf stack.
*
* - aot runtime functions
* eg. aot_enlarge_memory.
*
* - w/o hw bound check, the intepreter loop
*
* - stack check wrapper functions generated by the aot compiler
* (--stack-bounds-checks=1)
*
* Note: on platforms with lazy function binding, don't forget to consider
* the symbol resolution overhead on the first call. For example,
* on Ubuntu amd64 20.04, it seems to consume about 1500 bytes.
*/
#ifndef WASM_STACK_GUARD_SIZE
#if WASM_ENABLE_UVWASI != 0
/* UVWASI requires larger native stack */
@ -564,14 +586,31 @@
#endif
/* Support registering quick AOT/JIT function entries of some func types
to speedup the calling process of invoking the AOT/JIT functions of
to speed up the calling process of invoking the AOT/JIT functions of
these types from the host embedder */
#ifndef WASM_ENABLE_QUICK_AOT_ENTRY
#define WASM_ENABLE_QUICK_AOT_ENTRY 1
#endif
/* Support AOT intrinsic functions which can be called from the AOT code
when `--disable-llvm-intrinsics` flag or
`--enable-builtin-intrinsics=<intr1,intr2,...>` is used by wamrc to
generate the AOT file */
#ifndef WASM_ENABLE_AOT_INTRINSICS
#define WASM_ENABLE_AOT_INTRINSICS 1
#endif
/* Disable memory64 by default */
#ifndef WASM_ENABLE_MEMORY64
#define WASM_ENABLE_MEMORY64 0
#endif
#ifndef WASM_TABLE_MAX_SIZE
#define WASM_TABLE_MAX_SIZE 1024
#endif
#ifndef WASM_MEM_ALLOC_WITH_USAGE
#define WASM_MEM_ALLOC_WITH_USAGE 0
#endif
#endif /* end of _CONFIG_H_ */

View File

@ -5,86 +5,6 @@
#include "aot_intrinsic.h"
typedef struct {
const char *llvm_intrinsic;
const char *native_intrinsic;
uint64 flag;
} aot_intrinsic;
/* clang-format off */
static const aot_intrinsic g_intrinsic_mapping[] = {
{ "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD },
{ "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD },
{ "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB },
{ "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB },
{ "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL },
{ "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL },
{ "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV },
{ "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV },
{ "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS },
{ "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS },
{ "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL },
{ "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL },
{ "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR },
{ "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR },
{ "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC },
{ "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC },
{ "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT },
{ "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT },
{ "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT },
{ "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT },
{ "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN },
{ "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN },
{ "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN },
{ "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN },
{ "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX },
{ "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX },
{ "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ },
{ "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ },
{ "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ },
{ "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ },
{ "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT },
{ "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT },
{ "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
{ "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 },
{ "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 },
{ "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 },
{ "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
{ "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 },
{ "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 },
{ "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 },
{ "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 },
{ "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 },
{ "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 },
{ "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 },
{ "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 },
{ "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 },
{ "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 },
{ "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 },
{ "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 },
{ "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 },
{ "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP },
{ "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP },
{ "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST },
{ "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST },
{ "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST },
{ "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST },
{ "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S},
{ "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S},
{ "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U},
{ "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S},
{ "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U},
{ "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U},
{ "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S},
{ "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U},
{ "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR},
{ "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND},
};
/* clang-format on */
static const uint32 g_intrinsic_count =
sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic);
float32
aot_intrinsic_fadd_f32(float32 a, float32 b)
{
@ -565,6 +485,88 @@ aot_intrinsic_i64_bit_and(uint64 l, uint64 r)
return l & r;
}
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
typedef struct {
const char *llvm_intrinsic;
const char *native_intrinsic;
uint64 flag;
} aot_intrinsic;
/* clang-format off */
static const aot_intrinsic g_intrinsic_mapping[] = {
{ "llvm.experimental.constrained.fadd.f32", "aot_intrinsic_fadd_f32", AOT_INTRINSIC_FLAG_F32_FADD },
{ "llvm.experimental.constrained.fadd.f64", "aot_intrinsic_fadd_f64", AOT_INTRINSIC_FLAG_F64_FADD },
{ "llvm.experimental.constrained.fsub.f32", "aot_intrinsic_fsub_f32", AOT_INTRINSIC_FLAG_F32_FSUB },
{ "llvm.experimental.constrained.fsub.f64", "aot_intrinsic_fsub_f64", AOT_INTRINSIC_FLAG_F64_FSUB },
{ "llvm.experimental.constrained.fmul.f32", "aot_intrinsic_fmul_f32", AOT_INTRINSIC_FLAG_F32_FMUL },
{ "llvm.experimental.constrained.fmul.f64", "aot_intrinsic_fmul_f64", AOT_INTRINSIC_FLAG_F64_FMUL },
{ "llvm.experimental.constrained.fdiv.f32", "aot_intrinsic_fdiv_f32", AOT_INTRINSIC_FLAG_F32_FDIV },
{ "llvm.experimental.constrained.fdiv.f64", "aot_intrinsic_fdiv_f64", AOT_INTRINSIC_FLAG_F64_FDIV },
{ "llvm.fabs.f32", "aot_intrinsic_fabs_f32", AOT_INTRINSIC_FLAG_F32_FABS },
{ "llvm.fabs.f64", "aot_intrinsic_fabs_f64", AOT_INTRINSIC_FLAG_F64_FABS },
{ "llvm.ceil.f32", "aot_intrinsic_ceil_f32", AOT_INTRINSIC_FLAG_F32_CEIL },
{ "llvm.ceil.f64", "aot_intrinsic_ceil_f64", AOT_INTRINSIC_FLAG_F64_CEIL },
{ "llvm.floor.f32", "aot_intrinsic_floor_f32", AOT_INTRINSIC_FLAG_F32_FLOOR },
{ "llvm.floor.f64", "aot_intrinsic_floor_f64", AOT_INTRINSIC_FLAG_F64_FLOOR },
{ "llvm.trunc.f32", "aot_intrinsic_trunc_f32", AOT_INTRINSIC_FLAG_F32_TRUNC },
{ "llvm.trunc.f64", "aot_intrinsic_trunc_f64", AOT_INTRINSIC_FLAG_F64_TRUNC },
{ "llvm.rint.f32", "aot_intrinsic_rint_f32", AOT_INTRINSIC_FLAG_F32_RINT },
{ "llvm.rint.f64", "aot_intrinsic_rint_f64", AOT_INTRINSIC_FLAG_F64_RINT },
{ "llvm.sqrt.f32", "aot_intrinsic_sqrt_f32", AOT_INTRINSIC_FLAG_F32_SQRT },
{ "llvm.sqrt.f64", "aot_intrinsic_sqrt_f64", AOT_INTRINSIC_FLAG_F64_SQRT },
{ "llvm.copysign.f32", "aot_intrinsic_copysign_f32", AOT_INTRINSIC_FLAG_F32_COPYSIGN },
{ "llvm.copysign.f64", "aot_intrinsic_copysign_f64", AOT_INTRINSIC_FLAG_F64_COPYSIGN },
{ "llvm.minnum.f32", "aot_intrinsic_fmin_f32", AOT_INTRINSIC_FLAG_F32_MIN },
{ "llvm.minnum.f64", "aot_intrinsic_fmin_f64", AOT_INTRINSIC_FLAG_F64_MIN },
{ "llvm.maxnum.f32", "aot_intrinsic_fmax_f32", AOT_INTRINSIC_FLAG_F32_MAX },
{ "llvm.maxnum.f64", "aot_intrinsic_fmax_f64", AOT_INTRINSIC_FLAG_F64_MAX },
{ "llvm.ctlz.i32", "aot_intrinsic_clz_i32", AOT_INTRINSIC_FLAG_I32_CLZ },
{ "llvm.ctlz.i64", "aot_intrinsic_clz_i64", AOT_INTRINSIC_FLAG_I64_CLZ },
{ "llvm.cttz.i32", "aot_intrinsic_ctz_i32", AOT_INTRINSIC_FLAG_I32_CTZ },
{ "llvm.cttz.i64", "aot_intrinsic_ctz_i64", AOT_INTRINSIC_FLAG_I64_CTZ },
{ "llvm.ctpop.i32", "aot_intrinsic_popcnt_i32", AOT_INTRINSIC_FLAG_I32_POPCNT },
{ "llvm.ctpop.i64", "aot_intrinsic_popcnt_i64", AOT_INTRINSIC_FLAG_I64_POPCNT },
{ "f64_convert_i32_s", "aot_intrinsic_i32_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
{ "f64_convert_i32_u", "aot_intrinsic_u32_to_f64", AOT_INTRINSIC_FLAG_U32_TO_F64 },
{ "f32_convert_i32_s", "aot_intrinsic_i32_to_f32", AOT_INTRINSIC_FLAG_I32_TO_F32 },
{ "f32_convert_i32_u", "aot_intrinsic_u32_to_f32", AOT_INTRINSIC_FLAG_U32_TO_F32 },
{ "f64_convert_i64_s", "aot_intrinsic_i64_to_f64", AOT_INTRINSIC_FLAG_I32_TO_F64 },
{ "f64_convert_i64_u", "aot_intrinsic_u64_to_f64", AOT_INTRINSIC_FLAG_U64_TO_F64 },
{ "f32_convert_i64_s", "aot_intrinsic_i64_to_f32", AOT_INTRINSIC_FLAG_I64_TO_F32 },
{ "f32_convert_i64_u", "aot_intrinsic_u64_to_f32", AOT_INTRINSIC_FLAG_U64_TO_F32 },
{ "i32_trunc_f32_u", "aot_intrinsic_f32_to_u32", AOT_INTRINSIC_FLAG_F32_TO_U32 },
{ "i32_trunc_f32_s", "aot_intrinsic_f32_to_i32", AOT_INTRINSIC_FLAG_F32_TO_I32 },
{ "i32_trunc_f64_u", "aot_intrinsic_f64_to_u32", AOT_INTRINSIC_FLAG_F64_TO_U32 },
{ "i32_trunc_f64_s", "aot_intrinsic_f64_to_i32", AOT_INTRINSIC_FLAG_F64_TO_I32 },
{ "i64_trunc_f64_u", "aot_intrinsic_f64_to_u64", AOT_INTRINSIC_FLAG_F64_TO_U64 },
{ "i64_trunc_f32_s", "aot_intrinsic_f32_to_i64", AOT_INTRINSIC_FLAG_F32_TO_I64 },
{ "i64_trunc_f32_u", "aot_intrinsic_f32_to_u64", AOT_INTRINSIC_FLAG_F32_TO_U64 },
{ "i64_trunc_f64_s", "aot_intrinsic_f64_to_i64", AOT_INTRINSIC_FLAG_F64_TO_I64 },
{ "f32_demote_f64", "aot_intrinsic_f64_to_f32", AOT_INTRINSIC_FLAG_F64_TO_F32 },
{ "f64_promote_f32", "aot_intrinsic_f32_to_f64", AOT_INTRINSIC_FLAG_F32_TO_F64 },
{ "f32_cmp", "aot_intrinsic_f32_cmp", AOT_INTRINSIC_FLAG_F32_CMP },
{ "f64_cmp", "aot_intrinsic_f64_cmp", AOT_INTRINSIC_FLAG_F64_CMP },
{ "i32.const", NULL, AOT_INTRINSIC_FLAG_I32_CONST },
{ "i64.const", NULL, AOT_INTRINSIC_FLAG_I64_CONST },
{ "f32.const", NULL, AOT_INTRINSIC_FLAG_F32_CONST },
{ "f64.const", NULL, AOT_INTRINSIC_FLAG_F64_CONST },
{ "i64.div_s", "aot_intrinsic_i64_div_s", AOT_INTRINSIC_FLAG_I64_DIV_S},
{ "i32.div_s", "aot_intrinsic_i32_div_s", AOT_INTRINSIC_FLAG_I32_DIV_S},
{ "i32.div_u", "aot_intrinsic_i32_div_u", AOT_INTRINSIC_FLAG_I32_DIV_U},
{ "i32.rem_s", "aot_intrinsic_i32_rem_s", AOT_INTRINSIC_FLAG_I32_REM_S},
{ "i32.rem_u", "aot_intrinsic_i32_rem_u", AOT_INTRINSIC_FLAG_I32_REM_U},
{ "i64.div_u", "aot_intrinsic_i64_div_u", AOT_INTRINSIC_FLAG_I64_DIV_U},
{ "i64.rem_s", "aot_intrinsic_i64_rem_s", AOT_INTRINSIC_FLAG_I64_REM_S},
{ "i64.rem_u", "aot_intrinsic_i64_rem_u", AOT_INTRINSIC_FLAG_I64_REM_U},
{ "i64.or", "aot_intrinsic_i64_bit_or", AOT_INTRINSIC_FLAG_I64_BIT_OR},
{ "i64.and", "aot_intrinsic_i64_bit_and", AOT_INTRINSIC_FLAG_I64_BIT_AND},
};
/* clang-format on */
static const uint32 g_intrinsic_count =
sizeof(g_intrinsic_mapping) / sizeof(aot_intrinsic);
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic)
{
@ -577,8 +579,6 @@ aot_intrinsic_get_symbol(const char *llvm_intrinsic)
return NULL;
}
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
static void
add_intrinsic_capability(AOTCompContext *comp_ctx, uint64 flag)
{

View File

@ -287,10 +287,10 @@ aot_intrinsic_i64_bit_or(uint64 l, uint64 r);
uint64
aot_intrinsic_i64_bit_and(uint64 l, uint64 r);
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
const char *
aot_intrinsic_get_symbol(const char *llvm_intrinsic);
#if WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0
bool
aot_intrinsic_check_capability(const AOTCompContext *comp_ctx,
const char *llvm_intrinsic);

View File

@ -16,6 +16,10 @@
#include "debug/jit_debug.h"
#endif
#if WASM_ENABLE_LINUX_PERF != 0
#include "aot_perf_map.h"
#endif
#define YMM_PLT_PREFIX "__ymm@"
#define XMM_PLT_PREFIX "__xmm@"
#define REAL_PLT_PREFIX "__real@"
@ -1430,9 +1434,20 @@ load_table_init_data_list(const uint8 **p_buf, const uint8 *buf_end,
read_uint64(buf, buf_end, init_expr_value);
#if WASM_ENABLE_GC != 0
if (wasm_is_type_multi_byte_type(elem_type)) {
/* TODO: check ref_type */
read_uint16(buf, buf_end, reftype.ref_ht_common.ref_type);
read_uint16(buf, buf_end, reftype.ref_ht_common.nullable);
uint16 ref_type, nullable;
read_uint16(buf, buf_end, ref_type);
if (elem_type != ref_type) {
set_error_buf(error_buf, error_buf_size, "invalid elem type");
return false;
}
reftype.ref_ht_common.ref_type = (uint8)ref_type;
read_uint16(buf, buf_end, nullable);
if (nullable != 0 && nullable != 1) {
set_error_buf(error_buf, error_buf_size,
"invalid nullable value");
return false;
}
reftype.ref_ht_common.nullable = (uint8)nullable;
read_uint32(buf, buf_end, reftype.ref_ht_common.heap_type);
}
else
@ -1511,29 +1526,41 @@ fail:
}
static void
destroy_types(AOTType **types, uint32 count)
destroy_type(AOTType *type)
{
uint32 i;
for (i = 0; i < count; i++) {
if (types[i]) {
#if WASM_ENABLE_GC != 0
if (types[i]->type_flag == WASM_TYPE_FUNC) {
AOTFuncType *func_type = (AOTFuncType *)types[i];
if (type->ref_count > 1) {
/* The type is referenced by other types
of current aot module */
type->ref_count--;
return;
}
if (type->type_flag == WASM_TYPE_FUNC) {
AOTFuncType *func_type = (AOTFuncType *)type;
if (func_type->ref_type_maps != NULL) {
bh_assert(func_type->ref_type_map_count > 0);
wasm_runtime_free(func_type->ref_type_maps);
}
}
else if (types[i]->type_flag == WASM_TYPE_STRUCT) {
AOTStructType *struct_type = (AOTStructType *)types[i];
else if (type->type_flag == WASM_TYPE_STRUCT) {
AOTStructType *struct_type = (AOTStructType *)type;
if (struct_type->ref_type_maps != NULL) {
bh_assert(struct_type->ref_type_map_count > 0);
wasm_runtime_free(struct_type->ref_type_maps);
}
}
#endif
wasm_runtime_free(types[i]);
wasm_runtime_free(type);
}
static void
destroy_types(AOTType **types, uint32 count)
{
uint32 i;
for (i = 0; i < count; i++) {
if (types[i]) {
destroy_type(types[i]);
}
}
wasm_runtime_free(types);
@ -1541,14 +1568,17 @@ destroy_types(AOTType **types, uint32 count)
#if WASM_ENABLE_GC != 0
static void
init_base_type(AOTType *base_type, uint16 type_flag, bool is_sub_final,
uint32 parent_type_idx, uint16 rec_count, uint16 rec_idx)
init_base_type(AOTType *base_type, uint32 type_idx, uint16 type_flag,
bool is_sub_final, uint32 parent_type_idx, uint16 rec_count,
uint16 rec_idx)
{
base_type->type_flag = type_flag;
base_type->ref_count = 1;
base_type->is_sub_final = is_sub_final;
base_type->parent_type_idx = parent_type_idx;
base_type->rec_count = rec_count;
base_type->rec_idx = rec_idx;
base_type->rec_begin_type_idx = type_idx - rec_idx;
}
static bool
@ -1561,7 +1591,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
uint32 i, j;
uint32 type_flag, param_cell_num, ret_cell_num;
uint16 param_count, result_count, ref_type_map_count, rec_count, rec_idx;
bool is_sub_final;
bool is_equivalence_type, is_sub_final;
uint32 parent_type_idx;
WASMRefType ref_type;
@ -1575,12 +1605,31 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
/* Create each type */
for (i = 0; i < module->type_count; i++) {
buf = align_ptr(buf, 4);
/* Read base type info */
read_uint16(buf, buf_end, type_flag);
read_uint16(buf, buf_end, is_sub_final);
read_uint8(buf, buf_end, is_equivalence_type);
/* If there is an equivalence type, re-use it */
if (is_equivalence_type) {
uint8 u8;
/* padding */
read_uint8(buf, buf_end, u8);
(void)u8;
read_uint32(buf, buf_end, j);
if (module->types[j]->ref_count == UINT16_MAX) {
set_error_buf(error_buf, error_buf_size,
"wasm type's ref count too large");
goto fail;
}
module->types[j]->ref_count++;
module->types[i] = module->types[j];
continue;
}
read_uint8(buf, buf_end, is_sub_final);
read_uint32(buf, buf_end, parent_type_idx);
read_uint16(buf, buf_end, rec_count);
read_uint16(buf, buf_end, rec_idx);
@ -1605,7 +1654,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
types[i] = (AOTType *)func_type;
init_base_type((AOTType *)func_type, type_flag, is_sub_final,
init_base_type((AOTType *)func_type, i, type_flag, is_sub_final,
parent_type_idx, rec_count, rec_idx);
func_type->param_count = param_count;
func_type->result_count = result_count;
@ -1711,7 +1760,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
offset = (uint32)offsetof(WASMStructObject, field_data);
types[i] = (AOTType *)struct_type;
init_base_type((AOTType *)struct_type, type_flag, is_sub_final,
init_base_type((AOTType *)struct_type, i, type_flag, is_sub_final,
parent_type_idx, rec_count, rec_idx);
struct_type->field_count = field_count;
struct_type->ref_type_map_count = ref_type_map_count;
@ -1797,7 +1846,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
types[i] = (AOTType *)array_type;
init_base_type((AOTType *)array_type, type_flag, is_sub_final,
init_base_type((AOTType *)array_type, i, type_flag, is_sub_final,
parent_type_idx, rec_count, rec_idx);
read_uint16(buf, buf_end, array_type->elem_flags);
read_uint8(buf, buf_end, array_type->elem_type);
@ -1826,7 +1875,6 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
if (rec_count == 0) {
bh_assert(rec_idx == 0);
}
for (j = i - rec_idx; j <= i; j++) {
AOTType *cur_type = module->types[j];
parent_type_idx = cur_type->parent_type_idx;
@ -1835,6 +1883,11 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
module->types[j]->parent_type = parent_type;
module->types[j]->root_type = parent_type->root_type;
if (parent_type->inherit_depth == UINT16_MAX) {
set_error_buf(error_buf, error_buf_size,
"parent type's inherit depth too large");
goto fail;
}
module->types[j]->inherit_depth =
parent_type->inherit_depth + 1;
}
@ -1852,7 +1905,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
AOTType *parent_type = module->types[parent_type_idx];
/* subtyping has been checked during compilation */
bh_assert(wasm_type_is_subtype_of(
module->types[j], parent_type, module->types, i));
module->types[j], parent_type, module->types, i + 1));
(void)parent_type;
}
}
@ -3590,104 +3643,6 @@ fail:
return ret;
}
#if WASM_ENABLE_LINUX_PERF != 0
struct func_info {
uint32 idx;
void *ptr;
};
static uint32
get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
uint32 idx)
{
uint32 func_sz;
if (idx == module->func_count - 1)
func_sz = (uintptr_t)module->code + module->code_size
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
else
func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
return func_sz;
}
static int
compare_func_ptrs(const void *f1, const void *f2)
{
return (intptr_t)((struct func_info *)f1)->ptr
- (intptr_t)((struct func_info *)f2)->ptr;
}
static struct func_info *
sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
{
uint64 content_len;
struct func_info *sorted_func_ptrs;
unsigned i;
content_len = (uint64)sizeof(struct func_info) * module->func_count;
sorted_func_ptrs = loader_malloc(content_len, error_buf, error_buf_size);
if (!sorted_func_ptrs)
return NULL;
for (i = 0; i < module->func_count; i++) {
sorted_func_ptrs[i].idx = i;
sorted_func_ptrs[i].ptr = module->func_ptrs[i];
}
qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
compare_func_ptrs);
return sorted_func_ptrs;
}
static bool
create_perf_map(const AOTModule *module, char *error_buf, uint32 error_buf_size)
{
struct func_info *sorted_func_ptrs = NULL;
char perf_map_info[128] = { 0 };
FILE *perf_map = NULL;
uint32 i;
pid_t pid = getpid();
bool ret = false;
sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
if (!sorted_func_ptrs)
goto quit;
snprintf(perf_map_info, 128, "/tmp/perf-%d.map", pid);
perf_map = fopen(perf_map_info, "w");
if (!perf_map) {
LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
strerror(errno));
goto quit;
}
for (i = 0; i < module->func_count; i++) {
memset(perf_map_info, 0, 128);
snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
(uintptr_t)sorted_func_ptrs[i].ptr,
get_func_size(module, sorted_func_ptrs, i),
sorted_func_ptrs[i].idx);
fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
}
LOG_VERBOSE("generate /tmp/perf-%d.map", pid);
ret = true;
quit:
if (sorted_func_ptrs)
free(sorted_func_ptrs);
if (perf_map)
fclose(perf_map);
return ret;
}
#endif /* WASM_ENABLE_LINUX_PERF != 0*/
static bool
load_from_sections(AOTModule *module, AOTSection *sections,
bool is_load_from_file_buf, char *error_buf,
@ -3878,7 +3833,7 @@ load_from_sections(AOTModule *module, AOTSection *sections,
}
static AOTModule *
create_module(char *error_buf, uint32 error_buf_size)
create_module(char *name, char *error_buf, uint32 error_buf_size)
{
AOTModule *module =
loader_malloc(sizeof(AOTModule), error_buf, error_buf_size);
@ -3890,7 +3845,7 @@ create_module(char *error_buf, uint32 error_buf_size)
module->module_type = Wasm_Module_AoT;
module->name = "";
module->name = name;
#if WASM_ENABLE_MULTI_MODULE != 0
module->import_module_list = &module->import_module_list_head;
@ -3926,7 +3881,7 @@ AOTModule *
aot_load_from_sections(AOTSection *section_list, char *error_buf,
uint32 error_buf_size)
{
AOTModule *module = create_module(error_buf, error_buf_size);
AOTModule *module = create_module("", error_buf, error_buf_size);
if (!module)
return NULL;
@ -4172,7 +4127,7 @@ load(const uint8 *buf, uint32 size, AOTModule *module, char *error_buf,
#if WASM_ENABLE_LINUX_PERF != 0
if (wasm_runtime_get_linux_perf())
if (!create_perf_map(module, error_buf, error_buf_size))
if (!aot_create_perf_map(module, error_buf, error_buf_size))
goto fail;
#endif
@ -4182,10 +4137,10 @@ fail:
}
AOTModule *
aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size)
aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
char *error_buf, uint32 error_buf_size)
{
AOTModule *module = create_module(error_buf, error_buf_size);
AOTModule *module = create_module(args->name, error_buf, error_buf_size);
if (!module)
return NULL;
@ -4379,7 +4334,7 @@ aot_unload(AOTModule *module)
}
if (module->string_literal_ptrs) {
wasm_runtime_free(module->string_literal_ptrs);
wasm_runtime_free((void *)module->string_literal_ptrs);
}
}
#endif

View File

@ -0,0 +1,120 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#include "aot_perf_map.h"
#include "bh_log.h"
#include "bh_platform.h"
#if WASM_ENABLE_LINUX_PERF != 0
struct func_info {
uint32 idx;
void *ptr;
};
static uint32
get_func_size(const AOTModule *module, struct func_info *sorted_func_ptrs,
uint32 idx)
{
uint32 func_sz;
if (idx == module->func_count - 1)
func_sz = (uintptr_t)module->code + module->code_size
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
else
func_sz = (uintptr_t)(sorted_func_ptrs[idx + 1].ptr)
- (uintptr_t)(sorted_func_ptrs[idx].ptr);
return func_sz;
}
static int
compare_func_ptrs(const void *f1, const void *f2)
{
return (intptr_t)((struct func_info *)f1)->ptr
- (intptr_t)((struct func_info *)f2)->ptr;
}
static struct func_info *
sort_func_ptrs(const AOTModule *module, char *error_buf, uint32 error_buf_size)
{
uint64 content_len;
struct func_info *sorted_func_ptrs;
unsigned i;
content_len = (uint64)sizeof(struct func_info) * module->func_count;
sorted_func_ptrs = wasm_runtime_malloc(content_len);
if (!sorted_func_ptrs) {
snprintf(error_buf, error_buf_size,
"allocate memory failed when creating perf map");
return NULL;
}
for (i = 0; i < module->func_count; i++) {
sorted_func_ptrs[i].idx = i;
sorted_func_ptrs[i].ptr = module->func_ptrs[i];
}
qsort(sorted_func_ptrs, module->func_count, sizeof(struct func_info),
compare_func_ptrs);
return sorted_func_ptrs;
}
bool
aot_create_perf_map(const AOTModule *module, char *error_buf,
uint32 error_buf_size)
{
struct func_info *sorted_func_ptrs = NULL;
char perf_map_path[64] = { 0 };
char perf_map_info[128] = { 0 };
FILE *perf_map = NULL;
uint32 i;
pid_t pid = getpid();
bool ret = false;
sorted_func_ptrs = sort_func_ptrs(module, error_buf, error_buf_size);
if (!sorted_func_ptrs)
goto quit;
snprintf(perf_map_path, sizeof(perf_map_path) - 1, "/tmp/perf-%d.map", pid);
perf_map = fopen(perf_map_path, "a");
if (!perf_map) {
LOG_WARNING("warning: can't create /tmp/perf-%d.map, because %s", pid,
strerror(errno));
goto quit;
}
const char *module_name = aot_get_module_name((AOTModule *)module);
for (i = 0; i < module->func_count; i++) {
memset(perf_map_info, 0, 128);
if (strlen(module_name) > 0)
snprintf(perf_map_info, 128, "%lx %x [%s]#aot_func#%u\n",
(uintptr_t)sorted_func_ptrs[i].ptr,
get_func_size(module, sorted_func_ptrs, i), module_name,
sorted_func_ptrs[i].idx);
else
snprintf(perf_map_info, 128, "%lx %x aot_func#%u\n",
(uintptr_t)sorted_func_ptrs[i].ptr,
get_func_size(module, sorted_func_ptrs, i),
sorted_func_ptrs[i].idx);
/* fwrite() is thread safe */
fwrite(perf_map_info, 1, strlen(perf_map_info), perf_map);
}
LOG_VERBOSE("write map information from %s into /tmp/perf-%d.map",
module_name, pid);
ret = true;
quit:
if (sorted_func_ptrs)
wasm_runtime_free(sorted_func_ptrs);
if (perf_map)
fclose(perf_map);
return ret;
}
#endif /* WASM_ENABLE_LINUX_PERF != 0 */

View File

@ -0,0 +1,15 @@
/*
* Copyright (C) 2019 Intel Corporation. All rights reserved.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _AOT_PERF_MAP_H_
#define _AOT_PERF_MAP_H_
#include "aot_runtime.h"
bool
aot_create_perf_map(const AOTModule *module, char *error_buf,
uint32 error_buf_size);
#endif /* _AOT_PERF_MAP_H_ */

View File

@ -62,6 +62,7 @@ typedef struct {
#define REG_AOT_TRACE_SYM()
#endif
#if WASM_ENABLE_AOT_INTRINSICS != 0
#define REG_INTRINSIC_SYM() \
REG_SYM(aot_intrinsic_fabs_f32), \
REG_SYM(aot_intrinsic_fabs_f64), \
@ -124,7 +125,10 @@ typedef struct {
REG_SYM(aot_intrinsic_i32_div_s), \
REG_SYM(aot_intrinsic_i32_div_u), \
REG_SYM(aot_intrinsic_i32_rem_s), \
REG_SYM(aot_intrinsic_i32_rem_u), \
REG_SYM(aot_intrinsic_i32_rem_u),
#else
#define REG_INTRINSIC_SYM()
#endif
#if WASM_ENABLE_STATIC_PGO != 0
#define REG_LLVM_PGO_SYM() \
@ -139,6 +143,7 @@ typedef struct {
REG_SYM(aot_array_init_with_data), \
REG_SYM(aot_create_func_obj), \
REG_SYM(aot_obj_is_instance_of), \
REG_SYM(aot_func_type_is_super_of), \
REG_SYM(aot_rtt_type_new), \
REG_SYM(wasm_array_obj_copy), \
REG_SYM(wasm_array_obj_new), \

View File

@ -880,7 +880,7 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
global_addr = module_inst->global_data
+ module->globals[global_idx].data_offset;
*(uint32 *)global_addr = (uint32)aux_heap_base;
LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base);
LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base);
}
else {
/* Insert app heap before new page */
@ -906,17 +906,19 @@ memory_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
LOG_VERBOSE("Memory instantiate:");
LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u",
num_bytes_per_page, init_page_count, max_page_count);
LOG_VERBOSE(" data offset: %u, stack size: %d", module->aux_data_end,
module->aux_stack_size);
LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size);
LOG_VERBOSE(" data offset: %" PRIu64 ", stack size: %d",
module->aux_data_end, module->aux_stack_size);
LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %d\n", heap_offset,
heap_size);
max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
(void)max_memory_data_size;
if (wasm_allocate_linear_memory(&p, is_shared_memory, num_bytes_per_page,
init_page_count, max_page_count,
&memory_data_size)
/* TODO: memory64 uses is_memory64 flag */
if (wasm_allocate_linear_memory(&p, is_shared_memory, false,
num_bytes_per_page, init_page_count,
max_page_count, &memory_data_size)
!= BHT_OK) {
set_error_buf(error_buf, error_buf_size,
"allocate linear memory failed");
@ -1069,8 +1071,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
/* Check memory data */
/* check offset since length might negative */
if (base_offset > memory_inst->memory_data_size) {
LOG_DEBUG("base_offset(%d) > memory_data_size(%d)", base_offset,
memory_inst->memory_data_size);
LOG_DEBUG("base_offset(%d) > memory_data_size(%" PRIu64 ")",
base_offset, memory_inst->memory_data_size);
#if WASM_ENABLE_REF_TYPES != 0
set_error_buf(error_buf, error_buf_size,
"out of bounds memory access");
@ -1084,7 +1086,8 @@ memories_instantiate(AOTModuleInstance *module_inst, AOTModuleInstance *parent,
/* check offset + length(could be zero) */
length = data_seg->byte_count;
if (base_offset + length > memory_inst->memory_data_size) {
LOG_DEBUG("base_offset(%d) + length(%d) > memory_data_size(%d)",
LOG_DEBUG("base_offset(%d) + length(%d) > memory_data_size(%" PRIu64
")",
base_offset, length, memory_inst->memory_data_size);
#if WASM_ENABLE_REF_TYPES != 0
set_error_buf(error_buf, error_buf_size,
@ -1718,6 +1721,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
bh_assert(table_init_data);
bh_assert(table_init_data->table_index < module_inst->table_count);
table = module_inst->tables[table_init_data->table_index];
bh_assert(table);
@ -1725,8 +1729,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
bh_assert(table_data);
wasm_runtime_get_table_inst_elem_type(
(WASMModuleInstanceCommon *)module_inst, i, &tbl_elem_type,
&tbl_elem_ref_type, &tbl_init_size, &tbl_max_size);
(WASMModuleInstanceCommon *)module_inst,
table_init_data->table_index, &tbl_elem_type, &tbl_elem_ref_type,
&tbl_init_size, &tbl_max_size);
if (!wasm_elem_is_declarative(table_init_data->mode)
&& !wasm_reftype_is_subtype_of(
@ -2522,7 +2527,8 @@ aot_module_malloc_internal(AOTModuleInstance *module_inst,
aot_set_exception(module_inst, "app heap corrupted");
}
else {
LOG_WARNING("warning: allocate %u bytes memory failed", size);
LOG_WARNING("warning: allocate %" PRIu64 " bytes memory failed",
size);
}
return 0;
}
@ -2805,7 +2811,7 @@ aot_call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 table_elem_idx,
}
#if WASM_ENABLE_GC == 0
func_idx = tbl_elem_val;
func_idx = (uint32)tbl_elem_val;
#else
func_idx =
wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val);
@ -3362,39 +3368,49 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
}
uint32
aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx,
uint32 inc_entries, table_elem_type_t init_val)
aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 inc_size,
table_elem_type_t init_val)
{
uint32 entry_count, i, orig_tbl_sz;
AOTTableInstance *tbl_inst;
uint32 i, orig_size, total_size;
tbl_inst = module_inst->tables[tbl_idx];
if (!tbl_inst) {
return (uint32)-1;
}
orig_tbl_sz = tbl_inst->cur_size;
orig_size = tbl_inst->cur_size;
if (!inc_entries) {
return orig_tbl_sz;
if (!inc_size) {
return orig_size;
}
if (tbl_inst->cur_size > UINT32_MAX - inc_entries) {
if (tbl_inst->cur_size > UINT32_MAX - inc_size) {
#if WASM_ENABLE_SPEC_TEST == 0
LOG_WARNING("table grow (%" PRIu32 "-> %" PRIu32
") failed because of integer overflow",
tbl_inst->cur_size, inc_size);
#endif
return (uint32)-1;
}
entry_count = tbl_inst->cur_size + inc_entries;
if (entry_count > tbl_inst->max_size) {
total_size = tbl_inst->cur_size + inc_size;
if (total_size > tbl_inst->max_size) {
#if WASM_ENABLE_SPEC_TEST == 0
LOG_WARNING("table grow (%" PRIu32 "-> %" PRIu32
") failed because of over max size",
tbl_inst->cur_size, inc_size);
#endif
return (uint32)-1;
}
/* fill in */
for (i = 0; i < inc_entries; ++i) {
for (i = 0; i < inc_size; ++i) {
tbl_inst->elems[tbl_inst->cur_size + i] = init_val;
}
tbl_inst->cur_size = entry_count;
return orig_tbl_sz;
tbl_inst->cur_size = total_size;
return orig_size;
}
#endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
@ -3696,14 +3712,14 @@ aot_create_call_stack(struct WASMExecEnv *exec_env)
frame.instance = module_inst;
frame.module_offset = 0;
frame.func_index = cur_frame->func_index;
frame.func_offset = cur_frame->ip_offset;
frame.func_name_wp =
get_func_name_from_index(module_inst, cur_frame->func_index);
frame.func_index = (uint32)cur_frame->func_index;
frame.func_offset = (uint32)cur_frame->ip_offset;
frame.func_name_wp = get_func_name_from_index(
module_inst, (uint32)cur_frame->func_index);
if (cur_frame->func_index >= module->import_func_count) {
uint32 aot_func_idx =
cur_frame->func_index - module->import_func_count;
(uint32)(cur_frame->func_index - module->import_func_count);
max_local_cell_num = module->max_local_cell_nums[aot_func_idx];
max_stack_cell_num = module->max_stack_cell_nums[aot_func_idx];
}
@ -4473,6 +4489,22 @@ aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
}
bool
aot_func_type_is_super_of(AOTModuleInstance *module_inst, uint32 type_idx1,
uint32 type_idx2)
{
AOTModule *aot_module = (AOTModule *)module_inst->module;
AOTType **types = aot_module->types;
if (type_idx1 == type_idx2)
return true;
bh_assert(types[type_idx1]->type_flag == WASM_TYPE_FUNC);
bh_assert(types[type_idx2]->type_flag == WASM_TYPE_FUNC);
return wasm_func_type_is_super_of((WASMFuncType *)types[type_idx1],
(WASMFuncType *)types[type_idx2]);
}
WASMRttTypeRef
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index)
{
@ -4720,8 +4752,11 @@ aot_set_module_name(AOTModule *module, const char *name, char *error_buf,
if (!name)
return false;
module->name =
aot_const_str_set_insert((const uint8 *)name, strlen(name) + 1, module,
module->name = aot_const_str_set_insert((const uint8 *)name,
(uint32)(strlen(name) + 1), module,
#if (WASM_ENABLE_WORD_ALIGN_READ != 0)
false,
#endif
error_buf, error_buf_size);
return module->name != NULL;
}

View File

@ -444,8 +444,8 @@ typedef struct LLVMProfileData_64 {
* @return return AOT module loaded, NULL if failed
*/
AOTModule *
aot_load_from_aot_file(const uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size);
aot_load_from_aot_file(const uint8 *buf, uint32 size, const LoadArgs *args,
char *error_buf, uint32 error_buf_size);
/**
* Load a AOT module from a specified AOT section list.
@ -752,6 +752,11 @@ bool
aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
uint32 type_index);
/* Whether func type1 is one of super types of func type2 */
bool
aot_func_type_is_super_of(AOTModuleInstance *module_inst, uint32 type_idx1,
uint32 type_idx2);
WASMRttTypeRef
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index);

View File

@ -304,7 +304,12 @@ wasm_defined_type_equal(WASMType *const def_type1, WASMType *const def_type2,
}
#endif
#if WASM_ENABLE_AOT != 0
/* TODO */
if (module->module_type == Wasm_Module_AoT) {
AOTModule *aot_module = (AOTModule *)module;
types = aot_module->types;
type_count = aot_module->type_count;
}
#endif
bh_assert(types);

View File

@ -148,7 +148,7 @@ wasm_dump_func_type(const WASMFuncType *type)
os_printf("] -> [");
for (; i < type->param_count + type->result_count; i++) {
for (; i < (uint32)(type->param_count + type->result_count); i++) {
if (wasm_is_type_multi_byte_type(type->types[i])) {
bh_assert(j < type->ref_type_map_count);
bh_assert(i == type->ref_type_maps[j].index);
@ -250,6 +250,51 @@ wasm_value_types_is_subtype_of(const uint8 *types1,
return true;
}
static bool
rec_ref_type_equal(const WASMRefType *ref_type1, const WASMRefType *ref_type2,
uint32 rec_begin_type_idx1, uint32 rec_begin_type_idx2,
uint32 rec_count, const WASMTypePtr *types,
uint32 type_count)
{
uint32 type_idx1, type_idx2;
if (!wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)
|| !wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common))
return ref_type1->ref_ht_common.heap_type
== ref_type2->ref_ht_common.heap_type
? true
: false;
/* Now both ref types are type of (ref type_idx) */
type_idx1 = ref_type1->ref_ht_typeidx.type_idx;
type_idx2 = ref_type2->ref_ht_typeidx.type_idx;
if (type_idx1 >= rec_begin_type_idx1
&& type_idx1 < rec_begin_type_idx1 + rec_count) {
/* The converted iso-recursive types should be the same */
bool ret = (type_idx2 >= rec_begin_type_idx2
&& type_idx2 < rec_begin_type_idx2 + rec_count
&& type_idx1 - rec_begin_type_idx1
== type_idx2 - rec_begin_type_idx2)
? true
: false;
return ret;
}
else if (type_idx2 >= rec_begin_type_idx2
&& type_idx2 < rec_begin_type_idx2 + rec_count) {
/* The converted iso-recursive types should be the same */
bool ret = (type_idx1 >= rec_begin_type_idx1
&& type_idx1 < rec_begin_type_idx1 + rec_count
&& type_idx1 - rec_begin_type_idx1
== type_idx2 - rec_begin_type_idx2)
? true
: false;
return ret;
}
return types[type_idx1] == types[type_idx2] ? true : false;
}
bool
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count)
@ -264,7 +309,7 @@ wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
|| type1->ref_type_map_count != type2->ref_type_map_count)
return false;
for (i = 0; i < type1->param_count + type1->result_count; i++) {
for (i = 0; i < (uint32)(type1->param_count + type1->result_count); i++) {
if (type1->types[i] != type2->types[i])
return false;
@ -277,9 +322,11 @@ wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
ref_type1 = type1->ref_type_maps[j].ref_type;
ref_type2 = type2->ref_type_maps[j].ref_type;
if (!wasm_reftype_equal(ref_type1->ref_type, ref_type1,
ref_type2->ref_type, ref_type2, types,
type_count))
if (!rec_ref_type_equal(
ref_type1, ref_type2, type1->base_type.rec_begin_type_idx,
type2->base_type.rec_begin_type_idx,
type1->base_type.rec_count, types, type_count))
return false;
j++;
@ -316,9 +363,11 @@ wasm_struct_type_equal(const WASMStructType *type1, const WASMStructType *type2,
ref_type1 = type1->ref_type_maps[j].ref_type;
ref_type2 = type2->ref_type_maps[j].ref_type;
if (!wasm_reftype_equal(ref_type1->ref_type, ref_type1,
ref_type2->ref_type, ref_type2, types,
type_count))
if (!rec_ref_type_equal(
ref_type1, ref_type2, type1->base_type.rec_begin_type_idx,
type2->base_type.rec_begin_type_idx,
type1->base_type.rec_count, types, type_count))
return false;
j++;
@ -338,21 +387,67 @@ wasm_array_type_equal(const WASMArrayType *type1, const WASMArrayType *type2,
if (type1->elem_flags != type2->elem_flags)
return false;
return wasm_reftype_equal(type1->elem_type, type1->elem_ref_type,
type2->elem_type, type2->elem_ref_type, types,
type_count);
if (type1->elem_type != type2->elem_type)
return false;
if (!wasm_is_type_multi_byte_type(type1->elem_type))
return true;
return rec_ref_type_equal(type1->elem_ref_type, type2->elem_ref_type,
type1->base_type.rec_begin_type_idx,
type2->base_type.rec_begin_type_idx,
type1->base_type.rec_count, types, type_count);
}
bool
wasm_type_equal(const WASMType *type1, const WASMType *type2,
const WASMTypePtr *types, uint32 type_count)
{
uint32 rec_begin_type_idx1 = type1->rec_begin_type_idx;
uint32 rec_begin_type_idx2 = type2->rec_begin_type_idx;
uint32 parent_type_idx1, parent_type_idx2, rec_count;
if (type1 == type2)
return true;
if (type1->type_flag != type2->type_flag)
if (!(type1->type_flag == type2->type_flag
&& type1->is_sub_final == type2->is_sub_final
&& type1->rec_count == type2->rec_count
&& type1->rec_idx == type2->rec_idx))
return false;
rec_count = type1->rec_count;
parent_type_idx1 = type1->parent_type_idx;
parent_type_idx2 = type2->parent_type_idx;
if (parent_type_idx1 >= rec_begin_type_idx1
&& parent_type_idx1 < rec_begin_type_idx1 + rec_count) {
/* The converted iso-recursive types should be the same */
if (!(parent_type_idx2 >= rec_begin_type_idx2
&& parent_type_idx2 < rec_begin_type_idx2 + rec_count
&& parent_type_idx1 - rec_begin_type_idx1
== parent_type_idx2 - rec_begin_type_idx2)) {
return false;
}
}
else if (parent_type_idx2 >= rec_begin_type_idx2
&& parent_type_idx2 < rec_begin_type_idx2 + rec_count) {
/* The converted iso-recursive types should be the same */
if (!(parent_type_idx1 >= rec_begin_type_idx1
&& parent_type_idx1 < rec_begin_type_idx1 + rec_count
&& parent_type_idx1 - rec_begin_type_idx1
== parent_type_idx2 - rec_begin_type_idx2)) {
return false;
}
}
else if (type1->parent_type != type2->parent_type) {
/* The parent types should be same since they have been
normalized and equivalence types with different type
indexes are referring to a same WASMType */
return false;
}
if (wasm_type_is_func_type(type1))
return wasm_func_type_equal((WASMFuncType *)type1,
(WASMFuncType *)type2, types, type_count);
@ -399,7 +494,7 @@ wasm_func_type_is_subtype_of(const WASMFuncType *type1,
}
}
for (; i < type1->param_count + type1->result_count; i++) {
for (; i < (uint32)(type1->param_count + type1->result_count); i++) {
if (wasm_is_type_multi_byte_type(type1->types[i])) {
bh_assert(j1 < type1->ref_type_map_count);
ref_type1 = type1->ref_type_maps[j1++].ref_type;
@ -653,12 +748,6 @@ wasm_reftype_struct_size(const WASMRefType *ref_type)
return (uint32)sizeof(RefHeapType_Common);
}
static bool
type_idx_equal(uint32 type_idx1, uint32 type_idx2)
{
return (type_idx1 == type_idx2) ? true : false;
}
bool
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
const RefHeapType_Common *ref_heap_type2,
@ -673,8 +762,16 @@ wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
if (ref_heap_type1->heap_type != ref_heap_type2->heap_type) {
if (wasm_is_refheaptype_typeidx(ref_heap_type1)
&& wasm_is_refheaptype_typeidx(ref_heap_type2)) {
return type_idx_equal(ref_heap_type1->heap_type,
ref_heap_type2->heap_type);
if (ref_heap_type1->heap_type == ref_heap_type2->heap_type)
return true;
else
/* the type_count may be 0 when called from reftype_equal */
return ((uint32)ref_heap_type1->heap_type < type_count
&& (uint32)ref_heap_type2->heap_type < type_count
&& types[ref_heap_type1->heap_type]
== types[ref_heap_type2->heap_type])
? true
: false;
}
return false;
}
@ -835,6 +932,13 @@ wasm_type_is_supers_of(const WASMType *type1, const WASMType *type2)
return false;
}
bool
wasm_func_type_is_super_of(const WASMFuncType *type1, const WASMFuncType *type2)
{
return wasm_type_is_supers_of((const WASMType *)type1,
(const WASMType *)type2);
}
bool
wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
uint8 type2, const WASMRefType *ref_type2,
@ -914,12 +1018,13 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
#endif
else if (type1 == REF_TYPE_HT_NULLABLE) {
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
bh_assert((uint32)ref_type1->ref_ht_typeidx.type_idx < type_count);
/* reftype1 is (ref null $t) */
if (type2 == REF_TYPE_HT_NULLABLE && ref_type2 != NULL
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx,
ref_type2->ref_ht_typeidx.type_idx)
|| wasm_type_is_supers_of(
bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
< type_count);
return wasm_type_is_supers_of(
types[ref_type2->ref_ht_typeidx.type_idx],
types[ref_type1->ref_ht_typeidx.type_idx]);
}
@ -963,14 +1068,15 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
else if (type1 == REF_TYPE_HT_NON_NULLABLE) {
bh_assert(ref_type1);
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) {
bh_assert((uint32)ref_type1->ref_ht_typeidx.type_idx < type_count);
/* reftype1 is (ref $t) */
if ((type2 == REF_TYPE_HT_NULLABLE
|| type2 == REF_TYPE_HT_NON_NULLABLE)
&& ref_type2 != NULL
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx,
ref_type2->ref_ht_typeidx.type_idx)
|| wasm_type_is_supers_of(
bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
< type_count);
return wasm_type_is_supers_of(
types[ref_type2->ref_ht_typeidx.type_idx],
types[ref_type1->ref_ht_typeidx.type_idx]);
}

View File

@ -47,6 +47,12 @@ wasm_func_type_is_subtype_of(const WASMFuncType *type1,
const WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count);
/* Whether func type1 is one of super types of func type2,
used for the func type check in call_indirect/call_ref opcodes */
bool
wasm_func_type_is_super_of(const WASMFuncType *type1,
const WASMFuncType *type2);
/* Whether func type1's result types are subtype of
func type2's result types */
bool

View File

@ -61,7 +61,7 @@ static union {
* Implementation of wasm_application_execute_main()
*/
static bool
check_main_func_type(const WASMFuncType *type)
check_main_func_type(const WASMFuncType *type, bool is_memory64)
{
if (!(type->param_count == 0 || type->param_count == 2)
|| type->result_count > 1) {
@ -72,7 +72,8 @@ check_main_func_type(const WASMFuncType *type)
if (type->param_count == 2
&& !(type->types[0] == VALUE_TYPE_I32
&& type->types[1] == VALUE_TYPE_I32)) {
&& type->types[1]
== (is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32))) {
LOG_ERROR(
"WASM execute application failed: invalid main function type.\n");
return false;
@ -94,14 +95,18 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
WASMFunctionInstanceCommon *func;
WASMFuncType *func_type = NULL;
WASMExecEnv *exec_env = NULL;
uint32 argc1 = 0, argv1[2] = { 0 };
uint32 argc1 = 0, argv1[3] = { 0 };
uint32 total_argv_size = 0;
uint64 total_size;
uint64 argv_buf_offset = 0;
int32 i;
char *argv_buf, *p, *p_end;
uint32 *argv_offsets, module_type;
bool ret, is_import_func = true;
bool ret, is_import_func = true, is_memory64 = false;
#if WASM_ENABLE_MEMORY64 != 0
WASMModuleInstance *wasm_module_inst = (WASMModuleInstance *)module_inst;
is_memory64 = wasm_module_inst->memories[0]->is_memory64;
#endif
exec_env = wasm_runtime_get_exec_env_singleton(module_inst);
if (!exec_env) {
@ -187,7 +192,7 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
return false;
}
if (!check_main_func_type(func_type)) {
if (!check_main_func_type(func_type, is_memory64)) {
wasm_runtime_set_exception(module_inst,
"invalid function type of main function");
return false;
@ -218,11 +223,21 @@ execute_main(WASMModuleInstanceCommon *module_inst, int32 argc, char *argv[])
p += strlen(argv[i]) + 1;
}
argc1 = 2;
argv1[0] = (uint32)argc;
/* TODO: memory64 uint64 when the memory idx is i64 */
argv1[1] =
(uint32)wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
argc1 = 3;
uint64 app_addr =
wasm_runtime_addr_native_to_app(module_inst, argv_offsets);
PUT_I64_TO_ADDR(&argv[1], app_addr);
}
else
#endif
{
argc1 = 2;
argv1[1] = (uint32)wasm_runtime_addr_native_to_app(module_inst,
argv_offsets);
}
}
ret = wasm_runtime_call_wasm(exec_env, func, argc1, argv1);
@ -563,8 +578,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
is_anyref = true;
}
if (wasm_is_type_multi_byte_type(
type->types[type->param_count + i])) {
if (wasm_is_type_multi_byte_type(type->types[i])) {
WASMRefType *ref_type = ref_type_map->ref_type;
if (wasm_is_refheaptype_common(
&ref_type->ref_ht_common)) {

View File

@ -2234,7 +2234,8 @@ quit:
#endif /* WASM_ENABLE_WASM_CACHE != 0 */
wasm_module_t *
wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
wasm_module_new_ex(wasm_store_t *store, const wasm_byte_vec_t *binary,
const LoadArgs *args)
{
char error_buf[128] = { 0 };
wasm_module_ex_t *module_ex = NULL;
@ -2290,8 +2291,8 @@ wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
if (!module_ex->binary->data)
goto free_binary;
module_ex->module_comm_rt = wasm_runtime_load(
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size,
module_ex->module_comm_rt = wasm_runtime_load_ex(
(uint8 *)module_ex->binary->data, (uint32)module_ex->binary->size, args,
error_buf, (uint32)sizeof(error_buf));
if (!(module_ex->module_comm_rt)) {
LOG_ERROR("%s", error_buf);
@ -2337,6 +2338,14 @@ quit:
return NULL;
}
wasm_module_t *
wasm_module_new(wasm_store_t *store, const wasm_byte_vec_t *binary)
{
LoadArgs args = { 0 };
args.name = "";
return wasm_module_new_ex(store, binary, &args);
}
bool
wasm_module_validate(wasm_store_t *store, const wasm_byte_vec_t *binary)
{
@ -3987,7 +3996,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
if (index >= table_interp->cur_size) {
return NULL;
}
ref_idx = table_interp->elems[index];
ref_idx = (uint32)table_interp->elems[index];
}
#endif
@ -3998,7 +4007,7 @@ wasm_table_get(const wasm_table_t *table, wasm_table_size_t index)
if (index >= table_aot->cur_size) {
return NULL;
}
ref_idx = table_aot->elems[index];
ref_idx = (uint32)table_aot->elems[index];
}
#endif

View File

@ -117,6 +117,9 @@ typedef struct WASMExecEnv {
/* whether current thread is detached */
bool thread_is_detached;
/* whether the aux stack is allocated */
bool is_aux_stack_allocated;
#endif
#if WASM_ENABLE_GC != 0

View File

@ -29,24 +29,43 @@ static void *enlarge_memory_error_user_data;
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
static void *allocator_user_data = NULL;
static void *(*malloc_func)(void *user_data, unsigned int size) = NULL;
static void *(*realloc_func)(void *user_data, void *ptr,
unsigned int size) = NULL;
static void (*free_func)(void *user_data, void *ptr) = NULL;
#else
static void *(*malloc_func)(unsigned int size) = NULL;
static void *(*realloc_func)(void *ptr, unsigned int size) = NULL;
static void (*free_func)(void *ptr) = NULL;
#endif
static void *(*malloc_func)(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
unsigned int size) = NULL;
static void *(*realloc_func)(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage, bool full_size_mmaped,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
void *ptr, unsigned int size) = NULL;
static void (*free_func)(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
void *ptr) = NULL;
static unsigned int global_pool_size;
static uint32
static uint64
align_as_and_cast(uint64 size, uint64 alignment)
{
uint64 aligned_size = (size + alignment - 1) & ~(alignment - 1);
return aligned_size > UINT32_MAX ? UINT32_MAX : (uint32)aligned_size;
return aligned_size;
}
static bool
@ -177,11 +196,14 @@ wasm_runtime_malloc_internal(unsigned int size)
return mem_allocator_malloc(pool_allocator, size);
}
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
return malloc_func(allocator_user_data, size);
#else
return malloc_func(size);
return malloc_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
Alloc_For_Runtime,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
allocator_user_data,
#endif
size);
}
else {
return os_malloc(size);
@ -201,11 +223,14 @@ wasm_runtime_realloc_internal(void *ptr, unsigned int size)
}
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
if (realloc_func)
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
return realloc_func(allocator_user_data, ptr, size);
#else
return realloc_func(ptr, size);
return realloc_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
Alloc_For_Runtime, false,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
allocator_user_data,
#endif
ptr, size);
else
return NULL;
}
@ -233,11 +258,14 @@ wasm_runtime_free_internal(void *ptr)
mem_allocator_free(pool_allocator, ptr);
}
else if (memory_mode == MEMORY_MODE_ALLOCATOR) {
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
free_func(allocator_user_data, ptr);
#else
free_func(ptr);
free_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
Alloc_For_Runtime,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
allocator_user_data,
#endif
ptr);
}
else {
os_free(ptr);
@ -286,6 +314,7 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst;
uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
@ -299,9 +328,13 @@ wasm_runtime_validate_app_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail;
}
#if WASM_ENABLE_MEMORY64 != 0
if (memory_inst->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check */
if (size > MAX_LINEAR_MEMORY_SIZE
|| app_offset > MAX_LINEAR_MEMORY_SIZE - size) {
if (size > max_linear_memory_size
|| app_offset > max_linear_memory_size - size) {
goto fail;
}
@ -324,7 +357,7 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
uint64 app_str_offset)
{
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
uint64 app_end_offset;
uint64 app_end_offset, max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
char *str, *str_end;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
@ -338,10 +371,14 @@ wasm_runtime_validate_app_str_addr(WASMModuleInstanceCommon *module_inst_comm,
&app_end_offset))
goto fail;
#if WASM_ENABLE_MEMORY64 != 0
if (module_inst->memories[0]->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check, max start offset can only be size - 1, while end
* offset can be size */
if (app_str_offset >= MAX_LINEAR_MEMORY_SIZE
|| app_end_offset > MAX_LINEAR_MEMORY_SIZE)
if (app_str_offset >= max_linear_memory_size
|| app_end_offset > max_linear_memory_size)
goto fail;
str = wasm_runtime_addr_app_to_native(module_inst_comm, app_str_offset);
@ -364,6 +401,7 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
WASMModuleInstance *module_inst = (WASMModuleInstance *)module_inst_comm;
WASMMemoryInstance *memory_inst;
uint8 *addr = (uint8 *)native_ptr;
uint64 max_linear_memory_size = MAX_LINEAR_MEMORY_SIZE;
bh_assert(module_inst_comm->module_type == Wasm_Module_Bytecode
|| module_inst_comm->module_type == Wasm_Module_AoT);
@ -377,8 +415,12 @@ wasm_runtime_validate_native_addr(WASMModuleInstanceCommon *module_inst_comm,
goto fail;
}
#if WASM_ENABLE_MEMORY64 != 0
if (memory_inst->is_memory64)
max_linear_memory_size = MAX_LINEAR_MEM64_MEMORY_SIZE;
#endif
/* boundary overflow check */
if (size > MAX_LINEAR_MEMORY_SIZE || (uintptr_t)addr > UINTPTR_MAX - size) {
if (size > max_linear_memory_size || (uintptr_t)addr > UINTPTR_MAX - size) {
goto fail;
}
@ -748,12 +790,36 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
goto return_func;
}
bh_assert(total_size_new <= MAX_LINEAR_MEMORY_SIZE);
bh_assert(total_size_new
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
#if WASM_MEM_ALLOC_WITH_USAGE != 0
if (!(memory_data_new =
realloc_func(Alloc_For_LinearMemory, full_size_mmaped,
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
NULL,
#endif
memory_data_old, total_size_new))) {
ret = false;
goto return_func;
}
if (heap_size > 0) {
if (mem_allocator_migrate(memory->heap_handle,
(char *)heap_data_old
+ (memory_data_new - memory_data_old),
heap_size)
!= 0) {
ret = false;
}
}
memory->heap_data = memory_data_new + (heap_data_old - memory_data_old);
memory->heap_data_end = memory->heap_data + heap_size;
memory->memory_data = memory_data_new;
#else
if (full_size_mmaped) {
#ifdef BH_PLATFORM_WINDOWS
if (!os_mem_commit(memory->memory_data_end,
(uint32)(total_size_new - total_size_old),
(mem_offset_t)(total_size_new - total_size_old),
MMAP_PROT_READ | MMAP_PROT_WRITE)) {
ret = false;
goto return_func;
@ -761,12 +827,12 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
#endif
if (os_mprotect(memory->memory_data_end,
(uint32)(total_size_new - total_size_old),
(mem_offset_t)(total_size_new - total_size_old),
MMAP_PROT_READ | MMAP_PROT_WRITE)
!= 0) {
#ifdef BH_PLATFORM_WINDOWS
os_mem_decommit(memory->memory_data_end,
(uint32)(total_size_new - total_size_old));
(mem_offset_t)(total_size_new - total_size_old));
#endif
ret = false;
goto return_func;
@ -808,6 +874,7 @@ wasm_enlarge_memory_internal(WASMModuleInstance *module, uint32 inc_page_count)
os_writegsbase(memory_data_new);
#endif
}
#endif /* end of WASM_MEM_ALLOC_WITH_USAGE */
memory->num_bytes_per_page = num_bytes_per_page;
memory->cur_page_count = total_page_count;
@ -888,15 +955,27 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst)
#else
map_size = 8 * (uint64)BH_GB;
#endif
#if WASM_MEM_ALLOC_WITH_USAGE != 0
(void)map_size;
free_func(Alloc_For_LinearMemory,
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
NULL,
#endif
memory_inst->memory_data);
#else
wasm_munmap_linear_memory(memory_inst->memory_data,
memory_inst->memory_data_size, map_size);
#endif
memory_inst->memory_data = NULL;
}
int
wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
uint64 num_bytes_per_page, uint64 init_page_count,
uint64 max_page_count, uint64 *memory_data_size)
bool is_memory64, uint64 num_bytes_per_page,
uint64 init_page_count, uint64 max_page_count,
uint64 *memory_data_size)
{
uint64 map_size, page_size;
@ -925,13 +1004,33 @@ wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
page_size = os_getpagesize();
*memory_data_size = init_page_count * num_bytes_per_page;
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
bh_assert(*memory_data_size <= MAX_LINEAR_MEM64_MEMORY_SIZE);
}
else
#endif
{
bh_assert(*memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
align_as_and_cast(*memory_data_size, page_size);
}
*memory_data_size = align_as_and_cast(*memory_data_size, page_size);
if (map_size > 0) {
#if WASM_MEM_ALLOC_WITH_USAGE != 0
(void)wasm_mmap_linear_memory;
if (!(*data = malloc_func(Alloc_For_LinearMemory,
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
NULL,
#endif
*memory_data_size))) {
return BHT_ERROR;
}
#else
if (!(*data = wasm_mmap_linear_memory(map_size, *memory_data_size))) {
return BHT_ERROR;
}
#endif
}
return BHT_OK;

View File

@ -64,8 +64,9 @@ wasm_deallocate_linear_memory(WASMMemoryInstance *memory_inst);
int
wasm_allocate_linear_memory(uint8 **data, bool is_shared_memory,
uint64 num_bytes_per_page, uint64 init_page_count,
uint64 max_page_count, uint64 *memory_data_size);
bool is_memory64, uint64 num_bytes_per_page,
uint64 init_page_count, uint64 max_page_count,
uint64 *memory_data_size);
#ifdef __cplusplus
}

View File

@ -84,9 +84,9 @@ compare_type_with_signautre(uint8 type, const char signature)
if ('r' == signature
#if WASM_ENABLE_GC != 0
#if WASM_ENABLE_STRINGREF != 0
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_FUNCREF)
&& (type >= REF_TYPE_STRINGVIEWITER && type <= REF_TYPE_NULLFUNCREF)
#else
&& (type >= REF_TYPE_NULLREF && type <= REF_TYPE_FUNCREF)
&& (type >= REF_TYPE_HT_NULLABLE && type <= REF_TYPE_NULLFUNCREF)
#endif
#else
&& type == VALUE_TYPE_EXTERNREF

View File

@ -65,7 +65,7 @@
#if WASM_ENABLE_MULTI_MODULE != 0
/**
* A safety insurance to prevent
* circular depencies which leads stack overflow
* circular dependencies which leads stack overflow
* try to break early
*/
typedef struct LoadingModule {
@ -275,11 +275,11 @@ decode_insn(uint8 *insn)
buffer, sizeof(buffer),
runtime_address);
#if 0
/* Print current instruction */
/*
os_printf("%012" PRIX64 " ", runtime_address);
puts(buffer);
*/
#endif
return instruction.length;
}
@ -564,8 +564,20 @@ wasm_runtime_exec_env_check(WASMExecEnv *exec_env)
&& exec_env->wasm_stack.top <= exec_env->wasm_stack.top_boundary;
}
bool
wasm_runtime_init()
#if defined(OS_THREAD_MUTEX_INITIALIZER)
/**
* lock for wasm_runtime_init/wasm_runtime_full_init and runtime_ref_count
* Note: if the platform has mutex initializer, we use a global lock to
* lock the operations of runtime init/full_init, otherwise when there are
* operations happening simultaneously in multiple threads, developer
* must create the lock by himself, and use it to lock the operations
*/
static korp_mutex runtime_lock = OS_THREAD_MUTEX_INITIALIZER;
#endif
static int32 runtime_ref_count = 0;
static bool
wasm_runtime_init_internal()
{
if (!wasm_runtime_memory_init(Alloc_With_System_Allocator, NULL))
return false;
@ -578,8 +590,32 @@ wasm_runtime_init()
return true;
}
void
wasm_runtime_destroy()
bool
wasm_runtime_init()
{
bool ret = true;
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_lock(&runtime_lock);
#endif
bh_assert(runtime_ref_count >= 0);
if (runtime_ref_count == 0) {
ret = wasm_runtime_init_internal();
}
if (ret) {
runtime_ref_count++;
}
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_unlock(&runtime_lock);
#endif
return ret;
}
static void
wasm_runtime_destroy_internal()
{
#if WASM_ENABLE_GC == 0 && WASM_ENABLE_REF_TYPES != 0
wasm_externref_map_destroy();
@ -640,6 +676,24 @@ wasm_runtime_destroy()
wasm_runtime_memory_destroy();
}
void
wasm_runtime_destroy()
{
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_lock(&runtime_lock);
#endif
bh_assert(runtime_ref_count > 0);
runtime_ref_count--;
if (runtime_ref_count == 0) {
wasm_runtime_destroy_internal();
}
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_unlock(&runtime_lock);
#endif
}
RunningMode
wasm_runtime_get_default_running_mode(void)
{
@ -662,8 +716,8 @@ wasm_runtime_get_gc_heap_size_default(void)
}
#endif
bool
wasm_runtime_full_init(RuntimeInitArgs *init_args)
static bool
wasm_runtime_full_init_internal(RuntimeInitArgs *init_args)
{
if (!wasm_runtime_memory_init(init_args->mem_alloc_type,
&init_args->mem_alloc_option))
@ -725,6 +779,30 @@ wasm_runtime_full_init(RuntimeInitArgs *init_args)
return true;
}
bool
wasm_runtime_full_init(RuntimeInitArgs *init_args)
{
bool ret = true;
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_lock(&runtime_lock);
#endif
bh_assert(runtime_ref_count >= 0);
if (runtime_ref_count == 0) {
ret = wasm_runtime_full_init_internal(init_args);
}
if (ret) {
runtime_ref_count++;
}
#if defined(OS_THREAD_MUTEX_INITIALIZER)
os_mutex_unlock(&runtime_lock);
#endif
return ret;
}
void
wasm_runtime_set_log_level(log_level_t level)
{
@ -965,7 +1043,7 @@ wasm_runtime_register_module_internal(const char *module_name,
/* module hasn't been registered */
node = runtime_malloc(sizeof(WASMRegisteredModule), NULL, NULL, 0);
if (!node) {
LOG_DEBUG("malloc WASMRegisteredModule failed. SZ=%d",
LOG_DEBUG("malloc WASMRegisteredModule failed. SZ=%zu",
sizeof(WASMRegisteredModule));
return false;
}
@ -1255,11 +1333,15 @@ register_module_with_null_name(WASMModuleCommon *module_common, char *error_buf,
}
WASMModuleCommon *
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size)
wasm_runtime_load_ex(uint8 *buf, uint32 size, const LoadArgs *args,
char *error_buf, uint32 error_buf_size)
{
WASMModuleCommon *module_common = NULL;
if (!args) {
return NULL;
}
if (get_package_type(buf, size) == Wasm_Module_Bytecode) {
#if WASM_ENABLE_INTERP != 0
module_common =
@ -1267,13 +1349,13 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
#if WASM_ENABLE_MULTI_MODULE != 0
true,
#endif
error_buf, error_buf_size);
args, error_buf, error_buf_size);
#endif
}
else if (get_package_type(buf, size) == Wasm_Module_AoT) {
#if WASM_ENABLE_AOT != 0
module_common = (WASMModuleCommon *)aot_load_from_aot_file(
buf, size, error_buf, error_buf_size);
buf, size, args, error_buf, error_buf_size);
#endif
}
else {
@ -1289,10 +1371,21 @@ wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
LOG_DEBUG("WASM module load failed");
return NULL;
}
/*TODO: use file name as name and register with name? */
return register_module_with_null_name(module_common, error_buf,
error_buf_size);
}
WASMModuleCommon *
wasm_runtime_load(uint8 *buf, uint32 size, char *error_buf,
uint32 error_buf_size)
{
LoadArgs args = { 0 };
args.name = "";
return wasm_runtime_load_ex(buf, size, &args, error_buf, error_buf_size);
}
WASMModuleCommon *
wasm_runtime_load_from_sections(WASMSection *section_list, bool is_aot,
char *error_buf, uint32 error_buf_size)
@ -1702,7 +1795,7 @@ wasm_runtime_dump_mem_consumption(WASMExecEnv *exec_env)
wasm_runtime_dump_module_inst_mem_consumption(module_inst_common);
wasm_runtime_dump_exec_env_mem_consumption(exec_env);
os_printf("\nTotal memory consumption of module, module inst and "
"exec env: %u\n",
"exec env: %" PRIu64 "\n",
total_size);
os_printf("Total interpreter stack used: %u\n",
exec_env->max_wasm_stack_used);
@ -3668,7 +3761,7 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
WASMModuleInstanceCommon *module = wasm_runtime_get_module_inst(exec_env);
typedef void (*NativeRawFuncPtr)(WASMExecEnv *, uint64 *);
NativeRawFuncPtr invoke_native_raw = (NativeRawFuncPtr)func_ptr;
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size;
uint64 argv_buf[16] = { 0 }, *argv1 = argv_buf, *argv_dst, size, arg_i64;
uint32 *argv_src = argv, i, argc1, ptr_len;
uint32 arg_i32;
bool ret = false;
@ -3692,9 +3785,11 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
case VALUE_TYPE_FUNCREF:
#endif
{
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
*(uint32 *)argv_dst = arg_i32 = *argv_src++;
/* TODO: memory64 if future there is a way for supporting
* wasm64 and wasm32 in libc at the same time, remove the
* macro control */
#if WASM_ENABLE_MEMORY64 == 0
if (signature) {
if (signature[i + 1] == '*') {
/* param is a pointer */
@ -3724,9 +3819,49 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
module, (uint64)arg_i32);
}
}
#endif
break;
}
case VALUE_TYPE_I64:
#if WASM_ENABLE_MEMORY64 != 0
{
PUT_I64_TO_ADDR((uint32 *)argv_dst,
GET_I64_FROM_ADDR(argv_src));
argv_src += 2;
arg_i64 = *argv_dst;
if (signature) {
/* TODO: memory64 pointer with length need a new symbol
* to represent type i64, with '~' still represent i32
* length */
if (signature[i + 1] == '*') {
/* param is a pointer */
if (signature[i + 2] == '~')
/* pointer with length followed */
ptr_len = *argv_src;
else
/* pointer without length followed */
ptr_len = 1;
if (!wasm_runtime_validate_app_addr(module, arg_i64,
(uint64)ptr_len))
goto fail;
*argv_dst = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
else if (signature[i + 1] == '$') {
/* param is a string */
if (!wasm_runtime_validate_app_str_addr(module,
arg_i64))
goto fail;
*argv_dst = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
}
break;
}
#endif
case VALUE_TYPE_F64:
bh_memcpy_s(argv_dst, sizeof(uint64), argv_src,
sizeof(uint32) * 2);
@ -3855,6 +3990,9 @@ wasm_runtime_invoke_native_raw(WASMExecEnv *exec_env, void *func_ptr,
fail:
if (argv1 != argv_buf)
wasm_runtime_free(argv1);
#if WASM_ENABLE_MEMORY64 == 0
(void)arg_i64;
#endif
return ret;
}
@ -4117,8 +4255,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{
arg_i32 = *argv_src++;
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
if (signature) {
if (signature[i + 1] == '*') {
/* param is a pointer */
@ -4494,8 +4630,6 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{
arg_i32 = *argv++;
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
if (signature) {
if (signature[i + 1] == '*') {
/* param is a pointer */
@ -4811,8 +4945,10 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
{
arg_i32 = *argv_src++;
arg_i64 = arg_i32;
/* TODO: memory64 the data type of ptr_len and argc depends on
* mem idx type */
/* TODO: memory64 if future there is a way for supporting
* wasm64 and wasm32 in libc at the same time, remove the
* macro control */
#if WASM_ENABLE_MEMORY64 == 0
if (signature) {
if (signature[i + 1] == '*') {
/* param is a pointer */
@ -4840,6 +4976,7 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
module, (uint64)arg_i32);
}
}
#endif
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = arg_i64;
else
@ -4847,6 +4984,47 @@ wasm_runtime_invoke_native(WASMExecEnv *exec_env, void *func_ptr,
break;
}
case VALUE_TYPE_I64:
#if WASM_ENABLE_MEMORY64 != 0
{
arg_i64 = GET_I64_FROM_ADDR(argv_src);
argv_src += 2;
if (signature) {
/* TODO: memory64 pointer with length need a new symbol
* to represent type i64, with '~' still represent i32
* length */
if (signature[i + 1] == '*') {
/* param is a pointer */
if (signature[i + 2] == '~')
/* pointer with length followed */
ptr_len = *argv_src;
else
/* pointer without length followed */
ptr_len = 1;
if (!wasm_runtime_validate_app_addr(module, arg_i64,
(uint64)ptr_len))
goto fail;
arg_i64 = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
else if (signature[i + 1] == '$') {
/* param is a string */
if (!wasm_runtime_validate_app_str_addr(module,
arg_i64))
goto fail;
arg_i64 = (uint64)wasm_runtime_addr_app_to_native(
module, arg_i64);
}
}
if (n_ints < MAX_REG_INTS)
ints[n_ints++] = arg_i64;
else
stacks[n_stacks++] = arg_i64;
break;
}
#endif
#if WASM_ENABLE_GC != 0
case REF_TYPE_FUNCREF:
case REF_TYPE_EXTERNREF:
@ -5325,6 +5503,7 @@ wasm_externref_set_cleanup(WASMModuleInstanceCommon *module_inst,
if (lookup_user_data.found) {
void *key = (void *)(uintptr_t)lookup_user_data.externref_idx;
ExternRefMapNode *node = bh_hash_map_find(externref_map, key);
bh_assert(node);
node->cleanup = extern_obj_cleanup;
ok = true;
}
@ -6337,6 +6516,7 @@ wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
bool ret = false;
uint8 *buffer = NULL;
uint32 buffer_size = 0;
LoadArgs args = { 0 };
/* check the registered module list of the parent */
sub_module = wasm_runtime_search_sub_module(parent_module, sub_module_name);
@ -6376,23 +6556,25 @@ wasm_runtime_load_depended_module(const WASMModuleCommon *parent_module,
if (!ret) {
LOG_DEBUG("read the file of %s failed", sub_module_name);
set_error_buf_v(parent_module, error_buf, error_buf_size,
"unknown import", sub_module_name);
"unknown import %s", sub_module_name);
goto delete_loading_module;
}
if (get_package_type(buffer, buffer_size) != parent_module->module_type) {
LOG_DEBUG("moudle %s type error", sub_module_name);
goto delete_loading_module;
goto destroy_file_buffer;
}
args.name = (char *)sub_module_name;
if (get_package_type(buffer, buffer_size) == Wasm_Module_Bytecode) {
#if WASM_ENABLE_INTERP != 0
sub_module = (WASMModuleCommon *)wasm_load(buffer, buffer_size, false,
error_buf, error_buf_size);
sub_module = (WASMModuleCommon *)wasm_load(
buffer, buffer_size, false, &args, error_buf, error_buf_size);
#endif
}
else if (get_package_type(buffer, buffer_size) == Wasm_Module_AoT) {
#if WASM_ENABLE_AOT != 0
sub_module = (WASMModuleCommon *)aot_load_from_aot_file(
buffer, buffer_size, error_buf, error_buf_size);
buffer, buffer_size, &args, error_buf, error_buf_size);
#endif
}
if (!sub_module) {
@ -6487,7 +6669,7 @@ wasm_runtime_sub_module_instantiate(WASMModuleCommon *module,
sub_module_inst_list_node = loader_malloc(sizeof(WASMSubModInstNode),
error_buf, error_buf_size);
if (!sub_module_inst_list_node) {
LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ:%d",
LOG_DEBUG("Malloc WASMSubModInstNode failed, SZ: %zu",
sizeof(WASMSubModInstNode));
if (sub_module_inst)
wasm_runtime_deinstantiate_internal(sub_module_inst, false);

View File

@ -373,7 +373,7 @@ typedef struct WASMModuleCommon {
/* The following uint8[1] member is a dummy just to indicate
some module_type dependent members follow.
Typically it should be accessed by casting to the corresponding
Typically, it should be accessed by casting to the corresponding
actual module_type dependent structure, not via this member. */
uint8 module_data[1];
} WASMModuleCommon;
@ -389,7 +389,7 @@ typedef struct WASMModuleInstanceCommon {
/* The following uint8[1] member is a dummy just to indicate
some module_type dependent members follow.
Typically it should be accessed by casting to the corresponding
Typically, it should be accessed by casting to the corresponding
actual module_type dependent structure, not via this member. */
uint8 module_inst_data[1];
} WASMModuleInstanceCommon;

View File

@ -330,7 +330,7 @@ aot_gen_commit_values(AOTCompFrame *frame)
if (!p->dirty)
continue;
n = p - frame->lp;
n = (uint32)(p - frame->lp);
/* Commit reference flag */
if (comp_ctx->enable_gc) {
@ -432,7 +432,7 @@ aot_gen_commit_values(AOTCompFrame *frame)
continue;
p->dirty = 0;
n = p - frame->lp;
n = (uint32)(p - frame->lp);
/* Commit values */
switch (p->type) {
@ -538,7 +538,7 @@ aot_gen_commit_values(AOTCompFrame *frame)
/* Clear reference flags for unused stack slots. */
for (p = frame->sp; p < end; p++) {
bh_assert(!p->ref);
n = p - frame->lp;
n = (uint32)(p - frame->lp);
/* Commit reference flag. */
if (p->ref != p->committed_ref - 1) {
@ -621,7 +621,7 @@ aot_gen_commit_sp_ip(AOTCompFrame *frame, bool commit_sp, bool commit_ip)
}
if (commit_sp) {
n = sp - frame->lp;
n = (uint32)(sp - frame->lp);
value = I32_CONST(offset_of_local(comp_ctx, n));
if (!value) {
aot_set_last_error("llvm build const failed");
@ -966,7 +966,9 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
location = dwarf_gen_location(
comp_ctx, func_ctx,
(frame_ip - 1) - comp_ctx->comp_data->wasm_module->buf_code);
if (location != NULL) {
LLVMSetCurrentDebugLocation2(comp_ctx->builder, location);
}
#endif
switch (opcode) {
@ -3450,16 +3452,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_i32x4_narrow_i64x2_s:
case SIMD_i32x4_narrow_i64x2_u:
{
if (!aot_compile_simd_i32x4_narrow_i64x2(
comp_ctx, func_ctx,
SIMD_i32x4_narrow_i64x2_s == opcode))
return false;
break;
}
case SIMD_i32x4_extend_low_i16x8_s:
case SIMD_i32x4_extend_high_i16x8_s:
{
@ -3499,16 +3491,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_i32x4_add_sat_s:
case SIMD_i32x4_add_sat_u:
{
if (!aot_compile_simd_i32x4_saturate(
comp_ctx, func_ctx, V128_ADD,
opcode == SIMD_i32x4_add_sat_s))
return false;
break;
}
case SIMD_i32x4_sub:
{
if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
@ -3517,16 +3499,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_i32x4_sub_sat_s:
case SIMD_i32x4_sub_sat_u:
{
if (!aot_compile_simd_i32x4_saturate(
comp_ctx, func_ctx, V128_SUB,
opcode == SIMD_i32x4_add_sat_s))
return false;
break;
}
case SIMD_i32x4_mul:
{
if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
@ -3563,13 +3535,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_i32x4_avgr_u:
{
if (!aot_compile_simd_i32x4_avgr_u(comp_ctx, func_ctx))
return false;
break;
}
case SIMD_i32x4_extmul_low_i16x8_s:
case SIMD_i32x4_extmul_high_i16x8_s:
{
@ -3726,13 +3691,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_f32x4_round:
{
if (!aot_compile_simd_f32x4_round(comp_ctx, func_ctx))
return false;
break;
}
case SIMD_f32x4_sqrt:
{
if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx))
@ -3786,13 +3744,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break;
}
case SIMD_f64x2_round:
{
if (!aot_compile_simd_f64x2_round(comp_ctx, func_ctx))
return false;
break;
}
case SIMD_f64x2_sqrt:
{
if (!aot_compile_simd_f64x2_sqrt(comp_ctx, func_ctx))

View File

@ -484,15 +484,15 @@ static uint32
get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
{
#if WASM_ENABLE_GC != 0
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + param
* count + result count
* + ref_type_map_count + types + context of ref_type_map */
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
+ rec_count + rec_idx + param count + result count
+ ref_type_map_count + types + context of ref_type_map */
if (comp_ctx->enable_gc) {
uint32 size = 0;
/* type flag */
size += sizeof(func_type->base_type.type_flag);
/* is_sub_final */
/* equivalence type flag + is_sub_final */
size += sizeof(uint16);
/* parent_type_idx */
size += sizeof(func_type->base_type.parent_type_idx);
@ -529,12 +529,12 @@ static uint32
get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
{
uint32 size = 0;
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + field
* count + fields */
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
+ rec_count + rec_idx + field count + fields */
/* type flag */
size += sizeof(struct_type->base_type.type_flag);
/* is_sub_final */
/* equivalence type flag + is_sub_final */
size += sizeof(uint16);
/* parent_type_idx */
size += sizeof(struct_type->base_type.parent_type_idx);
@ -558,12 +558,12 @@ static uint32
get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
{
uint32 size = 0;
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx +
elem_flags + elem_type + elem_ref_type */
/* type flag + equivalence type flag + is_sub_final + parent_type_idx
+ rec_count + rec_idx + elem_flags + elem_type + elem_ref_type */
/* type flag */
size += sizeof(array_type->base_type.type_flag);
/* is_sub_final */
/* equivalence type flag + is_sub_final */
size += sizeof(uint16);
/* parent_type_idx (u32) */
size += sizeof(array_type->base_type.parent_type_idx);
@ -597,7 +597,22 @@ get_type_info_size(AOTCompContext *comp_ctx, AOTCompData *comp_data)
#if WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc) {
for (i = 0; i < comp_data->type_count; i++) {
uint32 j;
size = align_uint(size, 4);
/* Emit simple info if there is an equivalence type */
for (j = 0; j < i; j++) {
if (comp_data->types[j] == comp_data->types[i]) {
/* type_flag (2 bytes) + equivalence type flag (1 byte)
+ padding (1 byte) + equivalence type index */
size += 8;
break;
}
}
if (j < i)
continue;
if (comp_data->types[i]->type_flag == WASM_TYPE_FUNC)
size += get_func_type_size(comp_ctx,
(AOTFuncType *)comp_data->types[i]);
@ -2093,13 +2108,32 @@ aot_emit_type_info(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
#if WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc) {
int32 idx;
AOTType **types = comp_data->types;
int32 idx;
uint32 j;
for (i = 0; i < comp_data->type_count; i++) {
offset = align_uint(offset, 4);
/* Emit simple info if there is an equivalence type */
for (j = 0; j < i; j++) {
if (types[j] == types[i]) {
EMIT_U16(types[i]->type_flag);
EMIT_U16(types[i]->is_sub_final);
/* equivalence type flag is true */
EMIT_U8(1);
EMIT_U8(0);
/* equivalence type index */
EMIT_U32(j);
break;
}
}
if (j < i)
continue;
EMIT_U16(types[i]->type_flag);
/* equivalence type flag is false */
EMIT_U8(0);
EMIT_U8(types[i]->is_sub_final);
EMIT_U32(types[i]->parent_type_idx);
EMIT_U16(types[i]->rec_count);
@ -2593,7 +2627,7 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
if (comp_ctx->enable_gc) {
/* emit func_local_ref_flag arrays for both import and AOTed funcs */
AOTFuncType *func_type;
uint32 j, local_ref_flags_cell_num;
uint32 j, local_ref_flags_cell_num, paddings;
for (i = 0; i < comp_data->import_func_count; i++) {
func_type = comp_data->import_funcs[i].func_type;
@ -2603,6 +2637,8 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
func_type->types[j], comp_ctx->pointer_size);
}
paddings =
local_ref_flags_cell_num < 2 ? 2 - local_ref_flags_cell_num : 0;
local_ref_flags_cell_num =
local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2;
@ -2614,7 +2650,7 @@ aot_emit_func_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
func_type->types[j]))
return false;
}
for (; j < 2; j++)
for (j = 0; j < paddings; j++)
EMIT_U8(0);
}

View File

@ -374,7 +374,9 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
#if WASM_ENABLE_DEBUG_AOT != 0
if (return_location != NULL) {
LLVMInstructionSetDebugLoc(ret, return_location);
}
#endif
}
else {
@ -383,7 +385,9 @@ handle_next_reachable_block(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
#if WASM_ENABLE_DEBUG_AOT != 0
if (return_location != NULL) {
LLVMInstructionSetDebugLoc(ret, return_location);
}
#endif
}
}
@ -1265,6 +1269,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
PUSH(values[j], target_block->result_types[j]);
}
wasm_runtime_free(values);
values = NULL;
}
target_block->is_reachable = true;
if (i == br_count)
@ -1290,6 +1295,7 @@ aot_compile_op_br_table(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
PUSH(values[j], target_block->param_types[j]);
}
wasm_runtime_free(values);
values = NULL;
}
if (i == br_count)
default_llvm_block = target_block->llvm_entry_block;

View File

@ -1826,6 +1826,52 @@ fail:
return ret;
}
#if WASM_ENABLE_GC != 0
static LLVMValueRef
call_aot_func_type_is_super_of_func(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
LLVMValueRef type_idx1,
LLVMValueRef type_idx2)
{
LLVMValueRef param_values[3], ret_value, value, func;
LLVMTypeRef param_types[3], ret_type, func_type, func_ptr_type;
param_types[0] = comp_ctx->aot_inst_type;
param_types[1] = I32_TYPE;
param_types[2] = I32_TYPE;
ret_type = INT8_TYPE;
#if WASM_ENABLE_JIT != 0
if (comp_ctx->is_jit_mode)
GET_AOT_FUNCTION(llvm_jit_func_type_is_super_of, 3);
else
#endif
GET_AOT_FUNCTION(aot_func_type_is_super_of, 3);
param_values[0] = func_ctx->aot_inst;
param_values[1] = type_idx1;
param_values[2] = type_idx2;
if (!(ret_value =
LLVMBuildCall2(comp_ctx->builder, func_type, func, param_values,
3, "call_aot_func_type_is_super_of"))) {
aot_set_last_error("llvm build call failed.");
return NULL;
}
if (!(ret_value = LLVMBuildICmp(comp_ctx->builder, LLVMIntEQ, ret_value,
I8_ZERO, "check_fail"))) {
aot_set_last_error("llvm build icmp failed.");
return NULL;
}
return ret_value;
fail:
return NULL;
}
#endif
static bool
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *aot_func_type,
@ -2018,15 +2064,23 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false;
}
if (!comp_ctx->enable_gc) {
/* Find the equivalent function type whose type index is the smallest:
the callee function's type index is also converted to the smallest
one in wasm loader, so we can just check whether the two type indexes
are equal (the type index of call_indirect opcode and callee func),
we don't need to check whether the whole function types are equal,
including param types and result types. */
type_idx =
wasm_get_smallest_type_idx((WASMTypePtr *)comp_ctx->comp_data->types,
type_idx = wasm_get_smallest_type_idx(
(WASMTypePtr *)comp_ctx->comp_data->types,
comp_ctx->comp_data->type_count, type_idx);
}
else {
/* Call aot_func_type_is_super_of to check whether the func type
provided in the bytecode is a super type of the func type of
the function to call */
}
ftype_idx_const = I32_CONST(type_idx);
CHECK_LLVM_CONST(ftype_idx_const);
@ -2254,12 +2308,24 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail;
}
#if WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc) {
if (!(cmp_ftype_idx = call_aot_func_type_is_super_of_func(
comp_ctx, func_ctx, ftype_idx_const, ftype_idx))) {
goto fail;
}
}
else
#endif
{
/* Check if function type index not equal */
if (!(cmp_ftype_idx = LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx,
if (!(cmp_ftype_idx =
LLVMBuildICmp(comp_ctx->builder, LLVMIntNE, ftype_idx,
ftype_idx_const, "cmp_ftype_idx"))) {
aot_set_last_error("llvm build icmp failed.");
goto fail;
}
}
/* Throw exception if ftype_idx != ftype_idx_const */
if (!(check_ftype_idx_succ = LLVMAppendBasicBlockInContext(

View File

@ -85,7 +85,7 @@ aot_add_llvm_func1(const AOTCompContext *comp_ctx, LLVMModuleRef module,
uint32 func_index, uint32 param_count, LLVMTypeRef func_type,
const char *prefix)
{
char func_name[48];
char func_name[48] = { 0 };
LLVMValueRef func;
LLVMValueRef local_value;
uint32 i, j;
@ -674,7 +674,8 @@ aot_add_llvm_func(AOTCompContext *comp_ctx, LLVMModuleRef module,
uint32 backend_thread_num, compile_thread_num;
/* Check function parameter types and result types */
for (i = 0; i < aot_func_type->param_count + aot_func_type->result_count;
for (i = 0;
i < (uint32)(aot_func_type->param_count + aot_func_type->result_count);
i++) {
if (!check_wasm_type(comp_ctx, aot_func_type->types[i]))
return NULL;
@ -2547,6 +2548,9 @@ aot_create_comp_context(const AOTCompData *comp_data, aot_comp_option_t option)
aot_set_last_error("create LLVM module failed.");
goto fail;
}
#if LLVM_VERSION_MAJOR >= 19
LLVMSetIsNewDbgInfoFormat(comp_ctx->module, true);
#endif
#if WASM_ENABLE_LINUX_PERF != 0
if (wasm_runtime_get_linux_perf()) {

View File

@ -295,6 +295,28 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
const size_t num_function_args = function_args.GetSize();
dwarf_extractor *extractor;
/*
* Process only known languages.
* We have a few assumptions which might not be true for non-C functions.
*
* At least it's known broken for C++ and Rust:
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/3187
* https://github.com/bytecodealliance/wasm-micro-runtime/issues/3163
*/
LanguageType language_type = function.GetLanguage();
switch (language_type) {
case eLanguageTypeC89:
case eLanguageTypeC:
case eLanguageTypeC99:
case eLanguageTypeC11:
case eLanguageTypeC17:
break;
default:
LOG_WARNING("func %s has unsuppoted language_type 0x%x",
function_name, (int)language_type);
return NULL;
}
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
return NULL;
@ -313,6 +335,17 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
if (function_arg_type.IsValid()) {
ParamTypes[function_arg_idx + 1] =
lldb_type_to_type_dbi(comp_ctx, function_arg_type);
if (ParamTypes[function_arg_idx + 1] == NULL) {
LOG_WARNING(
"func %s arg %" PRIu32
" has a type not implemented by lldb_type_to_type_dbi",
function_name, function_arg_idx);
}
}
else {
LOG_WARNING("func %s arg %" PRIu32 ": GetTypeAtIndex failed",
function_name, function_arg_idx);
ParamTypes[function_arg_idx + 1] = NULL;
}
}
@ -354,28 +387,11 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
LLVMDIBuilderCreateExpression(DIB, NULL, 0);
auto variable_list =
function.GetBlock().GetVariables(extractor->target, true, false, false);
unsigned int variable_offset = 0;
if (num_function_args != variable_list.GetSize()) {
// A hack to detect C++ "this" pointer.
//
// REVISIT: is there a more reliable way?
// At the DWARF level, we can probably look at DW_AT_object_pointer
// and DW_AT_artificial. I'm not sure how it can be done via the
// LLDB API though.
if (num_function_args + 1 == variable_list.GetSize()) {
SBValue variable(variable_list.GetValueAtIndex(0));
const char *varname = variable.GetName();
if (varname != NULL && !strcmp(varname, "this")) {
variable_offset = 1;
}
}
if (!variable_offset) {
LOG_ERROR("function args number dismatch!:function %s %s value "
"number=%d, function args=%d",
function_name, function.GetMangledName(),
LOG_ERROR(
"function args number dismatch!:value number=%d, function args=%d",
variable_list.GetSize(), num_function_args);
}
}
LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
comp_ctx->context, line_entry.GetLine(), 0, FunctionMetadata, NULL);
@ -395,11 +411,10 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar, ParamExpression,
ParamLocation, block_curr);
for (uint32_t function_arg_idx = 0; function_arg_idx < num_function_args;
++function_arg_idx) {
uint32_t variable_idx = variable_offset + function_arg_idx;
SBValue variable(variable_list.GetValueAtIndex(variable_idx));
if (variable.IsValid()) {
for (uint32_t function_arg_idx = 0;
function_arg_idx < variable_list.GetSize(); ++function_arg_idx) {
SBValue variable(variable_list.GetValueAtIndex(function_arg_idx));
if (variable.IsValid() && ParamTypes[function_arg_idx + 1] != NULL) {
SBDeclaration dec(variable.GetDeclaration());
auto valtype = variable.GetType();
LLVMMetadataRef ParamLocation = LLVMDIBuilderCreateDebugLocation(
@ -408,11 +423,12 @@ lldb_function_to_function_dbi(const AOTCompContext *comp_ctx,
const char *varname = variable.GetName();
LLVMMetadataRef ParamVar = LLVMDIBuilderCreateParameterVariable(
DIB, FunctionMetadata, varname, varname ? strlen(varname) : 0,
variable_idx + 1 + 1,
function_arg_idx + 1 + 1,
File, // starts form 1, and 1 is exenv,
dec.GetLine(), ParamTypes[function_arg_idx + 1], true,
LLVMDIFlagZero);
LLVMValueRef Param = LLVMGetParam(func_ctx->func, variable_idx + 1);
LLVMValueRef Param =
LLVMGetParam(func_ctx->func, function_arg_idx + 1);
LLVMDIBuilderInsertDbgValueAtEnd(DIB, Param, ParamVar,
ParamExpression, ParamLocation,
block_curr);
@ -491,6 +507,8 @@ dwarf_gen_location(const AOTCompContext *comp_ctx,
dwarf_extractor *extractor;
AOTFunc *func = func_ctx->aot_func;
if (func_ctx->debug_func == NULL)
return NULL;
if (!(extractor = TO_EXTACTOR(comp_ctx->comp_data->extractor)))
return NULL;

View File

@ -226,15 +226,6 @@ aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
}
}
bool
aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_signed)
{
/* TODO: x86 intrinsics */
return simd_integer_narrow_common(comp_ctx, func_ctx, e_sat_i64x2,
is_signed);
}
enum integer_extend_type {
e_ext_i8x16,
e_ext_i16x8,

View File

@ -20,10 +20,6 @@ bool
aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_signed);
bool
aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_signed);
bool
aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_low,

View File

@ -129,20 +129,6 @@ aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
"llvm.fabs.v2f64");
}
bool
aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
return simd_float_intrinsic(comp_ctx, func_ctx, V128_f32x4_TYPE,
"llvm.round.v4f32");
}
bool
aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{
return simd_float_intrinsic(comp_ctx, func_ctx, V128_f64x2_TYPE,
"llvm.round.v2f64");
}
bool
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
{

View File

@ -32,14 +32,6 @@ aot_compile_simd_f32x4_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
bool
aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);
bool
aot_compile_simd_f32x4_round(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);
bool
aot_compile_simd_f64x2_round(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);
bool
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx);

View File

@ -243,7 +243,6 @@ aot_compile_simd_i64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx)
enum integer_avgr_u {
e_avgr_u_i8x16,
e_avgr_u_i16x8,
e_avgr_u_i32x4,
};
/* TODO: try int_x86_mmx_pavg_b and int_x86_mmx_pavg_w */
@ -257,9 +256,8 @@ simd_v128_avg(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
LLVMTypeRef vector_type[] = {
V128_i8x16_TYPE,
V128_i16x8_TYPE,
V128_i32x4_TYPE,
};
unsigned lanes[] = { 16, 8, 4 };
unsigned lanes[] = { 16, 8 };
if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
vector_type[itype], "rhs"))
@ -325,13 +323,6 @@ aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i16x8);
}
bool
aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx)
{
return simd_v128_avg(comp_ctx, func_ctx, e_avgr_u_i32x4);
}
bool
aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx)

View File

@ -76,10 +76,6 @@ bool
aot_compile_simd_i16x8_avgr_u(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);
bool
aot_compile_simd_i32x4_avgr_u(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);
bool
aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx);

View File

@ -64,18 +64,3 @@ aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
is_signed ? intrinsics[arith_op][0]
: intrinsics[arith_op][1]);
}
bool
aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
V128Arithmetic arith_op, bool is_signed)
{
char *intrinsics[][2] = {
{ "llvm.sadd.sat.v4i32", "llvm.uadd.sat.v4i32" },
{ "llvm.ssub.sat.v4i32", "llvm.usub.sat.v4i32" },
};
return simd_sat_int_arith(comp_ctx, func_ctx, V128_i16x8_TYPE,
is_signed ? intrinsics[arith_op][0]
: intrinsics[arith_op][1]);
}

View File

@ -22,10 +22,6 @@ aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
V128Arithmetic arith_op, bool is_signed);
bool
aot_compile_simd_i32x4_saturate(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx,
V128Arithmetic arith_op, bool is_signed);
#ifdef __cplusplus
} /* end of extern "C" */
#endif

View File

@ -7511,7 +7511,7 @@ at_rmw_xor_r_base_r_offset_r(x86::Assembler &a, uint32 bytes_dst,
CHECK_KIND(r3, JIT_REG_KIND_I64); \
} \
/* r0: read/return value r2: memory base addr can't be const */ \
/* already check it's not const in LOAD_4ARGS(); */ \
/* already check it's not const in LOAD_4ARGS() */ \
reg_no_dst = jit_reg_no(r0); \
CHECK_REG_NO(reg_no_dst, jit_reg_kind(r0)); \
/* mem_data base address has to be non-const */ \
@ -9293,7 +9293,7 @@ jit_codegen_init()
imm.setValue(INT32_MAX);
a.jne(imm);
char *stream = (char *)a.code()->sectionById(0)->buffer().data()
char *stream_old = (char *)a.code()->sectionById(0)->buffer().data()
+ a.code()->sectionById(0)->buffer().size();
/* If yes, call jit_set_exception_with_id to throw exception,
@ -9319,7 +9319,7 @@ jit_codegen_init()
/* Patch the offset of jne instruction */
char *stream_new = (char *)a.code()->sectionById(0)->buffer().data()
+ a.code()->sectionById(0)->buffer().size();
*(int32 *)(stream - 4) = (int32)(stream_new - stream);
*(int32 *)(stream_old - 4) = (int32)(stream_new - stream_old);
}
/* Load compiled func ptr and call it */
@ -9419,7 +9419,7 @@ static uint8 hreg_info_F64[3][16] = {
1, 1, 1, 1, 1, 1, 1, 0 }, /* caller_saved_jitted */
};
static const JitHardRegInfo hreg_info = {
static const JitHardRegInfo g_hreg_info = {
{
{ 0, NULL, NULL, NULL }, /* VOID */
@ -9459,7 +9459,7 @@ static const JitHardRegInfo hreg_info = {
const JitHardRegInfo *
jit_codegen_get_hreg_info()
{
return &hreg_info;
return &g_hreg_info;
}
static const char *reg_names_i32[] = {

View File

@ -636,7 +636,7 @@ wasm_init_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 seg_idx,
/* if d + n > the length of mem.data */
mem_inst = inst->memories[mem_idx];
mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page;
if (mem_size < mem_offset || mem_size - mem_offset < len)
goto out_of_bounds;
@ -724,8 +724,10 @@ wasm_copy_memory(WASMModuleInstance *inst, uint32 src_mem_idx,
src_mem = inst->memories[src_mem_idx];
dst_mem = inst->memories[dst_mem_idx];
src_mem_size = src_mem->cur_page_count * src_mem->num_bytes_per_page;
dst_mem_size = dst_mem->cur_page_count * dst_mem->num_bytes_per_page;
src_mem_size =
src_mem->cur_page_count * (uint64)src_mem->num_bytes_per_page;
dst_mem_size =
dst_mem->cur_page_count * (uint64)dst_mem->num_bytes_per_page;
/* if s + n > the length of mem.data */
if (src_mem_size < src_offset || src_mem_size - src_offset < len)
@ -788,7 +790,7 @@ wasm_fill_memory(WASMModuleInstance *inst, uint32 mem_idx, uint32 len,
uint8 *dst_addr;
mem_inst = inst->memories[mem_idx];
mem_size = mem_inst->cur_page_count * mem_inst->num_bytes_per_page;
mem_size = mem_inst->cur_page_count * (uint64)mem_inst->num_bytes_per_page;
if (mem_size < dst || mem_size - dst < len)
goto out_of_bounds;

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/**
* @file aot_export.h
*
* @brief This file defines the exported AOT compilation APIs
*/
#ifndef _AOT_EXPORT_H
#define _AOT_EXPORT_H

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/**
* @file gc_export.h
*
* @brief This file defines the exported GC APIs
*/
#ifndef _GC_EXPORT_H
#define _GC_EXPORT_H

View File

@ -3,6 +3,11 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/**
* @file lib_export.h
*
*/
#ifndef _LIB_EXPORT_H_
#define _LIB_EXPORT_H_

View File

@ -1,5 +1,11 @@
// WebAssembly C API
/**
* @file wasm_c_api.h
*
* @brief This file defines the WebAssembly C APIs
*/
#ifndef _WASM_C_API_H_
#define _WASM_C_API_H_
@ -517,10 +523,21 @@ struct WASMModuleCommon;
typedef struct WASMModuleCommon *wasm_module_t;
#endif
#ifndef LOAD_ARGS_OPTION_DEFINED
#define LOAD_ARGS_OPTION_DEFINED
typedef struct LoadArgs {
char *name;
/* TODO: more fields? */
} LoadArgs;
#endif /* LOAD_ARGS_OPTION_DEFINED */
WASM_API_EXTERN own wasm_module_t* wasm_module_new(
wasm_store_t*, const wasm_byte_vec_t* binary);
// please refer to wasm_runtime_load_ex(...) in core/iwasm/include/wasm_export.h
WASM_API_EXTERN own wasm_module_t* wasm_module_new_ex(
wasm_store_t*, const wasm_byte_vec_t* binary, const LoadArgs *args);
WASM_API_EXTERN void wasm_module_delete(own wasm_module_t*);
WASM_API_EXTERN bool wasm_module_validate(wasm_store_t*, const wasm_byte_vec_t* binary);

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
/**
* @file wasm_export.h
*
* @brief This file defines the exported common runtime APIs
*/
#ifndef _WASM_EXPORT_H
#define _WASM_EXPORT_H
@ -107,6 +113,11 @@ typedef enum {
Alloc_With_System_Allocator,
} mem_alloc_type_t;
typedef enum {
Alloc_For_Runtime,
Alloc_For_LinearMemory
} mem_alloc_usage_t;
/* Memory allocator option */
typedef union MemAllocOption {
struct {
@ -114,6 +125,9 @@ typedef union MemAllocOption {
uint32_t heap_size;
} pool;
struct {
/* the function signature is varied when
WASM_MEM_ALLOC_WITH_USER_DATA and
WASM_MEM_ALLOC_WITH_USAGE are defined */
void *malloc_func;
void *realloc_func;
void *free_func;
@ -183,6 +197,14 @@ typedef struct RuntimeInitArgs {
bool enable_linux_perf;
} RuntimeInitArgs;
#ifndef LOAD_ARGS_OPTION_DEFINED
#define LOAD_ARGS_OPTION_DEFINED
typedef struct LoadArgs {
char *name;
/* TODO: more fields? */
} LoadArgs;
#endif /* LOAD_ARGS_OPTION_DEFINED */
#ifndef INSTANTIATION_ARGS_OPTION_DEFINED
#define INSTANTIATION_ARGS_OPTION_DEFINED
/* WASM module instantiation arguments */
@ -419,6 +441,13 @@ WASM_RUNTIME_API_EXTERN wasm_module_t
wasm_runtime_load(uint8_t *buf, uint32_t size,
char *error_buf, uint32_t error_buf_size);
/**
* Load a WASM module with specified load argument.
*/
WASM_RUNTIME_API_EXTERN wasm_module_t
wasm_runtime_load_ex(uint8_t *buf, uint32_t size, const LoadArgs *args,
char *error_buf, uint32_t error_buf_size);
/**
* Load a WASM module from a specified WASM or AOT section list.
*

View File

@ -90,11 +90,22 @@ extern "C" {
*/
#define VALUE_TYPE_GC_REF 0x43
#define MAX_PAGE_COUNT_FLAG 0x01
#define SHARED_MEMORY_FLAG 0x02
#define MEMORY64_FLAG 0x04
#define DEFAULT_NUM_BYTES_PER_PAGE 65536
#define DEFAULT_MAX_PAGES 65536
#define DEFAULT_MEM64_MAX_PAGES UINT32_MAX
/* Max size of linear memory */
#define MAX_LINEAR_MEMORY_SIZE (4 * (uint64)BH_GB)
/* Roughly 274 TB */
#define MAX_LINEAR_MEM64_MEMORY_SIZE \
(DEFAULT_MEM64_MAX_PAGES * (uint64)64 * (uint64)BH_KB)
/* Macro to check memory flag and return appropriate memory size */
#define GET_MAX_LINEAR_MEMORY_SIZE(is_memory64) \
(is_memory64 ? MAX_LINEAR_MEM64_MEMORY_SIZE : MAX_LINEAR_MEMORY_SIZE)
#if WASM_ENABLE_GC == 0
typedef uintptr_t table_elem_type_t;
@ -263,7 +274,7 @@ typedef struct InitializerExpression {
*/
typedef struct RefHeapType_TypeIdx {
/* ref_type is REF_TYPE_HT_NULLABLE or
REF_TYPE_HT_NON_NULLABLE, (0x6C or 0x6B) */
REF_TYPE_HT_NON_NULLABLE, (0x63 or 0x64) */
uint8 ref_type;
/* true if ref_type is REF_TYPE_HT_NULLABLE */
bool nullable;
@ -277,7 +288,7 @@ typedef struct RefHeapType_TypeIdx {
*/
typedef struct RefHeapType_Common {
/* ref_type is REF_TYPE_HT_NULLABLE or
REF_TYPE_HT_NON_NULLABLE (0x6C or 0x6B) */
REF_TYPE_HT_NON_NULLABLE (0x63 or 0x64) */
uint8 ref_type;
/* true if ref_type is REF_TYPE_HT_NULLABLE */
bool nullable;
@ -327,18 +338,24 @@ typedef struct WASMType {
uint16 type_flag;
bool is_sub_final;
/* How many types are referring to this type */
uint16 ref_count;
/* The inheritance depth */
uint32 inherit_depth;
uint16 inherit_depth;
/* The root type */
struct WASMType *root_type;
/* The parent type */
struct WASMType *parent_type;
uint32 parent_type_idx;
/* number of internal types in the current rec group, if the type is not in
* a recursive group, rec_count = 0 */
/* The number of internal types in the current rec group, and if
the type is not in a recursive group, rec_count is 1 since a
single type definition is reinterpreted as a short-hand for a
recursive group containing just one type */
uint16 rec_count;
uint16 rec_idx;
/* The index of the begin type of this group */
uint32 rec_begin_type_idx;
} WASMType, *WASMTypePtr;
#endif /* end of WASM_ENABLE_GC */
@ -364,9 +381,6 @@ typedef struct WASMFuncType {
uint16 ref_type_map_count;
WASMRefTypeMap *ref_type_maps;
WASMRefTypeMap *result_ref_type_maps;
/* minimal type index of the type equal to this type,
used in type equal check in call_indirect opcode */
uint32 min_type_idx_normalized;
#else
uint16 ref_count;
#endif
@ -484,6 +498,12 @@ typedef struct WASMTable {
#endif
} WASMTable;
#if WASM_ENABLE_MEMORY64 != 0
typedef uint64 mem_offset_t;
#else
typedef uint32 mem_offset_t;
#endif
typedef struct WASMMemory {
uint32 flags;
uint32 num_bytes_per_page;
@ -1312,8 +1332,8 @@ block_type_get_param_types(BlockType *block_type, uint8 **p_param_types,
param_count = func_type->param_count;
#if WASM_ENABLE_GC != 0
*p_param_reftype_maps = func_type->ref_type_maps;
*p_param_reftype_map_count =
func_type->result_ref_type_maps - func_type->ref_type_maps;
*p_param_reftype_map_count = (uint32)(func_type->result_ref_type_maps
- func_type->ref_type_maps);
#endif
}
else {

View File

@ -46,8 +46,10 @@ typedef float64 CellType_F64;
#define get_linear_mem_size() GET_LINEAR_MEMORY_SIZE(memory)
#endif
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0
#if WASM_ENABLE_MEMORY64 == 0
#if (!defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0)
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
@ -69,7 +71,8 @@ typedef float64 CellType_F64;
else \
goto out_of_bounds; \
} while (0)
#else
#else /* else of !defined(OS_ENABLE_HW_BOUND_CHECK) || \
WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
@ -80,8 +83,37 @@ typedef float64 CellType_F64;
do { \
maddr = memory->memory_data + (uint32)(start); \
} while (0)
#endif /* !defined(OS_ENABLE_HW_BOUND_CHECK) \
|| WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
#endif /* end of !defined(OS_ENABLE_HW_BOUND_CHECK) || \
WASM_CPU_SUPPORTS_UNALIGNED_ADDR_ACCESS == 0 */
#else /* else of WASM_ENABLE_MEMORY64 == 0 */
#define CHECK_MEMORY_OVERFLOW(bytes) \
do { \
uint64 offset1 = (uint64)offset + (uint64)addr; \
/* If memory64 is enabled, offset1, offset1 + bytes can overflow */ \
if (disable_bounds_checks \
|| (offset1 >= offset && offset1 + bytes >= offset1 \
&& offset1 + bytes <= get_linear_mem_size())) \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#define CHECK_BULK_MEMORY_OVERFLOW(start, bytes, maddr) \
do { \
uint64 offset1 = (uint64)(start); \
/* If memory64 is enabled, offset1 + bytes can overflow */ \
if (disable_bounds_checks \
|| (offset1 + bytes >= offset1 \
&& offset1 + bytes <= get_linear_mem_size())) \
/* App heap space is not valid space for \
bulk memory operation */ \
maddr = memory->memory_data + offset1; \
else \
goto out_of_bounds; \
} while (0)
#endif /* end of WASM_ENABLE_MEMORY64 == 0 */
#define CHECK_ATOMIC_MEMORY_ACCESS() \
do { \
@ -472,6 +504,23 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
#define SET_LABEL_TYPE(_label_type) (void)0
#endif
#if WASM_ENABLE_MEMORY64 != 0
#define PUSH_MEM_OFFSET(value) \
do { \
if (is_memory64) { \
PUT_I64_TO_ADDR(frame_sp, value); \
frame_sp += 2; \
} \
else { \
*(int32 *)frame_sp++ = (int32)(value); \
} \
} while (0)
#else
#define PUSH_MEM_OFFSET(value) PUSH_I32(value)
#endif
#define PUSH_PAGE_COUNT(value) PUSH_MEM_OFFSET(value)
#define PUSH_CSP(_label_type, param_cell_num, cell_num, _target_addr) \
do { \
bh_assert(frame_csp < frame->csp_boundary); \
@ -501,6 +550,14 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
GET_REF_FROM_ADDR(frame_sp))
#endif
#if WASM_ENABLE_MEMORY64 != 0
#define POP_MEM_OFFSET() (is_memory64 ? POP_I64() : POP_I32())
#else
#define POP_MEM_OFFSET() POP_I32()
#endif
#define POP_PAGE_COUNT() POP_MEM_OFFSET()
#define POP_CSP_CHECK_OVERFLOW(n) \
do { \
bh_assert(frame_csp - n >= frame->csp_bottom); \
@ -576,11 +633,12 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
/* sign extend */ \
res |= 0xFFFFFFFFFFFFFF80LL; \
p++; \
break; \
} \
else { \
uint32 _off = 0; \
res = (int64)read_leb(p, &_off, 64, true); \
p += _off; \
} \
} while (0)
#define read_leb_uint32(p, p_end, res) \
@ -589,11 +647,12 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
if (!(_val & 0x80)) { \
res = _val; \
p++; \
break; \
} \
else { \
uint32 _off = 0; \
res = (uint32)read_leb(p, &_off, 32, false); \
p += _off; \
} \
} while (0)
#define read_leb_int32(p, p_end, res) \
@ -605,13 +664,33 @@ wasm_interp_get_frame_ref(WASMInterpFrame *frame)
/* sign extend */ \
res |= 0xFFFFFF80; \
p++; \
break; \
} \
else { \
uint32 _off = 0; \
res = (int32)read_leb(p, &_off, 32, true); \
p += _off; \
} \
} while (0)
#if WASM_ENABLE_MEMORY64 != 0
#define read_leb_mem_offset(p, p_end, res) \
do { \
uint8 _val = *p; \
if (!(_val & 0x80)) { \
res = (mem_offset_t)_val; \
p++; \
} \
else { \
uint32 _off = 0; \
res = (mem_offset_t)read_leb(p, &_off, is_memory64 ? 64 : 32, \
false); \
p += _off; \
} \
} while (0)
#else
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
#endif
#if WASM_ENABLE_LABELS_AS_VALUES == 0
#define RECOVER_FRAME_IP_END() frame_ip_end = wasm_get_func_code_end(cur_func)
#else
@ -872,7 +951,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
uint32 readv, sval; \
\
sval = POP_I32(); \
addr = POP_I32(); \
addr = POP_MEM_OFFSET(); \
\
if (opcode == WASM_OP_ATOMIC_RMW_I32_##OP_NAME##8_U) { \
CHECK_MEMORY_OVERFLOW(1); \
@ -912,7 +991,7 @@ trunc_f64_to_int(WASMModuleInstance *module, uint32 *frame_sp, float64 src_min,
uint64 readv, sval; \
\
sval = (uint64)POP_I64(); \
addr = POP_I32(); \
addr = POP_MEM_OFFSET(); \
\
if (opcode == WASM_OP_ATOMIC_RMW_I64_##OP_NAME##8_U) { \
CHECK_MEMORY_OVERFLOW(1); \
@ -1430,6 +1509,16 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMStringviewIterObjectRef stringview_iter_obj;
#endif
#endif
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
bool is_return_call = false;
#endif
#if WASM_ENABLE_MEMORY64 != 0
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
bool is_memory64 = false;
if (memory)
is_memory64 = memory->is_memory64;
#endif
#if WASM_ENABLE_DEBUG_INTERP != 0
uint8 *frame_ip_orig = NULL;
@ -2123,6 +2212,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFuncType *cur_type, *cur_func_type;
WASMTableInstance *tbl_inst;
uint32 tbl_idx;
#if WASM_ENABLE_TAIL_CALL != 0
opcode = *(frame_ip - 1);
#endif
@ -2193,8 +2283,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto got_exception;
}
#else
if (cur_type->min_type_idx_normalized
!= cur_func_type->min_type_idx_normalized) {
if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
wasm_set_exception(module, "indirect call type mismatch");
goto got_exception;
}
@ -4087,8 +4176,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bh_assert(global_idx < module->e->global_count);
global = globals + global_idx;
global_addr = get_global_addr(global_data, global);
/* TODO: Memory64 the data type depends on mem idx type */
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
aux_stack_top = *(uint64 *)(frame_sp - 2);
}
else
#endif
{
aux_stack_top = (uint64)(*(uint32 *)(frame_sp - 1));
}
if (aux_stack_top <= (uint64)exec_env->aux_stack_boundary) {
wasm_set_exception(module, "wasm auxiliary stack overflow");
goto got_exception;
@ -4098,8 +4194,17 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
"wasm auxiliary stack underflow");
goto got_exception;
}
*(int32 *)global_addr = aux_stack_top;
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
*(uint64 *)global_addr = aux_stack_top;
frame_sp -= 2;
}
else
#endif
{
*(uint32 *)global_addr = aux_stack_top;
frame_sp--;
}
#if WASM_ENABLE_MEMORY_PROFILING != 0
if (module->module->aux_stack_top_global_index != (uint32)-1) {
uint32 aux_stack_used =
@ -4126,11 +4231,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD)
HANDLE_OP(WASM_OP_F32_LOAD)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
PUSH_I32(LOAD_I32(maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4141,11 +4247,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD)
HANDLE_OP(WASM_OP_F64_LOAD)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8);
PUSH_I64(LOAD_I64(maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4155,11 +4262,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD8_S)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
PUSH_I32(sign_ext_8_32(*(int8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4169,11 +4277,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD8_U)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
PUSH_I32((uint32)(*(uint8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4183,11 +4292,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD16_S)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
PUSH_I32(sign_ext_16_32(LOAD_I16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4197,11 +4307,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_LOAD16_U)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
PUSH_I32((uint32)(LOAD_U16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4211,11 +4322,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD8_S)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
PUSH_I64(sign_ext_8_64(*(int8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4225,11 +4337,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD8_U)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(1);
PUSH_I64((uint64)(*(uint8 *)maddr));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4239,11 +4352,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD16_S)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
PUSH_I64(sign_ext_16_64(LOAD_I16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4253,11 +4367,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD16_U)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(2);
PUSH_I64((uint64)(LOAD_U16(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4267,12 +4382,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD32_S)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
PUSH_I64(sign_ext_32_64(LOAD_I32(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4282,11 +4398,12 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_LOAD32_U)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
addr = POP_I32();
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
PUSH_I64((uint64)(LOAD_U32(maddr)));
CHECK_READ_WATCHPOINT(addr, offset);
@ -4298,14 +4415,23 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_STORE)
HANDLE_OP(WASM_OP_F32_STORE)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
frame_sp--;
addr = POP_I32();
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
STORE_U32(maddr, frame_sp[2]);
}
else
#endif
{
STORE_U32(maddr, frame_sp[1]);
}
CHECK_WRITE_WATCHPOINT(addr, offset);
(void)flags;
HANDLE_OP_END();
@ -4314,15 +4440,26 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_STORE)
HANDLE_OP(WASM_OP_F64_STORE)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
frame_sp -= 2;
addr = POP_I32();
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8);
#if WASM_ENABLE_MEMORY64 != 0
if (is_memory64) {
PUT_I64_TO_ADDR((mem_offset_t *)maddr,
GET_I64_FROM_ADDR(frame_sp + 2));
}
else
#endif
{
PUT_I64_TO_ADDR((uint32 *)maddr,
GET_I64_FROM_ADDR(frame_sp + 1));
}
CHECK_WRITE_WATCHPOINT(addr, offset);
(void)flags;
HANDLE_OP_END();
@ -4331,14 +4468,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I32_STORE8)
HANDLE_OP(WASM_OP_I32_STORE16)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
uint32 sval;
opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
sval = (uint32)POP_I32();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_I32_STORE8) {
CHECK_MEMORY_OVERFLOW(1);
@ -4357,14 +4495,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
HANDLE_OP(WASM_OP_I64_STORE16)
HANDLE_OP(WASM_OP_I64_STORE32)
{
uint32 offset, flags, addr;
uint32 flags;
mem_offset_t offset, addr;
uint64 sval;
opcode = *(frame_ip - 1);
read_leb_uint32(frame_ip, frame_ip_end, flags);
read_leb_uint32(frame_ip, frame_ip_end, offset);
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
sval = (uint64)POP_I64();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_I64_STORE8) {
CHECK_MEMORY_OVERFLOW(1);
@ -4388,7 +4527,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
uint32 reserved;
read_leb_uint32(frame_ip, frame_ip_end, reserved);
PUSH_I32(memory->cur_page_count);
PUSH_PAGE_COUNT(memory->cur_page_count);
(void)reserved;
HANDLE_OP_END();
}
@ -4399,15 +4538,15 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
prev_page_count = memory->cur_page_count;
read_leb_uint32(frame_ip, frame_ip_end, reserved);
delta = (uint32)POP_I32();
delta = (uint32)POP_PAGE_COUNT();
if (!wasm_enlarge_memory(module, delta)) {
/* failed to memory.grow, return -1 */
PUSH_I32(-1);
PUSH_PAGE_COUNT(-1);
}
else {
/* success, return previous page count */
PUSH_I32(prev_page_count);
PUSH_PAGE_COUNT(prev_page_count);
/* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */
#if !defined(OS_ENABLE_HW_BOUND_CHECK) \
@ -5407,7 +5546,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_BULK_MEMORY != 0
case WASM_OP_MEMORY_INIT:
{
uint32 addr, segment;
uint32 segment;
mem_offset_t addr;
uint64 bytes, offset, seg_len;
uint8 *data;
@ -5417,7 +5557,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
bytes = (uint64)(uint32)POP_I32();
offset = (uint64)(uint32)POP_I32();
addr = (uint32)POP_I32();
addr = (mem_offset_t)POP_MEM_OFFSET();
#if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size();
@ -5460,14 +5600,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
case WASM_OP_MEMORY_COPY:
{
uint32 dst, src, len;
mem_offset_t dst, src, len;
uint8 *mdst, *msrc;
frame_ip += 2;
len = POP_I32();
src = POP_I32();
dst = POP_I32();
len = POP_MEM_OFFSET();
src = POP_MEM_OFFSET();
dst = POP_MEM_OFFSET();
#if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size();
@ -5493,13 +5632,13 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
case WASM_OP_MEMORY_FILL:
{
uint32 dst, len;
mem_offset_t dst, len;
uint8 fill_val, *mdst;
frame_ip++;
len = POP_I32();
len = POP_MEM_OFFSET();
fill_val = POP_I32();
dst = POP_I32();
dst = POP_MEM_OFFSET();
#if WASM_ENABLE_THREAD_MGR != 0
linear_mem_size = get_linear_mem_size();
@ -5729,7 +5868,8 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
#if WASM_ENABLE_SHARED_MEMORY != 0
HANDLE_OP(WASM_OP_ATOMIC_PREFIX)
{
uint32 offset = 0, align = 0, addr;
mem_offset_t offset = 0, addr;
uint32 align = 0;
uint32 opcode1;
read_leb_uint32(frame_ip, frame_ip_end, opcode1);
@ -5739,7 +5879,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (opcode != WASM_OP_ATOMIC_FENCE) {
read_leb_uint32(frame_ip, frame_ip_end, align);
read_leb_uint32(frame_ip, frame_ip_end, offset);
read_leb_mem_offset(frame_ip, frame_ip_end, offset);
}
switch (opcode) {
@ -5748,7 +5888,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 notify_count, ret;
notify_count = POP_I32();
addr = POP_I32();
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
CHECK_ATOMIC_MEMORY_ACCESS();
@ -5768,7 +5908,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
timeout = POP_I64();
expect = POP_I32();
addr = POP_I32();
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(4);
CHECK_ATOMIC_MEMORY_ACCESS();
@ -5792,7 +5932,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
timeout = POP_I64();
expect = POP_I64();
addr = POP_I32();
addr = POP_MEM_OFFSET();
CHECK_MEMORY_OVERFLOW(8);
CHECK_ATOMIC_MEMORY_ACCESS();
@ -5823,7 +5963,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
uint32 readv;
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I32_LOAD8_U) {
CHECK_MEMORY_OVERFLOW(1);
@ -5858,7 +5998,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
uint64 readv;
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I64_LOAD8_U) {
CHECK_MEMORY_OVERFLOW(1);
@ -5900,7 +6040,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint32 sval;
sval = (uint32)POP_I32();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I32_STORE8) {
CHECK_MEMORY_OVERFLOW(1);
@ -5934,7 +6074,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
uint64 sval;
sval = (uint64)POP_I64();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_I64_STORE8) {
CHECK_MEMORY_OVERFLOW(1);
@ -5961,7 +6101,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
CHECK_MEMORY_OVERFLOW(8);
CHECK_ATOMIC_MEMORY_ACCESS();
shared_memory_lock(memory);
PUT_I64_TO_ADDR((uint32 *)maddr, sval);
STORE_I64(maddr, sval);
shared_memory_unlock(memory);
}
break;
@ -5975,7 +6115,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
sval = POP_I32();
expect = POP_I32();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_RMW_I32_CMPXCHG8_U) {
CHECK_MEMORY_OVERFLOW(1);
@ -6021,7 +6161,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
sval = (uint64)POP_I64();
expect = (uint64)POP_I64();
addr = POP_I32();
addr = POP_MEM_OFFSET();
if (opcode == WASM_OP_ATOMIC_RMW_I64_CMPXCHG8_U) {
CHECK_MEMORY_OVERFLOW(1);
@ -6090,6 +6230,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
frame_ip = frame->ip;
frame_sp = frame->sp;
frame_csp = frame->csp;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
goto call_func_from_entry;
}
@ -6183,6 +6326,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
FREE_FRAME(exec_env, frame);
wasm_exec_env_set_cur_frame(exec_env, prev_frame);
is_return_call = true;
goto call_func_from_entry;
}
#endif
@ -6196,6 +6340,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
SYNC_ALL_TO_FRAME();
prev_frame = frame;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
}
call_func_from_entry:
@ -6205,15 +6352,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (cur_func->import_func_inst) {
wasm_interp_call_func_import(module, exec_env, cur_func,
prev_frame);
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
if (is_return_call) {
/* the frame was freed before tail calling and
the prev_frame was set as exec_env's cur_frame,
so here we recover context from prev_frame */
RECOVER_CONTEXT(prev_frame);
}
else
#endif
{
prev_frame = frame->prev_frame;
cur_func = frame->function;
UPDATE_ALL_FROM_FRAME();
}
#if WASM_ENABLE_EXCE_HANDLING != 0
char uncaught_exception[128] = { 0 };
bool has_exception =
wasm_copy_exception(module, uncaught_exception);
if (has_exception
&& strstr(uncaught_exception, "uncaught wasm exception")) {
/* fix framesp */
UPDATE_ALL_FROM_FRAME();
uint32 import_exception;
/* initialize imported exception index to be invalid */
SET_INVALID_TAGINDEX(import_exception);
@ -6255,11 +6414,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
wasm_interp_call_func_native(module, exec_env, cur_func,
prev_frame);
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
if (is_return_call) {
/* the frame was freed before tail calling and
the prev_frame was set as exec_env's cur_frame,
so here we recover context from prev_frame */
RECOVER_CONTEXT(prev_frame);
}
else
#endif
{
prev_frame = frame->prev_frame;
cur_func = frame->function;
UPDATE_ALL_FROM_FRAME();
}
}
/* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */

View File

@ -1501,6 +1501,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMStringviewIterObjectRef stringview_iter_obj;
#endif
#endif
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
bool is_return_call = false;
#endif
#if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op
@ -1693,7 +1696,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
/* clang-format off */
#if WASM_ENABLE_GC == 0
fidx = tbl_inst->elems[val];
fidx = (uint32)tbl_inst->elems[val];
if (fidx == (uint32)-1) {
wasm_set_exception(module, "uninitialized element");
goto got_exception;
@ -1733,8 +1736,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto got_exception;
}
#else
if (cur_type->min_type_idx_normalized
!= cur_func_type->min_type_idx_normalized) {
if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
wasm_set_exception(module, "indirect call type mismatch");
goto got_exception;
}
@ -5618,6 +5620,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{
frame = prev_frame;
frame_ip = frame->ip;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
goto call_func_from_entry;
}
@ -5766,6 +5771,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
FREE_FRAME(exec_env, frame);
frame_ip += cur_func->param_count * sizeof(int16);
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame);
is_return_call = true;
goto call_func_from_entry;
}
#endif /* WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 */
@ -5838,6 +5844,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
}
SYNC_ALL_TO_FRAME();
prev_frame = frame;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
}
call_func_from_entry:
@ -5855,9 +5864,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
prev_frame);
}
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
if (is_return_call) {
/* the frame was freed before tail calling and
the prev_frame was set as exec_env's cur_frame,
so here we recover context from prev_frame */
RECOVER_CONTEXT(prev_frame);
}
else
#endif
{
prev_frame = frame->prev_frame;
cur_func = frame->function;
UPDATE_ALL_FROM_FRAME();
}
/* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */

File diff suppressed because it is too large Load Diff

View File

@ -28,7 +28,7 @@ wasm_loader_load(uint8 *buf, uint32 size,
#if WASM_ENABLE_MULTI_MODULE != 0
bool main_module,
#endif
char *error_buf, uint32 error_buf_size);
const LoadArgs *args, char *error_buf, uint32 error_buf_size);
/**
* Load a WASM module from a specified WASM section list.

View File

@ -47,6 +47,7 @@ set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
#define skip_leb_int64(p, p_end) skip_leb(p)
#define skip_leb_uint32(p, p_end) skip_leb(p)
#define skip_leb_int32(p, p_end) skip_leb(p)
#define skip_leb_mem_offset(p, p_end) skip_leb(p)
static bool
is_32bit_type(uint8 type)
@ -116,7 +117,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
}
else if (sign && maxbits == 32) {
if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */
/* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift;
}
@ -132,7 +133,7 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
}
else if (sign && maxbits == 64) {
if (shift < maxbits) {
/* Sign extend, second highest bit is the sign bit */
/* Sign extend, second-highest bit is the sign bit */
if ((uint8)byte & 0x40)
result |= (~((uint64)0)) << shift;
}
@ -180,6 +181,18 @@ read_leb(uint8 **p_buf, const uint8 *buf_end, uint32 maxbits, bool sign,
res = (int32)res64; \
} while (0)
#if WASM_ENABLE_MEMORY64 != 0
#define read_leb_mem_offset(p, p_end, res) \
do { \
uint64 res64; \
read_leb((uint8 **)&p, p_end, is_memory64 ? 64 : 32, false, &res64, \
error_buf, error_buf_size); \
res = (mem_offset_t)res64; \
} while (0)
#else
#define read_leb_mem_offset(p, p_end, res) read_leb_uint32(p, p_end, res)
#endif
static void *
loader_malloc(uint64 size, char *error_buf, uint32 error_buf_size)
{
@ -683,6 +696,38 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
return true;
}
static bool
check_memory_flag(const uint8 mem_flag)
{
/* Check whether certain features indicated by mem_flag are enabled in
* runtime */
if (mem_flag > MAX_PAGE_COUNT_FLAG) {
#if WASM_ENABLE_SHARED_MEMORY == 0
if (mem_flag & SHARED_MEMORY_FLAG) {
LOG_VERBOSE("shared memory flag was found, please enable shared "
"memory, lib-pthread or lib-wasi-threads");
return false;
}
#endif
#if WASM_ENABLE_MEMORY64 == 0
if (mem_flag & MEMORY64_FLAG) {
LOG_VERBOSE("memory64 flag was found, please enable memory64");
return false;
}
#endif
}
if (mem_flag > MAX_PAGE_COUNT_FLAG + SHARED_MEMORY_FLAG + MEMORY64_FLAG) {
return false;
}
else if ((mem_flag & SHARED_MEMORY_FLAG)
&& !(mem_flag & MAX_PAGE_COUNT_FLAG)) {
return false;
}
return true;
}
static bool
load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *parent_module, const char *sub_module_name,
@ -695,20 +740,28 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE;
#else
uint32 max_page_count = DEFAULT_MAX_PAGES;
uint32 max_page_count;
#endif /* WASM_ENABLE_APP_FRAMEWORK */
uint32 declare_max_page_count_flag = 0;
uint32 mem_flag = 0;
bool is_memory64 = false;
uint32 declare_init_page_count = 0;
uint32 declare_max_page_count = 0;
read_leb_uint32(p, p_end, declare_max_page_count_flag);
read_leb_uint32(p, p_end, declare_init_page_count);
bh_assert(declare_init_page_count <= 65536);
read_leb_uint32(p, p_end, mem_flag);
bh_assert(check_memory_flag(mem_flag));
if (declare_max_page_count_flag & 1) {
#if WASM_ENABLE_APP_FRAMEWORK == 0
is_memory64 = mem_flag & MEMORY64_FLAG;
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif
read_leb_uint32(p, p_end, declare_init_page_count);
bh_assert(declare_init_page_count <= max_page_count);
if (mem_flag & MAX_PAGE_COUNT_FLAG) {
read_leb_uint32(p, p_end, declare_max_page_count);
bh_assert(declare_init_page_count <= declare_max_page_count);
bh_assert(declare_max_page_count <= 65536);
bh_assert(declare_max_page_count <= max_page_count);
if (declare_max_page_count > max_page_count) {
declare_max_page_count = max_page_count;
}
@ -719,12 +772,13 @@ load_memory_import(const uint8 **p_buf, const uint8 *buf_end,
}
/* now we believe all declaration are ok */
memory->flags = declare_max_page_count_flag;
memory->flags = mem_flag;
memory->init_page_count = declare_init_page_count;
memory->max_page_count = declare_max_page_count;
memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
*p_buf = p;
(void)check_memory_flag;
return true;
}
@ -811,26 +865,28 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
uint32 max_page_count = pool_size * APP_MEMORY_MAX_GLOBAL_HEAP_PERCENT
/ DEFAULT_NUM_BYTES_PER_PAGE;
#else
uint32 max_page_count = DEFAULT_MAX_PAGES;
uint32 max_page_count;
bool is_memory64 = false;
#endif
p_org = p;
read_leb_uint32(p, p_end, memory->flags);
bh_assert(p - p_org <= 1);
(void)p_org;
#if WASM_ENABLE_SHARED_MEMORY == 0
bh_assert(memory->flags <= 1);
#else
bh_assert(memory->flags <= 3 && memory->flags != 2);
bh_assert(check_memory_flag(memory->flags));
#if WASM_ENABLE_APP_FRAMEWORK == 0
is_memory64 = memory->flags & MEMORY64_FLAG;
max_page_count = is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
#endif
read_leb_uint32(p, p_end, memory->init_page_count);
bh_assert(memory->init_page_count <= 65536);
bh_assert(memory->init_page_count <= max_page_count);
if (memory->flags & 1) {
read_leb_uint32(p, p_end, memory->max_page_count);
bh_assert(memory->init_page_count <= memory->max_page_count);
bh_assert(memory->max_page_count <= 65536);
bh_assert(memory->max_page_count <= max_page_count);
if (memory->max_page_count > max_page_count)
memory->max_page_count = max_page_count;
}
@ -842,6 +898,7 @@ load_memory(const uint8 **p_buf, const uint8 *buf_end, WASMMemory *memory,
memory->num_bytes_per_page = DEFAULT_NUM_BYTES_PER_PAGE;
*p_buf = p;
(void)check_memory_flag;
return true;
}
@ -1704,6 +1761,7 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
bool is_passive = false;
uint32 mem_flag;
#endif
uint8 mem_offset_type;
read_leb_uint32(p, p_end, data_seg_count);
@ -1750,11 +1808,35 @@ load_data_segment_section(const uint8 *buf, const uint8 *buf_end,
< module->import_memory_count + module->memory_count);
#endif /* WASM_ENABLE_BULK_MEMORY */
#if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive)
#endif /* WASM_ENABLE_BULK_MEMORY */
{
#if WASM_ENABLE_MEMORY64 != 0
/* This memory_flag is from memory instead of data segment */
uint8 memory_flag;
if (module->import_memory_count > 0) {
memory_flag =
module->import_memories[mem_index].u.memory.flags;
}
else {
memory_flag =
module
->memories[mem_index - module->import_memory_count]
.flags;
}
mem_offset_type = memory_flag & MEMORY64_FLAG ? VALUE_TYPE_I64
: VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif /* WASM_ENABLE_MEMORY64 */
}
#if WASM_ENABLE_BULK_MEMORY != 0
if (!is_passive)
#endif
if (!load_init_expr(module, &p, p_end, &init_expr,
VALUE_TYPE_I32, error_buf, error_buf_size))
mem_offset_type, error_buf, error_buf_size))
return false;
read_leb_uint32(p, p_end, data_seg_len);
@ -2485,8 +2567,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
*buf_func = NULL, *buf_func_end = NULL;
WASMGlobal *aux_data_end_global = NULL, *aux_heap_base_global = NULL;
WASMGlobal *aux_stack_top_global = NULL, *global;
uint64 aux_data_end = (uint64)-1, aux_heap_base = (uint64)-1,
aux_stack_top = (uint64)-1;
uint64 aux_data_end = (uint64)-1LL, aux_heap_base = (uint64)-1LL,
aux_stack_top = (uint64)-1LL;
uint32 global_index, func_index, i;
uint32 aux_data_end_global_index = (uint32)-1;
uint32 aux_heap_base_global_index = (uint32)-1;
@ -2607,7 +2689,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
aux_heap_base_global = global;
aux_heap_base = (uint64)(uint32)global->init_expr.u.i32;
aux_heap_base_global_index = export->index;
LOG_VERBOSE("Found aux __heap_base global, value: %d",
LOG_VERBOSE("Found aux __heap_base global, value: %" PRIu64,
aux_heap_base);
}
}
@ -2620,7 +2702,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
aux_data_end_global = global;
aux_data_end = (uint64)(uint32)global->init_expr.u.i32;
aux_data_end_global_index = export->index;
LOG_VERBOSE("Found aux __data_end global, value: %d",
LOG_VERBOSE("Found aux __data_end global, value: %" PRIu64,
aux_data_end);
aux_data_end = align_uint64(aux_data_end, 16);
}
@ -2669,7 +2751,8 @@ load_from_sections(WASMModule *module, WASMSection *sections,
aux_stack_top > aux_data_end
? (uint32)(aux_stack_top - aux_data_end)
: (uint32)aux_stack_top;
LOG_VERBOSE("Found aux stack top global, value: %d, "
LOG_VERBOSE(
"Found aux stack top global, value: %" PRIu64 ", "
"global index: %d, stack size: %d",
aux_stack_top, global_index,
module->aux_stack_size);
@ -2819,7 +2902,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
/* Reset memory info to decrease memory usage */
memory_import->num_bytes_per_page = shrunk_memory_size;
memory_import->init_page_count = 1;
LOG_VERBOSE("Shrink import memory size to %d",
LOG_VERBOSE("Shrink import memory size to %" PRIu64,
shrunk_memory_size);
}
}
@ -2832,7 +2915,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
/* Reset memory info to decrease memory usage */
memory->num_bytes_per_page = shrunk_memory_size;
memory->init_page_count = 1;
LOG_VERBOSE("Shrink memory size to %d",
LOG_VERBOSE("Shrink memory size to %" PRIu64,
shrunk_memory_size);
}
}
@ -2911,7 +2994,7 @@ load_from_sections(WASMModule *module, WASMSection *sections,
}
static WASMModule *
create_module(char *error_buf, uint32 error_buf_size)
create_module(char *name, char *error_buf, uint32 error_buf_size)
{
WASMModule *module =
loader_malloc(sizeof(WASMModule), error_buf, error_buf_size);
@ -2926,7 +3009,7 @@ create_module(char *error_buf, uint32 error_buf_size)
/* Set start_function to -1, means no start function */
module->start_function = (uint32)-1;
module->name = "";
module->name = name;
#if WASM_ENABLE_FAST_INTERP == 0
module->br_table_cache_list = &module->br_table_cache_list_head;
@ -2952,7 +3035,7 @@ WASMModule *
wasm_loader_load_from_sections(WASMSection *section_list, char *error_buf,
uint32 error_buf_size)
{
WASMModule *module = create_module(error_buf, error_buf_size);
WASMModule *module = create_module("", error_buf, error_buf_size);
if (!module)
return NULL;
@ -3123,10 +3206,10 @@ load(const uint8 *buf, uint32 size, WASMModule *module, char *error_buf,
}
WASMModule *
wasm_loader_load(uint8 *buf, uint32 size, char *error_buf,
wasm_loader_load(uint8 *buf, uint32 size, const LoadArgs *args, char *error_buf,
uint32 error_buf_size)
{
WASMModule *module = create_module(error_buf, error_buf_size);
WASMModule *module = create_module(args->name, error_buf, error_buf_size);
if (!module) {
return NULL;
}
@ -3533,7 +3616,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32:
skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */
skip_leb_mem_offset(p, p_end); /* offset */
break;
case WASM_OP_MEMORY_SIZE:
@ -3748,6 +3831,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
#if WASM_ENABLE_SHARED_MEMORY != 0
case WASM_OP_ATOMIC_PREFIX:
{
/* TODO: memory64 offset type changes */
uint32 opcode1;
/* atomic_op (u32_leb) + memarg (2 u32_leb) */
@ -3758,7 +3842,7 @@ wasm_loader_find_block_addr(WASMExecEnv *exec_env, BlockAddr *block_addr_cache,
if (opcode != WASM_OP_ATOMIC_FENCE) {
skip_leb_uint32(p, p_end); /* align */
skip_leb_uint32(p, p_end); /* offset */
skip_leb_mem_offset(p, p_end); /* offset */
}
else {
/* atomic.fence doesn't have memarg */
@ -4260,9 +4344,9 @@ wasm_loader_pop_frame_csp(WASMLoaderContext *ctx, char *error_buf,
wasm_loader_emit_ptr(loader_ctx, NULL); \
} while (0)
#define emit_br_info(frame_csp) \
#define emit_br_info(frame_csp, is_br) \
do { \
if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, error_buf, \
if (!wasm_loader_emit_br_info(loader_ctx, frame_csp, is_br, error_buf, \
error_buf_size)) \
goto fail; \
} while (0)
@ -4649,7 +4733,7 @@ apply_label_patch(WASMLoaderContext *ctx, uint8 depth, uint8 patch_type)
static bool
wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
char *error_buf, uint32 error_buf_size)
bool is_br, char *error_buf, uint32 error_buf_size)
{
/* br info layout:
* a) arity of target block
@ -4698,6 +4782,8 @@ wasm_loader_emit_br_info(WASMLoaderContext *ctx, BranchBlock *frame_csp,
/* Part e */
dynamic_offset =
frame_csp->dynamic_offset + wasm_get_cell_num(types, arity);
if (is_br)
ctx->dynamic_offset = dynamic_offset;
for (i = (int32)arity - 1; i >= 0; i--) {
cell = (uint8)wasm_value_type_cell_num(types[i]);
dynamic_offset -= cell;
@ -5073,6 +5159,11 @@ fail:
goto fail; \
} while (0)
#define PUSH_MEM_OFFSET() PUSH_OFFSET_TYPE(mem_offset_type)
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
#define POP_MEM_OFFSET() POP_OFFSET_TYPE(mem_offset_type)
#define POP_AND_PUSH(type_pop, type_push) \
do { \
if (!(wasm_loader_push_pop_frame_ref_offset( \
@ -5127,6 +5218,15 @@ fail:
goto fail; \
} while (0)
#define PUSH_MEM_OFFSET() \
do { \
if (!(wasm_loader_push_frame_ref(loader_ctx, mem_offset_type, \
error_buf, error_buf_size))) \
goto fail; \
} while (0)
#define PUSH_PAGE_COUNT() PUSH_MEM_OFFSET()
#define POP_I32() \
do { \
if (!(wasm_loader_pop_frame_ref(loader_ctx, VALUE_TYPE_I32, error_buf, \
@ -5162,6 +5262,13 @@ fail:
goto fail; \
} while (0)
#define POP_MEM_OFFSET() \
do { \
if (!(wasm_loader_pop_frame_ref(loader_ctx, mem_offset_type, \
error_buf, error_buf_size))) \
goto fail; \
} while (0)
#define POP_AND_PUSH(type_pop, type_push) \
do { \
if (!(wasm_loader_push_pop_frame_ref(loader_ctx, 1, type_push, \
@ -5382,8 +5489,8 @@ fail:
} while (0)
static bool
wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
bool is_br_table, char *error_buf, uint32 error_buf_size)
wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth, uint8 opcode,
char *error_buf, uint32 error_buf_size)
{
BranchBlock *target_block, *cur_block;
BlockType *target_block_type;
@ -5441,7 +5548,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
/* Backup stack data since it may be changed in the below
push operations, and the stack data may be used when
checking other target blocks of opcode br_table */
if (is_br_table) {
if (opcode == WASM_OP_BR_TABLE) {
uint64 total_size;
frame_ref_after_popped = loader_ctx->frame_ref;
@ -5479,13 +5586,13 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
}
#if WASM_ENABLE_FAST_INTERP != 0
emit_br_info(target_block);
emit_br_info(target_block, opcode == WASM_OP_BR);
#endif
/* Restore the stack data, note that frame_ref_bottom,
frame_reftype_map_bottom, frame_offset_bottom may be
re-allocated in the above push operations */
if (is_br_table) {
if (opcode == WASM_OP_BR_TABLE) {
uint32 total_size;
/* The stack operand num should not be smaller than before
@ -5529,7 +5636,7 @@ wasm_loader_check_br(WASMLoaderContext *loader_ctx, uint32 depth,
}
#if WASM_ENABLE_FAST_INTERP != 0
emit_br_info(target_block);
emit_br_info(target_block, opcode == WASM_OP_BR);
#endif
ret = true;
@ -5540,7 +5647,7 @@ fail:
wasm_runtime_free(frame_ref_buf);
#if WASM_ENABLE_FAST_INTERP != 0
if (frame_offset_buf && frame_offset_buf != frame_offset_tmp)
wasm_runtime_free(frame_offset_tmp);
wasm_runtime_free(frame_offset_buf);
#endif
return ret;
@ -5548,14 +5655,14 @@ fail:
static BranchBlock *
check_branch_block(WASMLoaderContext *loader_ctx, uint8 **p_buf, uint8 *buf_end,
bool is_br_table, char *error_buf, uint32 error_buf_size)
uint8 opcode, char *error_buf, uint32 error_buf_size)
{
uint8 *p = *p_buf, *p_end = buf_end;
BranchBlock *frame_csp_tmp;
uint32 depth;
read_leb_uint32(p, p_end, depth);
if (!wasm_loader_check_br(loader_ctx, depth, is_br_table, error_buf,
if (!wasm_loader_check_br(loader_ctx, depth, opcode, error_buf,
error_buf_size)) {
goto fail;
}
@ -5772,10 +5879,11 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
{
uint8 *p = func->code, *p_end = func->code + func->code_size, *p_org;
uint32 param_count, local_count, global_count;
uint8 *param_types, *local_types, local_type, global_type;
uint8 *param_types, *local_types, local_type, global_type, mem_offset_type;
BlockType func_block_type;
uint16 *local_offsets, local_offset;
uint32 count, local_idx, global_idx, u32, align, mem_offset, i;
uint32 count, local_idx, global_idx, u32, align, i;
mem_offset_t mem_offset;
int32 i32, i32_const = 0;
int64 i64_const;
uint8 opcode, u8;
@ -5797,6 +5905,19 @@ wasm_loader_prepare_bytecode(WASMModule *module, WASMFunction *func,
LOG_OP("\nProcessing func | [%d] params | [%d] locals | [%d] return\n",
func->param_cell_num, func->local_cell_num, func->ret_cell_num);
#endif
#if WASM_ENABLE_MEMORY64 != 0
bool is_memory64 = false;
/* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */
if (module->import_memory_count > 0)
is_memory64 = module->import_memories[0].u.memory.flags & MEMORY64_FLAG;
else if (module->memory_count > 0)
is_memory64 = module->memories[0].flags & MEMORY64_FLAG;
mem_offset_type = is_memory64 ? VALUE_TYPE_I64 : VALUE_TYPE_I32;
#else
mem_offset_type = VALUE_TYPE_I32;
#endif
global_count = module->import_global_count + module->global_count;
@ -6105,8 +6226,8 @@ re_scan:
bh_memcpy_s(loader_ctx->frame_offset, size,
block->param_frame_offsets, size);
loader_ctx->frame_offset += (size / sizeof(int16));
loader_ctx->dynamic_offset = block->start_dynamic_offset;
}
loader_ctx->dynamic_offset = block->start_dynamic_offset;
#endif
break;
@ -6179,7 +6300,7 @@ re_scan:
case WASM_OP_BR:
{
if (!(frame_csp_tmp =
check_branch_block(loader_ctx, &p, p_end, false,
check_branch_block(loader_ctx, &p, p_end, opcode,
error_buf, error_buf_size)))
goto fail;
@ -6193,7 +6314,7 @@ re_scan:
POP_I32();
if (!(frame_csp_tmp =
check_branch_block(loader_ctx, &p, p_end, false,
check_branch_block(loader_ctx, &p, p_end, opcode,
error_buf, error_buf_size)))
goto fail;
@ -6223,7 +6344,7 @@ re_scan:
#endif
for (i = 0; i <= count; i++) {
if (!(frame_csp_tmp =
check_branch_block(loader_ctx, &p, p_end, true,
check_branch_block(loader_ctx, &p, p_end, opcode,
error_buf, error_buf_size)))
goto fail;
@ -7106,7 +7227,7 @@ re_scan:
#endif
CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset);
#endif
@ -7120,7 +7241,7 @@ re_scan:
case WASM_OP_I32_LOAD8_U:
case WASM_OP_I32_LOAD16_S:
case WASM_OP_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break;
case WASM_OP_I64_LOAD:
case WASM_OP_I64_LOAD8_S:
@ -7129,35 +7250,35 @@ re_scan:
case WASM_OP_I64_LOAD16_U:
case WASM_OP_I64_LOAD32_S:
case WASM_OP_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break;
case WASM_OP_F32_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F32);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F32);
break;
case WASM_OP_F64_LOAD:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_F64);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_F64);
break;
/* store */
case WASM_OP_I32_STORE:
case WASM_OP_I32_STORE8:
case WASM_OP_I32_STORE16:
POP_I32();
POP_I32();
POP_MEM_OFFSET();
break;
case WASM_OP_I64_STORE:
case WASM_OP_I64_STORE8:
case WASM_OP_I64_STORE16:
case WASM_OP_I64_STORE32:
POP_I64();
POP_I32();
POP_MEM_OFFSET();
break;
case WASM_OP_F32_STORE:
POP_F32();
POP_I32();
POP_MEM_OFFSET();
break;
case WASM_OP_F64_STORE:
POP_F64();
POP_I32();
POP_MEM_OFFSET();
break;
default:
break;
@ -7170,7 +7291,7 @@ re_scan:
/* reserved byte 0x00 */
bh_assert(*p == 0x00);
p++;
PUSH_I32();
PUSH_PAGE_COUNT();
module->possible_memory_grow = true;
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
@ -7183,7 +7304,7 @@ re_scan:
/* reserved byte 0x00 */
bh_assert(*p == 0x00);
p++;
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
POP_AND_PUSH(mem_offset_type, mem_offset_type);
module->possible_memory_grow = true;
#if WASM_ENABLE_FAST_JIT != 0 || WASM_ENABLE_JIT != 0 \
@ -7230,6 +7351,7 @@ re_scan:
break;
case WASM_OP_F32_CONST:
CHECK_BUF(p, p_end, sizeof(float32));
p += sizeof(float32);
#if WASM_ENABLE_FAST_INTERP != 0
skip_label();
@ -7248,6 +7370,7 @@ re_scan:
break;
case WASM_OP_F64_CONST:
CHECK_BUF(p, p_end, sizeof(float64));
p += sizeof(float64);
#if WASM_ENABLE_FAST_INTERP != 0
skip_label();
@ -7534,7 +7657,7 @@ re_scan:
POP_I32();
POP_I32();
POP_I32();
POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true;
#endif
@ -7555,6 +7678,7 @@ re_scan:
}
case WASM_OP_MEMORY_COPY:
{
CHECK_BUF(p, p_end, sizeof(int16));
/* both src and dst memory index should be 0 */
bh_assert(*(int16 *)p == 0x0000);
p += 2;
@ -7563,9 +7687,9 @@ re_scan:
+ module->memory_count
> 0);
POP_I32();
POP_I32();
POP_I32();
POP_MEM_OFFSET();
POP_MEM_OFFSET();
POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true;
#endif
@ -7580,9 +7704,9 @@ re_scan:
+ module->memory_count
> 0);
POP_MEM_OFFSET();
POP_I32();
POP_I32();
POP_I32();
POP_MEM_OFFSET();
#if WASM_ENABLE_JIT != 0 || WASM_ENABLE_WAMR_COMPILER != 0
func->has_memory_operations = true;
#endif
@ -7747,7 +7871,7 @@ re_scan:
if (opcode1 != WASM_OP_ATOMIC_FENCE) {
CHECK_MEMORY();
read_leb_uint32(p, p_end, align); /* align */
read_leb_uint32(p, p_end, mem_offset); /* offset */
read_leb_mem_offset(p, p_end, mem_offset); /* offset */
#if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, mem_offset);
#endif
@ -7757,18 +7881,20 @@ re_scan:
#endif
switch (opcode1) {
case WASM_OP_ATOMIC_NOTIFY:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break;
case WASM_OP_ATOMIC_WAIT32:
POP_I64();
POP_I32();
POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break;
case WASM_OP_ATOMIC_WAIT64:
POP_I64();
POP_I64();
POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break;
case WASM_OP_ATOMIC_FENCE:
@ -7779,26 +7905,26 @@ re_scan:
case WASM_OP_ATOMIC_I32_LOAD:
case WASM_OP_ATOMIC_I32_LOAD8_U:
case WASM_OP_ATOMIC_I32_LOAD16_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I32);
break;
case WASM_OP_ATOMIC_I32_STORE:
case WASM_OP_ATOMIC_I32_STORE8:
case WASM_OP_ATOMIC_I32_STORE16:
POP_I32();
POP_I32();
POP_MEM_OFFSET();
break;
case WASM_OP_ATOMIC_I64_LOAD:
case WASM_OP_ATOMIC_I64_LOAD8_U:
case WASM_OP_ATOMIC_I64_LOAD16_U:
case WASM_OP_ATOMIC_I64_LOAD32_U:
POP_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I64);
POP_AND_PUSH(mem_offset_type, VALUE_TYPE_I64);
break;
case WASM_OP_ATOMIC_I64_STORE:
case WASM_OP_ATOMIC_I64_STORE8:
case WASM_OP_ATOMIC_I64_STORE16:
case WASM_OP_ATOMIC_I64_STORE32:
POP_I64();
POP_I32();
POP_MEM_OFFSET();
break;
case WASM_OP_ATOMIC_RMW_I32_ADD:
case WASM_OP_ATOMIC_RMW_I32_ADD8_U:
@ -7818,7 +7944,9 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_XCHG:
case WASM_OP_ATOMIC_RMW_I32_XCHG8_U:
case WASM_OP_ATOMIC_RMW_I32_XCHG16_U:
POP2_AND_PUSH(VALUE_TYPE_I32, VALUE_TYPE_I32);
POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break;
case WASM_OP_ATOMIC_RMW_I64_ADD:
case WASM_OP_ATOMIC_RMW_I64_ADD8_U:
@ -7845,7 +7973,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_XCHG16_U:
case WASM_OP_ATOMIC_RMW_I64_XCHG32_U:
POP_I64();
POP_I32();
POP_MEM_OFFSET();
PUSH_I64();
break;
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG:
@ -7853,7 +7981,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I32_CMPXCHG16_U:
POP_I32();
POP_I32();
POP_I32();
POP_MEM_OFFSET();
PUSH_I32();
break;
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG:
@ -7862,7 +7990,7 @@ re_scan:
case WASM_OP_ATOMIC_RMW_I64_CMPXCHG32_U:
POP_I64();
POP_I64();
POP_I32();
POP_MEM_OFFSET();
PUSH_I64();
break;
default:

View File

@ -593,8 +593,8 @@ typedef enum WASMSimdEXTOpcode {
/* placeholder = 0xa2 */
SIMD_i32x4_all_true = 0xa3,
SIMD_i32x4_bitmask = 0xa4,
SIMD_i32x4_narrow_i64x2_s = 0xa5,
SIMD_i32x4_narrow_i64x2_u = 0xa6,
/* placeholder = 0xa5 */
/* placeholder = 0xa6 */
SIMD_i32x4_extend_low_i16x8_s = 0xa7,
SIMD_i32x4_extend_high_i16x8_s = 0xa8,
SIMD_i32x4_extend_low_i16x8_u = 0xa9,
@ -603,11 +603,11 @@ typedef enum WASMSimdEXTOpcode {
SIMD_i32x4_shr_s = 0xac,
SIMD_i32x4_shr_u = 0xad,
SIMD_i32x4_add = 0xae,
SIMD_i32x4_add_sat_s = 0xaf,
SIMD_i32x4_add_sat_u = 0xb0,
/* placeholder = 0xaf */
/* placeholder = 0xb0 */
SIMD_i32x4_sub = 0xb1,
SIMD_i32x4_sub_sat_s = 0xb2,
SIMD_i32x4_sub_sat_u = 0xb3,
/* placeholder = 0xb2 */
/* placeholder = 0xb3 */
/* placeholder = 0xb4 */
SIMD_i32x4_mul = 0xb5,
SIMD_i32x4_min_s = 0xb6,
@ -615,7 +615,7 @@ typedef enum WASMSimdEXTOpcode {
SIMD_i32x4_max_s = 0xb8,
SIMD_i32x4_max_u = 0xb9,
SIMD_i32x4_dot_i16x8_s = 0xba,
SIMD_i32x4_avgr_u = 0xbb,
/* placeholder = 0xbb */
SIMD_i32x4_extmul_low_i16x8_s = 0xbc,
SIMD_i32x4_extmul_high_i16x8_s = 0xbd,
SIMD_i32x4_extmul_low_i16x8_u = 0xbe,
@ -658,7 +658,7 @@ typedef enum WASMSimdEXTOpcode {
/* f32x4 operation */
SIMD_f32x4_abs = 0xe0,
SIMD_f32x4_neg = 0xe1,
SIMD_f32x4_round = 0xe2,
/* placeholder = 0xe2 */
SIMD_f32x4_sqrt = 0xe3,
SIMD_f32x4_add = 0xe4,
SIMD_f32x4_sub = 0xe5,
@ -672,7 +672,7 @@ typedef enum WASMSimdEXTOpcode {
/* f64x2 operation */
SIMD_f64x2_abs = 0xec,
SIMD_f64x2_neg = 0xed,
SIMD_f64x2_round = 0xee,
/* placeholder = 0xee */
SIMD_f64x2_sqrt = 0xef,
SIMD_f64x2_add = 0xf0,
SIMD_f64x2_sub = 0xf1,

View File

@ -60,13 +60,13 @@ wasm_load(uint8 *buf, uint32 size,
#if WASM_ENABLE_MULTI_MODULE != 0
bool main_module,
#endif
char *error_buf, uint32 error_buf_size)
const LoadArgs *name, char *error_buf, uint32 error_buf_size)
{
return wasm_loader_load(buf, size,
#if WASM_ENABLE_MULTI_MODULE != 0
main_module,
#endif
error_buf, error_buf_size);
name, error_buf, error_buf_size);
}
WASMModule *
@ -162,7 +162,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
char *error_buf, uint32 error_buf_size)
{
WASMModule *module = module_inst->module;
uint32 inc_page_count, global_idx;
uint32 inc_page_count, global_idx, default_max_page;
uint32 bytes_of_last_page, bytes_to_page_end;
uint64 aux_heap_base,
heap_offset = (uint64)num_bytes_per_page * init_page_count;
@ -171,7 +171,7 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
bool is_shared_memory = false;
#if WASM_ENABLE_SHARED_MEMORY != 0
is_shared_memory = flags & 0x02 ? true : false;
is_shared_memory = flags & SHARED_MEMORY_FLAG ? true : false;
/* shared memory */
if (is_shared_memory && parent != NULL) {
@ -186,6 +186,14 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
(void)flags;
#endif /* end of WASM_ENABLE_SHARED_MEMORY */
#if WASM_ENABLE_MEMORY64 != 0
if (flags & MEMORY64_FLAG) {
memory->is_memory64 = 1;
}
#endif
default_max_page =
memory->is_memory64 ? DEFAULT_MEM64_MAX_PAGES : DEFAULT_MAX_PAGES;
if (heap_size > 0 && module_inst->module->malloc_function != (uint32)-1
&& module_inst->module->free_function != (uint32)-1) {
/* Disable app heap, use malloc/free function exported
@ -195,7 +203,8 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
/* If initial memory is the largest size allowed, disallowing insert host
* managed heap */
if (heap_size > 0 && heap_offset == MAX_LINEAR_MEMORY_SIZE) {
if (heap_size > 0
&& heap_offset == GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64)) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap-size=0` option");
@ -253,8 +262,18 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
&& global_idx < module_inst->e->global_count);
global_addr = module_inst->global_data
+ module_inst->e->globals[global_idx].data_offset;
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
/* For memory64, the global value should be i64 */
*(uint64 *)global_addr = aux_heap_base;
}
else
#endif
{
/* For memory32, the global value should be i32 */
*(uint32 *)global_addr = (uint32)aux_heap_base;
LOG_VERBOSE("Reset __heap_base global to %u", aux_heap_base);
}
LOG_VERBOSE("Reset __heap_base global to %" PRIu64, aux_heap_base);
}
else {
/* Insert app heap before new page */
@ -267,30 +286,34 @@ memory_instantiate(WASMModuleInstance *module_inst, WASMModuleInstance *parent,
}
init_page_count += inc_page_count;
max_page_count += inc_page_count;
if (init_page_count > DEFAULT_MAX_PAGES) {
if (init_page_count > default_max_page) {
set_error_buf(error_buf, error_buf_size,
"failed to insert app heap into linear memory, "
"try using `--heap-size=0` option");
return NULL;
}
if (max_page_count > DEFAULT_MAX_PAGES)
max_page_count = DEFAULT_MAX_PAGES;
if (max_page_count > default_max_page)
max_page_count = default_max_page;
}
LOG_VERBOSE("Memory instantiate:");
LOG_VERBOSE(" page bytes: %u, init pages: %u, max pages: %u",
num_bytes_per_page, init_page_count, max_page_count);
LOG_VERBOSE(" heap offset: %u, heap size: %d\n", heap_offset, heap_size);
LOG_VERBOSE(" heap offset: %" PRIu64 ", heap size: %u\n", heap_offset,
heap_size);
max_memory_data_size = (uint64)num_bytes_per_page * max_page_count;
bh_assert(max_memory_data_size <= MAX_LINEAR_MEMORY_SIZE);
bh_assert(max_memory_data_size
<= GET_MAX_LINEAR_MEMORY_SIZE(memory->is_memory64));
(void)max_memory_data_size;
bh_assert(memory != NULL);
if (wasm_allocate_linear_memory(&memory->memory_data, is_shared_memory,
num_bytes_per_page, init_page_count,
max_page_count, &memory_data_size)
memory->is_memory64, num_bytes_per_page,
init_page_count, max_page_count,
&memory_data_size)
!= BHT_OK) {
set_error_buf(error_buf, error_buf_size,
"allocate linear memory failed");
@ -1947,7 +1970,8 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
WASMGlobalInstance *globals = NULL, *global;
WASMTableInstance *first_table;
uint32 global_count, i;
uint32 base_offset, length, extra_info_offset;
uint32 length, extra_info_offset;
mem_offset_t base_offset;
uint32 module_inst_struct_size =
offsetof(WASMModuleInstance, global_table_data.bytes);
uint64 module_inst_mem_inst_size;
@ -2305,10 +2329,12 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
(uint64)memory->num_bytes_per_page * memory->cur_page_count;
bh_assert(memory_data || memory_size == 0);
bh_assert(data_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_I32_CONST
|| data_seg->base_offset.init_expr_type
== INIT_EXPR_TYPE_GET_GLOBAL);
bh_assert(
data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL
|| (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I32_CONST
&& !memory->is_memory64)
|| (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_I64_CONST
&& memory->is_memory64));
if (data_seg->base_offset.init_expr_type == INIT_EXPR_TYPE_GET_GLOBAL) {
if (!check_global_init_expr(module,
@ -2319,23 +2345,48 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
if (!globals
|| globals[data_seg->base_offset.u.global_index].type
!= VALUE_TYPE_I32) {
!= (memory->is_memory64 ? VALUE_TYPE_I64
: VALUE_TYPE_I32)) {
set_error_buf(error_buf, error_buf_size,
"data segment does not fit");
goto fail;
}
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset =
globals[data_seg->base_offset.u.global_index].initial_value.i32;
(uint64)globals[data_seg->base_offset.u.global_index]
.initial_value.i64;
}
else
#endif
{
base_offset =
(uint32)globals[data_seg->base_offset.u.global_index]
.initial_value.i32;
}
}
else {
#if WASM_ENABLE_MEMORY64 != 0
if (memory->is_memory64) {
base_offset = (uint64)data_seg->base_offset.u.i64;
}
else
#endif
{
base_offset = (uint32)data_seg->base_offset.u.i32;
}
}
/* check offset */
if (base_offset > memory_size) {
LOG_DEBUG("base_offset(%d) > memory_size(%d)", base_offset,
#if WASM_ENABLE_MEMORY64 != 0
LOG_DEBUG("base_offset(%" PRIu64 ") > memory_size(%" PRIu64 ")",
base_offset, memory_size);
#else
LOG_DEBUG("base_offset(%u) > memory_size(%" PRIu64 ")", base_offset,
memory_size);
#endif
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
set_error_buf(error_buf, error_buf_size,
"out of bounds memory access");
@ -2349,8 +2400,14 @@ wasm_instantiate(WASMModule *module, WASMModuleInstance *parent,
/* check offset + length(could be zero) */
length = data_seg->data_length;
if ((uint64)base_offset + length > memory_size) {
LOG_DEBUG("base_offset(%d) + length(%d) > memory_size(%d)",
#if WASM_ENABLE_MEMORY64 != 0
LOG_DEBUG("base_offset(%" PRIu64
") + length(%d) > memory_size(%" PRIu64 ")",
base_offset, length, memory_size);
#else
LOG_DEBUG("base_offset(%u) + length(%d) > memory_size(%" PRIu64 ")",
base_offset, length, memory_size);
#endif
#if WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0
set_error_buf(error_buf, error_buf_size,
"out of bounds memory access");
@ -3311,7 +3368,8 @@ wasm_module_malloc_internal(WASMModuleInstance *module_inst,
wasm_set_exception(module_inst, "app heap corrupted");
}
else {
LOG_WARNING("warning: allocate %u bytes memory failed", size);
LOG_WARNING("warning: allocate %" PRIu64 " bytes memory failed",
size);
}
return 0;
}
@ -3510,7 +3568,7 @@ call_indirect(WASMExecEnv *exec_env, uint32 tbl_idx, uint32 tbl_elem_idx,
}
#if WASM_ENABLE_GC == 0
func_idx = tbl_elem_val;
func_idx = (uint32)tbl_elem_val;
#else
func_idx =
wasm_func_obj_get_func_idx_bound((WASMFuncObjectRef)tbl_elem_val);
@ -4295,11 +4353,21 @@ llvm_jit_table_grow(WASMModuleInstance *module_inst, uint32 tbl_idx,
}
if (tbl_inst->cur_size > UINT32_MAX - inc_size) { /* integer overflow */
#if WASM_ENABLE_SPEC_TEST == 0
LOG_WARNING("table grow (%" PRIu32 "-> %" PRIu32
") failed because of integer overflow",
tbl_inst->cur_size, inc_size);
#endif
return (uint32)-1;
}
total_size = tbl_inst->cur_size + inc_size;
if (total_size > tbl_inst->max_size) {
#if WASM_ENABLE_SPEC_TEST == 0
LOG_WARNING("table grow (%" PRIu32 "-> %" PRIu32
") failed because of over max size",
tbl_inst->cur_size, inc_size);
#endif
return (uint32)-1;
}
@ -4336,6 +4404,22 @@ llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
return wasm_obj_is_instance_of(gc_obj, type_index, types, type_count);
}
bool
llvm_jit_func_type_is_super_of(WASMModuleInstance *module_inst,
uint32 type_idx1, uint32 type_idx2)
{
WASMModule *module = module_inst->module;
WASMType **types = module->types;
if (type_idx1 == type_idx2)
return true;
bh_assert(types[type_idx1]->type_flag == WASM_TYPE_FUNC);
bh_assert(types[type_idx2]->type_flag == WASM_TYPE_FUNC);
return wasm_func_type_is_super_of((WASMFuncType *)types[type_idx1],
(WASMFuncType *)types[type_idx2]);
}
WASMRttTypeRef
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index)
{
@ -4541,8 +4625,8 @@ wasm_set_module_name(WASMModule *module, const char *name, char *error_buf,
return false;
module->name =
wasm_const_str_list_insert((const uint8 *)name, strlen(name), module,
false, error_buf, error_buf_size);
wasm_const_str_list_insert((const uint8 *)name, (uint32)strlen(name),
module, false, error_buf, error_buf_size);
return module->name != NULL;
}

View File

@ -103,7 +103,7 @@ struct WASMMemoryInstance {
/* Whether the memory is shared */
uint8 is_shared_memory;
/* TODO: Memory64 whether the memory has 64-bit memory addresses */
/* Whether the memory has 64-bit memory addresses */
uint8 is_memory64;
/* Reference count of the memory instance:
@ -508,7 +508,7 @@ wasm_load(uint8 *buf, uint32 size,
#if WASM_ENABLE_MULTI_MODULE != 0
bool main_module,
#endif
char *error_buf, uint32 error_buf_size);
const LoadArgs *args, char *error_buf, uint32 error_buf_size);
WASMModule *
wasm_load_from_sections(WASMSection *section_list, char *error_buf,
@ -811,6 +811,11 @@ bool
llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
WASMObjectRef gc_obj, uint32 type_index);
/* Whether func type1 is one of super types of func type2 */
bool
llvm_jit_func_type_is_super_of(WASMModuleInstance *module_inst,
uint32 type_idx1, uint32 type_idx2);
WASMRttTypeRef
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index);

View File

@ -309,9 +309,11 @@ handle_general_query(WASMGDBServer *server, char *payload)
}
if (!strcmp(name, "WasmData")) {
write_packet(server, "");
}
if (!strcmp(name, "WasmMem")) {
write_packet(server, "");
}
if (!strcmp(name, "Symbol")) {
@ -447,7 +449,7 @@ send_thread_stop_status(WASMGDBServer *server, uint32 status, korp_tid tid)
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
pc_string, "trace");
}
else if (status > 0) {
else { /* status > 0 (== 0 is checked at the function beginning) */
len += snprintf(tmpbuf + len, MAX_PACKET_SIZE - len,
"thread-pcs:%" PRIx64 ";00:%s;reason:%s;", pc,
pc_string, "signal");

View File

@ -1123,7 +1123,8 @@ posix_memalign_wrapper(wasm_exec_env_t exec_env, void **memptr, int32 align,
wasm_module_inst_t module_inst = get_module_inst(exec_env);
void *p = NULL;
*((int32 *)memptr) = module_malloc(size, (void **)&p);
/* TODO: for memory 64, module_malloc may return uint64 offset */
*((uint32 *)memptr) = (uint32)module_malloc(size, (void **)&p);
if (!p)
return -1;

View File

@ -17,7 +17,7 @@ void
wasm_runtime_set_exception(wasm_module_inst_t module, const char *exception);
uint32
wasm_runtime_module_realloc(wasm_module_inst_t module, uint32 ptr, uint32 size,
wasm_runtime_module_realloc(wasm_module_inst_t module, uint64 ptr, uint64 size,
void **p_native_addr);
/* clang-format off */

View File

@ -3,6 +3,9 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*/
#ifndef _BLOCKING_OP_H_
#define _BLOCKING_OP_H_
#include "bh_platform.h"
#include "wasm_export.h"
@ -57,3 +60,5 @@ __wasi_errno_t
blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds, os_nfds_t nfds,
int timeout, int *retp);
#endif
#endif /* end of _BLOCKING_OP_H_ */

View File

@ -558,6 +558,7 @@ wasm_cluster_spawn_exec_env(WASMExecEnv *exec_env)
aux_stack_size)) {
goto fail3;
}
new_exec_env->is_aux_stack_allocated = true;
/* Inherit suspend_flags of parent thread */
new_exec_env->suspend_flags.flags =
@ -603,7 +604,9 @@ wasm_cluster_destroy_spawned_exec_env(WASMExecEnv *exec_env)
exec_env_tls = exec_env;
}
/* Free aux stack space */
/* Free aux stack space which was allocated in
wasm_cluster_spawn_exec_env */
bh_assert(exec_env_tls->is_aux_stack_allocated);
wasm_cluster_free_aux_stack(exec_env_tls,
(uint64)exec_env->aux_stack_bottom);
@ -655,7 +658,9 @@ thread_manager_start_routine(void *arg)
#endif
/* Free aux stack space */
wasm_cluster_free_aux_stack(exec_env, (uint64)exec_env->aux_stack_bottom);
if (exec_env->is_aux_stack_allocated)
wasm_cluster_free_aux_stack(exec_env,
(uint64)exec_env->aux_stack_bottom);
os_mutex_lock(&cluster_list_lock);
@ -723,11 +728,13 @@ wasm_cluster_create_thread(WASMExecEnv *exec_env,
aux_stack_size)) {
goto fail2;
}
new_exec_env->is_aux_stack_allocated = true;
}
else {
/* Disable aux stack */
new_exec_env->aux_stack_boundary = 0;
new_exec_env->aux_stack_bottom = UINTPTR_MAX;
new_exec_env->is_aux_stack_allocated = false;
}
/* Inherit suspend_flags of parent thread */
@ -1049,7 +1056,9 @@ wasm_cluster_exit_thread(WASMExecEnv *exec_env, void *retval)
#endif
/* Free aux stack space */
wasm_cluster_free_aux_stack(exec_env, (uint64)exec_env->aux_stack_bottom);
if (exec_env->is_aux_stack_allocated)
wasm_cluster_free_aux_stack(exec_env,
(uint64)exec_env->aux_stack_bottom);
/* App exit the thread, free the resources before exit native thread */

View File

@ -785,8 +785,8 @@ gc_alloc_wo_internal(void *vheap, gc_size_t size, const char *file, int line)
if (!hmu)
goto finish;
/* Do we need to memset the memory to 0? */
/* memset((char *)hmu + sizeof(*hmu), 0, tot_size - sizeof(*hmu)); */
/* Don't memset the memory to improve performance, the caller should
decide whether to memset it or not */
bh_assert(hmu_get_size(hmu) >= tot_size);
/* the total size allocated may be larger than

View File

@ -114,8 +114,8 @@ sweep_instance_heap(gc_heap_t *heap)
else {
/* current block is still live */
if (last) {
tot_free += (char *)cur - (char *)last;
gci_add_fc(heap, last, (char *)cur - (char *)last);
tot_free += (gc_size_t)((char *)cur - (char *)last);
gci_add_fc(heap, last, (gc_size_t)((char *)cur - (char *)last));
hmu_mark_pinuse(last);
last = NULL;
}
@ -132,8 +132,8 @@ sweep_instance_heap(gc_heap_t *heap)
bh_assert(cur == end);
if (last) {
tot_free += (char *)cur - (char *)last;
gci_add_fc(heap, last, (char *)cur - (char *)last);
tot_free += (gc_size_t)((char *)cur - (char *)last);
gci_add_fc(heap, last, (gc_size_t)((char *)cur - (char *)last));
hmu_mark_pinuse(last);
}
@ -449,7 +449,9 @@ gci_gc_heap(void *h)
LOG_VERBOSE("#reclaim instance heap %p", heap);
gct_vm_gc_prepare();
/* TODO: get exec_env of current thread when GC multi-threading
is enabled, and pass it to runtime */
gct_vm_gc_prepare(NULL);
gct_vm_mutex_lock(&heap->lock);
heap->is_doing_reclaim = 1;
@ -459,7 +461,9 @@ gci_gc_heap(void *h)
heap->is_doing_reclaim = 0;
gct_vm_mutex_unlock(&heap->lock);
gct_vm_gc_finished();
/* TODO: get exec_env of current thread when GC multi-threading
is enabled, and pass it to runtime */
gct_vm_gc_finished(NULL);
LOG_VERBOSE("#reclaim instance heap %p done", heap);

View File

@ -77,13 +77,13 @@ mem_allocator_free_with_gc(mem_allocator_t allocator, void *ptr)
void
mem_allocator_enable_gc_reclaim(mem_allocator_t allocator, void *exec_env)
{
return gc_enable_gc_reclaim((gc_handle_t)allocator, exec_env);
gc_enable_gc_reclaim((gc_handle_t)allocator, exec_env);
}
#else
void
mem_allocator_enable_gc_reclaim(mem_allocator_t allocator, void *cluster)
{
return gc_enable_gc_reclaim((gc_handle_t)allocator, cluster);
gc_enable_gc_reclaim((gc_handle_t)allocator, cluster);
}
#endif

View File

@ -823,7 +823,7 @@ os_fadvise(os_file_handle handle, __wasi_filesize_t offset,
int ret = posix_fadvise(handle, (off_t)offset, (off_t)length, nadvice);
if (ret < 0)
if (ret != 0)
return convert_errno(ret);
return __WASI_ESUCCESS;

View File

@ -65,9 +65,11 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
/* integer overflow */
return NULL;
#if WASM_ENABLE_MEMORY64 == 0
if (request_size > 16 * (uint64)UINT32_MAX)
/* at most 16 G is allowed */
/* at most 64 G is allowed */
return NULL;
#endif
if (prot & MMAP_PROT_READ)
map_prot |= PROT_READ;

View File

@ -55,7 +55,24 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
#else
uint32_t mem_caps = MALLOC_CAP_8BIT;
#endif
return heap_caps_malloc(size, mem_caps);
void *buf_origin =
heap_caps_malloc(size + 4 + sizeof(uintptr_t), mem_caps);
if (!buf_origin) {
return NULL;
}
// Memory allocation with MALLOC_CAP_SPIRAM or MALLOC_CAP_8BIT will
// return 4-byte aligned Reserve extra 4 byte to fixup alignment and
// size for the pointer to the originally allocated address
void *buf_fixed = buf_origin + sizeof(void *);
if ((uintptr_t)buf_fixed & (uintptr_t)0x7) {
buf_fixed = (void *)((uintptr_t)(buf_fixed + 4) & (~(uintptr_t)7));
}
uintptr_t *addr_field = buf_fixed - sizeof(uintptr_t);
*addr_field = (uintptr_t)buf_origin;
return buf_fixed;
}
}

View File

@ -6,6 +6,12 @@
#include "platform_api_vmcore.h"
#include "platform_api_extension.h"
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 0, 0)) \
&& (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 2, 0))
#define UTIMENSAT_TIMESPEC_POINTER 1
#define FUTIMENS_TIMESPEC_POINTER 1
#endif
int
bh_platform_init()
{
@ -234,7 +240,13 @@ unlinkat(int fd, const char *path, int flag)
}
int
utimensat(int fd, const char *path, const struct timespec ts[2], int flag)
utimensat(int fd, const char *path,
#if UTIMENSAT_TIMESPEC_POINTER
const struct timespec *ts,
#else
const struct timespec ts[2],
#endif
int flag)
{
errno = ENOSYS;
return -1;
@ -257,7 +269,13 @@ ftruncate(int fd, off_t length)
#endif
int
futimens(int fd, const struct timespec times[2])
futimens(int fd,
#if FUTIMENS_TIMESPEC_POINTER
const struct timespec *times
#else
const struct timespec times[2]
#endif
)
{
errno = ENOSYS;
return -1;

View File

@ -8,6 +8,10 @@ add_definitions(-DBH_PLATFORM_NUTTX)
include_directories(${PLATFORM_SHARED_DIR})
include_directories(${PLATFORM_SHARED_DIR}/../include)
include (${CMAKE_CURRENT_LIST_DIR}/../common/posix/platform_api_posix.cmake)
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)
file (GLOB_RECURSE source_all ${PLATFORM_SHARED_DIR}/*.c)
if (WAMR_BUILD_LIBC_WASI EQUAL 1)
@ -16,6 +20,7 @@ if (WAMR_BUILD_LIBC_WASI EQUAL 1)
set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE})
endif ()
include (${CMAKE_CURRENT_LIST_DIR}/../common/memory/platform_api_memory.cmake)
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE} ${PLATFORM_COMMON_MEMORY_SOURCE})
set (PLATFORM_SHARED_SOURCE ${source_all} ${PLATFORM_COMMON_MATH_SOURCE} ${PLATFORM_COMMON_POSIX_SOURCE} ${UNCOMMON_SHARED_SOURCE})
# remove posix_memmap.c for NuttX
list(REMOVE_ITEM ${PLATFORM_SHARED_SOURCE} ${PLATFORM_COMMON_POSIX_DIR}/posix_memmap.c)

View File

@ -578,3 +578,33 @@ os_thread_get_stack_boundary()
void
os_thread_jit_write_protect_np(bool enabled)
{}
int
os_thread_detach(korp_tid thread)
{
(void)thread;
return BHT_OK;
}
void
os_thread_exit(void *retval)
{
(void)retval;
os_thread_cleanup();
k_thread_abort(k_current_get());
}
int
os_cond_broadcast(korp_cond *cond)
{
os_thread_wait_node *node;
k_mutex_lock(&cond->wait_list_lock, K_FOREVER);
node = cond->thread_wait_list;
while (node) {
os_thread_wait_node *next = node->next;
k_sem_give(&node->sem);
node = next;
}
k_mutex_unlock(&cond->wait_list_lock);
return BHT_OK;
}

View File

@ -394,7 +394,7 @@ handle_expired_timers(timer_ctx_t ctx, app_timer_t *expired)
operation may change expired->next */
expired = expired->next;
if (t->is_periodic) {
/* if it is repeating, then reschedule it; */
/* if it is repeating, then reschedule it */
reschedule_timer(ctx, t);
}
else {

View File

@ -76,6 +76,11 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
#### **Enable bulk memory feature**
- **WAMR_BUILD_BULK_MEMORY**=1/0, default to disable if not set
#### **Enable memory64 feature**
- **WAMR_BUILD_MEMORY64**=1/0, default to disable if not set
> Note: Currently, the memory64 feature is only supported in classic interpreter running mode.
#### **Enable thread manager**
- **WAMR_BUILD_THREAD_MGR**=1/0, default to disable if not set
@ -129,6 +134,14 @@ cmake -DWAMR_BUILD_PLATFORM=linux -DWAMR_BUILD_TARGET=ARM
- **WAMR_BUILD_SIMD**=1/0, default to enable if not set
> Note: only supported in AOT mode x86-64 target.
#### **Enable Exception Handling**
- **WAMR_BUILD_EXCE_HANDLING**=1/0, default to disable if not set
> Note: Currently, the exception handling feature is only supported in classic interpreter running mode.
#### **Enable Garbage Collection**
- **WAMR_BUILD_GC**=1/0, default to disable if not set
#### **Configure Debug**
- **WAMR_BUILD_CUSTOM_NAME_SECTION**=1/0, load the function name from custom name section, default to disable if not set
@ -241,6 +254,10 @@ Currently we only profile the memory consumption of module, module_instance and
> See [Enable segue optimization for wamrc when generating the aot file](./perf_tune.md#3-enable-segue-optimization-for-wamrc-when-generating-the-aot-file) for more details.
#### **User defined linear memory allocator**
- **WAMR_BUILD_ALLOC_WITH_USAGE**=1/0, default to disable if not set
> Notes: by default, the linear memory is allocated by system. when it's set to 1 and Alloc_With_Allocator is selected, it will be allocated by customer.
#### **Enable running PGO(Profile-Guided Optimization) instrumented AOT file**
- **WAMR_BUILD_STATIC_PGO**=1/0, default to disable if not set
> Note: See [Use the AOT static PGO method](./perf_tune.md#5-use-the-aot-static-pgo-method) for more details.
@ -264,6 +281,10 @@ Currently we only profile the memory consumption of module, module_instance and
- **WAMR_BUILD_QUICK_AOT_ENTRY**=1/0, enable registering quick call entries to speedup the aot/jit func call process, default to enable if not set
> Note: See [Refine callings to AOT/JIT functions from host native](./perf_tune.md#83-refine-callings-to-aotjit-functions-from-host-native) for more details.
#### **Enable AOT intrinsics**
- **WAMR_BUILD_AOT_INTRINSICS**=1/0, enable the AOT intrinsic functions, default to enable if not set. These functions can be called from the AOT code when `--disable-llvm-intrinsics` flag or `--enable-builtin-intrinsics=<intr1,intr2,...>` flag is used by wamrc to generate the AOT file.
> Note: See [Tuning the XIP intrinsic functions](./xip.md#tuning-the-xip-intrinsic-functions) for more details.
#### **Configurale memory access boundary check**
- **WAMR_CONFIGUABLE_BOUNDS_CHECKS**=1/0, default to disable if not set
> Note: If it is enabled, allow to run `iwasm --disable-bounds-checks` to disable the memory access boundary checks for interpreter mode.

15
idf_component.yml Normal file
View File

@ -0,0 +1,15 @@
version: "2.0.0"
description: WebAssembly Micro Runtime - A lightweight standalone WebAssembly (Wasm) runtime with small footprint, high performance and highly configurable features
url: https://bytecodealliance.org/
repository: https://github.com/bytecodealliance/wasm-micro-runtime.git
documentation: https://wamr.gitbook.io/
issues: https://github.com/bytecodealliance/wasm-micro-runtime/issues
dependencies:
idf: ">=4.4"
targets:
- esp32
- esp32s3
- esp32c3
- esp32c6
examples:
- path: product-mini/platforms/esp-idf

View File

@ -6,7 +6,4 @@ cmake_minimum_required(VERSION 3.5)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set (COMPONENTS ${IDF_TARGET} main freertos esptool_py wamr)
list(APPEND EXTRA_COMPONENT_DIRS "$ENV{WAMR_PATH}/build-scripts/esp-idf")
project(wamr-simple)

View File

@ -2,5 +2,4 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
idf_component_register(SRCS "main.c"
INCLUDE_DIRS "."
REQUIRES wamr)
INCLUDE_DIRS ".")

View File

@ -0,0 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
wasm-micro-runtime:
version: "^2"
override_path: "../../../.."
idf:
version: ">=4.4"

View File

@ -12,11 +12,7 @@
#include "esp_log.h"
#ifdef CONFIG_IDF_TARGET_ESP32S3
#define IWASM_MAIN_STACK_SIZE 5120
#else
#define IWASM_MAIN_STACK_SIZE 4096
#endif
#define LOG_TAG "wamr"

View File

@ -0,0 +1,203 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# select platform configuration setting WAMR_BUILD_TARGET
set(WAMR_BUILD_PLATFORM nuttx)
if(CONFIG_ARCH_ARMV6M)
set(WAMR_BUILD_TARGET THUMBV6M)
elseif(CONFIG_ARCH_ARMV7A)
set(WAMR_BUILD_TARGET THUMBV7)
elseif(CONFIG_ARCH_ARMV7M)
set(WAMR_BUILD_TARGET THUMBV7EM)
elseif(CONFIG_ARCH_ARMV8M)
set(WAMR_BUILD_TARGET THUMBV8M)
elseif(CONFIG_ARCH_X86)
set(WAMR_BUILD_TARGET X86_32)
elseif(CONFIG_ARCH_X86_64)
set(WAMR_BUILD_TARGET X86_64)
elseif(CONFIG_ARCH_XTENSA)
set(WAMR_BUILD_TARGET XTENSA)
elseif(CONFIG_ARCH_RV64GC OR CONFIG_ARCH_RV64)
set(WAMR_BUILD_TARGET RISCV64)
elseif(CONFIG_ARCH_RV32IM OR CONFIG_ARCH_RV32)
set(WAMR_BUILD_TARGET RISCV32)
elseif(CONFIG_ARCH_SIM)
if(CONFIG_SIM_M32 OR CONFIG_HOST_X86)
set(WAMR_BUILD_TARGET X86_32)
elseif(CONFIG_HOST_ARM)
set(WAMR_BUILD_TARGET ARM)
elseif(CONFIG_HOST_ARM64)
set(WAMR_BUILD_TARGET AARCH64)
else()
set(WAMR_BUILD_TARGET X86_64)
endif()
if(CONFIG_HOST_MACOS)
add_definitions(-DBH_PLATFORM_DARWIN)
endif()
endif()
if(CONFIG_INTERPRETERS_WAMR_LOG)
add_definitions(-DWASM_ENABLE_LOG=1)
else()
add_definitions(-DWASM_ENABLE_LOG=0)
endif()
if(CONFIG_INTERPRETERS_WAMR_AOT_WORD_ALIGN_READ)
add_definitions(-DWASM_ENABLE_WORD_ALIGN_READ=1)
else()
add_definitions(-DWASM_ENABLE_WORD_ALIGN_READ=0)
endif()
if(CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE)
add_definitions(-DWASM_STACK_GUARD_SIZE=0)
else()
add_definitions(
-DWASM_STACK_GUARD_SIZE=${CONFIG_INTERPRETERS_WAMR_STACK_GUARD_SIZE})
endif()
if(CONFIG_INTERPRETERS_WAMR_MEMORY_TRACING)
add_definitions(-DWASM_ENABLE_MEMORY_TRACING=1)
else()
add_definitions(-DWASM_ENABLE_MEMORY_TRACING=0)
endif()
if(CONFIG_INTERPRETERS_WAMR_SHARED_MEMORY)
set(WAMR_BUILD_SHARED_MEMORY 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_BULK_MEMORY)
set(WAMR_BUILD_BULK_MEMORY 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_AOT_STACK_FRAME)
set(WAMR_BUILD_AOT_STACK_FRAME 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_PERF_PROFILING)
set(WAMR_BUILD_PERF_PROFILING 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_GC)
set(WAMR_BUILD_GC 1)
set(WAMR_BUILD_STRINGREF 1)
set(WAMR_BUILD_REF_TYPES 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_GC_MANUALLY)
add_definitions(-DWASM_GC_MANUALLY=1)
else()
add_definitions(-DWASM_GC_MANUALLY=0)
endif()
if(CONFIG_INTERPRETERS_WAMR_GC_PERF_PROFILING)
set(WAMR_BUILD_GC_PERF_PROFILING 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_ENABLE_EXCE_HANDLING)
set(WAMR_BUILD_EXCE_HANDLING 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_TAIL_CALL)
set(WAMR_BUILD_TAIL_CALL 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_MEMORY_PROFILING)
set(WAMR_BUILD_MEMORY_PROFILING 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_MULTI_MODULE)
set(WAMR_BUILD_MULTI_MODULE 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD_SEMAPHORE)
set(WAMR_BUILD_LIB_PTHREAD_SEMAPHORE 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_DISABLE_HW_BOUND_CHECK)
set(WAMR_DISABLE_HW_BOUND_CHECK 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_CUSTOM_NAME_SECTIONS)
set(WAMR_BUILD_CUSTOM_NAME_SECTION 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL)
set(WAMR_BUILD_GLOBAL_HEAP_POOL 1)
math(EXPR _HEAP_SIZE_
"${CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL_SIZE} * 1024")
set(WAMR_BUILD_GLOBAL_HEAP_SIZE ${_HEAP_SIZE_})
endif()
if (CONFIG_INTERPRETERS_WAMR_MEM_ALLOC_WITH_USAGE)
set(WAMR_BUILD_MEM_ALLOC_WITH_USAGE 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST)
set(WAMR_BUILD_SPEC_TEST 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_REF_TYPES)
set(WAMR_BUILD_REF_TYPES 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_CLASSIC)
# include iwasm_interp.cmake
set(WAMR_BUILD_INTERP 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_FAST)
# enable iwasm_interp.cmake
set(WAMR_BUILD_FAST_INTERP 1)
endif()
if((CONFIG_INTERPRETERS_WAMR_FAST OR CONFIG_INTERPRETERS_WAMR_CLASSIC)
AND CONFIG_INTERPRETERS_WAMR_MINILOADER)
# enable iwasm_interp.cmake
set(WAMR_BUILD_MINI_LOADER 1)
else()
set(WAMR_BUILD_MINI_LOADER 0)
endif()
if(CONFIG_INTERPRETERS_WAMR_AOT)
# include iwasm_aot.cmake
set(WAMR_BUILD_AOT 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_DEBUG_INTERP)
# include debug_engine.cmake
set(WAMR_BUILD_DEBUG_INTERP 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_LIBC_BUILTIN)
# include libc_builtin.cmake
set(WAMR_BUILD_LIBC_BUILTIN 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_LIBC_WASI)
# include libc_wasi.cmake
set(WAMR_BUILD_LIBC_WASI 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_THREAD_MGR)
# include thread_mgr.cmake
set(WAMR_BUILD_THREAD_MGR 1)
endif()
if(CONFIG_INTERPRETERS_WAMR_LIB_PTHREAD)
# include lib_pthread.cmake
set(WAMR_BUILD_LIB_PTHREAD 1)
endif()
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
# enable WAMR build system
include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
# NuttX wamr lib complie required: `WAMR_SOURCES` `WAMR_CFLAGS` `WAMR_INCDIRS`
# `WAMR_DEFINITIONS`
set(WAMR_SOURCES ${WAMR_RUNTIME_LIB_SOURCE})
set(WAMR_CFLAGS -Wno-strict-prototypes -Wno-shadow -Wno-unused-variable
-Wno-int-conversion -Wno-implicit-function-declaration)
get_directory_property(WAMR_INCDIRS INCLUDE_DIRECTORIES)
get_directory_property(WAMR_DEFINITIONS COMPILE_DEFINITIONS)

View File

@ -373,6 +373,11 @@ CFLAGS += -DWASM_ENABLE_GLOBAL_HEAP_POOL=1
CFLAGS += -DWASM_GLOBAL_HEAP_SIZE="$(CONFIG_INTERPRETERS_WAMR_GLOBAL_HEAP_POOL_SIZE) * 1024"
else
CFLAGS += -DWASM_ENABLE_GLOBAL_HEAP_POOL=0
ifeq ($(CONFIG_INTERPRETERS_WAMR_MEM_ALLOC_WITH_USAGE),y)
CFLAGS += -DWASM_MEM_ALLOC_WITH_USAGE=1
else
CFLAGS += -DWASM_MEM_ALLOC_WITH_USAGE=0
endif
endif
ifeq ($(CONFIG_INTERPRETERS_WAMR_ENABLE_SPEC_TEST),y)

View File

@ -445,6 +445,9 @@ static char global_heap_buf[WASM_GLOBAL_HEAP_SIZE] = { 0 };
#else
static void *
malloc_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
@ -455,6 +458,9 @@ malloc_func(
static void *
realloc_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage, bool full_size_mmaped,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
@ -465,6 +471,9 @@ realloc_func(
static void
free_func(
#if WASM_MEM_ALLOC_WITH_USAGE != 0
mem_alloc_usage_t usage,
#endif
#if WASM_MEM_ALLOC_WITH_USER_DATA != 0
void *user_data,
#endif
@ -675,7 +684,7 @@ main(int argc, char *argv[])
#endif
#if WASM_ENABLE_GC != 0
else if (!strncmp(argv[0], "--gc-heap-size=", 15)) {
if (argv[0][21] == '\0')
if (argv[0][15] == '\0')
return print_help();
gc_heap_size = atoi(argv[0] + 15);
}
@ -851,7 +860,8 @@ main(int argc, char *argv[])
#if WASM_ENABLE_DEBUG_INTERP != 0
init_args.instance_port = instance_port;
if (ip_addr)
strcpy(init_args.ip_addr, ip_addr);
/* ensure that init_args.ip_addr is null terminated */
strncpy(init_args.ip_addr, ip_addr, sizeof(init_args.ip_addr) - 1);
#endif
/* initialize runtime environment */

View File

@ -464,7 +464,9 @@ main(int argc, char *argv[])
#if WASM_ENABLE_DEBUG_INTERP != 0
init_args.instance_port = instance_port;
if (ip_addr)
strcpy(init_args.ip_addr, ip_addr);
/* ensure that init_args.ip_addr is null terminated */
strncpy_s(init_args.ip_addr, sizeof(init_args.ip_addr) - 1, ip_addr,
strlen(ip_addr));
#endif
/* initialize runtime environment */

View File

@ -7,6 +7,14 @@ include(CheckPIESupported)
project(debug_tools_sample)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(WASISDK REQUIRED)
option(SOURCE_MAP_DEMO "Enable source map demo" OFF)
if (SOURCE_MAP_DEMO)
find_package(EMSCRIPTEN 3.1.50 REQUIRED)
endif ()
################ runtime settings ################
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
if (APPLE)
@ -61,7 +69,30 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
################ wasm application ################
add_subdirectory(wasm-apps)
include(ExternalProject)
# wasm32-wasi
ExternalProject_Add(wasm33-wasi
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps"
CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps -B build
-DWASI_SDK_PREFIX=${WASISDK_HOME}
-DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN}
BUILD_COMMAND ${CMAKE_COMMAND} --build build
INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR}
)
if (EMSCRIPTEN_FOUND)
# wasm32-emscripten
ExternalProject_Add(wasm32-emscripten
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps"
CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm-apps -B build
-DCMAKE_TOOLCHAIN_FILE=${EMSCRIPTEN_TOOLCHAIN}
-DCMAKE_VERBOSE_MAKEFILE=On
-DSOURCE_MAP_DEMO=On
BUILD_COMMAND ${CMAKE_COMMAND} --build build
INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR}/emscripten
)
endif ()
################ wamr runtime ################
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)

View File

@ -63,7 +63,7 @@ The output should be something like:
at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:17:12
3: main
at wasm-micro-runtime/samples/debug-tools/wasm-apps/trap.c:24:5
4: <unknown>
4: __main_void
at unknown:?:?
5: _start
```
@ -79,3 +79,55 @@ $ python3 ../../../test-tools/addr2line/addr2line.py \
--wasm-file wasm-apps/trap.wasm \
call_stack.txt --no-addr
```
#### sourcemap
This script also supports _sourcemap_ which is produced by [_emscripten_](https://emscripten.org/docs/tools_reference/emcc.html). The _sourcemap_ is used to map the wasm function to the original source file. To use it, add `-gsource-map` option to _emcc_ command line. The output should be a section named "sourceMappingURL" and a separated file named "_.map_.
If the wasm file is with _sourcemap_, the script will use it to get the source file and line info. It needs an extra command line option `--emsdk` to specify the path of _emsdk_. The script will use _emsymbolizer_ to query the source file and line info.
````bash
$ python3 ../../../test-tools/addr2line/addr2line.py \
--wasi-sdk /opt/wasi-sdk \
--wabt /opt/wabt \
--wasm-file emscripten/wasm-apps/trap.wasm \
--emsdk /opt/emsdk \
call_stack.from_wasm_w_sourcemap.txt
The output should be something like:
```text
1: c
at ../../../../../wasm-apps/trap.c:5:1
2: b
at ../../../../../wasm-apps/trap.c:11:12
3: a
at ../../../../../wasm-apps/trap.c:17:12
4: main
at ../../../../../wasm-apps/trap.c:24:5
5: __main_void
at ../../../../../../../../../emsdk/emscripten/system/lib/standalone/__main_void.c:53:10
6: _start
at ../../../../../../../../../emsdk/emscripten/system/lib/libc/crt1.c:27:3
````
> The script assume the separated map file _.map_ is in the same directory as the wasm file.
### Another approach
If the wasm file is with "name" section, it is able to output function name in the stack trace. To achieve that, need to enable `WAMR_BUILD_LOAD_CUSTOM_SECTION` and `WAMR_BUILD_CUSTOM_NAME_SECTION`. If using .aot file, need to add `--emit-custom-sections=name` into wamrc command line options.
Then the output should be something like
```text
#00: 0x0159 - c
#01: 0x01b2 - b
#02: 0x0200 - a
#03: 0x026b - main
#04: 0x236b - __main_void
#05: 0x011f - _start
Exception: unreachable
```
Also, it is able to use _addr2line.py_ to add file and line info to the stack trace.

View File

@ -0,0 +1,45 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
include(FindPackageHandleStandardArgs)
find_path(EMSCRIPTEN_HOME
NAMES upstream/emscripten
PATHS /opt/emsdk
NO_DEFAULT_PATH
NO_CMAKE_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
REQUIRED
)
find_file(EMSCRIPTEN_VERSION_FILE
NAMES emscripten-version.txt
PATHS ${EMSCRIPTEN_HOME}/upstream/emscripten
NO_DEFAULT_PATH
NO_CMAKE_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
REQUIRED
)
file(READ ${EMSCRIPTEN_VERSION_FILE} EMSCRIPTEN_VERSION_FILE_CONTENT)
string(REGEX
MATCH
"[0-9]+\.[0-9]+(\.[0-9]+)*"
EMSCRIPTEN_VERSION
${EMSCRIPTEN_VERSION_FILE_CONTENT}
)
find_package_handle_standard_args(EMSCRIPTEN
REQUIRED_VARS EMSCRIPTEN_HOME
VERSION_VAR EMSCRIPTEN_VERSION
HANDLE_VERSION_RANGE
)
if(EMSCRIPTEN_FOUND)
set(EMSCRIPTEN_TOOLCHAIN ${EMSCRIPTEN_HOME}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake)
set(EMCC ${EMSCRIPTEN_HOME}/upstream/emscripten/emcc)
endif()
mark_as_advanced(EMSCRIPTEN_TOOLCHAIN EMCC)

View File

@ -0,0 +1,27 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
include(FindPackageHandleStandardArgs)
find_path(WAMRC_HOME
wamr-compiler
PATHS ${CMAKE_CURRENT_SOURCE_DIR}/../../..
NO_DEFAULT_PATH
NO_CMAKE_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
REQUIRED
)
find_file(WAMRC_BIN
wamrc
HINTS ${WAMRC_HOME}/wamr-compiler/build
NO_DEFAULT_PATH
NO_CMAKE_PATH
NO_CMAKE_SYSTEM_PATH
NO_CMAKE_FIND_ROOT_PATH
REQUIRED
)
find_package_handle_standard_args(WAMRC REQUIRED_VARS WAMRC_BIN)
mark_as_advanced(WAMRC_BIN)

View File

@ -0,0 +1,24 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
include(FindPackageHandleStandardArgs)
file(GLOB WASISDK_SEARCH_PATH "/opt/wasi-sdk-*")
find_path(WASISDK_HOME
NAMES share/wasi-sysroot
PATHS ${WASISDK_SEARCH_PATH}
NO_DEFAULT_PATH
REQUIRED
)
string(REGEX MATCH [0-9]+\.[0-9]+\.*[0-9]* WASISDK_VERSION ${WASISDK_HOME})
find_package_handle_standard_args(WASISDK REQUIRED_VARS WASISDK_HOME VERSION_VAR WASISDK_VERSION)
if(WASISDK_FOUND)
set(WASISDK_CC_COMMAND ${WASISDK_HOME}/bin/clang)
set(WASISDK_CXX_COMMAND ${WASISDK_HOME}/bin/clang++)
set(WASISDK_TOOLCHAIN ${WASISDK_HOME}/share/cmake/wasi-sdk.cmake)
set(WASISDK_SYSROOT ${WASISDK_HOME}/share/wasi-sysroot)
endif()
mark_as_advanced(WASISDK_CC_COMMAND WASISDK_CXX_COMMAND WASISDK_TOOLCHAIN WASISDK_SYSROOT WASISDK_HOME)

View File

@ -1,91 +1,58 @@
# Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
if (APPLE)
set (HAVE_FLAG_SEARCH_PATHS_FIRST 0)
set (CMAKE_C_LINK_FLAGS "")
set (CMAKE_CXX_LINK_FLAGS "")
cmake_minimum_required (VERSION 3.14)
project (debut_tools_wasm)
set (CMAKE_BUILD_TYPE Debug) # Otherwise no debug symbols (addr2line)
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../cmake)
find_package (WAMRC REQUIRED)
option(SOURCE_MAP_DEMO "Enable source map demo" OFF)
if (SOURCE_MAP_DEMO)
find_package(EMSCRIPTEN 3.1.50 REQUIRED)
endif ()
if (NOT DEFINED WASI_SDK_DIR)
set (WASI_SDK_DIR "/opt/wasi-sdk")
endif ()
if (DEFINED WASI_SYSROOT)
set (CMAKE_SYSROOT "${WASI_SYSROOT}")
endif ()
set (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang")
set (CMAKE_ASM_COMPILER "${WASI_SDK_DIR}/bin/clang")
set (CMAKE_EXE_LINKER_FLAGS "-target wasm32-wasi")
################ wabt and wamrc dependencies ################
message(CHECK_START "Detecting WABT")
if(NOT (DEFINED WABT_DIR OR DEFINED CACHE{WABT_DIR}))
find_path(WABT_DIR
wabt
PATHS /opt
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(DEFINED WABT_DIR)
set(WABT_DIR ${WABT_DIR}/wabt)
endif()
endif()
if(WABT_DIR)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
message(CHECK_START "Detecting WASM_OBJDUMP at ${WABT_DIR}")
find_program(WASM_OBJDUMP
wasm-objdump
PATHS "${WABT_DIR}/bin"
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WASM_OBJDUMP)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
if((NOT EXISTS ${WASM_OBJDUMP}) )
message(FATAL_ERROR "Please make sure to have wasm-objdump under the path=${WABT_DIR}/bin ")
endif()
set(WAMR_COMPILER_DIR ${CMAKE_CURRENT_LIST_DIR}/../../wamr-compiler/build)
message(CHECK_START "Detecting WAMR_COMPILER at ${WAMR_COMPILER_DIR}")
find_file(WAMR_COMPILER
wamrc
PATHS "${CMAKE_CURRENT_LIST_DIR}/../../../wamr-compiler/build"
NO_DEFAULT_PATH
NO_CMAKE_FIND_ROOT_PATH
)
if(WAMR_COMPILER)
message(CHECK_PASS "found")
else()
message(CHECK_FAIL "not found")
endif()
if((NOT EXISTS ${WAMR_COMPILER}) )
message(FATAL_ERROR "Please build wamrc under the path=${WAMR_ROOT_DIR}/wamr-compiler/")
endif()
################ wasm and aot compilation ################
function (compile_sample SOURCE_FILE)
get_filename_component (FILE_NAME ${SOURCE_FILE} NAME_WLE)
set (WASM_MODULE ${FILE_NAME}.wasm)
add_executable (${WASM_MODULE} ${SOURCE_FILE})
add_custom_target(
wasm_to_aot
## wasm
set (WASM_FILE ${FILE_NAME}.wasm)
add_executable (${FILE_NAME} ${SOURCE_FILE})
set_target_properties (${FILE_NAME} PROPERTIES SUFFIX .wasm)
## aot
set (AOT_FILE ${FILE_NAME}.aot)
add_custom_target (
${FILE_NAME}_aot
ALL
DEPENDS ${WAMR_COMPILER} ${WASM_MODULE}
DEPENDS ${WAMRC_BIN} ${WASM_FILE}
# Use --enable-dump-call-stack to generate stack trace (addr2line)
COMMAND ${WAMR_COMPILER} --size-level=0 --enable-dump-call-stack -o wasm-apps/trap.aot wasm-apps/trap.wasm
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
COMMAND ${WAMRC_BIN} --size-level=0 --enable-dump-call-stack -o ${AOT_FILE} ${WASM_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
## wasm + sourcemap
if (DEFINED EMSCRIPTEN)
add_custom_target(
${FILE_NAME}_w_sourcemap
ALL
DEPENDS ${SOURCE_FILE}
COMMAND ${EMCC} -O0 -gsource-map -o ${FILE_NAME}.sourcemap.wasm ${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE_FILE}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
)
endif ()
## install both
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${WASM_FILE} DESTINATION wasm-apps)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${AOT_FILE} DESTINATION wasm-apps)
if (DEFINED EMSCRIPTEN)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.sourcemap.wasm DESTINATION wasm-apps)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${FILE_NAME}.sourcemap.wasm.map DESTINATION wasm-apps)
endif ()
endfunction ()
set(CMAKE_BUILD_TYPE Debug) # Otherwise no debug symbols (addr2line)
compile_sample(trap.c)

View File

@ -0,0 +1,63 @@
# Copyright (C) 2019 Intel Corporation. All rights reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
cmake_minimum_required (VERSION 3.14)
project(linux_perf_sample)
if(NOT CMAKE_HOST_LINUX)
message(FATAL_ERROR "This sample only works on linux")
endif()
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release)
endif()
set(CMAKE_CXX_STANDARD 17)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
find_package(WASISDK REQUIRED)
################ runtime settings ################
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
include(CheckPIESupported)
# AOT and JIT byd default
set(WAMR_BUILD_AOT 1)
set(WAMR_BUILD_INTERP 0)
set(WAMR_BUILD_JIT 1)
# wasm32-wasi
set(WAMR_BUILD_LIBC_BUILTIN 0)
set(WAMR_BUILD_LIBC_WASI 1)
# mvp
set(WAMR_BUILD_BULK_MEMORY 1)
set(WAMR_BUILD_REF_TYPES 1)
set(WAMR_BUILD_SIMD 1)
set(WAMR_BUILD_TAIL_CALL 1)
# trap information
set(WAMR_BUILD_DUMP_CALL_STACK 1)
# linux perf
set(WAMR_BUILD_LINUX_PERF 1)
#
#set(WAMR_BUILD_THREAD_MGR 0)
# vmlib
set(WAMR_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
include(${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib SHARED ${WAMR_RUNTIME_LIB_SOURCE})
target_include_directories(vmlib INTERFACE ${WAMR_ROOT_DIR}/core/iwasm/include)
target_link_libraries (vmlib ${LLVM_AVAILABLE_LIBS} -lm -ldl)
################ host ################
add_executable(${PROJECT_NAME} host/demo.c)
target_link_libraries(${PROJECT_NAME} vmlib)
################ aot + wasm ################
include(ExternalProject)
ExternalProject_Add(wasm
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/wasm"
CONFIGURE_COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_SOURCE_DIR}/wasm -B build
-DCMAKE_TOOLCHAIN_FILE=${WASISDK_TOOLCHAIN}
BUILD_COMMAND ${CMAKE_COMMAND} --build build
INSTALL_COMMAND ${CMAKE_COMMAND} --install build --prefix ${CMAKE_CURRENT_BINARY_DIR}
)

View File

@ -0,0 +1,90 @@
# linux perf sample introduction
This is a sample to show how to use the Linux perf tool to profile the execution of a WebAssembly application. And how to use the [Flamegraph](https://www.brendangregg.com/flamegraphs.html) tool to visualize the profiling result.
## Build and run the sample
There are two Wasm modules and their instance will be created and run in the sample. [The first module](./wasm/fib.c) is a simple Wasm module that calculates the Fibonacci number. [The second module](./wasm/ackermann.c) is a simple Wasm module that execute the Ackermann function. The target is enable to profile the execution of both two modules separately.
```bash
$ cmake -S . -B build
$ cmake --build build
```
### Profile the execution
```bash
$ cd build
$ perf record -k mono -g --output=perf.data -- ./linux_perf_sample
```
Enable to use `perf report --stdio` to do a quick analysis of the profiling result.
### Visualize the profiling result
Need to download Flamegraph tool from [Flamegraph](https://github.com/brendangregg/FlameGraph/releases/tag/v1.0) firstly.
```bash
$ perf script > out.perf
$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
$ ./FlameGraph/flamegraph.pl out.folded > perf.svg
```
In this result, you'll see two modules's profiling result and all wasm functions are named as "aot_func#N" which is a little hard to distinguish.
![perf.png](./pics/perf.png)
### Separate profiling result
[process_folded_data.py](../../test-tools/flame-graph-helper/process_folded_data.py) is a script can a) translate "aot_func#N" into its original function name in name sections, b) separate the profiling result of different modules.
In this sample, we want to separate `fib` and `ackermann` profiling data from _out.folded_. In [demo](host/demo.c), we decide to name the module of `fib1.wasm` as `fib2` and the module of `ackermann1.wasm` as `ackermann2`.
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names fib2=./fib1.wasm,ackermann2=./ackermann1.wasm out.folded
-> write into out.fib2.translated
-> write into out.ackermann2.translated
-> write into out.translated
```
More scenarios:
if only using one wasm during profiling, the script can be used like this:
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm <wasm_file> --folded <folded_file>
```
if only using one wasm during profiling and specify the module name via APIs, the script can be used like this:
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names <module name>=<wasm_file> --folded <folded_file>
```
if only using one wasm during profiling and specify the module name, which is same with the basename of wasm file, via APIs, the script can be used like this:
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm <wasm_file> --folded <folded_file>
```
if using multiple wasm during profiling and specify module names, which are same with basename of wasm files, via APIs, the script can be used like this:
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm <wasm_file> --wasm <wasm_file> --wasm <wasm_file> --folded <folded_file>
```
if using multiple wasm during profiling and specify module names via APIs, the script can be used like this:
```bash
$ python process_folded_data.py --wabt_home /opt/wabt --wasm_names <module_name>=<wasm_file>,<module_name>=<wasm_file>,<module_name>=<wasm_file> --folded <folded_file>
```
Now we have two flame-graphs for two wasm modules:
![fib.svg](./pics/perf.fib.svg)
![ackermann.svg](./pics/perf.ackermann.svg)
## Reference
- [perf_tune](../../doc/perf_tune.md)

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