Merge branch 'main' into feature/user_classified_mem_mng

This commit is contained in:
dongsheng28849455 2024-04-18 13:08:12 +08:00 committed by GitHub
commit acce5b74b4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
67 changed files with 1352 additions and 811 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 #!/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 update
sudo apt install -y build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ninja-build ccache sudo apt install -y build-essential cmake g++-multilib libgcc-11-dev lib32gcc-11-dev ccache ninja-build ccache

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(): 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) p = subprocess.run(shlex.split(list_tag_cmd), capture_output=True, check=True)
all_tags = p.stdout.decode().strip() all_tags = p.stdout.decode().strip()

View File

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

View File

@ -58,6 +58,12 @@ jobs:
sudo rm ${basename} sudo rm ${basename}
sudo mv wasi-sdk-* wasi-sdk 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 - name: generate wamr-sdk release
run: | run: |
cd ./wamr-app-framework/wamr-sdk cd ./wamr-app-framework/wamr-sdk

View File

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

View File

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

@ -389,14 +389,14 @@ jobs:
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz 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 - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz 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 - name: Get LLVM libraries
id: retrieve_llvm_libs id: retrieve_llvm_libs
uses: actions/cache@v4 uses: actions/cache@v4

View File

@ -273,14 +273,14 @@ jobs:
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz 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 - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz 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] - name: Build Sample [basic]
run: | run: |

View File

@ -32,8 +32,22 @@ jobs:
- name: prepare - name: prepare
id: preparation id: preparation
run: | run: |
# show latest 3 versions # show latest 3 versions on the branch that create release
git tag --list WAMR-*.*.* --sort=committerdate --format="%(refname:short)" | tail -n 3 # 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 # compare latest git tag and semantic version definition
result=$(python3 ./.github/scripts/fetch_and_compare_version.py) result=$(python3 ./.github/scripts/fetch_and_compare_version.py)
echo "script result is ${result}" echo "script result is ${result}"

View File

@ -459,13 +459,13 @@ jobs:
cd /opt cd /opt
sudo wget ${{ matrix.wasi_sdk_release }} sudo wget ${{ matrix.wasi_sdk_release }}
sudo tar -xzf wasi-sdk-*.tar.gz 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 - name: download and install wabt
run: | run: |
cd /opt cd /opt
sudo wget ${{ matrix.wabt_release }} sudo wget ${{ matrix.wabt_release }}
sudo tar -xzf wabt-1.0.31-*.tar.gz 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 - name: Get LLVM libraries
id: retrieve_llvm_libs id: retrieve_llvm_libs

View File

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

View File

@ -67,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) - [Port WAMR to a new platform](./doc/port_wamr.md)
- [VS Code development container](./doc/devcontainer.md) - [VS Code development container](./doc/devcontainer.md)
- [Samples](./samples) and [Benchmarks](./tests/benchmarks) - [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 # Sanitizers
if (NOT DEFINED WAMR_BUILD_SANITIZER)
set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER}) set(WAMR_BUILD_SANITIZER $ENV{WAMR_BUILD_SANITIZER})
endif ()
if (NOT DEFINED WAMR_BUILD_SANITIZER) if (NOT DEFINED WAMR_BUILD_SANITIZER)
set(WAMR_BUILD_SANITIZER "") set(WAMR_BUILD_SANITIZER "")
@ -557,3 +559,6 @@ endif ()
if (WAMR_BUILD_ALLOC_WITH_USAGE EQUAL 1) if (WAMR_BUILD_ALLOC_WITH_USAGE EQUAL 1)
add_definitions(-DWASM_MEM_ALLOC_WITH_USAGE=1) add_definitions(-DWASM_MEM_ALLOC_WITH_USAGE=1)
endif() endif()
if (NOT WAMR_BUILD_SANITIZER STREQUAL "")
message (" Sanitizer ${WAMR_BUILD_SANITIZER} enabled")
endif ()

View File

@ -1526,29 +1526,41 @@ fail:
} }
static void 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 WASM_ENABLE_GC != 0
if (types[i]->type_flag == WASM_TYPE_FUNC) { if (type->ref_count > 1) {
AOTFuncType *func_type = (AOTFuncType *)types[i]; /* 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) { if (func_type->ref_type_maps != NULL) {
bh_assert(func_type->ref_type_map_count > 0); bh_assert(func_type->ref_type_map_count > 0);
wasm_runtime_free(func_type->ref_type_maps); wasm_runtime_free(func_type->ref_type_maps);
} }
} }
else if (types[i]->type_flag == WASM_TYPE_STRUCT) { else if (type->type_flag == WASM_TYPE_STRUCT) {
AOTStructType *struct_type = (AOTStructType *)types[i]; AOTStructType *struct_type = (AOTStructType *)type;
if (struct_type->ref_type_maps != NULL) { if (struct_type->ref_type_maps != NULL) {
bh_assert(struct_type->ref_type_map_count > 0); bh_assert(struct_type->ref_type_map_count > 0);
wasm_runtime_free(struct_type->ref_type_maps); wasm_runtime_free(struct_type->ref_type_maps);
} }
} }
#endif #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); wasm_runtime_free(types);
@ -1556,14 +1568,17 @@ destroy_types(AOTType **types, uint32 count)
#if WASM_ENABLE_GC != 0 #if WASM_ENABLE_GC != 0
static void static void
init_base_type(AOTType *base_type, uint16 type_flag, bool is_sub_final, init_base_type(AOTType *base_type, uint32 type_idx, uint16 type_flag,
uint32 parent_type_idx, uint16 rec_count, uint16 rec_idx) bool is_sub_final, uint32 parent_type_idx, uint16 rec_count,
uint16 rec_idx)
{ {
base_type->type_flag = type_flag; base_type->type_flag = type_flag;
base_type->ref_count = 1;
base_type->is_sub_final = is_sub_final; base_type->is_sub_final = is_sub_final;
base_type->parent_type_idx = parent_type_idx; base_type->parent_type_idx = parent_type_idx;
base_type->rec_count = rec_count; base_type->rec_count = rec_count;
base_type->rec_idx = rec_idx; base_type->rec_idx = rec_idx;
base_type->rec_begin_type_idx = type_idx - rec_idx;
} }
static bool static bool
@ -1576,7 +1591,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
uint32 i, j; uint32 i, j;
uint32 type_flag, param_cell_num, ret_cell_num; uint32 type_flag, param_cell_num, ret_cell_num;
uint16 param_count, result_count, ref_type_map_count, rec_count, rec_idx; 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; uint32 parent_type_idx;
WASMRefType ref_type; WASMRefType ref_type;
@ -1590,12 +1605,31 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
/* Create each type */ /* Create each type */
for (i = 0; i < module->type_count; i++) { for (i = 0; i < module->type_count; i++) {
buf = align_ptr(buf, 4); buf = align_ptr(buf, 4);
/* Read base type info */ /* Read base type info */
read_uint16(buf, buf_end, type_flag); 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_uint32(buf, buf_end, parent_type_idx);
read_uint16(buf, buf_end, rec_count); read_uint16(buf, buf_end, rec_count);
read_uint16(buf, buf_end, rec_idx); read_uint16(buf, buf_end, rec_idx);
@ -1620,7 +1654,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
types[i] = (AOTType *)func_type; 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); parent_type_idx, rec_count, rec_idx);
func_type->param_count = param_count; func_type->param_count = param_count;
func_type->result_count = result_count; func_type->result_count = result_count;
@ -1726,7 +1760,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
offset = (uint32)offsetof(WASMStructObject, field_data); offset = (uint32)offsetof(WASMStructObject, field_data);
types[i] = (AOTType *)struct_type; 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); parent_type_idx, rec_count, rec_idx);
struct_type->field_count = field_count; struct_type->field_count = field_count;
struct_type->ref_type_map_count = ref_type_map_count; struct_type->ref_type_map_count = ref_type_map_count;
@ -1812,7 +1846,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
types[i] = (AOTType *)array_type; 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); parent_type_idx, rec_count, rec_idx);
read_uint16(buf, buf_end, array_type->elem_flags); read_uint16(buf, buf_end, array_type->elem_flags);
read_uint8(buf, buf_end, array_type->elem_type); read_uint8(buf, buf_end, array_type->elem_type);
@ -1841,7 +1875,6 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
if (rec_count == 0) { if (rec_count == 0) {
bh_assert(rec_idx == 0); bh_assert(rec_idx == 0);
} }
for (j = i - rec_idx; j <= i; j++) { for (j = i - rec_idx; j <= i; j++) {
AOTType *cur_type = module->types[j]; AOTType *cur_type = module->types[j];
parent_type_idx = cur_type->parent_type_idx; parent_type_idx = cur_type->parent_type_idx;
@ -1850,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]->parent_type = parent_type;
module->types[j]->root_type = parent_type->root_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 = module->types[j]->inherit_depth =
parent_type->inherit_depth + 1; parent_type->inherit_depth + 1;
} }
@ -1867,7 +1905,7 @@ load_types(const uint8 **p_buf, const uint8 *buf_end, AOTModule *module,
AOTType *parent_type = module->types[parent_type_idx]; AOTType *parent_type = module->types[parent_type_idx];
/* subtyping has been checked during compilation */ /* subtyping has been checked during compilation */
bh_assert(wasm_type_is_subtype_of( 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; (void)parent_type;
} }
} }

View File

@ -143,6 +143,7 @@ typedef struct {
REG_SYM(aot_array_init_with_data), \ REG_SYM(aot_array_init_with_data), \
REG_SYM(aot_create_func_obj), \ REG_SYM(aot_create_func_obj), \
REG_SYM(aot_obj_is_instance_of), \ REG_SYM(aot_obj_is_instance_of), \
REG_SYM(aot_func_type_is_super_of), \
REG_SYM(aot_rtt_type_new), \ REG_SYM(aot_rtt_type_new), \
REG_SYM(wasm_array_obj_copy), \ REG_SYM(wasm_array_obj_copy), \
REG_SYM(wasm_array_obj_new), \ REG_SYM(wasm_array_obj_new), \

View File

@ -1721,6 +1721,7 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
bh_assert(table_init_data); 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]; table = module_inst->tables[table_init_data->table_index];
bh_assert(table); bh_assert(table);
@ -1728,8 +1729,9 @@ aot_instantiate(AOTModule *module, AOTModuleInstance *parent,
bh_assert(table_data); bh_assert(table_data);
wasm_runtime_get_table_inst_elem_type( wasm_runtime_get_table_inst_elem_type(
(WASMModuleInstanceCommon *)module_inst, i, &tbl_elem_type, (WASMModuleInstanceCommon *)module_inst,
&tbl_elem_ref_type, &tbl_init_size, &tbl_max_size); 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) if (!wasm_elem_is_declarative(table_init_data->mode)
&& !wasm_reftype_is_subtype_of( && !wasm_reftype_is_subtype_of(
@ -3366,39 +3368,49 @@ aot_table_fill(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 length,
} }
uint32 uint32
aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, aot_table_grow(AOTModuleInstance *module_inst, uint32 tbl_idx, uint32 inc_size,
uint32 inc_entries, table_elem_type_t init_val) table_elem_type_t init_val)
{ {
uint32 entry_count, i, orig_tbl_sz;
AOTTableInstance *tbl_inst; AOTTableInstance *tbl_inst;
uint32 i, orig_size, total_size;
tbl_inst = module_inst->tables[tbl_idx]; tbl_inst = module_inst->tables[tbl_idx];
if (!tbl_inst) { if (!tbl_inst) {
return (uint32)-1; return (uint32)-1;
} }
orig_tbl_sz = tbl_inst->cur_size; orig_size = tbl_inst->cur_size;
if (!inc_entries) { if (!inc_size) {
return orig_tbl_sz; 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; return (uint32)-1;
} }
entry_count = tbl_inst->cur_size + inc_entries; total_size = tbl_inst->cur_size + inc_size;
if (entry_count > tbl_inst->max_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; return (uint32)-1;
} }
/* fill in */ /* 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->elems[tbl_inst->cur_size + i] = init_val;
} }
tbl_inst->cur_size = entry_count; tbl_inst->cur_size = total_size;
return orig_tbl_sz; return orig_size;
} }
#endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */ #endif /* WASM_ENABLE_REF_TYPES != 0 || WASM_ENABLE_GC != 0 */
@ -4477,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); 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 WASMRttTypeRef
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index) aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index)
{ {

View File

@ -752,6 +752,11 @@ bool
aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj, aot_obj_is_instance_of(AOTModuleInstance *module_inst, WASMObjectRef gc_obj,
uint32 type_index); 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 WASMRttTypeRef
aot_rtt_type_new(AOTModuleInstance *module_inst, uint32 type_index); 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 #endif
#if WASM_ENABLE_AOT != 0 #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 #endif
bh_assert(types); bh_assert(types);

View File

@ -250,6 +250,51 @@ wasm_value_types_is_subtype_of(const uint8 *types1,
return true; 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 bool
wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2, wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count) const WASMTypePtr *types, uint32 type_count)
@ -277,9 +322,11 @@ wasm_func_type_equal(const WASMFuncType *type1, const WASMFuncType *type2,
ref_type1 = type1->ref_type_maps[j].ref_type; ref_type1 = type1->ref_type_maps[j].ref_type;
ref_type2 = type2->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, if (!rec_ref_type_equal(
type_count)) 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; return false;
j++; 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_type1 = type1->ref_type_maps[j].ref_type;
ref_type2 = type2->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, if (!rec_ref_type_equal(
type_count)) 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; return false;
j++; j++;
@ -338,21 +387,67 @@ wasm_array_type_equal(const WASMArrayType *type1, const WASMArrayType *type2,
if (type1->elem_flags != type2->elem_flags) if (type1->elem_flags != type2->elem_flags)
return false; return false;
return wasm_reftype_equal(type1->elem_type, type1->elem_ref_type, if (type1->elem_type != type2->elem_type)
type2->elem_type, type2->elem_ref_type, types, return false;
type_count);
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 bool
wasm_type_equal(const WASMType *type1, const WASMType *type2, wasm_type_equal(const WASMType *type1, const WASMType *type2,
const WASMTypePtr *types, uint32 type_count) 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) if (type1 == type2)
return true; 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; 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)) if (wasm_type_is_func_type(type1))
return wasm_func_type_equal((WASMFuncType *)type1, return wasm_func_type_equal((WASMFuncType *)type1,
(WASMFuncType *)type2, types, type_count); (WASMFuncType *)type2, types, type_count);
@ -653,12 +748,6 @@ wasm_reftype_struct_size(const WASMRefType *ref_type)
return (uint32)sizeof(RefHeapType_Common); return (uint32)sizeof(RefHeapType_Common);
} }
static bool
type_idx_equal(uint32 type_idx1, uint32 type_idx2)
{
return (type_idx1 == type_idx2) ? true : false;
}
bool bool
wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1, wasm_refheaptype_equal(const RefHeapType_Common *ref_heap_type1,
const RefHeapType_Common *ref_heap_type2, 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 (ref_heap_type1->heap_type != ref_heap_type2->heap_type) {
if (wasm_is_refheaptype_typeidx(ref_heap_type1) if (wasm_is_refheaptype_typeidx(ref_heap_type1)
&& wasm_is_refheaptype_typeidx(ref_heap_type2)) { && wasm_is_refheaptype_typeidx(ref_heap_type2)) {
return type_idx_equal(ref_heap_type1->heap_type, if (ref_heap_type1->heap_type == ref_heap_type2->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; return false;
} }
@ -835,6 +932,13 @@ wasm_type_is_supers_of(const WASMType *type1, const WASMType *type2)
return false; 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 bool
wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1, wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
uint8 type2, const WASMRefType *ref_type2, uint8 type2, const WASMRefType *ref_type2,
@ -914,12 +1018,13 @@ wasm_reftype_is_subtype_of(uint8 type1, const WASMRefType *ref_type1,
#endif #endif
else if (type1 == REF_TYPE_HT_NULLABLE) { else if (type1 == REF_TYPE_HT_NULLABLE) {
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) { 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) */ /* reftype1 is (ref null $t) */
if (type2 == REF_TYPE_HT_NULLABLE && ref_type2 != NULL if (type2 == REF_TYPE_HT_NULLABLE && ref_type2 != NULL
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) { && wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx, bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
ref_type2->ref_ht_typeidx.type_idx) < type_count);
|| wasm_type_is_supers_of( return wasm_type_is_supers_of(
types[ref_type2->ref_ht_typeidx.type_idx], types[ref_type2->ref_ht_typeidx.type_idx],
types[ref_type1->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) { else if (type1 == REF_TYPE_HT_NON_NULLABLE) {
bh_assert(ref_type1); bh_assert(ref_type1);
if (wasm_is_refheaptype_typeidx(&ref_type1->ref_ht_common)) { 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) */ /* reftype1 is (ref $t) */
if ((type2 == REF_TYPE_HT_NULLABLE if ((type2 == REF_TYPE_HT_NULLABLE
|| type2 == REF_TYPE_HT_NON_NULLABLE) || type2 == REF_TYPE_HT_NON_NULLABLE)
&& ref_type2 != NULL && ref_type2 != NULL
&& wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) { && wasm_is_refheaptype_typeidx(&ref_type2->ref_ht_common)) {
return type_idx_equal(ref_type1->ref_ht_typeidx.type_idx, bh_assert((uint32)ref_type2->ref_ht_typeidx.type_idx
ref_type2->ref_ht_typeidx.type_idx) < type_count);
|| wasm_type_is_supers_of( return wasm_type_is_supers_of(
types[ref_type2->ref_ht_typeidx.type_idx], types[ref_type2->ref_ht_typeidx.type_idx],
types[ref_type1->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 WASMFuncType *type2,
const WASMTypePtr *types, uint32 type_count); 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 /* Whether func type1's result types are subtype of
func type2's result types */ func type2's result types */
bool bool

View File

@ -578,8 +578,7 @@ execute_func(WASMModuleInstanceCommon *module_inst, const char *name,
is_anyref = true; is_anyref = true;
} }
if (wasm_is_type_multi_byte_type( if (wasm_is_type_multi_byte_type(type->types[i])) {
type->types[type->param_count + i])) {
WASMRefType *ref_type = ref_type_map->ref_type; WASMRefType *ref_type = ref_type_map->ref_type;
if (wasm_is_refheaptype_common( if (wasm_is_refheaptype_common(
&ref_type->ref_ht_common)) { &ref_type->ref_ht_common)) {

View File

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

View File

@ -3452,16 +3452,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; 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_low_i16x8_s:
case SIMD_i32x4_extend_high_i16x8_s: case SIMD_i32x4_extend_high_i16x8_s:
{ {
@ -3501,16 +3491,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; 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: case SIMD_i32x4_sub:
{ {
if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
@ -3519,16 +3499,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; 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: case SIMD_i32x4_mul:
{ {
if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx, if (!aot_compile_simd_i32x4_arith(comp_ctx, func_ctx,
@ -3565,13 +3535,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; 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_low_i16x8_s:
case SIMD_i32x4_extmul_high_i16x8_s: case SIMD_i32x4_extmul_high_i16x8_s:
{ {
@ -3728,13 +3691,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; break;
} }
case SIMD_f32x4_round:
{
if (!aot_compile_simd_f32x4_round(comp_ctx, func_ctx))
return false;
break;
}
case SIMD_f32x4_sqrt: case SIMD_f32x4_sqrt:
{ {
if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx)) if (!aot_compile_simd_f32x4_sqrt(comp_ctx, func_ctx))
@ -3788,13 +3744,6 @@ aot_compile_func(AOTCompContext *comp_ctx, uint32 func_index)
break; break;
} }
case SIMD_f64x2_round:
{
if (!aot_compile_simd_f64x2_round(comp_ctx, func_ctx))
return false;
break;
}
case SIMD_f64x2_sqrt: case SIMD_f64x2_sqrt:
{ {
if (!aot_compile_simd_f64x2_sqrt(comp_ctx, func_ctx)) 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) get_func_type_size(AOTCompContext *comp_ctx, AOTFuncType *func_type)
{ {
#if WASM_ENABLE_GC != 0 #if WASM_ENABLE_GC != 0
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + param /* type flag + equivalence type flag + is_sub_final + parent_type_idx
* count + result count + rec_count + rec_idx + param count + result count
* + ref_type_map_count + types + context of ref_type_map */ + ref_type_map_count + types + context of ref_type_map */
if (comp_ctx->enable_gc) { if (comp_ctx->enable_gc) {
uint32 size = 0; uint32 size = 0;
/* type flag */ /* type flag */
size += sizeof(func_type->base_type.type_flag); size += sizeof(func_type->base_type.type_flag);
/* is_sub_final */ /* equivalence type flag + is_sub_final */
size += sizeof(uint16); size += sizeof(uint16);
/* parent_type_idx */ /* parent_type_idx */
size += sizeof(func_type->base_type.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) get_struct_type_size(AOTCompContext *comp_ctx, AOTStructType *struct_type)
{ {
uint32 size = 0; uint32 size = 0;
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + field /* type flag + equivalence type flag + is_sub_final + parent_type_idx
* count + fields */ + rec_count + rec_idx + field count + fields */
/* type flag */ /* type flag */
size += sizeof(struct_type->base_type.type_flag); size += sizeof(struct_type->base_type.type_flag);
/* is_sub_final */ /* equivalence type flag + is_sub_final */
size += sizeof(uint16); size += sizeof(uint16);
/* parent_type_idx */ /* parent_type_idx */
size += sizeof(struct_type->base_type.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) get_array_type_size(AOTCompContext *comp_ctx, AOTArrayType *array_type)
{ {
uint32 size = 0; uint32 size = 0;
/* type flag + is_sub_final + parent_type_idx + rec_count + rec_idx + /* type flag + equivalence type flag + is_sub_final + parent_type_idx
elem_flags + elem_type + elem_ref_type */ + rec_count + rec_idx + elem_flags + elem_type + elem_ref_type */
/* type flag */ /* type flag */
size += sizeof(array_type->base_type.type_flag); size += sizeof(array_type->base_type.type_flag);
/* is_sub_final */ /* equivalence type flag + is_sub_final */
size += sizeof(uint16); size += sizeof(uint16);
/* parent_type_idx (u32) */ /* parent_type_idx (u32) */
size += sizeof(array_type->base_type.parent_type_idx); 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 WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc) { if (comp_ctx->enable_gc) {
for (i = 0; i < comp_data->type_count; i++) { for (i = 0; i < comp_data->type_count; i++) {
uint32 j;
size = align_uint(size, 4); 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) if (comp_data->types[i]->type_flag == WASM_TYPE_FUNC)
size += get_func_type_size(comp_ctx, size += get_func_type_size(comp_ctx,
(AOTFuncType *)comp_data->types[i]); (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 WASM_ENABLE_GC != 0
if (comp_ctx->enable_gc) { if (comp_ctx->enable_gc) {
int32 idx;
AOTType **types = comp_data->types; AOTType **types = comp_data->types;
int32 idx;
uint32 j;
for (i = 0; i < comp_data->type_count; i++) { for (i = 0; i < comp_data->type_count; i++) {
offset = align_uint(offset, 4); 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]->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_U32(types[i]->parent_type_idx);
EMIT_U16(types[i]->rec_count); 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) { if (comp_ctx->enable_gc) {
/* emit func_local_ref_flag arrays for both import and AOTed funcs */ /* emit func_local_ref_flag arrays for both import and AOTed funcs */
AOTFuncType *func_type; 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++) { for (i = 0; i < comp_data->import_func_count; i++) {
func_type = comp_data->import_funcs[i].func_type; 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( local_ref_flags_cell_num += wasm_value_type_cell_num_internal(
func_type->types[j], comp_ctx->pointer_size); 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 =
local_ref_flags_cell_num > 2 ? local_ref_flags_cell_num : 2; 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])) func_type->types[j]))
return false; return false;
} }
for (; j < 2; j++) for (j = 0; j < paddings; j++)
EMIT_U8(0); EMIT_U8(0);
} }

View File

@ -1826,6 +1826,52 @@ fail:
return ret; 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 static bool
call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx, call_aot_call_indirect_func(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
AOTFuncType *aot_func_type, AOTFuncType *aot_func_type,
@ -2018,15 +2064,23 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
return false; return false;
} }
if (!comp_ctx->enable_gc) {
/* Find the equivalent function type whose type index is the smallest: /* Find the equivalent function type whose type index is the smallest:
the callee function's type index is also converted to 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 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), 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, we don't need to check whether the whole function types are equal,
including param types and result types. */ including param types and result types. */
type_idx = type_idx = wasm_get_smallest_type_idx(
wasm_get_smallest_type_idx((WASMTypePtr *)comp_ctx->comp_data->types, (WASMTypePtr *)comp_ctx->comp_data->types,
comp_ctx->comp_data->type_count, type_idx); 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); ftype_idx_const = I32_CONST(type_idx);
CHECK_LLVM_CONST(ftype_idx_const); CHECK_LLVM_CONST(ftype_idx_const);
@ -2254,12 +2308,24 @@ aot_compile_op_call_indirect(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx,
goto fail; 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 */ /* 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"))) { ftype_idx_const, "cmp_ftype_idx"))) {
aot_set_last_error("llvm build icmp failed."); aot_set_last_error("llvm build icmp failed.");
goto fail; goto fail;
} }
}
/* Throw exception if ftype_idx != ftype_idx_const */ /* Throw exception if ftype_idx != ftype_idx_const */
if (!(check_ftype_idx_succ = LLVMAppendBasicBlockInContext( if (!(check_ftype_idx_succ = LLVMAppendBasicBlockInContext(

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 { enum integer_extend_type {
e_ext_i8x16, e_ext_i8x16,
e_ext_i16x8, e_ext_i16x8,

View File

@ -20,10 +20,6 @@ bool
aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx, aot_compile_simd_i16x8_narrow_i32x4(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_signed); AOTFuncContext *func_ctx, bool is_signed);
bool
aot_compile_simd_i32x4_narrow_i64x2(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_signed);
bool bool
aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx, aot_compile_simd_i16x8_extend_i8x16(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx, bool is_low, 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"); "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 bool
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx) 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 bool
aot_compile_simd_f64x2_abs(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); 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 bool
aot_compile_simd_f32x4_sqrt(AOTCompContext *comp_ctx, AOTFuncContext *func_ctx); 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 { enum integer_avgr_u {
e_avgr_u_i8x16, e_avgr_u_i8x16,
e_avgr_u_i16x8, e_avgr_u_i16x8,
e_avgr_u_i32x4,
}; };
/* TODO: try int_x86_mmx_pavg_b and int_x86_mmx_pavg_w */ /* 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[] = { LLVMTypeRef vector_type[] = {
V128_i8x16_TYPE, V128_i8x16_TYPE,
V128_i16x8_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, if (!(rhs = simd_pop_v128_and_bitcast(comp_ctx, func_ctx,
vector_type[itype], "rhs")) 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); 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 bool
aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx, aot_compile_simd_i32x4_dot_i16x8(AOTCompContext *comp_ctx,
AOTFuncContext *func_ctx) AOTFuncContext *func_ctx)

View File

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

View File

@ -64,18 +64,3 @@ aot_compile_simd_i16x8_saturate(AOTCompContext *comp_ctx,
is_signed ? intrinsics[arith_op][0] is_signed ? intrinsics[arith_op][0]
: intrinsics[arith_op][1]); : 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, AOTFuncContext *func_ctx,
V128Arithmetic arith_op, bool is_signed); 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 #ifdef __cplusplus
} /* end of extern "C" */ } /* end of extern "C" */
#endif #endif

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * 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 #ifndef _AOT_EXPORT_H
#define _AOT_EXPORT_H #define _AOT_EXPORT_H

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * 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 #ifndef _GC_EXPORT_H
#define _GC_EXPORT_H #define _GC_EXPORT_H

View File

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

View File

@ -1,5 +1,11 @@
// WebAssembly C API // WebAssembly C API
/**
* @file wasm_c_api.h
*
* @brief This file defines the WebAssembly C APIs
*/
#ifndef _WASM_C_API_H_ #ifndef _WASM_C_API_H_
#define _WASM_C_API_H_ #define _WASM_C_API_H_

View File

@ -3,6 +3,12 @@
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception * 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 #ifndef _WASM_EXPORT_H
#define _WASM_EXPORT_H #define _WASM_EXPORT_H

View File

@ -274,7 +274,7 @@ typedef struct InitializerExpression {
*/ */
typedef struct RefHeapType_TypeIdx { typedef struct RefHeapType_TypeIdx {
/* ref_type is REF_TYPE_HT_NULLABLE or /* 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; uint8 ref_type;
/* true if ref_type is REF_TYPE_HT_NULLABLE */ /* true if ref_type is REF_TYPE_HT_NULLABLE */
bool nullable; bool nullable;
@ -288,7 +288,7 @@ typedef struct RefHeapType_TypeIdx {
*/ */
typedef struct RefHeapType_Common { typedef struct RefHeapType_Common {
/* ref_type is REF_TYPE_HT_NULLABLE or /* 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; uint8 ref_type;
/* true if ref_type is REF_TYPE_HT_NULLABLE */ /* true if ref_type is REF_TYPE_HT_NULLABLE */
bool nullable; bool nullable;
@ -338,18 +338,24 @@ typedef struct WASMType {
uint16 type_flag; uint16 type_flag;
bool is_sub_final; bool is_sub_final;
/* How many types are referring to this type */
uint16 ref_count;
/* The inheritance depth */ /* The inheritance depth */
uint32 inherit_depth; uint16 inherit_depth;
/* The root type */ /* The root type */
struct WASMType *root_type; struct WASMType *root_type;
/* The parent type */ /* The parent type */
struct WASMType *parent_type; struct WASMType *parent_type;
uint32 parent_type_idx; uint32 parent_type_idx;
/* number of internal types in the current rec group, if the type is not in /* The number of internal types in the current rec group, and if
* a recursive group, rec_count = 0 */ 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_count;
uint16 rec_idx; uint16 rec_idx;
/* The index of the begin type of this group */
uint32 rec_begin_type_idx;
} WASMType, *WASMTypePtr; } WASMType, *WASMTypePtr;
#endif /* end of WASM_ENABLE_GC */ #endif /* end of WASM_ENABLE_GC */
@ -375,9 +381,6 @@ typedef struct WASMFuncType {
uint16 ref_type_map_count; uint16 ref_type_map_count;
WASMRefTypeMap *ref_type_maps; WASMRefTypeMap *ref_type_maps;
WASMRefTypeMap *result_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 #else
uint16 ref_count; uint16 ref_count;
#endif #endif

View File

@ -1509,6 +1509,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMStringviewIterObjectRef stringview_iter_obj; WASMStringviewIterObjectRef stringview_iter_obj;
#endif #endif
#endif #endif
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
bool is_return_call = false;
#endif
#if WASM_ENABLE_MEMORY64 != 0 #if WASM_ENABLE_MEMORY64 != 0
/* TODO: multi-memories for now assuming the memory idx type is consistent /* TODO: multi-memories for now assuming the memory idx type is consistent
* across multi-memories */ * across multi-memories */
@ -2209,6 +2212,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
WASMFuncType *cur_type, *cur_func_type; WASMFuncType *cur_type, *cur_func_type;
WASMTableInstance *tbl_inst; WASMTableInstance *tbl_inst;
uint32 tbl_idx; uint32 tbl_idx;
#if WASM_ENABLE_TAIL_CALL != 0 #if WASM_ENABLE_TAIL_CALL != 0
opcode = *(frame_ip - 1); opcode = *(frame_ip - 1);
#endif #endif
@ -2279,8 +2283,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto got_exception; goto got_exception;
} }
#else #else
if (cur_type->min_type_idx_normalized if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
!= cur_func_type->min_type_idx_normalized) {
wasm_set_exception(module, "indirect call type mismatch"); wasm_set_exception(module, "indirect call type mismatch");
goto got_exception; goto got_exception;
} }
@ -6227,6 +6230,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
frame_ip = frame->ip; frame_ip = frame->ip;
frame_sp = frame->sp; frame_sp = frame->sp;
frame_csp = frame->csp; frame_csp = frame->csp;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
goto call_func_from_entry; goto call_func_from_entry;
} }
@ -6320,6 +6326,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
} }
FREE_FRAME(exec_env, frame); FREE_FRAME(exec_env, frame);
wasm_exec_env_set_cur_frame(exec_env, prev_frame); wasm_exec_env_set_cur_frame(exec_env, prev_frame);
is_return_call = true;
goto call_func_from_entry; goto call_func_from_entry;
} }
#endif #endif
@ -6333,6 +6340,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
} }
SYNC_ALL_TO_FRAME(); SYNC_ALL_TO_FRAME();
prev_frame = frame; prev_frame = frame;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
} }
call_func_from_entry: call_func_from_entry:
@ -6342,15 +6352,27 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
if (cur_func->import_func_inst) { if (cur_func->import_func_inst) {
wasm_interp_call_func_import(module, exec_env, cur_func, wasm_interp_call_func_import(module, exec_env, cur_func,
prev_frame); 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 #if WASM_ENABLE_EXCE_HANDLING != 0
char uncaught_exception[128] = { 0 }; char uncaught_exception[128] = { 0 };
bool has_exception = bool has_exception =
wasm_copy_exception(module, uncaught_exception); wasm_copy_exception(module, uncaught_exception);
if (has_exception if (has_exception
&& strstr(uncaught_exception, "uncaught wasm exception")) { && strstr(uncaught_exception, "uncaught wasm exception")) {
/* fix framesp */
UPDATE_ALL_FROM_FRAME();
uint32 import_exception; uint32 import_exception;
/* initialize imported exception index to be invalid */ /* initialize imported exception index to be invalid */
SET_INVALID_TAGINDEX(import_exception); SET_INVALID_TAGINDEX(import_exception);
@ -6392,11 +6414,21 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
wasm_interp_call_func_native(module, exec_env, cur_func, wasm_interp_call_func_native(module, exec_env, cur_func,
prev_frame); 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; prev_frame = frame->prev_frame;
cur_func = frame->function; cur_func = frame->function;
UPDATE_ALL_FROM_FRAME(); UPDATE_ALL_FROM_FRAME();
}
}
/* update memory size, no need to update memory ptr as /* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */ 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; WASMStringviewIterObjectRef stringview_iter_obj;
#endif #endif
#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 #if WASM_ENABLE_LABELS_AS_VALUES != 0
#define HANDLE_OPCODE(op) &&HANDLE_##op #define HANDLE_OPCODE(op) &&HANDLE_##op
@ -1733,8 +1736,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
goto got_exception; goto got_exception;
} }
#else #else
if (cur_type->min_type_idx_normalized if (!wasm_func_type_is_super_of(cur_type, cur_func_type)) {
!= cur_func_type->min_type_idx_normalized) {
wasm_set_exception(module, "indirect call type mismatch"); wasm_set_exception(module, "indirect call type mismatch");
goto got_exception; goto got_exception;
} }
@ -5618,6 +5620,9 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
{ {
frame = prev_frame; frame = prev_frame;
frame_ip = frame->ip; frame_ip = frame->ip;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
goto call_func_from_entry; goto call_func_from_entry;
} }
@ -5766,6 +5771,7 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
FREE_FRAME(exec_env, frame); FREE_FRAME(exec_env, frame);
frame_ip += cur_func->param_count * sizeof(int16); frame_ip += cur_func->param_count * sizeof(int16);
wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame); wasm_exec_env_set_cur_frame(exec_env, (WASMRuntimeFrame *)prev_frame);
is_return_call = true;
goto call_func_from_entry; goto call_func_from_entry;
} }
#endif /* WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0 */ #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(); SYNC_ALL_TO_FRAME();
prev_frame = frame; prev_frame = frame;
#if WASM_ENABLE_TAIL_CALL != 0 || WASM_ENABLE_GC != 0
is_return_call = false;
#endif
} }
call_func_from_entry: call_func_from_entry:
@ -5855,9 +5864,20 @@ wasm_interp_call_func_bytecode(WASMModuleInstance *module,
prev_frame); 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; prev_frame = frame->prev_frame;
cur_func = frame->function; cur_func = frame->function;
UPDATE_ALL_FROM_FRAME(); UPDATE_ALL_FROM_FRAME();
}
/* update memory size, no need to update memory ptr as /* update memory size, no need to update memory ptr as
it isn't changed in wasm_enlarge_memory */ it isn't changed in wasm_enlarge_memory */

View File

@ -394,10 +394,10 @@ memory_realloc(void *mem_old, uint32 size_old, uint32 size_new, char *error_buf,
#if WASM_ENABLE_GC != 0 #if WASM_ENABLE_GC != 0
static bool static bool
check_type_index(const WASMModule *module, uint32 type_index, char *error_buf, check_type_index(const WASMModule *module, uint32 type_count, uint32 type_index,
uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
if (type_index >= module->type_count) { if (type_index >= type_count) {
set_error_buf_v(error_buf, error_buf_size, "unknown type %d", set_error_buf_v(error_buf, error_buf_size, "unknown type %d",
type_index); type_index);
return false; return false;
@ -409,7 +409,8 @@ static bool
check_array_type(const WASMModule *module, uint32 type_index, char *error_buf, check_array_type(const WASMModule *module, uint32 type_index, char *error_buf,
uint32 error_buf_size) uint32 error_buf_size)
{ {
if (!check_type_index(module, type_index, error_buf, error_buf_size)) { if (!check_type_index(module, module->type_count, type_index, error_buf,
error_buf_size)) {
return false; return false;
} }
if (module->types[type_index]->type_flag != WASM_TYPE_ARRAY) { if (module->types[type_index]->type_flag != WASM_TYPE_ARRAY) {
@ -775,8 +776,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
if (!is_byte_a_type(type1)) { if (!is_byte_a_type(type1)) {
p--; p--;
read_leb_uint32(p, p_end, type_idx); read_leb_uint32(p, p_end, type_idx);
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count, type_idx,
error_buf_size)) error_buf, error_buf_size))
goto fail; goto fail;
wasm_set_refheaptype_typeidx(&cur_ref_type.ref_ht_typeidx, wasm_set_refheaptype_typeidx(&cur_ref_type.ref_ht_typeidx,
@ -902,7 +903,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
uint32 field_count; uint32 field_count;
read_leb_uint32(p, p_end, type_idx); read_leb_uint32(p, p_end, type_idx);
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count,
type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -966,7 +968,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
read_leb_uint32(p, p_end, cur_value.type_index); read_leb_uint32(p, p_end, cur_value.type_index);
type_idx = cur_value.type_index; type_idx = cur_value.type_index;
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count,
type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -1001,7 +1004,8 @@ load_init_expr(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
read_leb_uint32(p, p_end, cur_value.type_index); read_leb_uint32(p, p_end, cur_value.type_index);
type_idx = cur_value.type_index; type_idx = cur_value.type_index;
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count,
type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -1275,6 +1279,13 @@ destroy_array_type(WASMArrayType *type)
static void static void
destroy_wasm_type(WASMType *type) destroy_wasm_type(WASMType *type)
{ {
if (type->ref_count > 1) {
/* The type is referenced by other types
of current wasm module */
type->ref_count--;
return;
}
if (type->type_flag == WASM_TYPE_FUNC) if (type->type_flag == WASM_TYPE_FUNC)
destroy_func_type((WASMFuncType *)type); destroy_func_type((WASMFuncType *)type);
else if (type->type_flag == WASM_TYPE_STRUCT) else if (type->type_flag == WASM_TYPE_STRUCT)
@ -1289,8 +1300,9 @@ destroy_wasm_type(WASMType *type)
/* Resolve (ref null ht) or (ref ht) */ /* Resolve (ref null ht) or (ref ht) */
static bool static bool
resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end, resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *module, bool nullable, WASMRefType *ref_type, WASMModule *module, uint32 type_count, bool nullable,
char *error_buf, uint32 error_buf_size) WASMRefType *ref_type, char *error_buf,
uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end; const uint8 *p = *p_buf, *p_end = buf_end;
@ -1301,8 +1313,9 @@ resolve_reftype_htref(const uint8 **p_buf, const uint8 *buf_end,
if (wasm_is_refheaptype_typeidx(&ref_type->ref_ht_common)) { if (wasm_is_refheaptype_typeidx(&ref_type->ref_ht_common)) {
/* heap type is (type i), i : typeidx, >= 0 */ /* heap type is (type i), i : typeidx, >= 0 */
if (!check_type_index(module, ref_type->ref_ht_typeidx.type_idx, if (!check_type_index(module, type_count,
error_buf, error_buf_size)) { ref_type->ref_ht_typeidx.type_idx, error_buf,
error_buf_size)) {
return false; return false;
} }
} }
@ -1320,9 +1333,10 @@ fail:
static bool static bool
resolve_value_type(const uint8 **p_buf, const uint8 *buf_end, resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *module, bool *p_need_ref_type_map, WASMModule *module, uint32 type_count,
WASMRefType *ref_type, bool allow_packed_type, bool *p_need_ref_type_map, WASMRefType *ref_type,
char *error_buf, uint32 error_buf_size) bool allow_packed_type, char *error_buf,
uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end; const uint8 *p = *p_buf, *p_end = buf_end;
uint8 type; uint8 type;
@ -1334,8 +1348,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
if (wasm_is_reftype_htref_nullable(type)) { if (wasm_is_reftype_htref_nullable(type)) {
/* (ref null ht) */ /* (ref null ht) */
if (!resolve_reftype_htref(&p, p_end, module, true, ref_type, error_buf, if (!resolve_reftype_htref(&p, p_end, module, type_count, true,
error_buf_size)) ref_type, error_buf, error_buf_size))
return false; return false;
if (!wasm_is_refheaptype_common(&ref_type->ref_ht_common)) if (!wasm_is_refheaptype_common(&ref_type->ref_ht_common))
*p_need_ref_type_map = true; *p_need_ref_type_map = true;
@ -1351,8 +1365,8 @@ resolve_value_type(const uint8 **p_buf, const uint8 *buf_end,
} }
else if (wasm_is_reftype_htref_non_nullable(type)) { else if (wasm_is_reftype_htref_non_nullable(type)) {
/* (ref ht) */ /* (ref ht) */
if (!resolve_reftype_htref(&p, p_end, module, false, ref_type, if (!resolve_reftype_htref(&p, p_end, module, type_count, false,
error_buf, error_buf_size)) ref_type, error_buf, error_buf_size))
return false; return false;
*p_need_ref_type_map = true; *p_need_ref_type_map = true;
#if WASM_ENABLE_STRINGREF != 0 #if WASM_ENABLE_STRINGREF != 0
@ -1401,7 +1415,8 @@ reftype_set_insert(HashMap *ref_type_set, const WASMRefType *ref_type,
static bool static bool
resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module, resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
uint32 type_idx, char *error_buf, uint32 error_buf_size) uint32 type_count, uint32 type_idx, char *error_buf,
uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end, *p_org; const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
uint32 param_count, result_count, i, j = 0; uint32 param_count, result_count, i, j = 0;
@ -1417,8 +1432,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
read_leb_uint32(p, p_end, param_count); read_leb_uint32(p, p_end, param_count);
p_org = p; p_org = p;
for (i = 0; i < param_count; i++) { for (i = 0; i < param_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
if (need_ref_type_map) if (need_ref_type_map)
@ -1427,8 +1443,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
read_leb_uint32(p, p_end, result_count); read_leb_uint32(p, p_end, result_count);
for (i = 0; i < result_count; i++) { for (i = 0; i < result_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
if (need_ref_type_map) { if (need_ref_type_map) {
@ -1468,8 +1485,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
} }
for (i = 0; i < param_count; i++) { for (i = 0; i < param_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
goto fail; goto fail;
} }
type->types[i] = ref_type.ref_type; type->types[i] = ref_type.ref_type;
@ -1485,8 +1503,9 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
read_leb_uint32(p, p_end, result_count); read_leb_uint32(p, p_end, result_count);
for (i = 0; i < result_count; i++) { for (i = 0; i < result_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
goto fail; goto fail;
} }
type->types[param_count + i] = ref_type.ref_type; type->types[param_count + i] = ref_type.ref_type;
@ -1527,18 +1546,6 @@ resolve_func_type(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
} }
#endif #endif
/* Calculate the minimal type index of the type equal to this type */
type->min_type_idx_normalized = type_idx;
for (i = 0; i < type_idx; i++) {
WASMFuncType *func_type = (WASMFuncType *)module->types[i];
if (func_type->base_type.type_flag == WASM_TYPE_FUNC
&& wasm_func_type_equal(type, func_type, module->types,
type_idx + 1)) {
type->min_type_idx_normalized = i;
break;
}
}
*p_buf = p; *p_buf = p;
module->types[type_idx] = (WASMType *)type; module->types[type_idx] = (WASMType *)type;
@ -1552,8 +1559,8 @@ fail:
static bool static bool
resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end, resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *module, uint32 type_idx, char *error_buf, WASMModule *module, uint32 type_count, uint32 type_idx,
uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end, *p_org; const uint8 *p = *p_buf, *p_end = buf_end, *p_org;
uint32 field_count, ref_type_map_count = 0, ref_field_count = 0; uint32 field_count, ref_type_map_count = 0, ref_field_count = 0;
@ -1569,8 +1576,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
read_leb_uint32(p, p_end, field_count); read_leb_uint32(p, p_end, field_count);
p_org = p; p_org = p;
for (i = 0; i < field_count; i++) { for (i = 0; i < field_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, true, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, true, error_buf,
error_buf_size)) {
return false; return false;
} }
if (need_ref_type_map) if (need_ref_type_map)
@ -1617,8 +1625,9 @@ resolve_struct_type(const uint8 **p_buf, const uint8 *buf_end,
offset = (uint32)offsetof(WASMStructObject, field_data); offset = (uint32)offsetof(WASMStructObject, field_data);
for (i = 0; i < field_count; i++) { for (i = 0; i < field_count; i++) {
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, type_count,
&ref_type, true, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, true, error_buf,
error_buf_size)) {
goto fail; goto fail;
} }
type->fields[i].field_type = ref_type.ref_type; type->fields[i].field_type = ref_type.ref_type;
@ -1671,8 +1680,8 @@ fail:
static bool static bool
resolve_array_type(const uint8 **p_buf, const uint8 *buf_end, resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
WASMModule *module, uint32 type_idx, char *error_buf, WASMModule *module, uint32 type_count, uint32 type_idx,
uint32 error_buf_size) char *error_buf, uint32 error_buf_size)
{ {
const uint8 *p = *p_buf, *p_end = buf_end; const uint8 *p = *p_buf, *p_end = buf_end;
uint8 mutable; uint8 mutable;
@ -1680,8 +1689,8 @@ resolve_array_type(const uint8 **p_buf, const uint8 *buf_end,
WASMRefType ref_type; WASMRefType ref_type;
WASMArrayType *type = NULL; WASMArrayType *type = NULL;
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type, if (!resolve_value_type(&p, p_end, module, type_count, &need_ref_type_map,
true, error_buf, error_buf_size)) { &ref_type, true, error_buf, error_buf_size)) {
return false; return false;
} }
@ -1730,7 +1739,8 @@ init_ref_type(WASMModule *module, WASMRefType *ref_type, bool nullable,
int32 heap_type, char *error_buf, uint32 error_buf_size) int32 heap_type, char *error_buf, uint32 error_buf_size)
{ {
if (heap_type >= 0) { if (heap_type >= 0) {
if (!check_type_index(module, heap_type, error_buf, error_buf_size)) { if (!check_type_index(module, module->type_count, heap_type, error_buf,
error_buf_size)) {
return false; return false;
} }
wasm_set_refheaptype_typeidx(&ref_type->ref_ht_typeidx, nullable, wasm_set_refheaptype_typeidx(&ref_type->ref_ht_typeidx, nullable,
@ -2010,6 +2020,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
if (flag == DEFINED_TYPE_FUNC) { if (flag == DEFINED_TYPE_FUNC) {
if (!resolve_func_type(&p, buf_end, module, if (!resolve_func_type(&p, buf_end, module,
processed_type_count + rec_count,
processed_type_count + j, error_buf, processed_type_count + j, error_buf,
error_buf_size)) { error_buf_size)) {
return false; return false;
@ -2017,6 +2028,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
} }
else if (flag == DEFINED_TYPE_STRUCT) { else if (flag == DEFINED_TYPE_STRUCT) {
if (!resolve_struct_type(&p, buf_end, module, if (!resolve_struct_type(&p, buf_end, module,
processed_type_count + rec_count,
processed_type_count + j, processed_type_count + j,
error_buf, error_buf_size)) { error_buf, error_buf_size)) {
return false; return false;
@ -2024,6 +2036,7 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
} }
else if (flag == DEFINED_TYPE_ARRAY) { else if (flag == DEFINED_TYPE_ARRAY) {
if (!resolve_array_type(&p, buf_end, module, if (!resolve_array_type(&p, buf_end, module,
processed_type_count + rec_count,
processed_type_count + j, error_buf, processed_type_count + j, error_buf,
error_buf_size)) { error_buf_size)) {
return false; return false;
@ -2037,13 +2050,13 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
cur_type = module->types[processed_type_count + j]; cur_type = module->types[processed_type_count + j];
cur_type->ref_count = 1;
cur_type->parent_type_idx = parent_type_idx; cur_type->parent_type_idx = parent_type_idx;
cur_type->is_sub_final = is_sub_final; cur_type->is_sub_final = is_sub_final;
if (rec_count > 1) {
cur_type->rec_count = rec_count; cur_type->rec_count = rec_count;
cur_type->rec_idx = j; cur_type->rec_idx = j;
} cur_type->rec_begin_type_idx = processed_type_count;
} }
/* resolve subtyping relationship in current rec group */ /* resolve subtyping relationship in current rec group */
@ -2055,6 +2068,11 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
module->types[cur_type->parent_type_idx]; module->types[cur_type->parent_type_idx];
cur_type->parent_type = parent_type; cur_type->parent_type = parent_type;
cur_type->root_type = parent_type->root_type; cur_type->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");
return false;
}
cur_type->inherit_depth = parent_type->inherit_depth + 1; cur_type->inherit_depth = parent_type->inherit_depth + 1;
} }
else { else {
@ -2080,6 +2098,49 @@ load_type_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
} }
} }
/* If there is already an equivalence type or a group of equivalence
recursive types created, use it or them instead */
for (j = 0; j < processed_type_count;) {
WASMType *src_type = module->types[j];
WASMType *cur_type = module->types[processed_type_count];
uint32 k, src_rec_count;
src_rec_count = src_type->rec_count;
if (src_rec_count != rec_count) {
/* no type equivalence */
j += src_rec_count;
continue;
}
for (k = 0; k < rec_count; k++) {
src_type = module->types[j + k];
cur_type = module->types[processed_type_count + k];
if (!wasm_type_equal(src_type, cur_type, module->types,
module->type_count)) {
break;
}
}
if (k < rec_count) {
/* no type equivalence */
j += src_rec_count;
continue;
}
/* type equivalence */
for (k = 0; k < rec_count; k++) {
if (module->types[j + k]->ref_count == UINT16_MAX) {
set_error_buf(error_buf, error_buf_size,
"wasm type's ref count too large");
return false;
}
destroy_wasm_type(module->types[processed_type_count + k]);
module->types[processed_type_count + k] =
module->types[j + k];
module->types[j + k]->ref_count++;
}
break;
}
if (rec_count > 1) { if (rec_count > 1) {
LOG_VERBOSE("Finished processing rec group [%d-%d]", LOG_VERBOSE("Finished processing rec group [%d-%d]",
processed_type_count, processed_type_count,
@ -2511,8 +2572,9 @@ load_table_import(const uint8 **p_buf, const uint8 *buf_end,
return false; return false;
} }
#else /* else of WASM_ENABLE_GC == 0 */ #else /* else of WASM_ENABLE_GC == 0 */
if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) { if (wasm_is_reftype_htref_non_nullable(ref_type.ref_type)) {
@ -2947,8 +3009,9 @@ load_global_import(const uint8 **p_buf, const uint8 *buf_end,
declare_type = read_uint8(p); declare_type = read_uint8(p);
declare_mutable = read_uint8(p); declare_mutable = read_uint8(p);
#else #else
if (!resolve_value_type(&p, p_end, parent_module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, parent_module, parent_module->type_count,
&ref_type, false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
declare_type = ref_type.ref_type; declare_type = ref_type.ref_type;
@ -3050,8 +3113,9 @@ load_table(const uint8 **p_buf, const uint8 *buf_end, WASMModule *module,
return false; return false;
} }
#else /* else of WASM_ENABLE_GC == 0 */ #else /* else of WASM_ENABLE_GC == 0 */
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, &ref_type, if (!resolve_value_type(&p, p_end, module, module->type_count,
false, error_buf, error_buf_size)) { &need_ref_type_map, &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
table->elem_type = ref_type.ref_type; table->elem_type = ref_type.ref_type;
@ -3536,7 +3600,8 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
type_index_org = type_index; type_index_org = type_index;
#endif #endif
#if (WASM_ENABLE_WAMR_COMPILER != 0) || (WASM_ENABLE_JIT != 0) #if (WASM_ENABLE_WAMR_COMPILER != 0 || WASM_ENABLE_JIT != 0) \
&& WASM_ENABLE_GC == 0
type_index = wasm_get_smallest_type_idx( type_index = wasm_get_smallest_type_idx(
module->types, module->type_count, type_index); module->types, module->type_count, type_index);
#endif #endif
@ -3577,8 +3642,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
#endif #endif
#else #else
if (!resolve_value_type(&p_code, buf_code_end, module, if (!resolve_value_type(&p_code, buf_code_end, module,
&need_ref_type_map, &ref_type, false, module->type_count, &need_ref_type_map,
error_buf, error_buf_size)) { &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
local_count += sub_local_count; local_count += sub_local_count;
@ -3664,8 +3730,9 @@ load_function_section(const uint8 *buf, const uint8 *buf_end,
} }
#else #else
if (!resolve_value_type(&p_code, buf_code_end, module, if (!resolve_value_type(&p_code, buf_code_end, module,
&need_ref_type_map, &ref_type, false, module->type_count, &need_ref_type_map,
error_buf, error_buf_size)) { &ref_type, false, error_buf,
error_buf_size)) {
return false; return false;
} }
if (need_ref_type_map) { if (need_ref_type_map) {
@ -3923,9 +3990,9 @@ load_global_section(const uint8 *buf, const uint8 *buf_end, WASMModule *module,
global->type = read_uint8(p); global->type = read_uint8(p);
mutable = read_uint8(p); mutable = read_uint8(p);
#else #else
if (!resolve_value_type(&p, p_end, module, &need_ref_type_map, if (!resolve_value_type(&p, p_end, module, module->type_count,
&ref_type, false, error_buf, &need_ref_type_map, &ref_type, false,
error_buf_size)) { error_buf, error_buf_size)) {
return false; return false;
} }
global->type = ref_type.ref_type; global->type = ref_type.ref_type;
@ -4231,8 +4298,8 @@ load_elem_type(WASMModule *module, const uint8 **p_buf, const uint8 *buf_end,
#else #else
p--; p--;
if (!resolve_value_type((const uint8 **)&p, p_end, module, if (!resolve_value_type((const uint8 **)&p, p_end, module,
&need_ref_type_map, &elem_ref_type, false, module->type_count, &need_ref_type_map,
error_buf, error_buf_size)) { &elem_ref_type, false, error_buf, error_buf_size)) {
return false; return false;
} }
if (!wasm_is_type_reftype(elem_ref_type.ref_type)) { if (!wasm_is_type_reftype(elem_ref_type.ref_type)) {
@ -10827,7 +10894,8 @@ re_scan:
p_org = p; p_org = p;
p--; p--;
if (!resolve_value_type((const uint8 **)&p, p_end, if (!resolve_value_type((const uint8 **)&p, p_end,
module, &need_ref_type_map, module, module->type_count,
&need_ref_type_map,
&wasm_ref_type, false, &wasm_ref_type, false,
error_buf, error_buf_size)) { error_buf, error_buf_size)) {
goto fail; goto fail;
@ -11303,8 +11371,8 @@ re_scan:
bh_memcpy_s(loader_ctx->frame_offset, size, bh_memcpy_s(loader_ctx->frame_offset, size,
block->param_frame_offsets, size); block->param_frame_offsets, size);
loader_ctx->frame_offset += (size / sizeof(int16)); loader_ctx->frame_offset += (size / sizeof(int16));
loader_ctx->dynamic_offset = block->start_dynamic_offset;
} }
loader_ctx->dynamic_offset = block->start_dynamic_offset;
#endif #endif
break; break;
@ -11598,6 +11666,15 @@ re_scan:
if (opcode == WASM_OP_CALL_REF if (opcode == WASM_OP_CALL_REF
|| opcode == WASM_OP_RETURN_CALL_REF) { || opcode == WASM_OP_RETURN_CALL_REF) {
read_leb_uint32(p, p_end, type_idx1); read_leb_uint32(p, p_end, type_idx1);
if (!check_type_index(module, module->type_count, type_idx1,
error_buf, error_buf_size)) {
goto fail;
}
if (module->types[type_idx1]->type_flag != WASM_TYPE_FUNC) {
set_error_buf(error_buf, error_buf_size,
"unkown function type");
goto fail;
}
if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type, if (!wasm_loader_pop_nullable_typeidx(loader_ctx, &type,
&type_idx, error_buf, &type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
@ -11606,8 +11683,8 @@ re_scan:
if (type == VALUE_TYPE_ANY) { if (type == VALUE_TYPE_ANY) {
type_idx = type_idx1; type_idx = type_idx1;
} }
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count, type_idx,
error_buf_size)) { error_buf, error_buf_size)) {
goto fail; goto fail;
} }
if (module->types[type_idx]->type_flag != WASM_TYPE_FUNC) { if (module->types[type_idx]->type_flag != WASM_TYPE_FUNC) {
@ -11615,7 +11692,9 @@ re_scan:
"unkown function type"); "unkown function type");
goto fail; goto fail;
} }
if (type_idx != type_idx1) { if (!wasm_func_type_is_super_of(
(WASMFuncType *)module->types[type_idx1],
(WASMFuncType *)module->types[type_idx])) {
set_error_buf(error_buf, error_buf_size, set_error_buf(error_buf, error_buf_size,
"function type mismatch"); "function type mismatch");
goto fail; goto fail;
@ -12055,8 +12134,9 @@ re_scan:
#else #else
p_org = p + 1; p_org = p + 1;
if (!resolve_value_type((const uint8 **)&p, p_end, module, if (!resolve_value_type((const uint8 **)&p, p_end, module,
&need_ref_type_map, &wasm_ref_type, module->type_count, &need_ref_type_map,
false, error_buf, error_buf_size)) { &wasm_ref_type, false, error_buf,
error_buf_size)) {
goto fail; goto fail;
} }
type = wasm_ref_type.ref_type; type = wasm_ref_type.ref_type;
@ -12223,8 +12303,8 @@ re_scan:
#else #else
read_leb_int32(p, p_end, heap_type); read_leb_int32(p, p_end, heap_type);
if (heap_type >= 0) { if (heap_type >= 0) {
if (!check_type_index(module, heap_type, error_buf, if (!check_type_index(module, module->type_count, heap_type,
error_buf_size)) { error_buf, error_buf_size)) {
goto fail; goto fail;
} }
wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx, wasm_set_refheaptype_typeidx(&wasm_ref_type.ref_ht_typeidx,
@ -13008,6 +13088,7 @@ re_scan:
break; break;
case WASM_OP_F32_CONST: case WASM_OP_F32_CONST:
CHECK_BUF(p, p_end, sizeof(float32));
p += sizeof(float32); p += sizeof(float32);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
skip_label(); skip_label();
@ -13026,6 +13107,7 @@ re_scan:
break; break;
case WASM_OP_F64_CONST: case WASM_OP_F64_CONST:
CHECK_BUF(p, p_end, sizeof(float64));
p += sizeof(float64); p += sizeof(float64);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
skip_label(); skip_label();
@ -13286,7 +13368,8 @@ re_scan:
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, type_idx); emit_uint32(loader_ctx, type_idx);
#endif #endif
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count,
type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -13372,7 +13455,8 @@ re_scan:
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
emit_uint32(loader_ctx, type_idx); emit_uint32(loader_ctx, type_idx);
#endif #endif
if (!check_type_index(module, type_idx, error_buf, if (!check_type_index(module, module->type_count,
type_idx, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -13785,7 +13869,8 @@ re_scan:
emit_uint32(loader_ctx, (uint32)heap_type); emit_uint32(loader_ctx, (uint32)heap_type);
#endif #endif
if (heap_type >= 0) { if (heap_type >= 0) {
if (!check_type_index(module, heap_type, error_buf, if (!check_type_index(module, module->type_count,
heap_type, error_buf,
error_buf_size)) { error_buf_size)) {
goto fail; goto fail;
} }
@ -14356,6 +14441,7 @@ re_scan:
} }
case WASM_OP_MEMORY_COPY: case WASM_OP_MEMORY_COPY:
{ {
CHECK_BUF(p, p_end, sizeof(int16));
/* both src and dst memory index should be 0 */ /* both src and dst memory index should be 0 */
if (*(int16 *)p != 0x0000) if (*(int16 *)p != 0x0000)
goto fail_zero_byte_expected; goto fail_zero_byte_expected;
@ -15129,13 +15215,6 @@ re_scan:
break; break;
} }
case SIMD_i32x4_narrow_i64x2_s:
case SIMD_i32x4_narrow_i64x2_u:
{
POP2_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
break;
}
case SIMD_i32x4_extend_low_i16x8_s: case SIMD_i32x4_extend_low_i16x8_s:
case SIMD_i32x4_extend_high_i16x8_s: case SIMD_i32x4_extend_high_i16x8_s:
case SIMD_i32x4_extend_low_i16x8_u: case SIMD_i32x4_extend_low_i16x8_u:
@ -15162,7 +15241,6 @@ re_scan:
case SIMD_i32x4_max_s: case SIMD_i32x4_max_s:
case SIMD_i32x4_max_u: case SIMD_i32x4_max_u:
case SIMD_i32x4_dot_i16x8_s: case SIMD_i32x4_dot_i16x8_s:
case SIMD_i32x4_avgr_u:
case SIMD_i32x4_extmul_low_i16x8_s: case SIMD_i32x4_extmul_low_i16x8_s:
case SIMD_i32x4_extmul_high_i16x8_s: case SIMD_i32x4_extmul_high_i16x8_s:
case SIMD_i32x4_extmul_low_i16x8_u: case SIMD_i32x4_extmul_low_i16x8_u:
@ -15226,7 +15304,6 @@ re_scan:
/* f32x4 operation */ /* f32x4 operation */
case SIMD_f32x4_abs: case SIMD_f32x4_abs:
case SIMD_f32x4_neg: case SIMD_f32x4_neg:
case SIMD_f32x4_round:
case SIMD_f32x4_sqrt: case SIMD_f32x4_sqrt:
{ {
POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);
@ -15249,7 +15326,6 @@ re_scan:
/* f64x2 operation */ /* f64x2 operation */
case SIMD_f64x2_abs: case SIMD_f64x2_abs:
case SIMD_f64x2_neg: case SIMD_f64x2_neg:
case SIMD_f64x2_round:
case SIMD_f64x2_sqrt: case SIMD_f64x2_sqrt:
{ {
POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128); POP_AND_PUSH(VALUE_TYPE_V128, VALUE_TYPE_V128);

View File

@ -6226,8 +6226,8 @@ re_scan:
bh_memcpy_s(loader_ctx->frame_offset, size, bh_memcpy_s(loader_ctx->frame_offset, size,
block->param_frame_offsets, size); block->param_frame_offsets, size);
loader_ctx->frame_offset += (size / sizeof(int16)); loader_ctx->frame_offset += (size / sizeof(int16));
loader_ctx->dynamic_offset = block->start_dynamic_offset;
} }
loader_ctx->dynamic_offset = block->start_dynamic_offset;
#endif #endif
break; break;
@ -7351,6 +7351,7 @@ re_scan:
break; break;
case WASM_OP_F32_CONST: case WASM_OP_F32_CONST:
CHECK_BUF(p, p_end, sizeof(float32));
p += sizeof(float32); p += sizeof(float32);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
skip_label(); skip_label();
@ -7369,6 +7370,7 @@ re_scan:
break; break;
case WASM_OP_F64_CONST: case WASM_OP_F64_CONST:
CHECK_BUF(p, p_end, sizeof(float64));
p += sizeof(float64); p += sizeof(float64);
#if WASM_ENABLE_FAST_INTERP != 0 #if WASM_ENABLE_FAST_INTERP != 0
skip_label(); skip_label();
@ -7676,6 +7678,7 @@ re_scan:
} }
case WASM_OP_MEMORY_COPY: case WASM_OP_MEMORY_COPY:
{ {
CHECK_BUF(p, p_end, sizeof(int16));
/* both src and dst memory index should be 0 */ /* both src and dst memory index should be 0 */
bh_assert(*(int16 *)p == 0x0000); bh_assert(*(int16 *)p == 0x0000);
p += 2; p += 2;

View File

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

View File

@ -4353,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 (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; return (uint32)-1;
} }
total_size = tbl_inst->cur_size + inc_size; total_size = tbl_inst->cur_size + inc_size;
if (total_size > tbl_inst->max_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; return (uint32)-1;
} }
@ -4394,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); 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 WASMRttTypeRef
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index) llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index)
{ {

View File

@ -811,6 +811,11 @@ bool
llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst, llvm_jit_obj_is_instance_of(WASMModuleInstance *module_inst,
WASMObjectRef gc_obj, uint32 type_index); 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 WASMRttTypeRef
llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index); llvm_jit_rtt_type_new(WASMModuleInstance *module_inst, uint32 type_index);

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); int ret = posix_fadvise(handle, (off_t)offset, (off_t)length, nadvice);
if (ret < 0) if (ret != 0)
return convert_errno(ret); return convert_errno(ret);
return __WASI_ESUCCESS; return __WASI_ESUCCESS;

View File

@ -55,7 +55,24 @@ os_mmap(void *hint, size_t size, int prot, int flags, os_file_handle file)
#else #else
uint32_t mem_caps = MALLOC_CAP_8BIT; uint32_t mem_caps = MALLOC_CAP_8BIT;
#endif #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_vmcore.h"
#include "platform_api_extension.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 int
bh_platform_init() bh_platform_init()
{ {
@ -234,7 +240,13 @@ unlinkat(int fd, const char *path, int flag)
} }
int 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; errno = ENOSYS;
return -1; return -1;
@ -257,7 +269,13 @@ ftruncate(int fd, off_t length)
#endif #endif
int 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; errno = ENOSYS;
return -1; return -1;

View File

@ -578,3 +578,33 @@ os_thread_get_stack_boundary()
void void
os_thread_jit_write_protect_np(bool enabled) 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;
}

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) 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) project(wamr-simple)

View File

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

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" #include "esp_log.h"
#ifdef CONFIG_IDF_TARGET_ESP32S3
#define IWASM_MAIN_STACK_SIZE 5120 #define IWASM_MAIN_STACK_SIZE 5120
#else
#define IWASM_MAIN_STACK_SIZE 4096
#endif
#define LOG_TAG "wamr" #define LOG_TAG "wamr"

View File

@ -7,6 +7,14 @@ include(CheckPIESupported)
project(debug_tools_sample) 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 ################ ################ runtime settings ################
string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM) string (TOLOWER ${CMAKE_HOST_SYSTEM_NAME} WAMR_BUILD_PLATFORM)
if (APPLE) if (APPLE)
@ -61,7 +69,30 @@ include (${WAMR_ROOT_DIR}/build-scripts/runtime_lib.cmake)
add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE}) add_library(vmlib ${WAMR_RUNTIME_LIB_SOURCE})
################ wasm application ################ ################ 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 ################ ################ wamr runtime ################
include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake) include (${SHARED_DIR}/utils/uncommon/shared_uncommon.cmake)

View File

@ -80,6 +80,39 @@ $ python3 ../../../test-tools/addr2line/addr2line.py \
call_stack.txt --no-addr 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 ### 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. 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.
@ -97,4 +130,4 @@ Then the output should be something like
Exception: unreachable Exception: unreachable
``` ```
Also, it is able to use *addr2line.py* to add file and line info to the stack trace. 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. # Copyright (C) 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
if (APPLE) cmake_minimum_required (VERSION 3.14)
set (HAVE_FLAG_SEARCH_PATHS_FIRST 0)
set (CMAKE_C_LINK_FLAGS "")
set (CMAKE_CXX_LINK_FLAGS "")
endif ()
if (NOT DEFINED WASI_SDK_DIR) project (debut_tools_wasm)
set (WASI_SDK_DIR "/opt/wasi-sdk")
endif ()
if (DEFINED WASI_SYSROOT) set (CMAKE_BUILD_TYPE Debug) # Otherwise no debug symbols (addr2line)
set (CMAKE_SYSROOT "${WASI_SYSROOT}")
endif ()
set (CMAKE_C_COMPILER "${WASI_SDK_DIR}/bin/clang") list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../cmake)
set (CMAKE_ASM_COMPILER "${WASI_SDK_DIR}/bin/clang") find_package (WAMRC REQUIRED)
set (CMAKE_EXE_LINKER_FLAGS "-target wasm32-wasi")
################ wabt and wamrc dependencies ################ option(SOURCE_MAP_DEMO "Enable source map demo" OFF)
message(CHECK_START "Detecting WABT") if (SOURCE_MAP_DEMO)
if(NOT (DEFINED WABT_DIR OR DEFINED CACHE{WABT_DIR})) find_package(EMSCRIPTEN 3.1.50 REQUIRED)
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 () endif ()
################ wasm and aot compilation ################ ################ wasm and aot compilation ################
function (compile_sample SOURCE_FILE) function (compile_sample SOURCE_FILE)
get_filename_component (FILE_NAME ${SOURCE_FILE} NAME_WLE) get_filename_component (FILE_NAME ${SOURCE_FILE} NAME_WLE)
set (WASM_MODULE ${FILE_NAME}.wasm)
add_executable (${WASM_MODULE} ${SOURCE_FILE})
## 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 ( add_custom_target (
wasm_to_aot ${FILE_NAME}_aot
ALL ALL
DEPENDS ${WAMR_COMPILER} ${WASM_MODULE} DEPENDS ${WAMRC_BIN} ${WASM_FILE}
# Use --enable-dump-call-stack to generate stack trace (addr2line) # 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 COMMAND ${WAMRC_BIN} --size-level=0 --enable-dump-call-stack -o ${AOT_FILE} ${WASM_FILE}
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} 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 () endfunction ()
set(CMAKE_BUILD_TYPE Debug) # Otherwise no debug symbols (addr2line)
compile_sample(trap.c) compile_sample(trap.c)

View File

@ -43,6 +43,28 @@ For example, there is a call-stack dump:
""" """
def locate_sourceMappingURL_section(wasm_objdump: Path, wasm_file: Path) -> bool:
"""
Figure out if the wasm file has a sourceMappingURL section.
"""
cmd = f"{wasm_objdump} -h {wasm_file}"
p = subprocess.run(
shlex.split(cmd),
check=True,
capture_output=True,
text=True,
universal_newlines=True,
)
outputs = p.stdout.split(os.linesep)
for line in outputs:
line = line.strip()
if "sourceMappingURL" in line:
return True
return False
def get_code_section_start(wasm_objdump: Path, wasm_file: Path) -> int: def get_code_section_start(wasm_objdump: Path, wasm_file: Path) -> int:
""" """
Find the start offset of Code section in a wasm file. Find the start offset of Code section in a wasm file.
@ -62,15 +84,6 @@ def get_code_section_start(wasm_objdump: Path, wasm_file: Path) -> int:
) )
outputs = p.stdout.split(os.linesep) outputs = p.stdout.split(os.linesep)
# if there is no .debug section, return -1
for line in outputs:
line = line.strip()
if ".debug_info" in line:
break
else:
print(f"No .debug_info section found {wasm_file}")
return -1
for line in outputs: for line in outputs:
line = line.strip() line = line.strip()
if "Code" in line: if "Code" in line:
@ -79,7 +92,7 @@ def get_code_section_start(wasm_objdump: Path, wasm_file: Path) -> int:
return -1 return -1
def get_line_info_from_function_addr( def get_line_info_from_function_addr_dwarf(
dwarf_dump: Path, wasm_file: Path, offset: int dwarf_dump: Path, wasm_file: Path, offset: int
) -> tuple[str, str, str, str]: ) -> tuple[str, str, str, str]:
""" """
@ -126,7 +139,7 @@ def get_dwarf_tag_value(tag: str, line: str) -> str:
return m.groups()[0] return m.groups()[0]
def get_line_info_from_function_name( def get_line_info_from_function_name_dwarf(
dwarf_dump: Path, wasm_file: Path, function_name: str dwarf_dump: Path, wasm_file: Path, function_name: str
) -> tuple[str, str, str]: ) -> tuple[str, str, str]:
""" """
@ -160,6 +173,51 @@ def get_line_info_from_function_name(
return (function_name, function_file, function_line) return (function_name, function_file, function_line)
def get_line_info_from_function_addr_sourcemapping(
emsymbolizer: Path, wasm_file: Path, offset: int
) -> tuple[str, str, str, str]:
"""
Find the location info of a given offset in a wasm file which is compiled with emcc.
{emsymbolizer} {wasm_file} {offset of file}
there usually are two lines:
??
relative path to source file:line:column
"""
debug_info_source = wasm_file.with_name(f"{wasm_file.name}.map")
cmd = f"{emsymbolizer} -t code -f {debug_info_source} {wasm_file} {offset}"
p = subprocess.run(
shlex.split(cmd),
check=False,
capture_output=True,
text=True,
universal_newlines=True,
cwd=Path.cwd(),
)
outputs = p.stdout.split(os.linesep)
function_name, function_file = "<unknown>", "unknown"
function_line, function_column = "?", "?"
for line in outputs:
line = line.strip()
if not line:
continue
m = re.match("(.*):(\d+):(\d+)", line)
if m:
function_file, function_line, function_column = m.groups()
continue
else:
# it's always ??, not sure about that
if "??" != line:
function_name = line
return (function_name, function_file, function_line, function_column)
def parse_line_info(line_info: str) -> tuple[str, str, str]: def parse_line_info(line_info: str) -> tuple[str, str, str]:
""" """
line_info -> [file, line, column] line_info -> [file, line, column]
@ -250,6 +308,7 @@ def main():
action="store_true", action="store_true",
help="use call stack without addresses or from fast interpreter mode", help="use call stack without addresses or from fast interpreter mode",
) )
parser.add_argument("--emsdk", type=Path, help="path to emsdk")
args = parser.parse_args() args = parser.parse_args()
wasm_objdump = args.wabt.joinpath("bin/wasm-objdump") wasm_objdump = args.wabt.joinpath("bin/wasm-objdump")
@ -261,6 +320,15 @@ def main():
llvm_cxxfilt = args.wasi_sdk.joinpath("bin/llvm-cxxfilt") llvm_cxxfilt = args.wasi_sdk.joinpath("bin/llvm-cxxfilt")
assert llvm_cxxfilt.exists() assert llvm_cxxfilt.exists()
emcc_production = locate_sourceMappingURL_section(wasm_objdump, args.wasm_file)
if emcc_production:
if args.emsdk is None:
print("Please provide the path to emsdk via --emsdk")
return -1
emsymbolizer = args.emsdk.joinpath("upstream/emscripten/emsymbolizer")
assert emsymbolizer.exists()
code_section_start = get_code_section_start(wasm_objdump, args.wasm_file) code_section_start = get_code_section_start(wasm_objdump, args.wasm_file)
if code_section_start == -1: if code_section_start == -1:
return -1 return -1
@ -281,6 +349,7 @@ def main():
_, offset, index = splitted _, offset, index = splitted
if args.no_addr: if args.no_addr:
# FIXME: w/ emcc production
if not index.startswith("$f"): # E.g. _start or Text format if not index.startswith("$f"): # E.g. _start or Text format
print(f"{i}: {index}") print(f"{i}: {index}")
continue continue
@ -290,19 +359,37 @@ def main():
print(f"{i}: {line}") print(f"{i}: {line}")
continue continue
line_info = get_line_info_from_function_name( if not emcc_production:
llvm_dwarf_dump, args.wasm_file, function_index_to_name[index] _, function_file, function_line = (
get_line_info_from_function_name_dwarf(
llvm_dwarf_dump,
args.wasm_file,
function_index_to_name[index],
) )
)
else:
_, function_file, function_line = _, "unknown", "?"
_, function_file, function_line = line_info
function_name = demangle(llvm_cxxfilt, function_index_to_name[index]) function_name = demangle(llvm_cxxfilt, function_index_to_name[index])
print(f"{i}: {function_name}") print(f"{i}: {function_name}")
print(f"\tat {function_file}:{function_line}") print(f"\tat {function_file}:{function_line}")
else: else:
offset = int(offset, 16) offset = int(offset, 16)
# match the algorithm in wasm_interp_create_call_stack()
# either a *offset* to *code* section start
# or a *offset* in a file
assert offset > code_section_start
offset = offset - code_section_start offset = offset - code_section_start
if emcc_production:
function_name, function_file, function_line, function_column = ( function_name, function_file, function_line, function_column = (
get_line_info_from_function_addr( get_line_info_from_function_addr_sourcemapping(
emsymbolizer, args.wasm_file, offset
)
)
else:
function_name, function_file, function_line, function_column = (
get_line_info_from_function_addr_dwarf(
llvm_dwarf_dump, args.wasm_file, offset llvm_dwarf_dump, args.wasm_file, offset
) )
) )

View File

@ -95,7 +95,7 @@ def ignore_the_case(
return True return True
if gc_flag: if gc_flag:
if case_name in ["type-equivalence", "type-rec", "array_init_elem", "array_init_data"]: if case_name in ["array_init_elem", "array_init_data"]:
return True return True
if sgx_flag: if sgx_flag:

View File

@ -9,78 +9,6 @@ index 335496f0..5b975028 100644
- "integer representation too long" - "integer representation too long"
+ "invalid type flag" ;; In GC extension, the first byte in rectype define is just one byte, not LEB128 encoded. + "invalid type flag" ;; In GC extension, the first byte in rectype define is just one byte, not LEB128 encoded.
) )
diff --git a/test/core/binary.wast b/test/core/binary.wast
index 1661a1c6..84c716b9 100644
--- a/test/core/binary.wast
+++ b/test/core/binary.wast
@@ -1082,7 +1082,7 @@
)
;; 1 br_table target declared, 2 given
-(assert_malformed
+(;assert_malformed
(module binary
"\00asm" "\01\00\00\00"
"\01\04\01" ;; type section
@@ -1132,3 +1132,4 @@
)
"unexpected content after last section"
)
+;)
diff --git a/test/core/data.wast b/test/core/data.wast
index a5c87fbb..6f948bae 100644
--- a/test/core/data.wast
+++ b/test/core/data.wast
@@ -306,9 +306,10 @@
"\02\01\41\00\0b" ;; active data segment 0 for memory 1
"\00" ;; empty vec(byte)
)
- "unknown memory 1"
+ "unknown memory"
)
+(; not supported by wat2wasm
;; Data segment with memory index 0 (no memory section)
(assert_invalid
(module binary
@@ -317,7 +318,7 @@
"\00\41\00\0b" ;; active data segment 0 for memory 0
"\00" ;; empty vec(byte)
)
- "unknown memory 0"
+ "unknown memory"
)
;; Data segment with memory index 1 (no memory section)
@@ -328,7 +329,7 @@
"\02\01\41\00\0b" ;; active data segment 0 for memory 1
"\00" ;; empty vec(byte)
)
- "unknown memory 1"
+ "unknown memory"
)
;; Data segment with memory index 1 and vec(byte) as above,
@@ -348,7 +349,7 @@
"\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
"\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
)
- "unknown memory 1"
+ "unknown memory"
)
;; Data segment with memory index 1 and specially crafted vec(byte) after.
@@ -368,8 +369,9 @@
"\20\21\22\23\24\25\26\27\28\29\2a\2b\2c\2d\2e\2f"
"\30\31\32\33\34\35\36\37\38\39\3a\3b\3c\3d"
)
- "unknown memory 1"
+ "unknown memory"
)
+;)
;; Invalid offsets
diff --git a/test/core/elem.wast b/test/core/elem.wast diff --git a/test/core/elem.wast b/test/core/elem.wast
index df1610f6..32c1d8b3 100644 index df1610f6..32c1d8b3 100644
--- a/test/core/elem.wast --- a/test/core/elem.wast
@ -268,196 +196,11 @@ index 00000000..32650644
+ ) + )
+ "unsupported initializer expression for table" + "unsupported initializer expression for table"
+) +)
diff --git a/test/core/gc/ref_test.wast b/test/core/gc/ref_test.wast
index 590b81b8..e0aa49ed 100644
--- a/test/core/gc/ref_test.wast
+++ b/test/core/gc/ref_test.wast
@@ -310,15 +310,16 @@
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 11)))))
(br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 12)))))
- (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 1)))))
- (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 2)))))
+ ;; Must have explicit sub relationship
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 1)))))
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1') (table.get (i32.const 2)))))
- (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 11)))))
- (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 12)))))
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 11)))))
+ ;; (br_if $l (i32.eqz (ref.test (ref $t1) (table.get (i32.const 12)))))
- (br_if $l (i32.eqz (ref.test (ref $t2') (table.get (i32.const 2)))))
+ ;; (br_if $l (i32.eqz (ref.test (ref $t2') (table.get (i32.const 2)))))
- (br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 12)))))
+ ;; (br_if $l (i32.eqz (ref.test (ref $t2) (table.get (i32.const 12)))))
(return)
)
diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast diff --git a/test/core/gc/type-subtyping.wast b/test/core/gc/type-subtyping.wast
index a9022fc3..4e22e91b 100644 index a9022fc3..4aa36e2a 100644
--- a/test/core/gc/type-subtyping.wast --- a/test/core/gc/type-subtyping.wast
+++ b/test/core/gc/type-subtyping.wast +++ b/test/core/gc/type-subtyping.wast
@@ -112,6 +112,8 @@ @@ -740,7 +740,7 @@
)
)
+;; don't support recursive type equality and subtype check
+(;
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
@@ -135,6 +137,7 @@
(func $g (type $g2))
(global (ref $g1) (ref.func $g))
)
+;)
(assert_invalid
(module
@@ -156,6 +159,8 @@
(global (ref $f1) (ref.func $g))
)
+;; don't support recursive type equality and subtype check
+(;
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
@@ -201,6 +206,7 @@
(global (ref $g12) (ref.func $g12))
(global (ref $g22) (ref.func $g12))
)
+;)
(assert_invalid
(module
@@ -226,6 +232,8 @@
;; Runtime types
+;; don't support recursive type equality and subtype check
+(;
(module
(type $t0 (sub (func (result (ref null func)))))
(rec (type $t1 (sub $t0 (func (result (ref null $t1))))))
@@ -286,6 +294,7 @@
(assert_trap (invoke "fail4") "cast")
(assert_trap (invoke "fail5") "cast")
(assert_trap (invoke "fail6") "cast")
+;)
(module
(type $t1 (sub (func)))
@@ -316,7 +325,8 @@
(assert_trap (invoke "fail3") "cast")
(assert_trap (invoke "fail4") "cast")
-
+;; don't support recursive type equality and subtype check
+(;
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
(rec (type $f2 (sub (func))) (type (struct (field (ref $f2)))))
@@ -346,6 +356,7 @@
)
)
(assert_return (invoke "run") (i32.const 1))
+;)
(module
(rec (type $f1 (sub (func))) (type (struct (field (ref $f1)))))
@@ -370,6 +381,8 @@
)
(assert_return (invoke "run") (i32.const 1))
+;; don't support recursive type equality and subtype check
+(;
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
@@ -390,7 +403,6 @@
)
(assert_return (invoke "run") (i32.const 1) (i32.const 1))
-
(module
(rec (type $f11 (sub (func (result (ref func))))) (type $f12 (sub $f11 (func (result (ref $f11))))))
(rec (type $f21 (sub (func (result (ref func))))) (type $f22 (sub $f21 (func (result (ref $f21))))))
@@ -429,7 +441,9 @@
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
(i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1)
)
+;)
+(; we use normalized function type index
(module
(rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func))))
(rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func))))
@@ -439,6 +453,7 @@
)
)
(assert_return (invoke "run") (i32.const 0))
+;)
(module
(rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func))))
@@ -547,15 +562,15 @@
(func (import "M3" "g") (type $g1))
)
-(module
- (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
- (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
- (rec
- (type $g2 (sub $f2 (func)))
- (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
- )
- (func (export "g") (type $g2))
-)
+;; (module
+;; (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
+;; (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
+;; (rec
+;; (type $g2 (sub $f2 (func)))
+;; (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
+;; )
+;; (func (export "g") (type $g2))
+;; )
(register "M4")
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
@@ -597,17 +612,17 @@
(func (import "M6" "g") (type $f1))
)
-(module
- (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
- (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
- (rec
- (type $g2 (sub $f2 (func)))
- (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
- )
- (rec (type $h (sub $g2 (func))) (type (struct)))
- (func (export "h") (type $h))
-)
-(register "M7")
+;; (module
+;; (rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
+;; (rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
+;; (rec
+;; (type $g2 (sub $f2 (func)))
+;; (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))))
+;; )
+;; (rec (type $h (sub $g2 (func))) (type (struct)))
+;; (func (export "h") (type $h))
+;; )
+;; (register "M7")
(module
(rec (type $f1 (sub (func))) (type $s1 (sub (struct (field (ref $f1))))))
(rec (type $f2 (sub (func))) (type $s2 (sub (struct (field (ref $f2))))))
@@ -740,7 +755,7 @@
"sub type" "sub type"
) )
@ -466,7 +209,7 @@ index a9022fc3..4e22e91b 100644
(module (module
(type $f0 (sub (func (param i32) (result i32)))) (type $f0 (sub (func (param i32) (result i32))))
(type $s0 (sub $f0 (struct))) (type $s0 (sub $f0 (struct)))
@@ -764,7 +779,7 @@ @@ -764,7 +764,7 @@
"sub type" "sub type"
) )
@ -475,7 +218,7 @@ index a9022fc3..4e22e91b 100644
(module (module
(type $s0 (sub (struct))) (type $s0 (sub (struct)))
(type $f0 (sub $s0 (func (param i32) (result i32)))) (type $f0 (sub $s0 (func (param i32) (result i32))))
@@ -772,7 +787,7 @@ @@ -772,7 +772,7 @@
"sub type" "sub type"
) )
@ -1262,29 +1005,3 @@ index 0b2d26f7..bdab6a01 100644
(table $t0 30 30 funcref) (table $t0 30 30 funcref)
(table $t1 30 30 funcref) (table $t1 30 30 funcref)
(elem (table $t1) (i32.const 2) func 3 1 4 1) (elem (table $t1) (i32.const 2) func 3 1 4 1)
diff --git a/test/core/unreached-valid.wast b/test/core/unreached-valid.wast
index f3feb0f3..d8ef8743 100644
--- a/test/core/unreached-valid.wast
+++ b/test/core/unreached-valid.wast
@@ -60,7 +60,7 @@
;; Validation after unreachable
-(module
+(;module
(func (export "meet-bottom")
(block (result f64)
(block (result f32)
@@ -76,7 +76,6 @@
(assert_trap (invoke "meet-bottom") "unreachable")
-
;; Bottom heap type
(module
@@ -106,3 +105,4 @@
(unreachable)
)
)
+;)