From 0921edd96ffc3390dba3049c9ba050fd8c93837c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 15 Nov 2024 21:06:11 -0800 Subject: [PATCH 1/3] Add the wasm-3.0 branch test suite to the sync script Update a few variables to handle that it's a branch of the `spec` repo itself. --- update-testsuite.sh | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/update-testsuite.sh b/update-testsuite.sh index 49dd07a..a8227b2 100755 --- a/update-testsuite.sh +++ b/update-testsuite.sh @@ -20,6 +20,7 @@ repos=' relaxed-simd custom-page-sizes wide-arithmetic + wasm-3.0 ' log_and_run() { @@ -44,18 +45,22 @@ popdir() { } update_repo() { - local repo=$1 + local dir=$1 + local branch=main + local repo=$dir + [ "${repo}" == "wasm-3.0" ] && branch="wasm-3.0" + [ "${repo}" == "wasm-3.0" ] && repo="spec" pushdir repos - if [ -d ${repo} ]; then - log_and_run git -C ${repo} fetch origin - log_and_run git -C ${repo} reset origin/HEAD --hard + if [ -d ${dir} ]; then + log_and_run git -C ${dir} fetch origin + log_and_run git -C ${dir} reset origin/${branch} --hard else - log_and_run git clone https://github.com/WebAssembly/${repo} + log_and_run git clone https://github.com/WebAssembly/${repo} ${dir} --branch ${branch} fi # Add upstream spec as "spec" remote. - if [ "${repo}" != "spec" ]; then - pushdir ${repo} + if [ "${dir}" != "spec" ]; then + pushdir ${dir} if ! git remote | grep spec >/dev/null; then log_and_run git remote add spec https://github.com/WebAssembly/spec fi @@ -80,6 +85,8 @@ merge_with_spec() { set_upstream ${repo} + [ "${repo}" == "wasm-3.0" ] && return + pushdir repos/${repo} # Create and checkout "try-merge" branch. if ! git branch | grep try-merge >/dev/null; then @@ -122,6 +129,7 @@ for repo in ${repos}; do continue fi + echo "++ updating222 ${repo}" if [ "${repo}" = "spec" ]; then wast_dir=. log_and_run cp $(find repos/${repo}/test/core -name \*.wast) ${wast_dir} @@ -165,10 +173,14 @@ for repo in ${repos}; do # Check whether any files were updated. if [ $(git status -s ${wast_dir} | wc -l) -ne 0 ]; then - log_and_run git add ${wast_dir}/*.wast - - repo_sha=$(git -C repos/${repo} log --max-count=1 --oneline origin/HEAD| sed -e 's/ .*//') - echo " ${repo}:" >> commit_message + log_and_run git add ${wast_dir} + + branch=main + dir=${repo} + [ "${repo}" == "wasm-3.0" ] && branch="wasm-3.0" + [ "${repo}" == "wasm-3.0" ] && repo="spec" + repo_sha=$(git -C repos/${dir} log --max-count=1 --oneline origin/$branch | sed -e 's/ .*//') + echo " ${dir}:" >> commit_message echo " https://github.com/WebAssembly/${repo}/commit/${repo_sha}" >> commit_message any_updated=1 fi From ea37baf47f1d7381adaabd55266e043f4cba39ab Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 15 Nov 2024 21:06:50 -0800 Subject: [PATCH 2/3] Update repos spec: https://github.com/WebAssembly/spec/commit/bd2aa85d memory64: https://github.com/WebAssembly/memory64/commit/334f93f9 custom-page-sizes: https://github.com/WebAssembly/custom-page-sizes/commit/ba05ecdd wasm-3.0: https://github.com/WebAssembly/spec/commit/90cbd509 This change was automatically generated by `update-testsuite.sh` --- .../custom-page-sizes-invalid.wast | 5 + .../custom-page-sizes/custom-page-sizes.wast | 30 + proposals/custom-page-sizes/memory_max.wast | 64 + proposals/memory64/memory.wast | 38 +- proposals/memory64/memory64.wast | 20 + proposals/memory64/table.wast | 10 +- proposals/{memory64 => wasm-3.0}/address.wast | 0 proposals/wasm-3.0/address0.wast | 212 +++ proposals/wasm-3.0/address1.wast | 295 ++++ .../{memory64 => wasm-3.0}/address64.wast | 0 proposals/wasm-3.0/align.wast | 964 ++++++++++ proposals/wasm-3.0/align0.wast | 43 + proposals/{memory64 => wasm-3.0}/align64.wast | 0 proposals/wasm-3.0/annotations.wast | 207 +++ proposals/wasm-3.0/array.wast | 315 ++++ proposals/wasm-3.0/array_copy.wast | 139 ++ proposals/wasm-3.0/array_fill.wast | 81 + proposals/wasm-3.0/array_init_data.wast | 110 ++ proposals/wasm-3.0/array_init_elem.wast | 108 ++ proposals/wasm-3.0/binary-gc.wast | 12 + .../{memory64 => wasm-3.0}/binary-leb128.wast | 0 proposals/{memory64 => wasm-3.0}/binary.wast | 0 proposals/{memory64 => wasm-3.0}/binary0.wast | 0 proposals/wasm-3.0/br_if.wast | 679 +++++++ proposals/wasm-3.0/br_on_cast.wast | 285 +++ proposals/wasm-3.0/br_on_cast_fail.wast | 300 ++++ proposals/wasm-3.0/br_on_non_null.wast | 90 + proposals/wasm-3.0/br_on_null.wast | 94 + proposals/wasm-3.0/br_table.wast | 1465 +++++++++++++++ .../{memory64 => wasm-3.0}/call_indirect.wast | 23 + proposals/wasm-3.0/call_ref.wast | 218 +++ proposals/wasm-3.0/data.wast | 525 ++++++ proposals/wasm-3.0/data0.wast | 73 + proposals/wasm-3.0/data1.wast | 146 ++ proposals/wasm-3.0/data_drop0.wast | 28 + proposals/wasm-3.0/elem.wast | 1110 ++++++++++++ .../{memory64 => wasm-3.0}/endianness64.wast | 0 proposals/wasm-3.0/exports.wast | 242 +++ proposals/wasm-3.0/exports0.wast | 51 + proposals/wasm-3.0/extern.wast | 54 + proposals/wasm-3.0/float_exprs0.wast | 38 + proposals/wasm-3.0/float_exprs1.wast | 105 ++ proposals/wasm-3.0/float_memory0.wast | 60 + .../float_memory64.wast | 0 proposals/wasm-3.0/func.wast | 988 +++++++++++ proposals/wasm-3.0/global.wast | 705 ++++++++ .../wasm-3.0/i16x8_relaxed_q15mulr_s.wast | 28 + proposals/wasm-3.0/i31.wast | 228 +++ proposals/wasm-3.0/i32x4_relaxed_trunc.wast | 124 ++ proposals/wasm-3.0/i8x16_relaxed_swizzle.wast | 45 + proposals/wasm-3.0/id.wast | 31 + proposals/wasm-3.0/if.wast | 1564 +++++++++++++++++ proposals/{memory64 => wasm-3.0}/imports.wast | 0 proposals/wasm-3.0/imports0.wast | 45 + proposals/wasm-3.0/imports1.wast | 16 + proposals/wasm-3.0/imports2.wast | 73 + proposals/wasm-3.0/imports3.wast | 75 + proposals/wasm-3.0/imports4.wast | 47 + proposals/wasm-3.0/instance.wast | 170 ++ proposals/wasm-3.0/legacy/rethrow.wast | 96 + proposals/wasm-3.0/legacy/throw.wast | 51 + proposals/wasm-3.0/legacy/try_catch.wast | 276 +++ proposals/wasm-3.0/legacy/try_delegate.wast | 244 +++ proposals/wasm-3.0/linking.wast | 610 +++++++ proposals/wasm-3.0/linking0.wast | 42 + proposals/wasm-3.0/linking1.wast | 65 + proposals/wasm-3.0/linking2.wast | 30 + proposals/wasm-3.0/linking3.wast | 83 + proposals/wasm-3.0/load.wast | 631 +++++++ proposals/wasm-3.0/load0.wast | 19 + proposals/wasm-3.0/load1.wast | 41 + proposals/wasm-3.0/load2.wast | 213 +++ proposals/{memory64 => wasm-3.0}/load64.wast | 0 proposals/wasm-3.0/local_get.wast | 225 +++ proposals/wasm-3.0/local_init.wast | 74 + proposals/wasm-3.0/local_tee.wast | 654 +++++++ proposals/wasm-3.0/memory-multi.wast | 42 + proposals/wasm-3.0/memory.wast | 277 +++ proposals/wasm-3.0/memory64.wast | 204 +++ .../{memory64 => wasm-3.0}/memory_copy.wast | 0 proposals/wasm-3.0/memory_copy0.wast | 60 + proposals/wasm-3.0/memory_copy1.wast | 40 + .../{memory64 => wasm-3.0}/memory_fill.wast | 0 proposals/wasm-3.0/memory_fill0.wast | 46 + proposals/wasm-3.0/memory_grow.wast | 535 ++++++ .../{memory64 => wasm-3.0}/memory_grow64.wast | 0 .../{memory64 => wasm-3.0}/memory_init.wast | 0 proposals/wasm-3.0/memory_init0.wast | 42 + .../memory_redundancy64.wast | 0 proposals/wasm-3.0/memory_size.wast | 111 ++ proposals/wasm-3.0/memory_size0.wast | 19 + proposals/wasm-3.0/memory_size1.wast | 29 + proposals/wasm-3.0/memory_size2.wast | 34 + proposals/wasm-3.0/memory_size3.wast | 25 + proposals/wasm-3.0/memory_trap0.wast | 36 + proposals/wasm-3.0/memory_trap1.wast | 250 +++ .../{memory64 => wasm-3.0}/memory_trap64.wast | 0 proposals/wasm-3.0/ref.wast | 80 + proposals/wasm-3.0/ref_as_non_null.wast | 46 + proposals/wasm-3.0/ref_cast.wast | 186 ++ proposals/wasm-3.0/ref_eq.wast | 168 ++ proposals/wasm-3.0/ref_is_null.wast | 85 + proposals/wasm-3.0/ref_null.wast | 81 + proposals/wasm-3.0/ref_test.wast | 330 ++++ proposals/wasm-3.0/relaxed_dot_product.wast | 107 ++ proposals/wasm-3.0/relaxed_laneselect.wast | 103 ++ proposals/wasm-3.0/relaxed_madd_nmadd.wast | 224 +++ proposals/wasm-3.0/relaxed_min_max.wast | 184 ++ proposals/wasm-3.0/return_call.wast | 210 +++ proposals/wasm-3.0/return_call_indirect.wast | 546 ++++++ proposals/wasm-3.0/return_call_ref.wast | 397 +++++ proposals/wasm-3.0/select.wast | 592 +++++++ .../{memory64 => wasm-3.0}/simd_address.wast | 0 proposals/wasm-3.0/simd_lane.wast | 1265 +++++++++++++ proposals/wasm-3.0/simd_memory-multi.wast | 42 + proposals/wasm-3.0/start0.wast | 42 + proposals/wasm-3.0/store.wast | 565 ++++++ proposals/wasm-3.0/store0.wast | 25 + proposals/wasm-3.0/store1.wast | 52 + proposals/wasm-3.0/struct.wast | 229 +++ proposals/wasm-3.0/table-sub.wast | 32 + proposals/wasm-3.0/table.wast | 186 ++ .../{memory64 => wasm-3.0}/table_copy.wast | 0 .../table_copy_mixed.wast | 0 .../{memory64 => wasm-3.0}/table_fill.wast | 0 .../{memory64 => wasm-3.0}/table_get.wast | 0 .../{memory64 => wasm-3.0}/table_grow.wast | 0 .../{memory64 => wasm-3.0}/table_init.wast | 0 .../{memory64 => wasm-3.0}/table_set.wast | 0 .../{memory64 => wasm-3.0}/table_size.wast | 0 proposals/wasm-3.0/tag.wast | 61 + proposals/wasm-3.0/throw.wast | 55 + proposals/wasm-3.0/throw_ref.wast | 118 ++ proposals/wasm-3.0/token.wast | 304 ++++ proposals/wasm-3.0/traps0.wast | 35 + proposals/wasm-3.0/try_table.wast | 468 +++++ proposals/wasm-3.0/type-canon.wast | 17 + proposals/wasm-3.0/type-equivalence.wast | 324 ++++ proposals/wasm-3.0/type-rec.wast | 158 ++ proposals/wasm-3.0/type-subtyping.wast | 833 +++++++++ proposals/wasm-3.0/unreached-invalid.wast | 782 +++++++++ proposals/wasm-3.0/unreached-valid.wast | 108 ++ 142 files changed, 26507 insertions(+), 15 deletions(-) create mode 100644 proposals/custom-page-sizes/memory_max.wast rename proposals/{memory64 => wasm-3.0}/address.wast (100%) create mode 100644 proposals/wasm-3.0/address0.wast create mode 100644 proposals/wasm-3.0/address1.wast rename proposals/{memory64 => wasm-3.0}/address64.wast (100%) create mode 100644 proposals/wasm-3.0/align.wast create mode 100644 proposals/wasm-3.0/align0.wast rename proposals/{memory64 => wasm-3.0}/align64.wast (100%) create mode 100644 proposals/wasm-3.0/annotations.wast create mode 100644 proposals/wasm-3.0/array.wast create mode 100644 proposals/wasm-3.0/array_copy.wast create mode 100644 proposals/wasm-3.0/array_fill.wast create mode 100644 proposals/wasm-3.0/array_init_data.wast create mode 100644 proposals/wasm-3.0/array_init_elem.wast create mode 100644 proposals/wasm-3.0/binary-gc.wast rename proposals/{memory64 => wasm-3.0}/binary-leb128.wast (100%) rename proposals/{memory64 => wasm-3.0}/binary.wast (100%) rename proposals/{memory64 => wasm-3.0}/binary0.wast (100%) create mode 100644 proposals/wasm-3.0/br_if.wast create mode 100644 proposals/wasm-3.0/br_on_cast.wast create mode 100644 proposals/wasm-3.0/br_on_cast_fail.wast create mode 100644 proposals/wasm-3.0/br_on_non_null.wast create mode 100644 proposals/wasm-3.0/br_on_null.wast create mode 100644 proposals/wasm-3.0/br_table.wast rename proposals/{memory64 => wasm-3.0}/call_indirect.wast (98%) create mode 100644 proposals/wasm-3.0/call_ref.wast create mode 100644 proposals/wasm-3.0/data.wast create mode 100644 proposals/wasm-3.0/data0.wast create mode 100644 proposals/wasm-3.0/data1.wast create mode 100644 proposals/wasm-3.0/data_drop0.wast create mode 100644 proposals/wasm-3.0/elem.wast rename proposals/{memory64 => wasm-3.0}/endianness64.wast (100%) create mode 100644 proposals/wasm-3.0/exports.wast create mode 100644 proposals/wasm-3.0/exports0.wast create mode 100644 proposals/wasm-3.0/extern.wast create mode 100644 proposals/wasm-3.0/float_exprs0.wast create mode 100644 proposals/wasm-3.0/float_exprs1.wast create mode 100644 proposals/wasm-3.0/float_memory0.wast rename proposals/{memory64 => wasm-3.0}/float_memory64.wast (100%) create mode 100644 proposals/wasm-3.0/func.wast create mode 100644 proposals/wasm-3.0/global.wast create mode 100644 proposals/wasm-3.0/i16x8_relaxed_q15mulr_s.wast create mode 100644 proposals/wasm-3.0/i31.wast create mode 100644 proposals/wasm-3.0/i32x4_relaxed_trunc.wast create mode 100644 proposals/wasm-3.0/i8x16_relaxed_swizzle.wast create mode 100644 proposals/wasm-3.0/id.wast create mode 100644 proposals/wasm-3.0/if.wast rename proposals/{memory64 => wasm-3.0}/imports.wast (100%) create mode 100644 proposals/wasm-3.0/imports0.wast create mode 100644 proposals/wasm-3.0/imports1.wast create mode 100644 proposals/wasm-3.0/imports2.wast create mode 100644 proposals/wasm-3.0/imports3.wast create mode 100644 proposals/wasm-3.0/imports4.wast create mode 100644 proposals/wasm-3.0/instance.wast create mode 100644 proposals/wasm-3.0/legacy/rethrow.wast create mode 100644 proposals/wasm-3.0/legacy/throw.wast create mode 100644 proposals/wasm-3.0/legacy/try_catch.wast create mode 100644 proposals/wasm-3.0/legacy/try_delegate.wast create mode 100644 proposals/wasm-3.0/linking.wast create mode 100644 proposals/wasm-3.0/linking0.wast create mode 100644 proposals/wasm-3.0/linking1.wast create mode 100644 proposals/wasm-3.0/linking2.wast create mode 100644 proposals/wasm-3.0/linking3.wast create mode 100644 proposals/wasm-3.0/load.wast create mode 100644 proposals/wasm-3.0/load0.wast create mode 100644 proposals/wasm-3.0/load1.wast create mode 100644 proposals/wasm-3.0/load2.wast rename proposals/{memory64 => wasm-3.0}/load64.wast (100%) create mode 100644 proposals/wasm-3.0/local_get.wast create mode 100644 proposals/wasm-3.0/local_init.wast create mode 100644 proposals/wasm-3.0/local_tee.wast create mode 100644 proposals/wasm-3.0/memory-multi.wast create mode 100644 proposals/wasm-3.0/memory.wast create mode 100644 proposals/wasm-3.0/memory64.wast rename proposals/{memory64 => wasm-3.0}/memory_copy.wast (100%) create mode 100644 proposals/wasm-3.0/memory_copy0.wast create mode 100644 proposals/wasm-3.0/memory_copy1.wast rename proposals/{memory64 => wasm-3.0}/memory_fill.wast (100%) create mode 100644 proposals/wasm-3.0/memory_fill0.wast create mode 100644 proposals/wasm-3.0/memory_grow.wast rename proposals/{memory64 => wasm-3.0}/memory_grow64.wast (100%) rename proposals/{memory64 => wasm-3.0}/memory_init.wast (100%) create mode 100644 proposals/wasm-3.0/memory_init0.wast rename proposals/{memory64 => wasm-3.0}/memory_redundancy64.wast (100%) create mode 100644 proposals/wasm-3.0/memory_size.wast create mode 100644 proposals/wasm-3.0/memory_size0.wast create mode 100644 proposals/wasm-3.0/memory_size1.wast create mode 100644 proposals/wasm-3.0/memory_size2.wast create mode 100644 proposals/wasm-3.0/memory_size3.wast create mode 100644 proposals/wasm-3.0/memory_trap0.wast create mode 100644 proposals/wasm-3.0/memory_trap1.wast rename proposals/{memory64 => wasm-3.0}/memory_trap64.wast (100%) create mode 100644 proposals/wasm-3.0/ref.wast create mode 100644 proposals/wasm-3.0/ref_as_non_null.wast create mode 100644 proposals/wasm-3.0/ref_cast.wast create mode 100644 proposals/wasm-3.0/ref_eq.wast create mode 100644 proposals/wasm-3.0/ref_is_null.wast create mode 100644 proposals/wasm-3.0/ref_null.wast create mode 100644 proposals/wasm-3.0/ref_test.wast create mode 100644 proposals/wasm-3.0/relaxed_dot_product.wast create mode 100644 proposals/wasm-3.0/relaxed_laneselect.wast create mode 100644 proposals/wasm-3.0/relaxed_madd_nmadd.wast create mode 100644 proposals/wasm-3.0/relaxed_min_max.wast create mode 100644 proposals/wasm-3.0/return_call.wast create mode 100644 proposals/wasm-3.0/return_call_indirect.wast create mode 100644 proposals/wasm-3.0/return_call_ref.wast create mode 100644 proposals/wasm-3.0/select.wast rename proposals/{memory64 => wasm-3.0}/simd_address.wast (100%) create mode 100644 proposals/wasm-3.0/simd_lane.wast create mode 100644 proposals/wasm-3.0/simd_memory-multi.wast create mode 100644 proposals/wasm-3.0/start0.wast create mode 100644 proposals/wasm-3.0/store.wast create mode 100644 proposals/wasm-3.0/store0.wast create mode 100644 proposals/wasm-3.0/store1.wast create mode 100644 proposals/wasm-3.0/struct.wast create mode 100644 proposals/wasm-3.0/table-sub.wast create mode 100644 proposals/wasm-3.0/table.wast rename proposals/{memory64 => wasm-3.0}/table_copy.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_copy_mixed.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_fill.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_get.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_grow.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_init.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_set.wast (100%) rename proposals/{memory64 => wasm-3.0}/table_size.wast (100%) create mode 100644 proposals/wasm-3.0/tag.wast create mode 100644 proposals/wasm-3.0/throw.wast create mode 100644 proposals/wasm-3.0/throw_ref.wast create mode 100644 proposals/wasm-3.0/token.wast create mode 100644 proposals/wasm-3.0/traps0.wast create mode 100644 proposals/wasm-3.0/try_table.wast create mode 100644 proposals/wasm-3.0/type-canon.wast create mode 100644 proposals/wasm-3.0/type-equivalence.wast create mode 100644 proposals/wasm-3.0/type-rec.wast create mode 100644 proposals/wasm-3.0/type-subtyping.wast create mode 100644 proposals/wasm-3.0/unreached-invalid.wast create mode 100644 proposals/wasm-3.0/unreached-valid.wast diff --git a/proposals/custom-page-sizes/custom-page-sizes-invalid.wast b/proposals/custom-page-sizes/custom-page-sizes-invalid.wast index 80cbcff..480d385 100644 --- a/proposals/custom-page-sizes/custom-page-sizes-invalid.wast +++ b/proposals/custom-page-sizes/custom-page-sizes-invalid.wast @@ -4,6 +4,11 @@ "invalid custom page size" ) +(assert_malformed + (module quote "(memory 0 (pagesize 0))") + "invalid custom page size" +) + ;; Power-of-two page sizes that are not 1 or 64KiB. (assert_invalid (module (memory 0 (pagesize 2))) diff --git a/proposals/custom-page-sizes/custom-page-sizes.wast b/proposals/custom-page-sizes/custom-page-sizes.wast index b312f1f..e7e8b68 100644 --- a/proposals/custom-page-sizes/custom-page-sizes.wast +++ b/proposals/custom-page-sizes/custom-page-sizes.wast @@ -106,3 +106,33 @@ (module (memory (import "m" "large-pages-memory") 0 (pagesize 65536)) ) + +;; Inline data segments + +;; pagesize 0 +(assert_malformed (module quote "(memory (pagesize 0) (data))") "invalid custom page size") + +;; pagesize 1 +(module + (memory (pagesize 1) (data "xyz")) + (func (export "size") (result i32) + memory.size) + (func (export "grow") (param i32) (result i32) + (memory.grow (local.get 0))) + (func (export "load") (param i32) (result i32) + (i32.load8_u (local.get 0)))) + +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "load" (i32.const 0)) (i32.const 120)) +(assert_return (invoke "load" (i32.const 1)) (i32.const 121)) +(assert_return (invoke "load" (i32.const 2)) (i32.const 122)) +(assert_trap (invoke "load" (i32.const 3)) "out of bounds") +(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) + +;; pagesize 65536 +(module + (memory (pagesize 65536) (data "xyz")) + (func (export "size") (result i32) + memory.size)) + +(assert_return (invoke "size") (i32.const 1)) diff --git a/proposals/custom-page-sizes/memory_max.wast b/proposals/custom-page-sizes/memory_max.wast new file mode 100644 index 0000000..7e0fdc0 --- /dev/null +++ b/proposals/custom-page-sizes/memory_max.wast @@ -0,0 +1,64 @@ +;; Maximum memory sizes. +;; +;; These modules are valid, but instantiating them is unnecessary +;; and would only allocate very large memories and slow down running +;; the spec tests. Therefore, add a missing import so that it cannot +;; be instantiated and use `assert_unlinkable`. This approach +;; enforces that the module itself is still valid, but that its +;; instantiation fails early (hopefully before any memories are +;; actually allocated). + +;; i32 (pagesize 1) +(assert_unlinkable + (module + (import "test" "unknown" (func)) + (memory 0xFFFF_FFFF (pagesize 1))) + "unknown import") + +;; i64 (pagesize 1) +(assert_unlinkable + (module + (import "test" "import" (func)) + (memory i64 0xFFFF_FFFF_FFFF_FFFF (pagesize 1))) + "unknown import") + +;; i32 (default pagesize) +(assert_unlinkable + (module + (import "test" "unknown" (func)) + (memory 65536 (pagesize 65536))) + "unknown import") + +;; i64 (default pagesize) +(assert_unlinkable + (module + (import "test" "unknown" (func)) + (memory i64 0x1_0000_0000_0000 (pagesize 65536))) + "unknown import") + +;; Memory size just over the maximum. +;; +;; These are malformed (for pagesize 1) +;; or invalid (for other pagesizes). + +;; i32 (pagesize 1) +(assert_malformed + (module quote "(memory 0x1_0000_0000 (pagesize 1))") + "constant out of range") + +;; i64 (pagesize 1) +(assert_malformed + (module quote "(memory i64 0x1_0000_0000_0000_0000 (pagesize 1))") + "constant out of range") + +;; i32 (default pagesize) +(assert_invalid + (module + (memory 65537 (pagesize 65536))) + "memory size must be at most") + +;; i64 (default pagesize) +(assert_invalid + (module + (memory i64 0x1_0000_0000_0001 (pagesize 65536))) + "memory size must be at most") diff --git a/proposals/memory64/memory.wast b/proposals/memory64/memory.wast index 1c57a8f..8ae51ec 100644 --- a/proposals/memory64/memory.wast +++ b/proposals/memory64/memory.wast @@ -5,6 +5,7 @@ (module (memory 0 0)) (module (memory 0 1)) (module (memory 1 256)) +(module definition (memory 65536)) (module (memory 0 65536)) (module (memory (data)) (func (export "memsize") (result i32) (memory.size))) @@ -50,40 +51,53 @@ ) (assert_invalid (module (memory 65537)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid (module (memory 2147483648)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid (module (memory 4294967295)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid (module (memory 0 65537)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid (module (memory 0 2147483648)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid (module (memory 0 4294967295)) - "memory size must be at most 65536 pages (4GiB)" + "memory size" ) (assert_invalid - (module quote "(memory 0x1_0000_0000)") - "memory size must be at most 65536 pages (4GiB)" + (module (memory 0x1_0000_0000)) + "memory size" ) (assert_invalid - (module quote "(memory 0x1_0000_0000 0x1_0000_0000)") - "memory size must be at most 65536 pages (4GiB)" + (module (memory 0x1_0000_0000 0x1_0000_0000)) + "memory size" ) (assert_invalid - (module quote "(memory 0 0x1_0000_0000)") - "memory size must be at most 65536 pages (4GiB)" + (module (memory 0 0x1_0000_0000)) + "memory size" +) + +(assert_invalid + (module (memory (import "M" "m") 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") 0x1_0000_0000 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") 0 0x1_0000_0000)) + "memory size" ) (module diff --git a/proposals/memory64/memory64.wast b/proposals/memory64/memory64.wast index 41e1bf0..b9d9ed9 100644 --- a/proposals/memory64/memory64.wast +++ b/proposals/memory64/memory64.wast @@ -5,6 +5,8 @@ (module (memory i64 0 1)) (module (memory i64 1 256)) (module (memory i64 0 65536)) +(module definition (memory i64 0x1_0000_0000_0000)) +(module (memory i64 0 0x1_0000_0000_0000)) (module (memory i64 (data)) (func (export "memsize") (result i64) (memory.size))) (assert_return (invoke "memsize") (i64.const 0)) @@ -48,6 +50,24 @@ "size minimum must not be greater than maximum" ) +(assert_invalid + (module (memory i64 0x1_0000_0000_0001)) + "memory size" +) +(assert_invalid + (module (memory i64 0 0x1_0000_0000_0001)) + "memory size" +) + +(assert_invalid + (module (memory (import "M" "m") i64 0x1_0000_0000_0001)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") i64 0 0x1_0000_0000_0001)) + "memory size" +) + (module (memory i64 1) (data (i64.const 0) "ABC\a7D") (data (i64.const 20) "WASM") diff --git a/proposals/memory64/table.wast b/proposals/memory64/table.wast index 8648df0..56baa19 100644 --- a/proposals/memory64/table.wast +++ b/proposals/memory64/table.wast @@ -6,6 +6,7 @@ (module (table 0 1 funcref)) (module (table 1 256 funcref)) (module (table 0 65536 funcref)) +(module definition (table 0xffff_ffff funcref)) (module (table 0 0xffff_ffff funcref)) (module (table 1 (ref null func))) @@ -33,15 +34,15 @@ (assert_invalid (module quote "(table 0x1_0000_0000 funcref)") - "table size must be at most 2^32-1" + "table size" ) (assert_invalid (module quote "(table 0x1_0000_0000 0x1_0000_0000 funcref)") - "table size must be at most 2^32-1" + "table size" ) (assert_invalid (module quote "(table 0 0x1_0000_0000 funcref)") - "table size must be at most 2^32-1" + "table size" ) ;; Same as above but with i64 address types @@ -53,6 +54,9 @@ (module (table i64 1 256 funcref)) (module (table i64 0 65536 funcref)) (module (table i64 0 0xffff_ffff funcref)) +(module (table i64 0 0x1_0000_0000 funcref)) +(module definition (table i64 0xffff_ffff_ffff_ffff funcref)) +(module (table i64 0 0xffff_ffff_ffff_ffff funcref)) (module (table i64 0 funcref) (table i64 0 funcref)) (module (table (import "spectest" "table64") i64 0 funcref) (table i64 0 funcref)) diff --git a/proposals/memory64/address.wast b/proposals/wasm-3.0/address.wast similarity index 100% rename from proposals/memory64/address.wast rename to proposals/wasm-3.0/address.wast diff --git a/proposals/wasm-3.0/address0.wast b/proposals/wasm-3.0/address0.wast new file mode 100644 index 0000000..a022365 --- /dev/null +++ b/proposals/wasm-3.0/address0.wast @@ -0,0 +1,212 @@ +;; Load i32 data with different offset/align arguments + +(module + (memory $mem0 0) + (memory $mem1 1) + (data (memory $mem1) (i32.const 0) "abcdefghijklmnopqrstuvwxyz") + + (func (export "8u_good1") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good2") (param $i i32) (result i32) + (i32.load8_u $mem1 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good3") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8u_good4") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8u_good5") (param $i i32) (result i32) + (i32.load8_u $mem1 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "8s_good1") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good2") (param $i i32) (result i32) + (i32.load8_s $mem1 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good3") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8s_good4") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8s_good5") (param $i i32) (result i32) + (i32.load8_s $mem1 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "16u_good1") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good2") (param $i i32) (result i32) + (i32.load16_u $mem1 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good3") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16u_good4") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16u_good5") (param $i i32) (result i32) + (i32.load16_u $mem1 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "16s_good1") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good2") (param $i i32) (result i32) + (i32.load16_s $mem1 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good3") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16s_good4") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16s_good5") (param $i i32) (result i32) + (i32.load16_s $mem1 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "32_good1") (param $i i32) (result i32) + (i32.load $mem1 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32_good2") (param $i i32) (result i32) + (i32.load $mem1 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32_good3") (param $i i32) (result i32) + (i32.load $mem1 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32_good4") (param $i i32) (result i32) + (i32.load $mem1 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32_good5") (param $i i32) (result i32) + (i32.load $mem1 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "8u_bad") (param $i i32) + (drop (i32.load8_u $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "8s_bad") (param $i i32) + (drop (i32.load8_s $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "16u_bad") (param $i i32) + (drop (i32.load16_u $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "16s_bad") (param $i i32) + (drop (i32.load16_s $mem1 offset=4294967295 (local.get $i))) + ) + (func (export "32_bad") (param $i i32) + (drop (i32.load $mem1 offset=4294967295 (local.get $i))) + ) +) + +(assert_return (invoke "8u_good1" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8u_good2" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8u_good3" (i32.const 0)) (i32.const 98)) +(assert_return (invoke "8u_good4" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "8u_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "8s_good1" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8s_good2" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "8s_good3" (i32.const 0)) (i32.const 98)) +(assert_return (invoke "8s_good4" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "8s_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "16u_good1" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16u_good2" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16u_good3" (i32.const 0)) (i32.const 25442)) +(assert_return (invoke "16u_good4" (i32.const 0)) (i32.const 25699)) +(assert_return (invoke "16u_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "16s_good1" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16s_good2" (i32.const 0)) (i32.const 25185)) +(assert_return (invoke "16s_good3" (i32.const 0)) (i32.const 25442)) +(assert_return (invoke "16s_good4" (i32.const 0)) (i32.const 25699)) +(assert_return (invoke "16s_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "32_good1" (i32.const 0)) (i32.const 1684234849)) +(assert_return (invoke "32_good2" (i32.const 0)) (i32.const 1684234849)) +(assert_return (invoke "32_good3" (i32.const 0)) (i32.const 1701077858)) +(assert_return (invoke "32_good4" (i32.const 0)) (i32.const 1717920867)) +(assert_return (invoke "32_good5" (i32.const 0)) (i32.const 122)) + +(assert_return (invoke "8u_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "32_good1" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good2" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good3" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good4" (i32.const 65507)) (i32.const 0)) +(assert_return (invoke "32_good5" (i32.const 65507)) (i32.const 0)) + +(assert_return (invoke "8u_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65508)) (i32.const 0)) + +(assert_return (invoke "32_good1" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good2" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good3" (i32.const 65508)) (i32.const 0)) +(assert_return (invoke "32_good4" (i32.const 65508)) (i32.const 0)) +(assert_trap (invoke "32_good5" (i32.const 65508)) "out of bounds memory access") + +(assert_trap (invoke "8u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "8s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32_good3" (i32.const -1)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32_bad" (i32.const 0)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "32_bad" (i32.const 1)) "out of bounds memory access") diff --git a/proposals/wasm-3.0/address1.wast b/proposals/wasm-3.0/address1.wast new file mode 100644 index 0000000..d43d647 --- /dev/null +++ b/proposals/wasm-3.0/address1.wast @@ -0,0 +1,295 @@ +;; Load i64 data with different offset/align arguments + +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 0) + (memory $mem3 0) + (memory $mem4 1) + (data (memory $mem4) (i32.const 0) "abcdefghijklmnopqrstuvwxyz") + + (func (export "8u_good1") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good2") (param $i i32) (result i64) + (i64.load8_u $mem4 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8u_good3") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8u_good4") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8u_good5") (param $i i32) (result i64) + (i64.load8_u $mem4 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "8s_good1") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=0 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good2") (param $i i32) (result i64) + (i64.load8_s $mem4 align=1 (local.get $i)) ;; 97 'a' + ) + (func (export "8s_good3") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=1 align=1 (local.get $i)) ;; 98 'b' + ) + (func (export "8s_good4") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=2 align=1 (local.get $i)) ;; 99 'c' + ) + (func (export "8s_good5") (param $i i32) (result i64) + (i64.load8_s $mem4 offset=25 align=1 (local.get $i)) ;; 122 'z' + ) + + (func (export "16u_good1") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good2") (param $i i32) (result i64) + (i64.load16_u $mem4 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16u_good3") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16u_good4") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16u_good5") (param $i i32) (result i64) + (i64.load16_u $mem4 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "16s_good1") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=0 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good2") (param $i i32) (result i64) + (i64.load16_s $mem4 align=1 (local.get $i)) ;; 25185 'ab' + ) + (func (export "16s_good3") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=1 align=1 (local.get $i)) ;; 25442 'bc' + ) + (func (export "16s_good4") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=2 align=2 (local.get $i)) ;; 25699 'cd' + ) + (func (export "16s_good5") (param $i i32) (result i64) + (i64.load16_s $mem4 offset=25 align=2 (local.get $i)) ;; 122 'z\0' + ) + + (func (export "32u_good1") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32u_good2") (param $i i32) (result i64) + (i64.load32_u $mem4 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32u_good3") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32u_good4") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32u_good5") (param $i i32) (result i64) + (i64.load32_u $mem4 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "32s_good1") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=0 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32s_good2") (param $i i32) (result i64) + (i64.load32_s $mem4 align=1 (local.get $i)) ;; 1684234849 'abcd' + ) + (func (export "32s_good3") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=1 align=1 (local.get $i)) ;; 1701077858 'bcde' + ) + (func (export "32s_good4") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=2 align=2 (local.get $i)) ;; 1717920867 'cdef' + ) + (func (export "32s_good5") (param $i i32) (result i64) + (i64.load32_s $mem4 offset=25 align=4 (local.get $i)) ;; 122 'z\0\0\0' + ) + + (func (export "64_good1") (param $i i32) (result i64) + (i64.load $mem4 offset=0 (local.get $i)) ;; 0x6867666564636261 'abcdefgh' + ) + (func (export "64_good2") (param $i i32) (result i64) + (i64.load $mem4 align=1 (local.get $i)) ;; 0x6867666564636261 'abcdefgh' + ) + (func (export "64_good3") (param $i i32) (result i64) + (i64.load $mem4 offset=1 align=1 (local.get $i)) ;; 0x6968676665646362 'bcdefghi' + ) + (func (export "64_good4") (param $i i32) (result i64) + (i64.load $mem4 offset=2 align=2 (local.get $i)) ;; 0x6a69686766656463 'cdefghij' + ) + (func (export "64_good5") (param $i i32) (result i64) + (i64.load $mem4 offset=25 align=8 (local.get $i)) ;; 122 'z\0\0\0\0\0\0\0' + ) + + (func (export "8u_bad") (param $i i32) + (drop (i64.load8_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "8s_bad") (param $i i32) + (drop (i64.load8_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "16u_bad") (param $i i32) + (drop (i64.load16_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "16s_bad") (param $i i32) + (drop (i64.load16_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "32u_bad") (param $i i32) + (drop (i64.load32_u $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "32s_bad") (param $i i32) + (drop (i64.load32_s $mem4 offset=4294967295 (local.get $i))) + ) + (func (export "64_bad") (param $i i32) + (drop (i64.load $mem4 offset=4294967295 (local.get $i))) + ) +) + +(assert_return (invoke "8u_good1" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8u_good2" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8u_good3" (i32.const 0)) (i64.const 98)) +(assert_return (invoke "8u_good4" (i32.const 0)) (i64.const 99)) +(assert_return (invoke "8u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "8s_good1" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8s_good2" (i32.const 0)) (i64.const 97)) +(assert_return (invoke "8s_good3" (i32.const 0)) (i64.const 98)) +(assert_return (invoke "8s_good4" (i32.const 0)) (i64.const 99)) +(assert_return (invoke "8s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "16u_good1" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16u_good2" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16u_good3" (i32.const 0)) (i64.const 25442)) +(assert_return (invoke "16u_good4" (i32.const 0)) (i64.const 25699)) +(assert_return (invoke "16u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "16s_good1" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16s_good2" (i32.const 0)) (i64.const 25185)) +(assert_return (invoke "16s_good3" (i32.const 0)) (i64.const 25442)) +(assert_return (invoke "16s_good4" (i32.const 0)) (i64.const 25699)) +(assert_return (invoke "16s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "32u_good1" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32u_good2" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32u_good3" (i32.const 0)) (i64.const 1701077858)) +(assert_return (invoke "32u_good4" (i32.const 0)) (i64.const 1717920867)) +(assert_return (invoke "32u_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "32s_good1" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32s_good2" (i32.const 0)) (i64.const 1684234849)) +(assert_return (invoke "32s_good3" (i32.const 0)) (i64.const 1701077858)) +(assert_return (invoke "32s_good4" (i32.const 0)) (i64.const 1717920867)) +(assert_return (invoke "32s_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "64_good1" (i32.const 0)) (i64.const 0x6867666564636261)) +(assert_return (invoke "64_good2" (i32.const 0)) (i64.const 0x6867666564636261)) +(assert_return (invoke "64_good3" (i32.const 0)) (i64.const 0x6968676665646362)) +(assert_return (invoke "64_good4" (i32.const 0)) (i64.const 0x6a69686766656463)) +(assert_return (invoke "64_good5" (i32.const 0)) (i64.const 122)) + +(assert_return (invoke "8u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "32u_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32u_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "32s_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "32s_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "64_good1" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good2" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good3" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good4" (i32.const 65503)) (i64.const 0)) +(assert_return (invoke "64_good5" (i32.const 65503)) (i64.const 0)) + +(assert_return (invoke "8u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "8s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "8s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "16u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "16s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "16s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "32u_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32u_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "32s_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good4" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "32s_good5" (i32.const 65504)) (i64.const 0)) + +(assert_return (invoke "64_good1" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good2" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good3" (i32.const 65504)) (i64.const 0)) +(assert_return (invoke "64_good4" (i32.const 65504)) (i64.const 0)) +(assert_trap (invoke "64_good5" (i32.const 65504)) "out of bounds memory access") + +(assert_trap (invoke "8u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "8s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "16s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32u_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "32s_good3" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "64_good3" (i32.const -1)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "64_bad" (i32.const 0)) "out of bounds memory access") + +(assert_trap (invoke "8u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "8s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16u_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "16s_bad" (i32.const 1)) "out of bounds memory access") +(assert_trap (invoke "32u_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "32s_bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "64_bad" (i32.const 1)) "out of bounds memory access") + diff --git a/proposals/memory64/address64.wast b/proposals/wasm-3.0/address64.wast similarity index 100% rename from proposals/memory64/address64.wast rename to proposals/wasm-3.0/address64.wast diff --git a/proposals/wasm-3.0/align.wast b/proposals/wasm-3.0/align.wast new file mode 100644 index 0000000..91331f9 --- /dev/null +++ b/proposals/wasm-3.0/align.wast @@ -0,0 +1,964 @@ +;; Test alignment annotation rules + +(module (memory 0) (func (drop (i32.load8_s align=1 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load8_u align=1 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load16_s align=2 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load16_u align=2 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load align=4 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load8_s align=1 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load8_u align=1 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load16_s align=2 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load16_u align=2 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load32_s align=4 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load32_u align=4 (i32.const 0))))) +(module (memory 0) (func (drop (i64.load align=8 (i32.const 0))))) +(module (memory 0) (func (drop (f32.load align=4 (i32.const 0))))) +(module (memory 0) (func (drop (f64.load align=8 (i32.const 0))))) +(module (memory 0) (func (i32.store8 align=1 (i32.const 0) (i32.const 1)))) +(module (memory 0) (func (i32.store16 align=2 (i32.const 0) (i32.const 1)))) +(module (memory 0) (func (i32.store align=4 (i32.const 0) (i32.const 1)))) +(module (memory 0) (func (i64.store8 align=1 (i32.const 0) (i64.const 1)))) +(module (memory 0) (func (i64.store16 align=2 (i32.const 0) (i64.const 1)))) +(module (memory 0) (func (i64.store32 align=4 (i32.const 0) (i64.const 1)))) +(module (memory 0) (func (i64.store align=8 (i32.const 0) (i64.const 1)))) +(module (memory 0) (func (f32.store align=4 (i32.const 0) (f32.const 1.0)))) +(module (memory 0) (func (f64.store align=8 (i32.const 0) (f64.const 1.0)))) + +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load8_s align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load8_s align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load8_u align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load8_u align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load16_s align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load16_s align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load16_u align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load16_u align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i32.load align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load8_s align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load8_s align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load8_u align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load8_u align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load16_s align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load16_s align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load16_u align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load16_u align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load32_s align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load32_s align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load32_u align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load32_u align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (i64.load align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (f32.load align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (f32.load align=7 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (f64.load align=0 (i32.const 0)))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (drop (f64.load align=7 (i32.const 0)))))" + ) + "alignment" +) + +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store8 align=0 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store8 align=7 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store16 align=0 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store16 align=7 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store align=0 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i32.store align=7 (i32.const 0) (i32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store8 align=0 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store8 align=7 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store16 align=0 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store16 align=7 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store32 align=0 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store32 align=7 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store align=0 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (i64.store align=7 (i32.const 0) (i64.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (f32.store align=0 (i32.const 0) (f32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (f32.store align=7 (i32.const 0) (f32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (f64.store align=0 (i32.const 0) (f32.const 0))))" + ) + "alignment" +) +(assert_malformed + (module quote + "(module (memory 0) (func (f64.store align=7 (i32.const 0) (f32.const 0))))" + ) + "alignment" +) + +(assert_invalid + (module (memory 0) (func (drop (i32.load8_s align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load8_u align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load16_s align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load16_u align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load8_s align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load8_u align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load16_s align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load16_u align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load32_s align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load32_u align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load align=16 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (f32.load align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (f64.load align=16 (i32.const 0))))) + "alignment must not be larger than natural" +) + +(assert_invalid + (module (memory 0) (func (drop (i32.load8_s align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load8_u align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load16_s align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load16_u align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i32.load align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load8_s align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load8_u align=2 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load16_s align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load16_u align=4 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load32_s align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load32_u align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (i64.load align=16 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (f32.load align=8 (i32.const 0))))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (drop (f64.load align=16 (i32.const 0))))) + "alignment must not be larger than natural" +) + +(assert_invalid + (module (memory 0) (func (i32.store8 align=2 (i32.const 0) (i32.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i32.store16 align=4 (i32.const 0) (i32.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i32.store align=8 (i32.const 0) (i32.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i64.store8 align=2 (i32.const 0) (i64.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i64.store16 align=4 (i32.const 0) (i64.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i64.store32 align=8 (i32.const 0) (i64.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (i64.store align=16 (i32.const 0) (i64.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (f32.store align=8 (i32.const 0) (f32.const 0)))) + "alignment must not be larger than natural" +) +(assert_invalid + (module (memory 0) (func (f64.store align=16 (i32.const 0) (f64.const 0)))) + "alignment must not be larger than natural" +) + +;; Test aligned and unaligned read/write + +(module + (memory 1) + + ;; $default: natural alignment, $1: align=1, $2: align=2, $4: align=4, $8: align=8 + + (func (export "f32_align_switch") (param i32) (result f32) + (local f32 f32) + (local.set 1 (f32.const 10.0)) + (block $4 + (block $2 + (block $1 + (block $default + (block $0 + (br_table $0 $default $1 $2 $4 (local.get 0)) + ) ;; 0 + (f32.store (i32.const 0) (local.get 1)) + (local.set 2 (f32.load (i32.const 0))) + (br $4) + ) ;; default + (f32.store align=1 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load align=1 (i32.const 0))) + (br $4) + ) ;; 1 + (f32.store align=2 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load align=2 (i32.const 0))) + (br $4) + ) ;; 2 + (f32.store align=4 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load align=4 (i32.const 0))) + ) ;; 4 + (local.get 2) + ) + + (func (export "f64_align_switch") (param i32) (result f64) + (local f64 f64) + (local.set 1 (f64.const 10.0)) + (block $8 + (block $4 + (block $2 + (block $1 + (block $default + (block $0 + (br_table $0 $default $1 $2 $4 $8 (local.get 0)) + ) ;; 0 + (f64.store (i32.const 0) (local.get 1)) + (local.set 2 (f64.load (i32.const 0))) + (br $8) + ) ;; default + (f64.store align=1 (i32.const 0) (local.get 1)) + (local.set 2 (f64.load align=1 (i32.const 0))) + (br $8) + ) ;; 1 + (f64.store align=2 (i32.const 0) (local.get 1)) + (local.set 2 (f64.load align=2 (i32.const 0))) + (br $8) + ) ;; 2 + (f64.store align=4 (i32.const 0) (local.get 1)) + (local.set 2 (f64.load align=4 (i32.const 0))) + (br $8) + ) ;; 4 + (f64.store align=8 (i32.const 0) (local.get 1)) + (local.set 2 (f64.load align=8 (i32.const 0))) + ) ;; 8 + (local.get 2) + ) + + ;; $8s: i32/i64.load8_s, $8u: i32/i64.load8_u, $16s: i32/i64.load16_s, $16u: i32/i64.load16_u, $32: i32.load + ;; $32s: i64.load32_s, $32u: i64.load32_u, $64: i64.load + + (func (export "i32_align_switch") (param i32 i32) (result i32) + (local i32 i32) + (local.set 2 (i32.const 10)) + (block $32 + (block $16u + (block $16s + (block $8u + (block $8s + (block $0 + (br_table $0 $8s $8u $16s $16u $32 (local.get 0)) + ) ;; 0 + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i32.store8 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load8_s (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i32.store8 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load8_s align=1 (i32.const 0))) + ) + ) + (br $32) + ) ;; 8s + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i32.store8 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load8_u (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i32.store8 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load8_u align=1 (i32.const 0))) + ) + ) + (br $32) + ) ;; 8u + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i32.store16 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_s (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i32.store16 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_s align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i32.store16 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_s align=2 (i32.const 0))) + ) + ) + (br $32) + ) ;; 16s + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i32.store16 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_u (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i32.store16 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_u align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i32.store16 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load16_u align=2 (i32.const 0))) + ) + ) + (br $32) + ) ;; 16u + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i32.store (i32.const 0) (local.get 2)) + (local.set 3 (i32.load (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i32.store align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i32.store align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load align=2 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 4)) + (then + (i32.store align=4 (i32.const 0) (local.get 2)) + (local.set 3 (i32.load align=4 (i32.const 0))) + ) + ) + ) ;; 32 + (local.get 3) + ) + + (func (export "i64_align_switch") (param i32 i32) (result i64) + (local i64 i64) + (local.set 2 (i64.const 10)) + (block $64 + (block $32u + (block $32s + (block $16u + (block $16s + (block $8u + (block $8s + (block $0 + (br_table $0 $8s $8u $16s $16u $32s $32u $64 (local.get 0)) + ) ;; 0 + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store8 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load8_s (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store8 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load8_s align=1 (i32.const 0))) + ) + ) + (br $64) + ) ;; 8s + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store8 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load8_u (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store8 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load8_u align=1 (i32.const 0))) + ) + ) + (br $64) + ) ;; 8u + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store16 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_s (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store16 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_s align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i64.store16 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_s align=2 (i32.const 0))) + ) + ) + (br $64) + ) ;; 16s + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store16 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_u (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store16 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_u align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i64.store16 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load16_u align=2 (i32.const 0))) + ) + ) + (br $64) + ) ;; 16u + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store32 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_s (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store32 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_s align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i64.store32 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_s align=2 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 4)) + (then + (i64.store32 align=4 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_s align=4 (i32.const 0))) + ) + ) + (br $64) + ) ;; 32s + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store32 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_u (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store32 align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_u align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i64.store32 align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_u align=2 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 4)) + (then + (i64.store32 align=4 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load32_u align=4 (i32.const 0))) + ) + ) + (br $64) + ) ;; 32u + (if (i32.eq (local.get 1) (i32.const 0)) + (then + (i64.store (i32.const 0) (local.get 2)) + (local.set 3 (i64.load (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 1)) + (then + (i64.store align=1 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load align=1 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 2)) + (then + (i64.store align=2 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load align=2 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 4)) + (then + (i64.store align=4 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load align=4 (i32.const 0))) + ) + ) + (if (i32.eq (local.get 1) (i32.const 8)) + (then + (i64.store align=8 (i32.const 0) (local.get 2)) + (local.set 3 (i64.load align=8 (i32.const 0))) + ) + ) + ) ;; 64 + (local.get 3) + ) +) + +(assert_return (invoke "f32_align_switch" (i32.const 0)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 1)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 2)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 3)) (f32.const 10.0)) + +(assert_return (invoke "f64_align_switch" (i32.const 0)) (f64.const 10.0)) +(assert_return (invoke "f64_align_switch" (i32.const 1)) (f64.const 10.0)) +(assert_return (invoke "f64_align_switch" (i32.const 2)) (f64.const 10.0)) +(assert_return (invoke "f64_align_switch" (i32.const 3)) (f64.const 10.0)) +(assert_return (invoke "f64_align_switch" (i32.const 4)) (f64.const 10.0)) + +(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 0) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 1) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 2) (i32.const 2)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 3) (i32.const 2)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 2)) (i32.const 10)) +(assert_return (invoke "i32_align_switch" (i32.const 4) (i32.const 4)) (i32.const 10)) + +(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 0) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 1) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 2) (i32.const 2)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 3) (i32.const 2)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 2)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 4) (i32.const 4)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 2)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 5) (i32.const 4)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 0)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 1)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 2)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 4)) (i64.const 10)) +(assert_return (invoke "i64_align_switch" (i32.const 6) (i32.const 8)) (i64.const 10)) + +;; Test that an i64 store with 4-byte alignment that's 4 bytes out of bounds traps without storing anything + +(module + (memory 1) + (func (export "store") (param i32 i64) + (i64.store align=4 (local.get 0) (local.get 1)) + ) + (func (export "load") (param i32) (result i32) + (i32.load (local.get 0)) + ) +) + +(assert_trap (invoke "store" (i32.const 65532) (i64.const -1)) "out of bounds memory access") +;; No memory was changed +(assert_return (invoke "load" (i32.const 65532)) (i32.const 0)) + +;; Test invalid alignment values that may cause overflow when parsed. +;; These use the binary format, because it stores alignment as a base-2 exponent. + +;; Signed 32-bit overflow +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\1f\00" ;; i32.load offset=0 align=2**31 + "\1a" ;; drop + "\0b" ;; end + ) + "alignment must not be larger than natural" +) + +;; Unsigned 32-bit overflow +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\20\00" ;; i32.load offset=0 align=2**32 + "\1a" ;; drop + "\0b" ;; end + ) + "alignment must not be larger than natural" +) + +;; 32-bit out of range +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\21\00" ;; i32.load offset=0 align=2**33 + "\1a" ;; drop + "\0b" ;; end + ) + "alignment must not be larger than natural" +) + +;; Signed 64-bit overflow +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\3f\00" ;; i32.load offset=0 align=2**63 + "\1a" ;; drop + "\0b" ;; end + ) + "alignment must not be larger than natural" +) + +;; 64-bit out of range +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\05\03\01\00\01" ;; Memory section: 1 memory + "\0a\0a\01" ;; Code section: 1 function + + ;; function 0 + "\08\00" + "\41\00" ;; i32.const 0 + "\28\41\00" ;; i32.load offset=0 align=2**65 (parsed as align=1, memidx present) + "\1a" ;; drop + "\0b" ;; end + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/align0.wast b/proposals/wasm-3.0/align0.wast new file mode 100644 index 0000000..f150708 --- /dev/null +++ b/proposals/wasm-3.0/align0.wast @@ -0,0 +1,43 @@ +;; Test aligned and unaligned read/write + +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 0) + + ;; $default: natural alignment, $1: align=1, $2: align=2, $4: align=4, $8: align=8 + + (func (export "f32_align_switch") (param i32) (result f32) + (local f32 f32) + (local.set 1 (f32.const 10.0)) + (block $4 + (block $2 + (block $1 + (block $default + (block $0 + (br_table $0 $default $1 $2 $4 (local.get 0)) + ) ;; 0 + (f32.store $mem1 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 (i32.const 0))) + (br $4) + ) ;; default + (f32.store $mem1 align=1 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=1 (i32.const 0))) + (br $4) + ) ;; 1 + (f32.store $mem1 align=2 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=2 (i32.const 0))) + (br $4) + ) ;; 2 + (f32.store $mem1 align=4 (i32.const 0) (local.get 1)) + (local.set 2 (f32.load $mem1 align=4 (i32.const 0))) + ) ;; 4 + (local.get 2) + ) +) + +(assert_return (invoke "f32_align_switch" (i32.const 0)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 1)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 2)) (f32.const 10.0)) +(assert_return (invoke "f32_align_switch" (i32.const 3)) (f32.const 10.0)) + diff --git a/proposals/memory64/align64.wast b/proposals/wasm-3.0/align64.wast similarity index 100% rename from proposals/memory64/align64.wast rename to proposals/wasm-3.0/align64.wast diff --git a/proposals/wasm-3.0/annotations.wast b/proposals/wasm-3.0/annotations.wast new file mode 100644 index 0000000..912d10f --- /dev/null +++ b/proposals/wasm-3.0/annotations.wast @@ -0,0 +1,207 @@ +(module + (@a) + (@0) + (@aas-3!@$d-@#4) + (@@) (@$) (@+) (@0) (@.) (@!$@#$23414@#$) + (@"a") + (@" @ asd\2a 045 \" fdaf \t \u{45}") + + (@a x y z) + (@a x-y $yz "aa" -2 0.3 0x3) + (@a x-y$yz"aa"-2) + (@a block func module i32.add) + (@a 0x 8q 0xfa #4g0-.@f#^&@#$*0sf -- @#) + (@a , ; ] [ }} }x{ ({) ,{{};}] ;) + (@a (bla) () (5-g) ("aa" a) ($x) (bla bla) (x (y)) ")" "(" x")"y) + (@a @ @x (@x) (@x y) (@) (@ x) (@(@(@(@))))) + (@a (;bla;) (; ) ;) + ;; bla) + ;; bla (@x + ) +) + +(assert_malformed (module quote "(@a \00)") "illegal character") +(assert_malformed (module quote "(@a \01)") "illegal character") +(assert_malformed (module quote "(@a \02)") "illegal character") +(assert_malformed (module quote "(@a \03)") "illegal character") +(assert_malformed (module quote "(@a \04)") "illegal character") +(assert_malformed (module quote "(@a \05)") "illegal character") +(assert_malformed (module quote "(@a \06)") "illegal character") +(assert_malformed (module quote "(@a \07)") "illegal character") +(assert_malformed (module quote "(@a \08)") "illegal character") +(module quote "(@a \09)") ;; \t +(module quote "(@a \0a)") ;; \n +(assert_malformed (module quote "(@a \0b)") "illegal character") +(assert_malformed (module quote "(@a \0c)") "illegal character") +(module quote "(@a \0d)") ;; \r +(assert_malformed (module quote "(@a \0e)") "illegal character") +(assert_malformed (module quote "(@a \0f)") "illegal character") +(assert_malformed (module quote "(@a \10)") "illegal character") +(assert_malformed (module quote "(@a \11)") "illegal character") +(assert_malformed (module quote "(@a \12)") "illegal character") +(assert_malformed (module quote "(@a \13)") "illegal character") +(assert_malformed (module quote "(@a \14)") "illegal character") +(assert_malformed (module quote "(@a \15)") "illegal character") +(assert_malformed (module quote "(@a \16)") "illegal character") +(assert_malformed (module quote "(@a \17)") "illegal character") +(assert_malformed (module quote "(@a \18)") "illegal character") +(assert_malformed (module quote "(@a \19)") "illegal character") +(assert_malformed (module quote "(@a \1a)") "illegal character") +(assert_malformed (module quote "(@a \1b)") "illegal character") +(assert_malformed (module quote "(@a \1c)") "illegal character") +(assert_malformed (module quote "(@a \1d)") "illegal character") +(assert_malformed (module quote "(@a \1e)") "illegal character") +(assert_malformed (module quote "(@a \1f)") "illegal character") +(module quote "(@a \20)") ;; space +(assert_malformed (module quote "(@a \7f)") "illegal character") +(assert_malformed (module quote "(@a \80)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \81)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \90)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \a0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \b0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \c0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \d0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \e0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \f0)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a \ff)") "malformed UTF-8 encoding") +(assert_malformed (module quote "(@a Heiße Würstchen)") "illegal character") +(assert_malformed (module quote "(@a )") "illegal character") + +(assert_malformed (module quote "( @a)") "unknown operator") + +(assert_malformed (module quote "(@)") "empty annotation id") +(assert_malformed (module quote "(@ )") "empty annotation id") +(assert_malformed (module quote "(@ x)") "empty annotation id") +(assert_malformed (module quote "(@(@a)x)") "empty annotation id") +(assert_malformed (module quote "(@\"\")") "empty annotation id") +(assert_malformed (module quote "(@ \"a\")") "empty annotation id") +(assert_malformed (module quote "(@\"\n\")") "empty annotation id") +(assert_malformed (module quote "(@\"\\ef\")") "malformed UTF-8") + +(assert_malformed (module quote "(@x ") "unclosed annotation") +(assert_malformed (module quote "(@x ()") "unclosed annotation") +(assert_malformed (module quote "(@x (y (z))") "unclosed annotation") +(assert_malformed (module quote "(@x (@y )") "unclosed annotation") + +(assert_malformed (module quote "(@x))") "unexpected token") +(assert_malformed (module quote "(@x ()))") "unexpected token") +(assert_malformed (module quote "(@x (y (z))))") "unexpected token") +(assert_malformed (module quote "(@x (@y )))") "unexpected token") + +(assert_malformed (module quote "(@x \"") "unclosed string") +(assert_malformed (module quote "(@x \")") "unclosed string") + +(assert_malformed (module quote "((@a)@b)") "unknown operator") +(assert_malformed (module quote "(func $(@a))") "empty identifier") +(assert_malformed (module quote "(func $(@a)f)") "empty identifier") + +((@a) module (@a) $m (@a) (@a) + ((@a) import (@a) "spectest" (@a) "global_i32" (@a) + ((@a) global (@a) $g (@a) i32 (@a)) (@a) + ) (@a) + ((@a) import (@a) "spectest" (@a) "table" (@a) + ((@a) table (@a) $t (@a) 10 (@a) 20 (@a) funcref (@a)) (@a) + ) (@a) + ((@a) import (@a) "spectest" (@a) "memory" (@a) + ((@a) memory (@a) $m (@a) 1 (@a) 2 (@a)) (@a) + ) (@a) + ((@a) import (@a) "spectest" (@a) "print_i32_f32" (@a) + ((@a) func (@a) $f (@a) + ((@a) param (@a) i32 (@a) f32 (@a)) (@a) + ((@a) result (@a)) (@a) + ) (@a) + ) (@a) + + ((@a) export (@a) "g" (@a) + ((@a) global (@a) $g (@a)) (@a) + ) (@a) + ((@a) export (@a) "t" (@a) + ((@a) table (@a) $t (@a)) (@a) + ) (@a) + ((@a) export (@a) "m" (@a) + ((@a) memory (@a) $m (@a)) (@a) + ) (@a) + ((@a) export (@a) "f" (@a) + ((@a) func (@a) $f (@a)) (@a) + ) (@a) +) + +((@a) module (@a) $m1 (@a) (@a) + ((@a) global (@a) $g (@a) + ((@a) export (@a) "g" (@a)) (@a) + ((@a) import (@a) "spectest" (@a) "global_i32" (@a)) (@a) + i32 (@a) + ) (@a) + ((@a) table (@a) $t (@a) + ((@a) export (@a) "t" (@a)) (@a) + ((@a) import (@a) "spectest" (@a) "table" (@a)) (@a) + 10 (@a) 20 (@a) + funcref (@a) + ) (@a) + ((@a) memory (@a) $m (@a) + ((@a) export (@a) "m" (@a)) (@a) + ((@a) import (@a) "spectest" (@a) "memory" (@a)) (@a) + 1 (@a) 2 (@a) + ) (@a) + ((@a) func (@a) $f (@a) + ((@a) export (@a) "f" (@a)) (@a) + ((@a) import (@a) "spectest" (@a) "print_i32_f32" (@a)) (@a) + ((@a) param (@a) i32 (@a) f32 (@a)) (@a) + ((@a) result (@a)) (@a) + ) (@a) +) + +((@a) module (@a) $m2 (@a) (@a) + ((@a) type (@a) $T (@a) + ((@a) func (@a) + ((@a) param (@a) i32 (@a) i64 (@a)) (@a) + ((@a) param (@a) $x (@a) i32 (@a)) (@a) + ((@a) result (@a) i32 (@a)) (@a) + ) (@a) + ) (@a) + + ((@a) global (@a) $g (@a) + ((@a) export (@a) "g" (@a)) (@a) + i32 (@a) + ((@a) i32.const (@a) 42 (@a)) (@a) + ) (@a) + ((@a) table (@a) $t (@a) + ((@a) export (@a) "t" (@a)) (@a) + 10 (@a) 20 (@a) + funcref (@a) + ) (@a) + ((@a) memory (@a) $m (@a) + ((@a) export (@a) "m" (@a)) (@a) + 1 (@a) 2 (@a) + ) (@a) + ((@a) func (@a) $f (@a) + ((@a) export (@a) "f" (@a)) (@a) + ((@a) param (@a) i32 (@a) i64 (@a)) (@a) + ((@a) param (@a) $x (@a) i32 (@a)) (@a) + ((@a) result (@a) i32 (@a)) (@a) + ((@a) local (@a) i32 (@a) i32 (@a)) (@a) + ((@a) local (@a) $y (@a) i32 (@a)) (@a) + ((@a) block (@a) + ((@a) result (@a) i32 (@a)) (@a) + ((@a) i32.add (@a) + ((@a) local.get (@a) $x (@a)) (@a) + ((@a) local.get (@a) 0 (@a)) (@a) + ) + ) + ) (@a) + + ((@a) elem (@a) + ((@a) offset (@a) ((@a) i32.const (@a) 0 (@a)) (@a)) (@a) + $f (@a) $f (@a) (@a) $f (@a) + ) (@a) + ((@a) data (@a) + ((@a) offset (@a) ((@a) i32.const (@a) 0 (@a)) (@a)) (@a) + "bla" (@a) "\43" (@a) (@a) "" (@a) + ) (@a) + + (func $s) + ((@a) start (@a) $s (@a)) (@a) +) + +(module quote "(@a) (func)") +(module quote "(func) (@a)") diff --git a/proposals/wasm-3.0/array.wast b/proposals/wasm-3.0/array.wast new file mode 100644 index 0000000..6ad95c0 --- /dev/null +++ b/proposals/wasm-3.0/array.wast @@ -0,0 +1,315 @@ +;; Type syntax + +(module + (type (array i8)) + (type (array i16)) + (type (array i32)) + (type (array i64)) + (type (array f32)) + (type (array f64)) + (type (array anyref)) + (type (array (ref struct))) + (type (array (ref 0))) + (type (array (ref null 1))) + (type (array (mut i8))) + (type (array (mut i16))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut i32))) + (type (array (mut i64))) + (type (array (mut anyref))) + (type (array (mut (ref struct)))) + (type (array (mut (ref 0)))) + (type (array (mut (ref null i31)))) +) + + +(assert_invalid + (module + (type (array (mut (ref null 10)))) + ) + "unknown type" +) + + +;; Binding structure + +(module + (rec + (type $s0 (array (ref $s1))) + (type $s1 (array (ref $s0))) + ) + + (func (param (ref $forward))) + + (type $forward (array i32)) +) + +(assert_invalid + (module (type (array (ref 1)))) + "unknown type" +) +(assert_invalid + (module (type (array (mut (ref 1))))) + "unknown type" +) + + +;; Basic instructions + +(module + (type $vec (array f32)) + (type $mvec (array (mut f32))) + + (global (ref $vec) (array.new $vec (f32.const 1) (i32.const 3))) + (global (ref $vec) (array.new_default $vec (i32.const 3))) + + (func $new (export "new") (result (ref $vec)) + (array.new_default $vec (i32.const 3)) + ) + + (func $get (param $i i32) (param $v (ref $vec)) (result f32) + (array.get $vec (local.get $v) (local.get $i)) + ) + (func (export "get") (param $i i32) (result f32) + (call $get (local.get $i) (call $new)) + ) + + (func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32) + (array.set $mvec (local.get $v) (local.get $i) (local.get $y)) + (array.get $mvec (local.get $v) (local.get $i)) + ) + (func (export "set_get") (param $i i32) (param $y f32) (result f32) + (call $set_get (local.get $i) + (array.new_default $mvec (i32.const 3)) + (local.get $y) + ) + ) + + (func $len (param $v (ref array)) (result i32) + (array.len (local.get $v)) + ) + (func (export "len") (result i32) + (call $len (call $new)) + ) +) + +(assert_return (invoke "new") (ref.array)) +(assert_return (invoke "new") (ref.eq)) +(assert_return (invoke "get" (i32.const 0)) (f32.const 0)) +(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) +(assert_return (invoke "len") (i32.const 3)) + +(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access") +(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds array access") + +(module + (type $vec (array f32)) + (type $mvec (array (mut f32))) + + (global (ref $vec) (array.new_fixed $vec 2 (f32.const 1) (f32.const 2))) + + (func $new (export "new") (result (ref $vec)) + (array.new_fixed $vec 2 (f32.const 1) (f32.const 2)) + ) + + (func $get (param $i i32) (param $v (ref $vec)) (result f32) + (array.get $vec (local.get $v) (local.get $i)) + ) + (func (export "get") (param $i i32) (result f32) + (call $get (local.get $i) (call $new)) + ) + + (func $set_get (param $i i32) (param $v (ref $mvec)) (param $y f32) (result f32) + (array.set $mvec (local.get $v) (local.get $i) (local.get $y)) + (array.get $mvec (local.get $v) (local.get $i)) + ) + (func (export "set_get") (param $i i32) (param $y f32) (result f32) + (call $set_get (local.get $i) + (array.new_fixed $mvec 3 (f32.const 1) (f32.const 2) (f32.const 3)) + (local.get $y) + ) + ) + + (func $len (param $v (ref array)) (result i32) + (array.len (local.get $v)) + ) + (func (export "len") (result i32) + (call $len (call $new)) + ) +) + +(assert_return (invoke "new") (ref.array)) +(assert_return (invoke "new") (ref.eq)) +(assert_return (invoke "get" (i32.const 0)) (f32.const 1)) +(assert_return (invoke "set_get" (i32.const 1) (f32.const 7)) (f32.const 7)) +(assert_return (invoke "len") (i32.const 2)) + +(assert_trap (invoke "get" (i32.const 10)) "out of bounds array access") +(assert_trap (invoke "set_get" (i32.const 10) (f32.const 7)) "out of bounds array access") + +(module + (type $vec (array i8)) + (type $mvec (array (mut i8))) + + (data $d "\00\01\02\ff\04") + + (func $new (export "new") (result (ref $vec)) + (array.new_data $vec $d (i32.const 1) (i32.const 3)) + ) + + (func $get_u (param $i i32) (param $v (ref $vec)) (result i32) + (array.get_u $vec (local.get $v) (local.get $i)) + ) + (func (export "get_u") (param $i i32) (result i32) + (call $get_u (local.get $i) (call $new)) + ) + + (func $get_s (param $i i32) (param $v (ref $vec)) (result i32) + (array.get_s $vec (local.get $v) (local.get $i)) + ) + (func (export "get_s") (param $i i32) (result i32) + (call $get_s (local.get $i) (call $new)) + ) + + (func $set_get (param $i i32) (param $v (ref $mvec)) (param $y i32) (result i32) + (array.set $mvec (local.get $v) (local.get $i) (local.get $y)) + (array.get_u $mvec (local.get $v) (local.get $i)) + ) + (func (export "set_get") (param $i i32) (param $y i32) (result i32) + (call $set_get (local.get $i) + (array.new_data $mvec $d (i32.const 1) (i32.const 3)) + (local.get $y) + ) + ) + + (func $len (param $v (ref array)) (result i32) + (array.len (local.get $v)) + ) + (func (export "len") (result i32) + (call $len (call $new)) + ) +) + +(assert_return (invoke "new") (ref.array)) +(assert_return (invoke "new") (ref.eq)) +(assert_return (invoke "get_u" (i32.const 2)) (i32.const 0xff)) +(assert_return (invoke "get_s" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "set_get" (i32.const 1) (i32.const 7)) (i32.const 7)) +(assert_return (invoke "len") (i32.const 3)) + +(assert_trap (invoke "get_u" (i32.const 10)) "out of bounds array access") +(assert_trap (invoke "get_s" (i32.const 10)) "out of bounds array access") +(assert_trap (invoke "set_get" (i32.const 10) (i32.const 7)) "out of bounds array access") + +(module + (type $bvec (array i8)) + (type $vec (array (ref $bvec))) + (type $mvec (array (mut (ref $bvec)))) + (type $nvec (array (ref null $bvec))) + (type $avec (array (mut anyref))) + + (elem $e (ref $bvec) + (array.new $bvec (i32.const 7) (i32.const 3)) + (array.new_fixed $bvec 2 (i32.const 1) (i32.const 2)) + ) + + (func $new (export "new") (result (ref $vec)) + (array.new_elem $vec $e (i32.const 0) (i32.const 2)) + ) + + (func $sub1 (result (ref $nvec)) + (array.new_elem $nvec $e (i32.const 0) (i32.const 2)) + ) + (func $sub2 (result (ref $avec)) + (array.new_elem $avec $e (i32.const 0) (i32.const 2)) + ) + + (func $get (param $i i32) (param $j i32) (param $v (ref $vec)) (result i32) + (array.get_u $bvec (array.get $vec (local.get $v) (local.get $i)) (local.get $j)) + ) + (func (export "get") (param $i i32) (param $j i32) (result i32) + (call $get (local.get $i) (local.get $j) (call $new)) + ) + + (func $set_get (param $i i32) (param $j i32) (param $v (ref $mvec)) (param $y i32) (result i32) + (array.set $mvec (local.get $v) (local.get $i) (array.get $mvec (local.get $v) (local.get $y))) + (array.get_u $bvec (array.get $mvec (local.get $v) (local.get $i)) (local.get $j)) + ) + (func (export "set_get") (param $i i32) (param $j i32) (param $y i32) (result i32) + (call $set_get (local.get $i) (local.get $j) + (array.new_elem $mvec $e (i32.const 0) (i32.const 2)) + (local.get $y) + ) + ) + + (func $len (param $v (ref array)) (result i32) + (array.len (local.get $v)) + ) + (func (export "len") (result i32) + (call $len (call $new)) + ) +) + +(assert_return (invoke "new") (ref.array)) +(assert_return (invoke "new") (ref.eq)) +(assert_return (invoke "get" (i32.const 0) (i32.const 0)) (i32.const 7)) +(assert_return (invoke "get" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "set_get" (i32.const 0) (i32.const 1) (i32.const 1)) (i32.const 2)) +(assert_return (invoke "len") (i32.const 2)) + +(assert_trap (invoke "get" (i32.const 10) (i32.const 0)) "out of bounds array access") +(assert_trap (invoke "set_get" (i32.const 10) (i32.const 0) (i32.const 0)) "out of bounds array access") + +(assert_invalid + (module + (type $a (array i64)) + (func (export "array.set-immutable") (param $a (ref $a)) + (array.set $a (local.get $a) (i32.const 0) (i64.const 1)) + ) + ) + "array is immutable" +) + +(assert_invalid + (module + (type $bvec (array i8)) + + (data $d "\00\01\02\03\04") + + (global (ref $bvec) + (array.new_data $bvec $d (i32.const 1) (i32.const 3)) + ) + ) + "constant expression required" +) + +(assert_invalid + (module + (type $bvec (array i8)) + (type $vvec (array (ref $bvec))) + + (elem $e (ref $bvec) (ref.null $bvec)) + + (global (ref $vvec) + (array.new_elem $vvec $e (i32.const 0) (i32.const 1)) + ) + ) + "constant expression required" +) + + +;; Null dereference + +(module + (type $t (array (mut i32))) + (func (export "array.get-null") + (local (ref null $t)) (drop (array.get $t (local.get 0) (i32.const 0))) + ) + (func (export "array.set-null") + (local (ref null $t)) (array.set $t (local.get 0) (i32.const 0) (i32.const 0)) + ) +) + +(assert_trap (invoke "array.get-null") "null array reference") +(assert_trap (invoke "array.set-null") "null array reference") diff --git a/proposals/wasm-3.0/array_copy.wast b/proposals/wasm-3.0/array_copy.wast new file mode 100644 index 0000000..d1caf12 --- /dev/null +++ b/proposals/wasm-3.0/array_copy.wast @@ -0,0 +1,139 @@ +;; Bulk instructions + +;; invalid uses + +(assert_invalid + (module + (type $a (array i8)) + (type $b (array (mut i8))) + + (func (export "array.copy-immutable") (param $1 (ref $a)) (param $2 (ref $b)) + (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0)) + ) + ) + "array is immutable" +) + +(assert_invalid + (module + (type $a (array (mut i8))) + (type $b (array i16)) + + (func (export "array.copy-packed-invalid") (param $1 (ref $a)) (param $2 (ref $b)) + (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0)) + ) + ) + "array types do not match" +) + +(assert_invalid + (module + (type $a (array (mut i8))) + (type $b (array (mut (ref $a)))) + + (func (export "array.copy-ref-invalid-1") (param $1 (ref $a)) (param $2 (ref $b)) + (array.copy $a $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0)) + ) + ) + "array types do not match" +) + +(assert_invalid + (module + (type $a (array (mut i8))) + (type $b (array (mut (ref $a)))) + (type $c (array (mut (ref $b)))) + + (func (export "array.copy-ref-invalid-1") (param $1 (ref $b)) (param $2 (ref $c)) + (array.copy $b $c (local.get $1) (i32.const 0) (local.get $2) (i32.const 0) (i32.const 0)) + ) + ) + "array types do not match" +) + +(module + (type $arr8 (array i8)) + (type $arr8_mut (array (mut i8))) + + (global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12))) + (global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12))) + + (data $d1 "abcdefghijkl") + + (func (export "array_get_nth") (param $1 i32) (result i32) + (array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1)) + ) + + (func (export "array_copy-null-left") + (array.copy $arr8_mut $arr8 (ref.null $arr8_mut) (i32.const 0) (global.get $g_arr8) (i32.const 0) (i32.const 0)) + ) + + (func (export "array_copy-null-right") + (array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (i32.const 0) (ref.null $arr8) (i32.const 0) (i32.const 0)) + ) + + (func (export "array_copy") (param $1 i32) (param $2 i32) (param $3 i32) + (array.copy $arr8_mut $arr8 (global.get $g_arr8_mut) (local.get $1) (global.get $g_arr8) (local.get $2) (local.get $3)) + ) + + (func (export "array_copy_overlap_test-1") + (local $1 (ref $arr8_mut)) + (array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12)) + (local.set $1) + (array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 1) (local.get $1) (i32.const 0) (i32.const 11)) + (global.set $g_arr8_mut (local.get $1)) + ) + + (func (export "array_copy_overlap_test-2") + (local $1 (ref $arr8_mut)) + (array.new_data $arr8_mut $d1 (i32.const 0) (i32.const 12)) + (local.set $1) + (array.copy $arr8_mut $arr8_mut (local.get $1) (i32.const 0) (local.get $1) (i32.const 1) (i32.const 11)) + (global.set $g_arr8_mut (local.get $1)) + ) +) + +;; null array argument traps +(assert_trap (invoke "array_copy-null-left") "null array reference") +(assert_trap (invoke "array_copy-null-right") "null array reference") + +;; OOB initial index traps +(assert_trap (invoke "array_copy" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access") +(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds array access") + +;; OOB length traps +(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") +(assert_trap (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") + +;; start index = array size, len = 0 doesn't trap +(assert_return (invoke "array_copy" (i32.const 12) (i32.const 0) (i32.const 0))) +(assert_return (invoke "array_copy" (i32.const 0) (i32.const 12) (i32.const 0))) + +;; check arrays were not modified +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0)) +(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access") + +;; normal case +(assert_return (invoke "array_copy" (i32.const 0) (i32.const 0) (i32.const 2))) +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 10)) +(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 10)) +(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 0)) + +;; test that overlapping array.copy works as if intermediate copy taken +(assert_return (invoke "array_copy_overlap_test-1")) +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 97)) +(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 97)) +(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 98)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 101)) +(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 106)) +(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 107)) + +(assert_return (invoke "array_copy_overlap_test-2")) +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 98)) +(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 99)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 103)) +(assert_return (invoke "array_get_nth" (i32.const 9)) (i32.const 107)) +(assert_return (invoke "array_get_nth" (i32.const 10)) (i32.const 108)) +(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 108)) diff --git a/proposals/wasm-3.0/array_fill.wast b/proposals/wasm-3.0/array_fill.wast new file mode 100644 index 0000000..0379ad5 --- /dev/null +++ b/proposals/wasm-3.0/array_fill.wast @@ -0,0 +1,81 @@ +;; Bulk instructions + +;; invalid uses + +(assert_invalid + (module + (type $a (array i8)) + + (func (export "array.fill-immutable") (param $1 (ref $a)) (param $2 i32) + (array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0)) + ) + ) + "array is immutable" +) + +(assert_invalid + (module + (type $a (array (mut i8))) + + (func (export "array.fill-invalid-1") (param $1 (ref $a)) (param $2 funcref) + (array.fill $a (local.get $1) (i32.const 0) (local.get $2) (i32.const 0)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $b (array (mut funcref))) + + (func (export "array.fill-invalid-1") (param $1 (ref $b)) (param $2 i32) + (array.fill $b (local.get $1) (i32.const 0) (local.get $2) (i32.const 0)) + ) + ) + "type mismatch" +) + +(module + (type $arr8 (array i8)) + (type $arr8_mut (array (mut i8))) + + (global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12))) + (global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12))) + + (func (export "array_get_nth") (param $1 i32) (result i32) + (array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1)) + ) + + (func (export "array_fill-null") + (array.fill $arr8_mut (ref.null $arr8_mut) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + + (func (export "array_fill") (param $1 i32) (param $2 i32) (param $3 i32) + (array.fill $arr8_mut (global.get $g_arr8_mut) (local.get $1) (local.get $2) (local.get $3)) + ) +) + +;; null array argument traps +(assert_trap (invoke "array_fill-null") "null array reference") + +;; OOB initial index traps +(assert_trap (invoke "array_fill" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access") + +;; OOB length traps +(assert_trap (invoke "array_fill" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") + +;; start index = array size, len = 0 doesn't trap +(assert_return (invoke "array_fill" (i32.const 12) (i32.const 0) (i32.const 0))) + +;; check arrays were not modified +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0)) +(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access") + +;; normal case +(assert_return (invoke "array_fill" (i32.const 2) (i32.const 11) (i32.const 2))) +(assert_return (invoke "array_get_nth" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 2)) (i32.const 11)) +(assert_return (invoke "array_get_nth" (i32.const 3)) (i32.const 11)) +(assert_return (invoke "array_get_nth" (i32.const 4)) (i32.const 0)) diff --git a/proposals/wasm-3.0/array_init_data.wast b/proposals/wasm-3.0/array_init_data.wast new file mode 100644 index 0000000..3bee026 --- /dev/null +++ b/proposals/wasm-3.0/array_init_data.wast @@ -0,0 +1,110 @@ +;; Bulk instructions + +;; invalid uses + +(assert_invalid + (module + (type $a (array i8)) + + (data $d1 "a") + + (func (export "array.init_data-immutable") (param $1 (ref $a)) + (array.init_data $a $d1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + ) + "array is immutable" +) + +(assert_invalid + (module + (type $a (array (mut funcref))) + + (data $d1 "a") + + (func (export "array.init_data-invalid-1") (param $1 (ref $a)) + (array.init_data $a $d1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + ) + "array type is not numeric or vector" +) + +(module + (type $arr8 (array i8)) + (type $arr8_mut (array (mut i8))) + (type $arr16_mut (array (mut i16))) + + (global $g_arr8 (ref $arr8) (array.new $arr8 (i32.const 10) (i32.const 12))) + (global $g_arr8_mut (mut (ref $arr8_mut)) (array.new_default $arr8_mut (i32.const 12))) + (global $g_arr16_mut (ref $arr16_mut) (array.new_default $arr16_mut (i32.const 6))) + + (data $d1 "abcdefghijkl") + + (func (export "array_get_nth") (param $1 i32) (result i32) + (array.get_u $arr8_mut (global.get $g_arr8_mut) (local.get $1)) + ) + + (func (export "array_get_nth_i16") (param $1 i32) (result i32) + (array.get_u $arr16_mut (global.get $g_arr16_mut) (local.get $1)) + ) + + (func (export "array_init_data-null") + (array.init_data $arr8_mut $d1 (ref.null $arr8_mut) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + + (func (export "array_init_data") (param $1 i32) (param $2 i32) (param $3 i32) + (array.init_data $arr8_mut $d1 (global.get $g_arr8_mut) (local.get $1) (local.get $2) (local.get $3)) + ) + + (func (export "array_init_data_i16") (param $1 i32) (param $2 i32) (param $3 i32) + (array.init_data $arr16_mut $d1 (global.get $g_arr16_mut) (local.get $1) (local.get $2) (local.get $3)) + ) + + (func (export "drop_segs") + (data.drop $d1) + ) +) + +;; null array argument traps +(assert_trap (invoke "array_init_data-null") "null array reference") + +;; OOB initial index traps +(assert_trap (invoke "array_init_data" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access") +(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds memory access") + +;; OOB length traps +(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") +(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") +(assert_trap (invoke "array_init_data_i16" (i32.const 0) (i32.const 0) (i32.const 7)) "out of bounds array access") + +;; start index = array size, len = 0 doesn't trap +(assert_return (invoke "array_init_data" (i32.const 12) (i32.const 0) (i32.const 0))) +(assert_return (invoke "array_init_data" (i32.const 0) (i32.const 12) (i32.const 0))) +(assert_return (invoke "array_init_data_i16" (i32.const 0) (i32.const 6) (i32.const 0))) + +;; check arrays were not modified +(assert_return (invoke "array_get_nth" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 11)) (i32.const 0)) +(assert_trap (invoke "array_get_nth" (i32.const 12)) "out of bounds array access") +(assert_return (invoke "array_get_nth_i16" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "array_get_nth_i16" (i32.const 2)) (i32.const 0)) +(assert_return (invoke "array_get_nth_i16" (i32.const 5)) (i32.const 0)) +(assert_trap (invoke "array_get_nth_i16" (i32.const 6)) "out of bounds array access") + +;; normal cases +(assert_return (invoke "array_init_data" (i32.const 4) (i32.const 2) (i32.const 2))) +(assert_return (invoke "array_get_nth" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "array_get_nth" (i32.const 4)) (i32.const 99)) +(assert_return (invoke "array_get_nth" (i32.const 5)) (i32.const 100)) +(assert_return (invoke "array_get_nth" (i32.const 6)) (i32.const 0)) + +(assert_return (invoke "array_init_data_i16" (i32.const 2) (i32.const 5) (i32.const 2))) +(assert_return (invoke "array_get_nth_i16" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "array_get_nth_i16" (i32.const 2)) (i32.const 0x6766)) +(assert_return (invoke "array_get_nth_i16" (i32.const 3)) (i32.const 0x6968)) +(assert_return (invoke "array_get_nth_i16" (i32.const 4)) (i32.const 0)) + +;; init_data/elem with dropped segments traps for non-zero length +(assert_return (invoke "drop_segs")) +(assert_return (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 0))) +(assert_trap (invoke "array_init_data" (i32.const 0) (i32.const 0) (i32.const 1)) "out of bounds memory access") diff --git a/proposals/wasm-3.0/array_init_elem.wast b/proposals/wasm-3.0/array_init_elem.wast new file mode 100644 index 0000000..34a1259 --- /dev/null +++ b/proposals/wasm-3.0/array_init_elem.wast @@ -0,0 +1,108 @@ +;; Bulk instructions + +;; invalid uses + +(assert_invalid + (module + (type $a (array funcref)) + + (elem $e1 funcref) + + (func (export "array.init_elem-immutable") (param $1 (ref $a)) + (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + ) + "array is immutable" +) + +(assert_invalid + (module + (type $a (array (mut i8))) + + (elem $e1 funcref) + + (func (export "array.init_elem-invalid-1") (param $1 (ref $a)) + (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $a (array (mut funcref))) + + (elem $e1 externref) + + (func (export "array.init_elem-invalid-2") (param $1 (ref $a)) + (array.init_elem $a $e1 (local.get $1) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + ) + "type mismatch" +) + +(module + (type $t_f (func)) + (type $arrref (array (ref $t_f))) + (type $arrref_mut (array (mut funcref))) + + (global $g_arrref (ref $arrref) (array.new $arrref (ref.func $dummy) (i32.const 12))) + (global $g_arrref_mut (ref $arrref_mut) (array.new_default $arrref_mut (i32.const 12))) + + (table $t 1 funcref) + + (elem $e1 func $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy $dummy) + + (func $dummy + ) + + (func (export "array_call_nth") (param $1 i32) + (table.set $t (i32.const 0) (array.get $arrref_mut (global.get $g_arrref_mut) (local.get $1))) + (call_indirect $t (i32.const 0)) + ) + + (func (export "array_init_elem-null") + (array.init_elem $arrref_mut $e1 (ref.null $arrref_mut) (i32.const 0) (i32.const 0) (i32.const 0)) + ) + + (func (export "array_init_elem") (param $1 i32) (param $2 i32) (param $3 i32) + (array.init_elem $arrref_mut $e1 (global.get $g_arrref_mut) (local.get $1) (local.get $2) (local.get $3)) + ) + + (func (export "drop_segs") + (elem.drop $e1) + ) +) + +;; null array argument traps +(assert_trap (invoke "array_init_elem-null") "null array reference") + +;; OOB initial index traps +(assert_trap (invoke "array_init_elem" (i32.const 13) (i32.const 0) (i32.const 0)) "out of bounds array access") +(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 13) (i32.const 0)) "out of bounds table access") + +;; OOB length traps +(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") +(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 13)) "out of bounds array access") + +;; start index = array size, len = 0 doesn't trap +(assert_return (invoke "array_init_elem" (i32.const 12) (i32.const 0) (i32.const 0))) +(assert_return (invoke "array_init_elem" (i32.const 0) (i32.const 12) (i32.const 0))) + +;; check arrays were not modified +(assert_trap (invoke "array_call_nth" (i32.const 0)) "uninitialized element") +(assert_trap (invoke "array_call_nth" (i32.const 5)) "uninitialized element") +(assert_trap (invoke "array_call_nth" (i32.const 11)) "uninitialized element") +(assert_trap (invoke "array_call_nth" (i32.const 12)) "out of bounds array access") + +;; normal cases +(assert_return (invoke "array_init_elem" (i32.const 2) (i32.const 3) (i32.const 2))) +(assert_trap (invoke "array_call_nth" (i32.const 1)) "uninitialized element") +(assert_return (invoke "array_call_nth" (i32.const 2))) +(assert_return (invoke "array_call_nth" (i32.const 3))) +(assert_trap (invoke "array_call_nth" (i32.const 4)) "uninitialized element") + +;; init_data/elem with dropped segments traps for non-zero length +(assert_return (invoke "drop_segs")) +(assert_return (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 0))) +(assert_trap (invoke "array_init_elem" (i32.const 0) (i32.const 0) (i32.const 1)) "out of bounds table access") diff --git a/proposals/wasm-3.0/binary-gc.wast b/proposals/wasm-3.0/binary-gc.wast new file mode 100644 index 0000000..589573f --- /dev/null +++ b/proposals/wasm-3.0/binary-gc.wast @@ -0,0 +1,12 @@ +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\01" ;; Type section id + "\04" ;; Type section length + "\01" ;; Types vector length + "\5e" ;; Array type, -0x22 + "\78" ;; Storage type: i8 or -0x08 + "\02" ;; Mutability, should be 0 or 1, but isn't + ) + "malformed mutability" +) diff --git a/proposals/memory64/binary-leb128.wast b/proposals/wasm-3.0/binary-leb128.wast similarity index 100% rename from proposals/memory64/binary-leb128.wast rename to proposals/wasm-3.0/binary-leb128.wast diff --git a/proposals/memory64/binary.wast b/proposals/wasm-3.0/binary.wast similarity index 100% rename from proposals/memory64/binary.wast rename to proposals/wasm-3.0/binary.wast diff --git a/proposals/memory64/binary0.wast b/proposals/wasm-3.0/binary0.wast similarity index 100% rename from proposals/memory64/binary0.wast rename to proposals/wasm-3.0/binary0.wast diff --git a/proposals/wasm-3.0/br_if.wast b/proposals/wasm-3.0/br_if.wast new file mode 100644 index 0000000..9d0cdd8 --- /dev/null +++ b/proposals/wasm-3.0/br_if.wast @@ -0,0 +1,679 @@ +;; Test `br_if` operator + +(module + (func $dummy) + + (func (export "type-i32") + (block (drop (i32.ctz (br_if 0 (i32.const 0) (i32.const 1))))) + ) + (func (export "type-i64") + (block (drop (i64.ctz (br_if 0 (i64.const 0) (i32.const 1))))) + ) + (func (export "type-f32") + (block (drop (f32.neg (br_if 0 (f32.const 0) (i32.const 1))))) + ) + (func (export "type-f64") + (block (drop (f64.neg (br_if 0 (f64.const 0) (i32.const 1))))) + ) + + (func (export "type-i32-value") (result i32) + (block (result i32) (i32.ctz (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "type-i64-value") (result i64) + (block (result i64) (i64.ctz (br_if 0 (i64.const 2) (i32.const 1)))) + ) + (func (export "type-f32-value") (result f32) + (block (result f32) (f32.neg (br_if 0 (f32.const 3) (i32.const 1)))) + ) + (func (export "type-f64-value") (result f64) + (block (result f64) (f64.neg (br_if 0 (f64.const 4) (i32.const 1)))) + ) + + (func (export "as-block-first") (param i32) (result i32) + (block (br_if 0 (local.get 0)) (return (i32.const 2))) (i32.const 3) + ) + (func (export "as-block-mid") (param i32) (result i32) + (block (call $dummy) (br_if 0 (local.get 0)) (return (i32.const 2))) + (i32.const 3) + ) + (func (export "as-block-last") (param i32) + (block (call $dummy) (call $dummy) (br_if 0 (local.get 0))) + ) + (func (export "as-block-first-value") (param i32) (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 10) (local.get 0))) (return (i32.const 11)) + ) + ) + (func (export "as-block-mid-value") (param i32) (result i32) + (block (result i32) + (call $dummy) + (drop (br_if 0 (i32.const 20) (local.get 0))) + (return (i32.const 21)) + ) + ) + (func (export "as-block-last-value") (param i32) (result i32) + (block (result i32) + (call $dummy) (call $dummy) (br_if 0 (i32.const 11) (local.get 0)) + ) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (block (loop (br_if 1 (local.get 0)) (return (i32.const 2)))) (i32.const 3) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (block (loop (call $dummy) (br_if 1 (local.get 0)) (return (i32.const 2)))) + (i32.const 4) + ) + (func (export "as-loop-last") (param i32) + (loop (call $dummy) (br_if 1 (local.get 0))) + ) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (br_if 0 (i32.const 1) (i32.const 2)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (br_if 0 (i32.const 1) (i32.const 2)) (i32.const 3))) + (i32.const 4) + ) + ) + (func (export "as-br_if-value-cond") (param i32) (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 2) (br_if 0 (i32.const 1) (local.get 0)))) + (i32.const 4) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (br_if 0 (i32.const 1) (i32.const 2)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (br_if 0 (i32.const 1) (i32.const 2)) (i32.const 3)) (i32.const 4) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 2) (br_if 0 (i32.const 1) (i32.const 3))) (i32.const 4) + ) + ) + (func (export "as-return-value") (result i64) + (block (result i64) (return (br_if 0 (i64.const 1) (i32.const 2)))) + ) + + (func (export "as-if-cond") (param i32) (result i32) + (block (result i32) + (if (result i32) + (br_if 0 (i32.const 1) (local.get 0)) + (then (i32.const 2)) + (else (i32.const 3)) + ) + ) + ) + (func (export "as-if-then") (param i32 i32) + (block + (if (local.get 0) (then (br_if 1 (local.get 1))) (else (call $dummy))) + ) + ) + (func (export "as-if-else") (param i32 i32) + (block + (if (local.get 0) (then (call $dummy)) (else (br_if 1 (local.get 1)))) + ) + ) + + (func (export "as-select-first") (param i32) (result i32) + (block (result i32) + (select (br_if 0 (i32.const 3) (i32.const 10)) (i32.const 2) (local.get 0)) + ) + ) + (func (export "as-select-second") (param i32) (result i32) + (block (result i32) + (select (i32.const 1) (br_if 0 (i32.const 3) (i32.const 10)) (local.get 0)) + ) + ) + (func (export "as-select-cond") (result i32) + (block (result i32) + (select (i32.const 1) (i32.const 2) (br_if 0 (i32.const 3) (i32.const 10))) + ) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (block (result i32) + (call $f + (br_if 0 (i32.const 12) (i32.const 1)) (i32.const 2) (i32.const 3) + ) + ) + ) + (func (export "as-call-mid") (result i32) + (block (result i32) + (call $f + (i32.const 1) (br_if 0 (i32.const 13) (i32.const 1)) (i32.const 3) + ) + ) + ) + (func (export "as-call-last") (result i32) + (block (result i32) + (call $f + (i32.const 1) (i32.const 2) (br_if 0 (i32.const 14) (i32.const 1)) + ) + ) + ) + + (func $func (param i32 i32 i32) (result i32) (local.get 0)) + (type $check (func (param i32 i32 i32) (result i32))) + (table funcref (elem $func)) + (func (export "as-call_indirect-func") (result i32) + (block (result i32) + (call_indirect (type $check) + (br_if 0 (i32.const 4) (i32.const 10)) + (i32.const 1) (i32.const 2) (i32.const 0) + ) + ) + ) + + (func (export "as-call_indirect-first") (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 1) (br_if 0 (i32.const 4) (i32.const 10)) (i32.const 2) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 1) (i32.const 2) (br_if 0 (i32.const 4) (i32.const 10)) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 1) (i32.const 2) (i32.const 3) (br_if 0 (i32.const 4) (i32.const 10)) + ) + ) + ) + + (func (export "as-local.set-value") (param i32) (result i32) + (local i32) + (block (result i32) + (local.set 0 (br_if 0 (i32.const 17) (local.get 0))) + (i32.const -1) + ) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (block (result i32) + (local.tee 0 (br_if 0 (i32.const 1) (local.get 0))) + (return (i32.const -1)) + ) + ) + (global $a (mut i32) (i32.const 10)) + (func (export "as-global.set-value") (param i32) (result i32) + (block (result i32) + (global.set $a (br_if 0 (i32.const 1) (local.get 0))) + (return (i32.const -1)) + ) + ) + + (memory 1) + (func (export "as-load-address") (result i32) + (block (result i32) (i32.load (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "as-loadN-address") (result i32) + (block (result i32) (i32.load8_s (br_if 0 (i32.const 30) (i32.const 1)))) + ) + + (func (export "as-store-address") (result i32) + (block (result i32) + (i32.store (br_if 0 (i32.const 30) (i32.const 1)) (i32.const 7)) (i32.const -1) + ) + ) + (func (export "as-store-value") (result i32) + (block (result i32) + (i32.store (i32.const 2) (br_if 0 (i32.const 31) (i32.const 1))) (i32.const -1) + ) + ) + + (func (export "as-storeN-address") (result i32) + (block (result i32) + (i32.store8 (br_if 0 (i32.const 32) (i32.const 1)) (i32.const 7)) (i32.const -1) + ) + ) + (func (export "as-storeN-value") (result i32) + (block (result i32) + (i32.store16 (i32.const 2) (br_if 0 (i32.const 33) (i32.const 1))) (i32.const -1) + ) + ) + + (func (export "as-unary-operand") (result f64) + (block (result f64) (f64.neg (br_if 0 (f64.const 1.0) (i32.const 1)))) + ) + (func (export "as-binary-left") (result i32) + (block (result i32) (i32.add (br_if 0 (i32.const 1) (i32.const 1)) (i32.const 10))) + ) + (func (export "as-binary-right") (result i32) + (block (result i32) (i32.sub (i32.const 10) (br_if 0 (i32.const 1) (i32.const 1)))) + ) + (func (export "as-test-operand") (result i32) + (block (result i32) (i32.eqz (br_if 0 (i32.const 0) (i32.const 1)))) + ) + (func (export "as-compare-left") (result i32) + (block (result i32) (i32.le_u (br_if 0 (i32.const 1) (i32.const 1)) (i32.const 10))) + ) + (func (export "as-compare-right") (result i32) + (block (result i32) (i32.ne (i32.const 10) (br_if 0 (i32.const 1) (i32.const 42)))) + ) + + (func (export "as-memory.grow-size") (result i32) + (block (result i32) (memory.grow (br_if 0 (i32.const 1) (i32.const 1)))) + ) + + (func (export "nested-block-value") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (i32.add + (i32.const 4) + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) + (i32.const 16) + ) + ) + ) + ) + ) + + (func (export "nested-br-value") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (br 0 + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) (i32.const 4) + ) + ) + (i32.const 16) + ) + ) + ) + + (func (export "nested-br_if-value") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop (br_if 0 + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) (i32.const 4) + ) + (i32.const 1) + )) + (i32.const 16) + ) + ) + ) + + (func (export "nested-br_if-value-cond") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop (br_if 0 + (i32.const 4) + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) (i32.const 1) + ) + )) + (i32.const 16) + ) + ) + ) + + (func (export "nested-br_table-value") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (br_table 0 + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) (i32.const 4) + ) + (i32.const 1) + ) + (i32.const 16) + ) + ) + ) + + (func (export "nested-br_table-value-index") (param i32) (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (br_table 0 + (i32.const 4) + (block (result i32) + (drop (br_if 1 (i32.const 8) (local.get 0))) (i32.const 1) + ) + ) + (i32.const 16) + ) + ) + ) + +) + +(assert_return (invoke "type-i32")) +(assert_return (invoke "type-i64")) +(assert_return (invoke "type-f32")) +(assert_return (invoke "type-f64")) + +(assert_return (invoke "type-i32-value") (i32.const 1)) +(assert_return (invoke "type-i64-value") (i64.const 2)) +(assert_return (invoke "type-f32-value") (f32.const 3)) +(assert_return (invoke "type-f64-value") (f64.const 4)) + +(assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-block-first" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-block-mid" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-block-last" (i32.const 0))) +(assert_return (invoke "as-block-last" (i32.const 1))) + +(assert_return (invoke "as-block-first-value" (i32.const 0)) (i32.const 11)) +(assert_return (invoke "as-block-first-value" (i32.const 1)) (i32.const 10)) +(assert_return (invoke "as-block-mid-value" (i32.const 0)) (i32.const 21)) +(assert_return (invoke "as-block-mid-value" (i32.const 1)) (i32.const 20)) +(assert_return (invoke "as-block-last-value" (i32.const 0)) (i32.const 11)) +(assert_return (invoke "as-block-last-value" (i32.const 1)) (i32.const 11)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 4)) +(assert_return (invoke "as-loop-last" (i32.const 0))) +(assert_return (invoke "as-loop-last" (i32.const 1))) + +(assert_return (invoke "as-br-value") (i32.const 1)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 1)) +(assert_return (invoke "as-br_if-value-cond" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-br_if-value-cond" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 1)) +(assert_return (invoke "as-br_table-value-index") (i32.const 1)) + +(assert_return (invoke "as-return-value") (i64.const 1)) + +(assert_return (invoke "as-if-cond" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-if-cond" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 0))) +(assert_return (invoke "as-if-then" (i32.const 4) (i32.const 0))) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 1))) +(assert_return (invoke "as-if-then" (i32.const 4) (i32.const 1))) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 0))) +(assert_return (invoke "as-if-else" (i32.const 3) (i32.const 0))) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 1))) +(assert_return (invoke "as-if-else" (i32.const 3) (i32.const 1))) + +(assert_return (invoke "as-select-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-select-first" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-select-second" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-select-second" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-select-cond") (i32.const 3)) + +(assert_return (invoke "as-call-first") (i32.const 12)) +(assert_return (invoke "as-call-mid") (i32.const 13)) +(assert_return (invoke "as-call-last") (i32.const 14)) + +(assert_return (invoke "as-call_indirect-func") (i32.const 4)) +(assert_return (invoke "as-call_indirect-first") (i32.const 4)) +(assert_return (invoke "as-call_indirect-mid") (i32.const 4)) +(assert_return (invoke "as-call_indirect-last") (i32.const 4)) + +(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 17)) + +(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-global.set-value" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-global.set-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-load-address") (i32.const 1)) +(assert_return (invoke "as-loadN-address") (i32.const 30)) + +(assert_return (invoke "as-store-address") (i32.const 30)) +(assert_return (invoke "as-store-value") (i32.const 31)) +(assert_return (invoke "as-storeN-address") (i32.const 32)) +(assert_return (invoke "as-storeN-value") (i32.const 33)) + +(assert_return (invoke "as-unary-operand") (f64.const 1.0)) +(assert_return (invoke "as-binary-left") (i32.const 1)) +(assert_return (invoke "as-binary-right") (i32.const 1)) +(assert_return (invoke "as-test-operand") (i32.const 0)) +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) +(assert_return (invoke "as-memory.grow-size") (i32.const 1)) + +(assert_return (invoke "nested-block-value" (i32.const 0)) (i32.const 21)) +(assert_return (invoke "nested-block-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br-value" (i32.const 0)) (i32.const 5)) +(assert_return (invoke "nested-br-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value" (i32.const 0)) (i32.const 5)) +(assert_return (invoke "nested-br_if-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 0)) (i32.const 5)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value" (i32.const 0)) (i32.const 5)) +(assert_return (invoke "nested-br_table-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 0)) (i32.const 5)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 1)) (i32.const 9)) + +(assert_invalid + (module (func $type-false-i32 (block (i32.ctz (br_if 0 (i32.const 0)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-false-i64 (block (i64.ctz (br_if 0 (i32.const 0)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-false-f32 (block (f32.neg (br_if 0 (i32.const 0)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-false-f64 (block (f64.neg (br_if 0 (i32.const 0)))))) + "type mismatch" +) + +(assert_invalid + (module (func $type-true-i32 (block (i32.ctz (br_if 0 (i32.const 1)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-true-i64 (block (i64.ctz (br_if 0 (i64.const 1)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-true-f32 (block (f32.neg (br_if 0 (f32.const 1)))))) + "type mismatch" +) +(assert_invalid + (module (func $type-true-f64 (block (f64.neg (br_if 0 (i64.const 1)))))) + "type mismatch" +) + +(assert_invalid + (module (func $type-false-arg-void-vs-num (result i32) + (block (result i32) (br_if 0 (i32.const 0)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-true-arg-void-vs-num (result i32) + (block (result i32) (br_if 0 (i32.const 1)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-false-arg-num-vs-void + (block (br_if 0 (i32.const 0) (i32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-true-arg-num-vs-void + (block (br_if 0 (i32.const 0) (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-false-arg-void-vs-num (result i32) + (block (result i32) (br_if 0 (nop) (i32.const 0)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-true-arg-void-vs-num (result i32) + (block (result i32) (br_if 0 (nop) (i32.const 1)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-false-arg-num-vs-num (result i32) + (block (result i32) + (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-true-arg-num-vs-num (result i32) + (block (result i32) + (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-cond-empty-vs-i32 + (block (br_if 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-cond-void-vs-i32 + (block (br_if 0 (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-cond-num-vs-i32 + (block (br_if 0 (i64.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-cond-void-vs-i32 (result i32) + (block (result i32) (br_if 0 (i32.const 0) (nop)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-void-vs-num-nested (result i32) + (block (result i32) (i32.const 0) (block (br_if 1 (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-cond-num-vs-i32 (result i32) + (block (result i32) (br_if 0 (i32.const 0) (i64.const 0)) (i32.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module + (func $type-1st-cond-empty-in-then + (block + (i32.const 0) (i32.const 0) + (if (result i32) (then (br_if 0))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-cond-empty-in-then + (block + (i32.const 0) (i32.const 0) + (if (result i32) (then (br_if 0 (i32.const 1)))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-1st-cond-empty-in-return + (block (result i32) + (return (br_if 0)) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-cond-empty-in-return + (block (result i32) + (return (br_if 0 (i32.const 1))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) + + +(assert_invalid + (module (func $unbound-label (br_if 1 (i32.const 1)))) + "unknown label" +) +(assert_invalid + (module (func $unbound-nested-label (block (block (br_if 5 (i32.const 1)))))) + "unknown label" +) +(assert_invalid + (module (func $large-label (br_if 0x10000001 (i32.const 1)))) + "unknown label" +) + +;; https://github.com/WebAssembly/gc/issues/516 +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t)) (result funcref) (local.get 0)) + (func (result funcref) + (ref.null $t) + (i32.const 0) + (br_if 0) ;; only leaves funcref on the stack + (call $f) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/br_on_cast.wast b/proposals/wasm-3.0/br_on_cast.wast new file mode 100644 index 0000000..3c895c0 --- /dev/null +++ b/proposals/wasm-3.0/br_on_cast.wast @@ -0,0 +1,285 @@ +;; Abstract Types + +(module + (type $ft (func (result i32))) + (type $st (struct (field i16))) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f (result i32) (i32.const 9)) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (ref.i31 (i32.const 7))) + (table.set (i32.const 2) (struct.new $st (i32.const 6))) + (table.set (i32.const 3) (array.new $at (i32.const 5) (i32.const 3))) + (table.set (i32.const 4) (any.convert_extern (local.get $x))) + ) + + (func (export "br_on_null") (param $i i32) (result i32) + (block $l + (br_on_null $l (table.get (local.get $i))) + (return (i32.const -1)) + ) + (i32.const 0) + ) + (func (export "br_on_i31") (param $i i32) (result i32) + (block $l (result (ref i31)) + (br_on_cast $l anyref (ref i31) (table.get (local.get $i))) + (return (i32.const -1)) + ) + (i31.get_u) + ) + (func (export "br_on_struct") (param $i i32) (result i32) + (block $l (result (ref struct)) + (br_on_cast $l anyref (ref struct) (table.get (local.get $i))) + (return (i32.const -1)) + ) + (block $l2 (param structref) (result (ref $st)) + (block $l3 (param structref) (result (ref $at)) + (br_on_cast $l2 structref (ref $st)) + (br_on_cast $l3 anyref (ref $at)) + (return (i32.const -2)) + ) + (return (array.get_u $at (i32.const 0))) + ) + (struct.get_s $st 0) + ) + (func (export "br_on_array") (param $i i32) (result i32) + (block $l (result (ref array)) + (br_on_cast $l anyref (ref array) (table.get (local.get $i))) + (return (i32.const -1)) + ) + (array.len) + ) + + (func (export "null-diff") (param $i i32) (result i32) + (block $l (result (ref null struct)) + (block (result (ref any)) + (br_on_cast $l (ref null any) (ref null struct) (table.get (local.get $i))) + ) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) +) + +(invoke "init" (ref.extern 0)) + +(assert_return (invoke "br_on_null" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "br_on_null" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_null" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_null" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_null" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_i31" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_i31" (i32.const 1)) (i32.const 7)) +(assert_return (invoke "br_on_i31" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_i31" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_i31" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_struct" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_struct" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_struct" (i32.const 2)) (i32.const 6)) +(assert_return (invoke "br_on_struct" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_struct" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_array" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_array" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_array" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_array" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "br_on_array" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "null-diff" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "null-diff" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "null-diff" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "null-diff" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "null-diff" (i32.const 4)) (i32.const 0)) + + +;; Concrete Types + +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 structref) + + (func $init + (table.set (i32.const 0) (struct.new_default $t0)) + (table.set (i32.const 10) (struct.new_default $t0')) + (table.set (i32.const 1) (struct.new_default $t1)) + (table.set (i32.const 11) (struct.new_default $t1')) + (table.set (i32.const 2) (struct.new_default $t2)) + (table.set (i32.const 12) (struct.new_default $t2')) + (table.set (i32.const 3) (struct.new_default $t3)) + (table.set (i32.const 4) (struct.new_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l (result structref) + ;; must succeed + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (ref.null struct)))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 2))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 3))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 4))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t1) (ref.null struct)))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 2))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t2) (ref.null struct)))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t2) (table.get (i32.const 2))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t3) (ref.null struct)))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t3) (table.get (i32.const 3))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t4) (ref.null struct)))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t4) (table.get (i32.const 4))))) + + ;; must not succeed + (br_on_cast $l anyref (ref $t1) (table.get (i32.const 0))) + (br_on_cast $l anyref (ref $t1) (table.get (i32.const 3))) + (br_on_cast $l anyref (ref $t1) (table.get (i32.const 4))) + + (br_on_cast $l anyref (ref $t2) (table.get (i32.const 0))) + (br_on_cast $l anyref (ref $t2) (table.get (i32.const 1))) + (br_on_cast $l anyref (ref $t2) (table.get (i32.const 3))) + (br_on_cast $l anyref (ref $t2) (table.get (i32.const 4))) + + (br_on_cast $l anyref (ref $t3) (table.get (i32.const 0))) + (br_on_cast $l anyref (ref $t3) (table.get (i32.const 1))) + (br_on_cast $l anyref (ref $t3) (table.get (i32.const 2))) + (br_on_cast $l anyref (ref $t3) (table.get (i32.const 4))) + + (br_on_cast $l anyref (ref $t4) (table.get (i32.const 0))) + (br_on_cast $l anyref (ref $t4) (table.get (i32.const 1))) + (br_on_cast $l anyref (ref $t4) (table.get (i32.const 2))) + (br_on_cast $l anyref (ref $t4) (table.get (i32.const 3))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l + (drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 2))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 3))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0') (table.get (i32.const 4))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 10))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 11))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t0) (table.get (i32.const 12))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t1') (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t1') (table.get (i32.const 2))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 11))))) + (drop (block (result structref) (br_on_cast 0 structref (ref $t1) (table.get (i32.const 12))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t2') (table.get (i32.const 2))))) + + (drop (block (result structref) (br_on_cast 0 structref (ref $t2) (table.get (i32.const 12))))) + + (return) + ) + (unreachable) + ) +) + +(invoke "test-sub") +(invoke "test-canon") + + +;; Cases of nullability + +(module + (type $t (struct)) + + (func (param (ref any)) (result (ref $t)) + (block (result (ref any)) (br_on_cast 1 (ref any) (ref $t) (local.get 0))) (unreachable) + ) + (func (param (ref null any)) (result (ref $t)) + (block (result (ref null any)) (br_on_cast 1 (ref null any) (ref $t) (local.get 0))) (unreachable) + ) + (func (param (ref null any)) (result (ref null $t)) + (block (result (ref null any)) (br_on_cast 1 (ref null any) (ref null $t) (local.get 0))) (unreachable) + ) +) + +(assert_invalid + (module + (type $t (struct)) + (func (param (ref any)) (result (ref $t)) + (block (result (ref any)) (br_on_cast 1 (ref null any) (ref null $t) (local.get 0))) (unreachable) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (struct)) + (func (param (ref any)) (result (ref null $t)) + (block (result (ref any)) (br_on_cast 1 (ref any) (ref null $t) (local.get 0))) (unreachable) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (struct)) + (func (param (ref null any)) (result (ref $t)) + (block (result (ref any)) (br_on_cast 1 (ref null any) (ref $t) (local.get 0))) (unreachable) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (result anyref) + (br_on_cast 0 eqref anyref (unreachable)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (result anyref) + (br_on_cast 0 structref arrayref (unreachable)) + ) + ) + "type mismatch" +) + + +;; https://github.com/WebAssembly/gc/issues/516 +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t)) (result funcref) (local.get 0)) + (func (param funcref) (result funcref funcref) + (ref.null $t) + (local.get 0) + (br_on_cast 0 funcref (ref $t)) ;; only leaves two funcref's on the stack + (drop) + (call $f) + (local.get 0) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/br_on_cast_fail.wast b/proposals/wasm-3.0/br_on_cast_fail.wast new file mode 100644 index 0000000..db6db11 --- /dev/null +++ b/proposals/wasm-3.0/br_on_cast_fail.wast @@ -0,0 +1,300 @@ +;; Abstract Types + +(module + (type $ft (func (result i32))) + (type $st (struct (field i16))) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f (result i32) (i32.const 9)) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (ref.i31 (i32.const 7))) + (table.set (i32.const 2) (struct.new $st (i32.const 6))) + (table.set (i32.const 3) (array.new $at (i32.const 5) (i32.const 3))) + (table.set (i32.const 4) (any.convert_extern (local.get $x))) + ) + + (func (export "br_on_non_null") (param $i i32) (result i32) + (block $l (result (ref any)) + (br_on_non_null $l (table.get (local.get $i))) + (return (i32.const 0)) + ) + (return (i32.const -1)) + ) + (func (export "br_on_non_i31") (param $i i32) (result i32) + (block $l (result anyref) + (br_on_cast_fail $l anyref (ref i31) (table.get (local.get $i))) + (return (i31.get_u)) + ) + (return (i32.const -1)) + ) + (func (export "br_on_non_struct") (param $i i32) (result i32) + (block $l (result anyref) + (br_on_cast_fail $l anyref (ref struct) (table.get (local.get $i))) + (block $l2 (param structref) (result (ref $st)) + (block $l3 (param structref) (result (ref $at)) + (br_on_cast $l2 structref (ref $st)) + (br_on_cast $l3 anyref (ref $at)) + (return (i32.const -2)) + ) + (return (array.get_u $at (i32.const 0))) + ) + (return (struct.get_s $st 0)) + ) + (return (i32.const -1)) + ) + (func (export "br_on_non_array") (param $i i32) (result i32) + (block $l (result anyref) + (br_on_cast_fail $l anyref (ref array) (table.get (local.get $i))) + (return (array.len)) + ) + (return (i32.const -1)) + ) + + (func (export "null-diff") (param $i i32) (result i32) + (block $l (result (ref any)) + (block (result (ref null struct)) + (br_on_cast_fail $l (ref null any) (ref null struct) (table.get (local.get $i))) + ) + (return (i32.const 1)) + ) + (return (i32.const 0)) + ) +) + +(invoke "init" (ref.extern 0)) + +(assert_return (invoke "br_on_non_null" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "br_on_non_null" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_non_null" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_non_null" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_non_null" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_non_i31" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_non_i31" (i32.const 1)) (i32.const 7)) +(assert_return (invoke "br_on_non_i31" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_non_i31" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_non_i31" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_non_struct" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_non_struct" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_non_struct" (i32.const 2)) (i32.const 6)) +(assert_return (invoke "br_on_non_struct" (i32.const 3)) (i32.const -1)) +(assert_return (invoke "br_on_non_struct" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "br_on_non_array" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "br_on_non_array" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "br_on_non_array" (i32.const 2)) (i32.const -1)) +(assert_return (invoke "br_on_non_array" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "br_on_non_array" (i32.const 4)) (i32.const -1)) + +(assert_return (invoke "null-diff" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "null-diff" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "null-diff" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "null-diff" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "null-diff" (i32.const 4)) (i32.const 0)) + + +;; Concrete Types + +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 structref) + + (func $init + (table.set (i32.const 0) (struct.new_default $t0)) + (table.set (i32.const 10) (struct.new_default $t0)) + (table.set (i32.const 1) (struct.new_default $t1)) + (table.set (i32.const 11) (struct.new_default $t1')) + (table.set (i32.const 2) (struct.new_default $t2)) + (table.set (i32.const 12) (struct.new_default $t2')) + (table.set (i32.const 3) (struct.new_default $t3 )) + (table.set (i32.const 4) (struct.new_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l (result structref) + ;; must not succeed + (br_on_cast_fail $l structref (ref null $t0) (ref.null struct)) + (br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 0))) + (br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 2))) + (br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 3))) + (br_on_cast_fail $l structref (ref null $t0) (table.get (i32.const 4))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 0))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 2))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 3))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 4))) + + (br_on_cast_fail $l structref (ref null $t1) (ref.null struct)) + (br_on_cast_fail $l structref (ref null $t1) (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref null $t1) (table.get (i32.const 2))) + (br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 2))) + + (br_on_cast_fail $l structref (ref null $t2) (ref.null struct)) + (br_on_cast_fail $l structref (ref null $t2) (table.get (i32.const 2))) + (br_on_cast_fail $l structref (ref $t2) (table.get (i32.const 2))) + + (br_on_cast_fail $l structref (ref null $t3) (ref.null struct)) + (br_on_cast_fail $l structref (ref null $t3) (table.get (i32.const 3))) + (br_on_cast_fail $l structref (ref $t3) (table.get (i32.const 3))) + + (br_on_cast_fail $l structref (ref null $t4) (ref.null struct)) + (br_on_cast_fail $l structref (ref null $t4) (table.get (i32.const 4))) + (br_on_cast_fail $l structref (ref $t4) (table.get (i32.const 4))) + + ;; must succeed + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t0) (ref.null struct)))) + + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (ref.null struct)))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 3))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t1) (table.get (i32.const 4))))) + + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (ref.null struct)))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 3))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t2) (table.get (i32.const 4))))) + + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (ref.null struct)))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 2))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t3) (table.get (i32.const 4))))) + + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (ref.null struct)))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 0))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 1))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 2))))) + (drop (block (result structref) (br_on_cast_fail 0 structref (ref $t4) (table.get (i32.const 3))))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l (result structref) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 0))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 2))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 3))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 4))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 10))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 11))) + (br_on_cast_fail $l structref (ref $t0) (table.get (i32.const 12))) + + (br_on_cast_fail $l structref (ref $t1') (table.get (i32.const 1))) + (br_on_cast_fail $l structref (ref $t1') (table.get (i32.const 2))) + + (br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 11))) + (br_on_cast_fail $l structref (ref $t1) (table.get (i32.const 12))) + + (br_on_cast_fail $l structref (ref $t2') (table.get (i32.const 2))) + + (br_on_cast_fail $l structref (ref $t2) (table.get (i32.const 12))) + + (return) + ) + (unreachable) + ) +) + +(invoke "test-sub") +(invoke "test-canon") + + +;; Cases of nullability + +(module + (type $t (struct)) + + (func (param (ref any)) (result (ref any)) + (block (result (ref $t)) (br_on_cast_fail 1 (ref any) (ref $t) (local.get 0))) + ) + (func (param (ref null any)) (result (ref null any)) + (block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref $t) (local.get 0))) + ) + (func (param (ref null any)) (result (ref null any)) + (block (result (ref null $t)) (br_on_cast_fail 1 (ref null any) (ref null $t) (local.get 0))) + ) +) + +(assert_invalid + (module + (type $t (struct)) + (func (param (ref any)) (result (ref any)) + (block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref null $t) (local.get 0))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (struct)) + (func (param (ref any)) (result (ref any)) + (block (result (ref null $t)) (br_on_cast_fail 1 (ref any) (ref null $t) (local.get 0))) (ref.as_non_null) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (struct)) + (func (param (ref null any)) (result (ref any)) + (block (result (ref $t)) (br_on_cast_fail 1 (ref null any) (ref $t) (local.get 0))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (result anyref) + (br_on_cast_fail 0 eqref anyref (unreachable)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (result anyref) + (br_on_cast_fail 0 structref arrayref (unreachable)) + ) + ) + "type mismatch" +) + + +;; https://github.com/WebAssembly/gc/issues/516 +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t)) (result funcref) (local.get 0)) + (func (param funcref) (result funcref funcref) + (ref.null $t) + (local.get 0) + (br_on_cast_fail 0 funcref (ref $t)) ;; only leaves two funcref's on the stack + (drop) + (call $f) + (local.get 0) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/br_on_non_null.wast b/proposals/wasm-3.0/br_on_non_null.wast new file mode 100644 index 0000000..4380019 --- /dev/null +++ b/proposals/wasm-3.0/br_on_non_null.wast @@ -0,0 +1,90 @@ +(module + (type $t (func (result i32))) + + (func $nn (param $r (ref $t)) (result i32) + (call_ref $t + (block $l (result (ref $t)) + (br_on_non_null $l (local.get $r)) + (return (i32.const -1)) + ) + ) + ) + (func $n (param $r (ref null $t)) (result i32) + (call_ref $t + (block $l (result (ref $t)) + (br_on_non_null $l (local.get $r)) + (return (i32.const -1)) + ) + ) + ) + + (elem func $f) + (func $f (result i32) (i32.const 7)) + + (func (export "nullable-null") (result i32) (call $n (ref.null $t))) + (func (export "nonnullable-f") (result i32) (call $nn (ref.func $f))) + (func (export "nullable-f") (result i32) (call $n (ref.func $f))) + + (func (export "unreachable") (result i32) + (block $l (result (ref $t)) + (br_on_non_null $l (unreachable)) + (return (i32.const -1)) + ) + (call_ref $t) + ) +) + +(assert_trap (invoke "unreachable") "unreachable") + +(assert_return (invoke "nullable-null") (i32.const -1)) +(assert_return (invoke "nonnullable-f") (i32.const 7)) +(assert_return (invoke "nullable-f") (i32.const 7)) + +(module + (type $t (func)) + (func (param $r (ref null $t)) (drop (block (result (ref $t)) (br_on_non_null 0 (local.get $r)) (unreachable)))) + (func (param $r (ref null func)) (drop (block (result (ref func)) (br_on_non_null 0 (local.get $r)) (unreachable)))) + (func (param $r (ref null extern)) (drop (block (result (ref extern)) (br_on_non_null 0 (local.get $r)) (unreachable)))) +) + + +(module + (type $t (func (param i32) (result i32))) + (elem func $f) + (func $f (param i32) (result i32) (i32.mul (local.get 0) (local.get 0))) + + (func $a (param $n i32) (param $r (ref null $t)) (result i32) + (call_ref $t + (block $l (result i32 (ref $t)) + (return (br_on_non_null $l (local.get $n) (local.get $r))) + ) + ) + ) + + (func (export "args-null") (param $n i32) (result i32) + (call $a (local.get $n) (ref.null $t)) + ) + (func (export "args-f") (param $n i32) (result i32) + (call $a (local.get $n) (ref.func $f)) + ) +) + +(assert_return (invoke "args-null" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "args-f" (i32.const 3)) (i32.const 9)) + + +;; https://github.com/WebAssembly/gc/issues/516 +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t)) (result funcref) (local.get 0)) + (func (param funcref) (result funcref funcref) + (ref.null $t) + (local.get 0) + (br_on_non_null 0) ;; only leaves a funcref on the stack + (call $f) + (local.get 0) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/br_on_null.wast b/proposals/wasm-3.0/br_on_null.wast new file mode 100644 index 0000000..e47dae5 --- /dev/null +++ b/proposals/wasm-3.0/br_on_null.wast @@ -0,0 +1,94 @@ +(module + (type $t (func (result i32))) + + (func $nn (param $r (ref $t)) (result i32) + (block $l + (return (call_ref $t (br_on_null $l (local.get $r)))) + ) + (i32.const -1) + ) + (func $n (param $r (ref null $t)) (result i32) + (block $l + (return (call_ref $t (br_on_null $l (local.get $r)))) + ) + (i32.const -1) + ) + + (elem func $f) + (func $f (result i32) (i32.const 7)) + + (func (export "nullable-null") (result i32) (call $n (ref.null $t))) + (func (export "nonnullable-f") (result i32) (call $nn (ref.func $f))) + (func (export "nullable-f") (result i32) (call $n (ref.func $f))) + + (func (export "unreachable") (result i32) + (block $l + (return (call_ref $t (br_on_null $l (unreachable)))) + ) + (i32.const -1) + ) +) + +(assert_trap (invoke "unreachable") "unreachable") + +(assert_return (invoke "nullable-null") (i32.const -1)) +(assert_return (invoke "nonnullable-f") (i32.const 7)) +(assert_return (invoke "nullable-f") (i32.const 7)) + +(module + (type $t (func)) + (func (param $r (ref null $t)) (drop (br_on_null 0 (local.get $r)))) + (func (param $r (ref null func)) (drop (br_on_null 0 (local.get $r)))) + (func (param $r (ref null extern)) (drop (br_on_null 0 (local.get $r)))) +) + + +(module + (type $t (func (param i32) (result i32))) + (elem func $f) + (func $f (param i32) (result i32) (i32.mul (local.get 0) (local.get 0))) + + (func $a (param $n i32) (param $r (ref null $t)) (result i32) + (block $l (result i32) + (return (call_ref $t (br_on_null $l (local.get $n) (local.get $r)))) + ) + ) + + (func (export "args-null") (param $n i32) (result i32) + (call $a (local.get $n) (ref.null $t)) + ) + (func (export "args-f") (param $n i32) (result i32) + (call $a (local.get $n) (ref.func $f)) + ) +) + +(assert_return (invoke "args-null" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "args-f" (i32.const 3)) (i32.const 9)) + + +;; https://github.com/WebAssembly/gc/issues/516 +;; Tests that validators are correctly doing +;; +;; pop_operands(label_types) +;; push_operands(label_types) +;; +;; for validating br_on_null, rather than incorrectly doing either +;; +;; push_operands(pop_operands(label_types)) +;; +;; or just inspecting the types on the stack without any pushing or +;; popping, neither of which handle subtyping correctly. +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t)) (result funcref) (local.get 0)) + (func (param funcref) (result funcref) + (ref.null $t) + (local.get 0) + (br_on_null 0) ;; only leaves two funcref's on the stack + (drop) + (call $f) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/br_table.wast b/proposals/wasm-3.0/br_table.wast new file mode 100644 index 0000000..2a5197c --- /dev/null +++ b/proposals/wasm-3.0/br_table.wast @@ -0,0 +1,1465 @@ +;; Test `br_table` operator + +(module + ;; Auxiliary definition + (func $dummy) + + (func (export "type-i32") + (block (drop (i32.ctz (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-i64") + (block (drop (i64.ctz (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-f32") + (block (drop (f32.neg (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-f64") + (block (drop (f64.neg (br_table 0 0 (i32.const 0))))) + ) + + (func (export "type-i32-value") (result i32) + (block (result i32) (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0)))) + ) + (func (export "type-i64-value") (result i64) + (block (result i64) (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0)))) + ) + (func (export "type-f32-value") (result f32) + (block (result f32) (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0)))) + ) + (func (export "type-f64-value") (result f64) + (block (result f64) (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0)))) + ) + + (func (export "empty") (param i32) (result i32) + (block (br_table 0 (local.get 0)) (return (i32.const 21))) + (i32.const 22) + ) + (func (export "empty-value") (param i32) (result i32) + (block (result i32) + (br_table 0 (i32.const 33) (local.get 0)) (i32.const 31) + ) + ) + + (func (export "singleton") (param i32) (result i32) + (block + (block + (br_table 1 0 (local.get 0)) + (return (i32.const 21)) + ) + (return (i32.const 20)) + ) + (i32.const 22) + ) + + (func (export "singleton-value") (param i32) (result i32) + (block (result i32) + (drop + (block (result i32) + (br_table 0 1 (i32.const 33) (local.get 0)) + (return (i32.const 31)) + ) + ) + (i32.const 32) + ) + ) + + (func (export "multiple") (param i32) (result i32) + (block + (block + (block + (block + (block + (br_table 3 2 1 0 4 (local.get 0)) + (return (i32.const 99)) + ) + (return (i32.const 100)) + ) + (return (i32.const 101)) + ) + (return (i32.const 102)) + ) + (return (i32.const 103)) + ) + (i32.const 104) + ) + + (func (export "multiple-value") (param i32) (result i32) + (local i32) + (local.set 1 (block (result i32) + (local.set 1 (block (result i32) + (local.set 1 (block (result i32) + (local.set 1 (block (result i32) + (local.set 1 (block (result i32) + (br_table 3 2 1 0 4 (i32.const 200) (local.get 0)) + (return (i32.add (local.get 1) (i32.const 99))) + )) + (return (i32.add (local.get 1) (i32.const 10))) + )) + (return (i32.add (local.get 1) (i32.const 11))) + )) + (return (i32.add (local.get 1) (i32.const 12))) + )) + (return (i32.add (local.get 1) (i32.const 13))) + )) + (i32.add (local.get 1) (i32.const 14)) + ) + + (func (export "large") (param i32) (result i32) + (block + (block + (br_table + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 + (local.get 0) + ) + (return (i32.const -1)) + ) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) + + (func (export "as-block-first") + (block (br_table 0 0 0 (i32.const 0)) (call $dummy)) + ) + (func (export "as-block-mid") + (block (call $dummy) (br_table 0 0 0 (i32.const 0)) (call $dummy)) + ) + (func (export "as-block-last") + (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 0))) + ) + (func (export "as-block-value") (result i32) + (block (result i32) + (nop) (call $dummy) (br_table 0 0 0 (i32.const 2) (i32.const 0)) + ) + ) + + (func (export "as-loop-first") (result i32) + (loop (result i32) (br_table 1 1 (i32.const 3) (i32.const 0)) (i32.const 1)) + ) + (func (export "as-loop-mid") (result i32) + (loop (result i32) + (call $dummy) + (br_table 1 1 1 (i32.const 4) (i32.const -1)) + (i32.const 2) + ) + ) + (func (export "as-loop-last") (result i32) + (loop (result i32) + (nop) (call $dummy) (br_table 1 1 1 (i32.const 5) (i32.const 1)) + ) + ) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (br_table 0 (i32.const 9) (i32.const 0)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (br_table 0 0 0 (i32.const 1)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (br_table 0 (i32.const 8) (i32.const 0)) (i32.const 1))) + (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (br_table 0 0 (i32.const 9) (i32.const 0)))) + (i32.const 7) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (br_table 0 (i32.const 1)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (br_table 0 (i32.const 10) (i32.const 0)) (i32.const 1)) + (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (br_table 0 (i32.const 11) (i32.const 1))) + (i32.const 7) + ) + ) + + (func (export "as-return-value") (result i64) + (block (result i64) (return (br_table 0 (i64.const 7) (i32.const 0)))) + ) + + (func (export "as-if-cond") (result i32) + (block (result i32) + (if (result i32) + (br_table 0 (i32.const 2) (i32.const 0)) + (then (i32.const 0)) + (else (i32.const 1)) + ) + ) + ) + (func (export "as-if-then") (param i32 i32) (result i32) + (block (result i32) + (if (result i32) + (local.get 0) + (then (br_table 1 (i32.const 3) (i32.const 0))) + (else (local.get 1)) + ) + ) + ) + (func (export "as-if-else") (param i32 i32) (result i32) + (block (result i32) + (if (result i32) + (local.get 0) + (then (local.get 1)) + (else (br_table 1 0 (i32.const 4) (i32.const 0))) + ) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (block (result i32) + (select + (br_table 0 (i32.const 5) (i32.const 0)) (local.get 0) (local.get 1) + ) + ) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (block (result i32) + (select + (local.get 0) (br_table 0 (i32.const 6) (i32.const 1)) (local.get 1) + ) + ) + ) + (func (export "as-select-cond") (result i32) + (block (result i32) + (select + (i32.const 0) (i32.const 1) (br_table 0 (i32.const 7) (i32.const 1)) + ) + ) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (block (result i32) + (call $f + (br_table 0 (i32.const 12) (i32.const 1)) (i32.const 2) (i32.const 3) + ) + ) + ) + (func (export "as-call-mid") (result i32) + (block (result i32) + (call $f + (i32.const 1) (br_table 0 (i32.const 13) (i32.const 1)) (i32.const 3) + ) + ) + ) + (func (export "as-call-last") (result i32) + (block (result i32) + (call $f + (i32.const 1) (i32.const 2) (br_table 0 (i32.const 14) (i32.const 1)) + ) + ) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (result i32) + (block (result i32) + (call_indirect (type $sig) + (br_table 0 (i32.const 20) (i32.const 1)) (i32.const 1) (i32.const 2) + (i32.const 3) + ) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (block (result i32) + (call_indirect (type $sig) + (i32.const 0) (br_table 0 (i32.const 21) (i32.const 1)) (i32.const 2) + (i32.const 3) + ) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (block (result i32) + (call_indirect (type $sig) + (i32.const 0) (i32.const 1) (br_table 0 (i32.const 22) (i32.const 1)) + (i32.const 3) + ) + ) + ) + (func (export "as-call_indirect-func") (result i32) + (block (result i32) + (call_indirect (type $sig) + (i32.const 0) (i32.const 1) (i32.const 2) + (br_table 0 (i32.const 23) (i32.const 1)) + ) + ) + ) + + (func (export "as-local.set-value") (result i32) + (local f32) + (block (result i32) + (local.set 0 (br_table 0 (i32.const 17) (i32.const 1))) + (i32.const -1) + ) + ) + (func (export "as-local.tee-value") (result i32) + (local i32) + (block (result i32) + (local.set 0 (br_table 0 (i32.const 1) (i32.const 1))) + (i32.const -1) + ) + ) + (global $a (mut i32) (i32.const 10)) + (func (export "as-global.set-value") (result i32) + (block (result i32) + (global.set $a (br_table 0 (i32.const 1) (i32.const 1))) + (i32.const -1) + ) + ) + + (memory 1) + (func (export "as-load-address") (result f32) + (block (result f32) (f32.load (br_table 0 (f32.const 1.7) (i32.const 1)))) + ) + (func (export "as-loadN-address") (result i64) + (block (result i64) (i64.load8_s (br_table 0 (i64.const 30) (i32.const 1)))) + ) + + (func (export "as-store-address") (result i32) + (block (result i32) + (f64.store (br_table 0 (i32.const 30) (i32.const 1)) (f64.const 7)) + (i32.const -1) + ) + ) + (func (export "as-store-value") (result i32) + (block (result i32) + (i64.store (i32.const 2) (br_table 0 (i32.const 31) (i32.const 1))) + (i32.const -1) + ) + ) + + (func (export "as-storeN-address") (result i32) + (block (result i32) + (i32.store8 (br_table 0 (i32.const 32) (i32.const 0)) (i32.const 7)) + (i32.const -1) + ) + ) + (func (export "as-storeN-value") (result i32) + (block (result i32) + (i64.store16 (i32.const 2) (br_table 0 (i32.const 33) (i32.const 0))) + (i32.const -1) + ) + ) + + (func (export "as-unary-operand") (result f32) + (block (result f32) (f32.neg (br_table 0 (f32.const 3.4) (i32.const 0)))) + ) + + (func (export "as-binary-left") (result i32) + (block (result i32) + (i32.add (br_table 0 0 (i32.const 3) (i32.const 0)) (i32.const 10)) + ) + ) + (func (export "as-binary-right") (result i64) + (block (result i64) + (i64.sub (i64.const 10) (br_table 0 (i64.const 45) (i32.const 0))) + ) + ) + + (func (export "as-test-operand") (result i32) + (block (result i32) (i32.eqz (br_table 0 (i32.const 44) (i32.const 0)))) + ) + + (func (export "as-compare-left") (result i32) + (block (result i32) + (f64.le (br_table 0 0 (i32.const 43) (i32.const 0)) (f64.const 10)) + ) + ) + (func (export "as-compare-right") (result i32) + (block (result i32) + (f32.ne (f32.const 10) (br_table 0 (i32.const 42) (i32.const 0))) + ) + ) + + (func (export "as-convert-operand") (result i32) + (block (result i32) + (i32.wrap_i64 (br_table 0 (i32.const 41) (i32.const 0))) + ) + ) + + (func (export "as-memory.grow-size") (result i32) + (block (result i32) (memory.grow (br_table 0 (i32.const 40) (i32.const 0)))) + ) + + (func (export "nested-block-value") (param i32) (result i32) + (block (result i32) + (drop (i32.const -1)) + (i32.add + (i32.const 1) + (block (result i32) + (i32.add + (i32.const 2) + (block (result i32) + (drop (i32.const 4)) + (i32.add + (i32.const 8) + (br_table 0 1 2 (i32.const 16) (local.get 0)) + ) + ) + ) + ) + ) + ) + ) + + (func (export "nested-br-value") (param i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop + (block (result i32) + (drop (i32.const 4)) + (br 0 (br_table 2 1 0 (i32.const 8) (local.get 0))) + ) + ) + (i32.const 16) + ) + ) + ) + ) + + (func (export "nested-br_if-value") (param i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop + (block (result i32) + (drop (i32.const 4)) + (drop + (br_if 0 + (br_table 0 1 2 (i32.const 8) (local.get 0)) + (i32.const 1) + ) + ) + (i32.const 32) + ) + ) + (i32.const 16) + ) + ) + ) + ) + + (func (export "nested-br_if-value-cond") (param i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop + (br_if 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (local.get 0))) + ) + (i32.const 16) + ) + ) + ) + ) + + (func (export "nested-br_table-value") (param i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (drop + (block (result i32) + (drop (i32.const 4)) + (br_table 0 (br_table 0 1 2 (i32.const 8) (local.get 0)) (i32.const 1)) + (i32.const 32) + ) + ) + (i32.const 16) + ) + ) + ) + ) + + (func (export "nested-br_table-value-index") (param i32) (result i32) + (block (result i32) + (i32.add + (i32.const 1) + (block (result i32) + (drop (i32.const 2)) + (br_table 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (local.get 0))) + (i32.const 16) + ) + ) + ) + ) + + (func (export "nested-br_table-loop-block") (param i32) (result i32) + (local.set 0 + (loop (result i32) + (block + (br_table 1 0 0 (local.get 0)) + ) + (i32.const 0) + ) + ) + (loop (result i32) + (block + (br_table 0 1 1 (local.get 0)) + ) + (i32.const 3) + ) + ) + + (func (export "meet-externref") (param i32) (param externref) (result externref) + (block $l1 (result externref) + (block $l2 (result externref) + (br_table $l1 $l2 $l1 (local.get 1) (local.get 0)) + ) + ) + ) + + (func (export "meet-bottom") + (block (result f64) + (block (result f32) + (unreachable) + (br_table 0 1 1 (i32.const 1)) + ) + (drop) + (f64.const 0) + ) + (drop) + ) + + (type $t (func)) + (func $tf) + (table $t (ref null $t) (elem $tf)) + (func (export "meet-funcref-1") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (br_table $l1 $l1 $l2 (table.get $t (i32.const 0)) (local.get 0)) + ) + ) + ) + (func (export "meet-funcref-2") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (br_table $l2 $l2 $l1 (table.get $t (i32.const 0)) (local.get 0)) + ) + ) + ) + (func (export "meet-funcref-3") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (br_table $l2 $l1 $l2 (table.get $t (i32.const 0)) (local.get 0)) + ) + ) + ) + (func (export "meet-funcref-4") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (br_table $l1 $l2 $l1 (table.get $t (i32.const 0)) (local.get 0)) + ) + ) + ) + + (func (export "meet-nullref") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (br_table $l1 $l2 $l1 (ref.null $t) (local.get 0)) + ) + ) + ) + + (func (export "meet-multi-ref") (param i32) (result (ref null func)) + (block $l1 (result (ref null func)) + (block $l2 (result (ref null $t)) + (block $l3 (result (ref $t)) + (br_table $l3 $l2 $l1 (ref.func $tf) (local.get 0)) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32")) +(assert_return (invoke "type-i64")) +(assert_return (invoke "type-f32")) +(assert_return (invoke "type-f64")) + +(assert_return (invoke "type-i32-value") (i32.const 1)) +(assert_return (invoke "type-i64-value") (i64.const 2)) +(assert_return (invoke "type-f32-value") (f32.const 3)) +(assert_return (invoke "type-f64-value") (f64.const 4)) + +(assert_return (invoke "empty" (i32.const 0)) (i32.const 22)) +(assert_return (invoke "empty" (i32.const 1)) (i32.const 22)) +(assert_return (invoke "empty" (i32.const 11)) (i32.const 22)) +(assert_return (invoke "empty" (i32.const -1)) (i32.const 22)) +(assert_return (invoke "empty" (i32.const -100)) (i32.const 22)) +(assert_return (invoke "empty" (i32.const 0xffffffff)) (i32.const 22)) + +(assert_return (invoke "empty-value" (i32.const 0)) (i32.const 33)) +(assert_return (invoke "empty-value" (i32.const 1)) (i32.const 33)) +(assert_return (invoke "empty-value" (i32.const 11)) (i32.const 33)) +(assert_return (invoke "empty-value" (i32.const -1)) (i32.const 33)) +(assert_return (invoke "empty-value" (i32.const -100)) (i32.const 33)) +(assert_return (invoke "empty-value" (i32.const 0xffffffff)) (i32.const 33)) + +(assert_return (invoke "singleton" (i32.const 0)) (i32.const 22)) +(assert_return (invoke "singleton" (i32.const 1)) (i32.const 20)) +(assert_return (invoke "singleton" (i32.const 11)) (i32.const 20)) +(assert_return (invoke "singleton" (i32.const -1)) (i32.const 20)) +(assert_return (invoke "singleton" (i32.const -100)) (i32.const 20)) +(assert_return (invoke "singleton" (i32.const 0xffffffff)) (i32.const 20)) + +(assert_return (invoke "singleton-value" (i32.const 0)) (i32.const 32)) +(assert_return (invoke "singleton-value" (i32.const 1)) (i32.const 33)) +(assert_return (invoke "singleton-value" (i32.const 11)) (i32.const 33)) +(assert_return (invoke "singleton-value" (i32.const -1)) (i32.const 33)) +(assert_return (invoke "singleton-value" (i32.const -100)) (i32.const 33)) +(assert_return (invoke "singleton-value" (i32.const 0xffffffff)) (i32.const 33)) + +(assert_return (invoke "multiple" (i32.const 0)) (i32.const 103)) +(assert_return (invoke "multiple" (i32.const 1)) (i32.const 102)) +(assert_return (invoke "multiple" (i32.const 2)) (i32.const 101)) +(assert_return (invoke "multiple" (i32.const 3)) (i32.const 100)) +(assert_return (invoke "multiple" (i32.const 4)) (i32.const 104)) +(assert_return (invoke "multiple" (i32.const 5)) (i32.const 104)) +(assert_return (invoke "multiple" (i32.const 6)) (i32.const 104)) +(assert_return (invoke "multiple" (i32.const 10)) (i32.const 104)) +(assert_return (invoke "multiple" (i32.const -1)) (i32.const 104)) +(assert_return (invoke "multiple" (i32.const 0xffffffff)) (i32.const 104)) + +(assert_return (invoke "multiple-value" (i32.const 0)) (i32.const 213)) +(assert_return (invoke "multiple-value" (i32.const 1)) (i32.const 212)) +(assert_return (invoke "multiple-value" (i32.const 2)) (i32.const 211)) +(assert_return (invoke "multiple-value" (i32.const 3)) (i32.const 210)) +(assert_return (invoke "multiple-value" (i32.const 4)) (i32.const 214)) +(assert_return (invoke "multiple-value" (i32.const 5)) (i32.const 214)) +(assert_return (invoke "multiple-value" (i32.const 6)) (i32.const 214)) +(assert_return (invoke "multiple-value" (i32.const 10)) (i32.const 214)) +(assert_return (invoke "multiple-value" (i32.const -1)) (i32.const 214)) +(assert_return (invoke "multiple-value" (i32.const 0xffffffff)) (i32.const 214)) + +(assert_return (invoke "large" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "large" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "large" (i32.const 100)) (i32.const 0)) +(assert_return (invoke "large" (i32.const 101)) (i32.const 1)) +(assert_return (invoke "large" (i32.const 10000)) (i32.const 0)) +(assert_return (invoke "large" (i32.const 10001)) (i32.const 1)) +(assert_return (invoke "large" (i32.const 1000000)) (i32.const 1)) +(assert_return (invoke "large" (i32.const 1000001)) (i32.const 1)) + +(assert_return (invoke "as-block-first")) +(assert_return (invoke "as-block-mid")) +(assert_return (invoke "as-block-last")) +(assert_return (invoke "as-block-value") (i32.const 2)) + +(assert_return (invoke "as-loop-first") (i32.const 3)) +(assert_return (invoke "as-loop-mid") (i32.const 4)) +(assert_return (invoke "as-loop-last") (i32.const 5)) + +(assert_return (invoke "as-br-value") (i32.const 9)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 8)) +(assert_return (invoke "as-br_if-value-cond") (i32.const 9)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 10)) +(assert_return (invoke "as-br_table-value-index") (i32.const 11)) + +(assert_return (invoke "as-return-value") (i64.const 7)) + +(assert_return (invoke "as-if-cond") (i32.const 2)) +(assert_return (invoke "as-if-then" (i32.const 1) (i32.const 6)) (i32.const 3)) +(assert_return (invoke "as-if-then" (i32.const 0) (i32.const 6)) (i32.const 6)) +(assert_return (invoke "as-if-else" (i32.const 0) (i32.const 6)) (i32.const 4)) +(assert_return (invoke "as-if-else" (i32.const 1) (i32.const 6)) (i32.const 6)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 6)) (i32.const 5)) +(assert_return (invoke "as-select-first" (i32.const 1) (i32.const 6)) (i32.const 5)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 6)) (i32.const 6)) +(assert_return (invoke "as-select-second" (i32.const 1) (i32.const 6)) (i32.const 6)) +(assert_return (invoke "as-select-cond") (i32.const 7)) + +(assert_return (invoke "as-call-first") (i32.const 12)) +(assert_return (invoke "as-call-mid") (i32.const 13)) +(assert_return (invoke "as-call-last") (i32.const 14)) + +(assert_return (invoke "as-call_indirect-first") (i32.const 20)) +(assert_return (invoke "as-call_indirect-mid") (i32.const 21)) +(assert_return (invoke "as-call_indirect-last") (i32.const 22)) +(assert_return (invoke "as-call_indirect-func") (i32.const 23)) + +(assert_return (invoke "as-local.set-value") (i32.const 17)) +(assert_return (invoke "as-local.tee-value") (i32.const 1)) +(assert_return (invoke "as-global.set-value") (i32.const 1)) + +(assert_return (invoke "as-load-address") (f32.const 1.7)) +(assert_return (invoke "as-loadN-address") (i64.const 30)) + +(assert_return (invoke "as-store-address") (i32.const 30)) +(assert_return (invoke "as-store-value") (i32.const 31)) +(assert_return (invoke "as-storeN-address") (i32.const 32)) +(assert_return (invoke "as-storeN-value") (i32.const 33)) + +(assert_return (invoke "as-unary-operand") (f32.const 3.4)) + +(assert_return (invoke "as-binary-left") (i32.const 3)) +(assert_return (invoke "as-binary-right") (i64.const 45)) + +(assert_return (invoke "as-test-operand") (i32.const 44)) + +(assert_return (invoke "as-compare-left") (i32.const 43)) +(assert_return (invoke "as-compare-right") (i32.const 42)) + +(assert_return (invoke "as-convert-operand") (i32.const 41)) + +(assert_return (invoke "as-memory.grow-size") (i32.const 40)) + +(assert_return (invoke "nested-block-value" (i32.const 0)) (i32.const 19)) +(assert_return (invoke "nested-block-value" (i32.const 1)) (i32.const 17)) +(assert_return (invoke "nested-block-value" (i32.const 2)) (i32.const 16)) +(assert_return (invoke "nested-block-value" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "nested-block-value" (i32.const -1)) (i32.const 16)) +(assert_return (invoke "nested-block-value" (i32.const 100000)) (i32.const 16)) + +(assert_return (invoke "nested-br-value" (i32.const 0)) (i32.const 8)) +(assert_return (invoke "nested-br-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br-value" (i32.const 2)) (i32.const 17)) +(assert_return (invoke "nested-br-value" (i32.const 11)) (i32.const 17)) +(assert_return (invoke "nested-br-value" (i32.const -4)) (i32.const 17)) +(assert_return (invoke "nested-br-value" (i32.const 10213210)) (i32.const 17)) + +(assert_return (invoke "nested-br_if-value" (i32.const 0)) (i32.const 17)) +(assert_return (invoke "nested-br_if-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value" (i32.const 2)) (i32.const 8)) +(assert_return (invoke "nested-br_if-value" (i32.const 9)) (i32.const 8)) +(assert_return (invoke "nested-br_if-value" (i32.const -9)) (i32.const 8)) +(assert_return (invoke "nested-br_if-value" (i32.const 999999)) (i32.const 8)) + +(assert_return (invoke "nested-br_if-value-cond" (i32.const 0)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 1)) (i32.const 8)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 2)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 3)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const -1000000)) (i32.const 9)) +(assert_return (invoke "nested-br_if-value-cond" (i32.const 9423975)) (i32.const 9)) + +(assert_return (invoke "nested-br_table-value" (i32.const 0)) (i32.const 17)) +(assert_return (invoke "nested-br_table-value" (i32.const 1)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value" (i32.const 2)) (i32.const 8)) +(assert_return (invoke "nested-br_table-value" (i32.const 9)) (i32.const 8)) +(assert_return (invoke "nested-br_table-value" (i32.const -9)) (i32.const 8)) +(assert_return (invoke "nested-br_table-value" (i32.const 999999)) (i32.const 8)) + +(assert_return (invoke "nested-br_table-value-index" (i32.const 0)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 1)) (i32.const 8)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 2)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 3)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value-index" (i32.const -1000000)) (i32.const 9)) +(assert_return (invoke "nested-br_table-value-index" (i32.const 9423975)) (i32.const 9)) + +(assert_return (invoke "nested-br_table-loop-block" (i32.const 1)) (i32.const 3)) + +(assert_return (invoke "meet-externref" (i32.const 0) (ref.extern 1)) (ref.extern 1)) +(assert_return (invoke "meet-externref" (i32.const 1) (ref.extern 1)) (ref.extern 1)) +(assert_return (invoke "meet-externref" (i32.const 2) (ref.extern 1)) (ref.extern 1)) + +(assert_return (invoke "meet-funcref-1" (i32.const 0)) (ref.func)) +(assert_return (invoke "meet-funcref-1" (i32.const 1)) (ref.func)) +(assert_return (invoke "meet-funcref-1" (i32.const 2)) (ref.func)) +(assert_return (invoke "meet-funcref-2" (i32.const 0)) (ref.func)) +(assert_return (invoke "meet-funcref-2" (i32.const 1)) (ref.func)) +(assert_return (invoke "meet-funcref-2" (i32.const 2)) (ref.func)) +(assert_return (invoke "meet-funcref-3" (i32.const 0)) (ref.func)) +(assert_return (invoke "meet-funcref-3" (i32.const 1)) (ref.func)) +(assert_return (invoke "meet-funcref-3" (i32.const 2)) (ref.func)) +(assert_return (invoke "meet-funcref-4" (i32.const 0)) (ref.func)) +(assert_return (invoke "meet-funcref-4" (i32.const 1)) (ref.func)) +(assert_return (invoke "meet-funcref-4" (i32.const 2)) (ref.func)) + +(assert_invalid + (module (func $type-arg-void-vs-num (result i32) + (block (br_table 0 (i32.const 1)) (i32.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-arg-empty-vs-num (result i32) + (block (br_table 0) (i32.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-arg-void-vs-num (result i32) + (block (result i32) (br_table 0 (nop) (i32.const 1)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-num-vs-num (result i32) + (block (result i32) + (br_table 0 0 0 (i64.const 1) (i32.const 1)) (i32.const 1) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-num-vs-arg-num + (block + (block (result f32) + (br_table 0 1 (f32.const 0) (i32.const 0)) + ) + (drop) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func + (block (result i32) + (block (result i64) + (br_table 0 1 (i32.const 0) (i32.const 0)) + ) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-index-void-vs-i32 + (block (br_table 0 0 0 (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-index-num-vs-i32 + (block (br_table 0 (i64.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-index-void-vs-i32 (result i32) + (block (result i32) (br_table 0 0 (i32.const 0) (nop)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-void-vs-num-nested (result i32) + (block (result i32) (i32.const 0) (block (br_table 1 (i32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-arg-index-num-vs-i32 (result i32) + (block (result i32) + (br_table 0 0 (i32.const 0) (i64.const 0)) (i32.const 1) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-arg-void-vs-num (result i32) + (block (br_table 0 (i32.const 1)) (i32.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module + (func $type-arg-index-empty-in-then + (block + (i32.const 0) (i32.const 0) + (if (result i32) (then (br_table 0))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-arg-value-empty-in-then + (block + (i32.const 0) (i32.const 0) + (if (result i32) (then (br_table 0 (i32.const 1)))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-arg-index-empty-in-return + (block (result i32) + (return (br_table 0)) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-arg-value-empty-in-return + (block (result i32) + (return (br_table 0 (i32.const 1))) + ) + (i32.eqz) (drop) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (func (param i32) (result i32) + (loop (result i32) + (block (result i32) + (br_table 0 1 (i32.const 1) (local.get 0)) + ) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (param i32) (result i32) + (block (result i32) + (loop (result i32) + (br_table 0 1 (i32.const 1) (local.get 0)) + ) + ) + ) + ) + "type mismatch" +) + + +(assert_invalid + (module (func $unbound-label + (block (br_table 2 1 (i32.const 1))) + )) + "unknown label" +) +(assert_invalid + (module (func $unbound-nested-label + (block (block (br_table 0 5 (i32.const 1)))) + )) + "unknown label" +) +(assert_invalid + (module (func $large-label + (block (br_table 0 0x10000001 0 (i32.const 1))) + )) + "unknown label" +) + +(assert_invalid + (module (func $unbound-label-default + (block (br_table 1 2 (i32.const 1))) + )) + "unknown label" +) +(assert_invalid + (module (func $unbound-nested-label-default + (block (block (br_table 0 5 (i32.const 1)))) + )) + "unknown label" +) +(assert_invalid + (module (func $large-label-default + (block (br_table 0 0 0x10000001 (i32.const 1))) + )) + "unknown label" +) diff --git a/proposals/memory64/call_indirect.wast b/proposals/wasm-3.0/call_indirect.wast similarity index 98% rename from proposals/memory64/call_indirect.wast rename to proposals/wasm-3.0/call_indirect.wast index ba267fe..cc26b1b 100644 --- a/proposals/memory64/call_indirect.wast +++ b/proposals/wasm-3.0/call_indirect.wast @@ -1000,6 +1000,15 @@ "type mismatch" ) +;; call_indirect expects funcref type but receives externref +(assert_invalid + (module + (type (func)) + (table 10 externref) + (func $call-indirect (call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) ;; Unbound type @@ -1018,6 +1027,20 @@ "unknown type" ) +;; pass very large number to call_indirect +(assert_invalid + (module + (type (func (param i32))) + (table 1 funcref) + (func $conditional-dangling-type + (if (i32.const 1) + (then (call_indirect (type 0xffffffff) (i32.const 0))) + ) + ) + ) + "unknown type" +) + ;; Unbound function in table diff --git a/proposals/wasm-3.0/call_ref.wast b/proposals/wasm-3.0/call_ref.wast new file mode 100644 index 0000000..aa9ac7b --- /dev/null +++ b/proposals/wasm-3.0/call_ref.wast @@ -0,0 +1,218 @@ +(module + (type $ii (func (param i32) (result i32))) + + (func $apply (param $f (ref $ii)) (param $x i32) (result i32) + (call_ref $ii (local.get $x) (local.get $f)) + ) + + (func $f (type $ii) (i32.mul (local.get 0) (local.get 0))) + (func $g (type $ii) (i32.sub (i32.const 0) (local.get 0))) + + (elem declare func $f $g) + + (func (export "run") (param $x i32) (result i32) + (local $rf (ref null $ii)) + (local $rg (ref null $ii)) + (local.set $rf (ref.func $f)) + (local.set $rg (ref.func $g)) + (call_ref $ii (call_ref $ii (local.get $x) (local.get $rf)) (local.get $rg)) + ) + + (func (export "null") (result i32) + (call_ref $ii (i32.const 1) (ref.null $ii)) + ) + + ;; Recursion + + (type $ll (func (param i64) (result i64))) + (type $lll (func (param i64 i64) (result i64))) + + (elem declare func $fac) + (global $fac (ref $ll) (ref.func $fac)) + + (func $fac (export "fac") (type $ll) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 1)) + (else + (i64.mul + (local.get 0) + (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fac)) + ) + ) + ) + ) + + (elem declare func $fac-acc) + (global $fac-acc (ref $lll) (ref.func $fac-acc)) + + (func $fac-acc (export "fac-acc") (type $lll) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (call_ref $lll + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (global.get $fac-acc) + ) + ) + ) + ) + + (elem declare func $fib) + (global $fib (ref $ll) (ref.func $fib)) + + (func $fib (export "fib") (type $ll) + (if (result i64) (i64.le_u (local.get 0) (i64.const 1)) + (then (i64.const 1)) + (else + (i64.add + (call_ref $ll (i64.sub (local.get 0) (i64.const 2)) (global.get $fib)) + (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $fib)) + ) + ) + ) + ) + + (elem declare func $even $odd) + (global $even (ref $ll) (ref.func $even)) + (global $odd (ref $ll) (ref.func $odd)) + + (func $even (export "even") (type $ll) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 44)) + (else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $odd))) + ) + ) + (func $odd (export "odd") (type $ll) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 99)) + (else (call_ref $ll (i64.sub (local.get 0) (i64.const 1)) (global.get $even))) + ) + ) +) + +(assert_return (invoke "run" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "run" (i32.const 3)) (i32.const -9)) + +(assert_trap (invoke "null") "null function reference") + +(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "fib" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fib" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fib" (i64.const 2)) (i64.const 2)) +(assert_return (invoke "fib" (i64.const 5)) (i64.const 8)) +(assert_return (invoke "fib" (i64.const 20)) (i64.const 10946)) + +(assert_return (invoke "even" (i64.const 0)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i64.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i64.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i64.const 44)) + + +;; Unreachable typing. + +(module + (type $t (func)) + (func (export "unreachable") (result i32) + (unreachable) + (call_ref $t) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.func $f) + (call_ref $t) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (i32.const 0) + (ref.func $f) + (call_ref $t) + (drop) + (i32.const 0) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (i64.const 0) + (ref.func $f) + (call_ref $t) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.func $f) + (call_ref $t) + (drop) + (i64.const 0) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $f (param $r externref) + (call_ref $t (local.get $r)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $f (param $r funcref) + (call_ref $t (local.get $r)) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/data.wast b/proposals/wasm-3.0/data.wast new file mode 100644 index 0000000..5e10a64 --- /dev/null +++ b/proposals/wasm-3.0/data.wast @@ -0,0 +1,525 @@ +;; Test the data section + +;; Syntax + +(module + (memory $m 1) + (data (i32.const 0)) + (data (i32.const 1) "a" "" "bcd") + (data (offset (i32.const 0))) + (data (offset (i32.const 0)) "" "a" "bc" "") + (data (memory 0) (i32.const 0)) + (data (memory 0x0) (i32.const 1) "a" "" "bcd") + (data (memory 0x000) (offset (i32.const 0))) + (data (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data (memory $m) (i32.const 0)) + (data (memory $m) (i32.const 1) "a" "" "bcd") + (data (memory $m) (offset (i32.const 0))) + (data (memory $m) (offset (i32.const 0)) "" "a" "bc" "") + + (data $d1 (i32.const 0)) + (data $d2 (i32.const 1) "a" "" "bcd") + (data $d3 (offset (i32.const 0))) + (data $d4 (offset (i32.const 0)) "" "a" "bc" "") + (data $d5 (memory 0) (i32.const 0)) + (data $d6 (memory 0x0) (i32.const 1) "a" "" "bcd") + (data $d7 (memory 0x000) (offset (i32.const 0))) + (data $d8 (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data $d9 (memory $m) (i32.const 0)) + (data $d10 (memory $m) (i32.const 1) "a" "" "bcd") + (data $d11 (memory $m) (offset (i32.const 0))) + (data $d12 (memory $m) (offset (i32.const 0)) "" "a" "bc" "") +) + +;; Basic use + +(module + (memory 1) + (data (i32.const 0) "a") +) +(module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0) "a") +) + +(module + (memory 1) + (data (i32.const 0) "a") + (data (i32.const 3) "b") + (data (i32.const 100) "cde") + (data (i32.const 5) "x") + (data (i32.const 3) "c") +) +(module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0) "a") + (data (i32.const 1) "b") + (data (i32.const 2) "cde") + (data (i32.const 3) "f") + (data (i32.const 2) "g") + (data (i32.const 1) "h") +) + +(module + (global (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get 0) "a") +) +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get 0) "a") +) + +(module + (global $g (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get $g) "a") +) +(module + (global $g (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get $g) "a") +) + +(module (memory 1) (global i32 (i32.const 0)) (data (global.get 0) "a")) +(module (memory 1) (global $g i32 (i32.const 0)) (data (global.get $g) "a")) + + +;; Corner cases + +(module + (memory 1) + (data (i32.const 0) "a") + (data (i32.const 0xffff) "b") +) +(module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0) "a") + (data (i32.const 0xffff) "b") +) + +(module + (memory 2) + (data (i32.const 0x1_ffff) "a") +) + +(module + (memory 0) + (data (i32.const 0)) +) +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 0)) +) + +(module + (memory 0 0) + (data (i32.const 0)) +) + +(module + (memory 1) + (data (i32.const 0x1_0000) "") +) + +(module + (memory 0) + (data (i32.const 0) "" "") +) +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 0) "" "") +) + +(module + (memory 0 0) + (data (i32.const 0) "" "") +) + +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 0) "a") +) + +(module + (import "spectest" "memory" (memory 0 3)) + (data (i32.const 0) "a") +) + +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 0)) + (data (global.get 0) "a") +) + +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 0 3)) + (data (global.get 0) "a") +) + +(module + (import "spectest" "memory" (memory 0)) + (data (i32.const 1) "a") +) + +(module + (import "spectest" "memory" (memory 0 3)) + (data (i32.const 1) "a") +) + +;; Extended contant expressions + +(module + (memory 1) + (data (i32.add (i32.const 0) (i32.const 42))) +) + +(module + (memory 1) + (data (i32.sub (i32.const 42) (i32.const 0))) +) + +(module + (memory 1) + (data (i32.mul (i32.const 1) (i32.const 2))) +) + +;; Combining add, sub, mul and global.get + +(module + (global (import "spectest" "global_i32") i32) + (memory 1) + (data (i32.mul + (i32.const 2) + (i32.add + (i32.sub (global.get 0) (i32.const 1)) + (i32.const 2) + ) + ) + ) +) + +;; Invalid bounds for data + +(assert_trap + (module + (memory 0) + (data (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 0 0) + (data (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 0 1) + (data (i32.const 0) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 0) + (data (i32.const 1)) + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 0 1) + (data (i32.const 1)) + ) + "out of bounds memory access" +) + +;; This seems to cause a time-out on Travis. +(;assert_unlinkable + (module + (memory 0x10000) + (data (i32.const 0xffffffff) "ab") + ) + "" ;; either out of memory or out of bounds +;) + +(assert_trap + (module + (global (import "spectest" "global_i32") i32) + (memory 0) + (data (global.get 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1 2) + (data (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2) + (data (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2 3) + (data (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1) + (data (i32.const -1) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (data (i32.const -1) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2) + (data (i32.const -100) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (data (i32.const -100) "a") + ) + "out of bounds memory access" +) + +;; Data without memory + +(assert_invalid + (module + (data (i32.const 0) "") + ) + "unknown memory" +) + +;; Data segment with memory index 1 (only memory 0 available) +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\05\03\01" ;; memory section + "\00\00" ;; memory 0 + "\0b\07\01" ;; data section + "\02\01\41\00\0b" ;; active data segment 0 for memory 1 + "\00" ;; empty vec(byte) + ) + "unknown memory 1" +) + +;; Data segment with memory index 0 (no memory section) +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\0b\06\01" ;; data section + "\00\41\00\0b" ;; active data segment 0 for memory 0 + "\00" ;; empty vec(byte) + ) + "unknown memory 0" +) + +;; Data segment with memory index 1 (no memory section) +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\0b\07\01" ;; data section + "\02\01\41\00\0b" ;; active data segment 0 for memory 1 + "\00" ;; empty vec(byte) + ) + "unknown memory 1" +) + +;; Data segment with memory index 1 and vec(byte) as above, +;; only memory 0 available. +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\05\03\01" ;; memory section + "\00\00" ;; memory 0 + "\0b\45\01" ;; data section + "\02" ;; active segment + "\01" ;; memory index + "\41\00\0b" ;; offset constant expression + "\3e" ;; vec(byte) length + "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" + "\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + "\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" +) + +;; Data segment with memory index 1 and specially crafted vec(byte) after. +;; This is to detect incorrect validation where memory index is interpreted +;; as a flag followed by "\41" interpreted as the size of vec(byte) +;; with the expected number of bytes following. +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" + "\0b\45\01" ;; data section + "\02" ;; active segment + "\01" ;; memory index + "\41\00\0b" ;; offset constant expression + "\3e" ;; vec(byte) length + "\00\01\02\03\04\05\06\07\08\09\0a\0b\0c\0d\0e\0f" + "\10\11\12\13\14\15\16\17\18\19\1a\1b\1c\1d\1e\1f" + "\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" +) + + +;; Invalid offsets + +(assert_invalid + (module + (memory 1) + (data (i64.const 0)) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (data (ref.null func)) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (data (offset (;empty instruction sequence;))) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (data (offset (i32.const 0) (i32.const 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (memory 1) + (data (offset (global.get 0) (global.get 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (memory 1) + (data (offset (global.get 0) (i32.const 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (data (i32.ctz (i32.const 0))) + ) + "constant expression required" +) + +(assert_invalid + (module + (memory 1) + (data (nop)) + ) + "constant expression required" +) + +(assert_invalid + (module + (memory 1) + (data (offset (nop) (i32.const 0))) + ) + "constant expression required" +) + +(assert_invalid + (module + (memory 1) + (data (offset (i32.const 0) (nop))) + ) + "constant expression required" +) + +(assert_invalid + (module + (global $g (import "test" "g") (mut i32)) + (memory 1) + (data (global.get $g)) + ) + "constant expression required" +) + +(assert_invalid + (module + (memory 1) + (data (global.get 0)) + ) + "unknown global 0" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (memory 1) + (data (global.get 1)) + ) + "unknown global 1" +) + +(assert_invalid + (module + (global (import "test" "global-mut-i32") (mut i32)) + (memory 1) + (data (global.get 0)) + ) + "constant expression required" +) diff --git a/proposals/wasm-3.0/data0.wast b/proposals/wasm-3.0/data0.wast new file mode 100644 index 0000000..2cb9585 --- /dev/null +++ b/proposals/wasm-3.0/data0.wast @@ -0,0 +1,73 @@ +;; Test the data section + +;; Syntax + +(module + (memory $mem0 1) + (memory $mem1 1) + (memory $mem2 1) + + (data (i32.const 0)) + (data (i32.const 1) "a" "" "bcd") + (data (offset (i32.const 0))) + (data (offset (i32.const 0)) "" "a" "bc" "") + (data (memory 0) (i32.const 0)) + (data (memory 0x0) (i32.const 1) "a" "" "bcd") + (data (memory 0x000) (offset (i32.const 0))) + (data (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data (memory $mem0) (i32.const 0)) + (data (memory $mem1) (i32.const 1) "a" "" "bcd") + (data (memory $mem2) (offset (i32.const 0))) + (data (memory $mem0) (offset (i32.const 0)) "" "a" "bc" "") + + (data $d1 (i32.const 0)) + (data $d2 (i32.const 1) "a" "" "bcd") + (data $d3 (offset (i32.const 0))) + (data $d4 (offset (i32.const 0)) "" "a" "bc" "") + (data $d5 (memory 0) (i32.const 0)) + (data $d6 (memory 0x0) (i32.const 1) "a" "" "bcd") + (data $d7 (memory 0x000) (offset (i32.const 0))) + (data $d8 (memory 0) (offset (i32.const 0)) "" "a" "bc" "") + (data $d9 (memory $mem0) (i32.const 0)) + (data $d10 (memory $mem1) (i32.const 1) "a" "" "bcd") + (data $d11 (memory $mem2) (offset (i32.const 0))) + (data $d12 (memory $mem0) (offset (i32.const 0)) "" "a" "bc" "") +) + +;; Basic use + +(module + (memory 1) + (data (i32.const 0) "a") +) +(module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 0) (i32.const 0) "a") + (data (memory 1) (i32.const 0) "a") + (data (memory 2) (i32.const 0) "a") +) + +(module + (global (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get 0) "a") +) +(module + (global (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get 0) "a") +) + +(module + (global $g (import "spectest" "global_i32") i32) + (memory 1) + (data (global.get $g) "a") +) +(module + (global $g (import "spectest" "global_i32") i32) + (import "spectest" "memory" (memory 1)) + (data (global.get $g) "a") +) + diff --git a/proposals/wasm-3.0/data1.wast b/proposals/wasm-3.0/data1.wast new file mode 100644 index 0000000..8348d5c --- /dev/null +++ b/proposals/wasm-3.0/data1.wast @@ -0,0 +1,146 @@ +;; Invalid bounds for data + +(assert_trap + (module + (memory 1) + (memory 0) + (memory 2) + (data (memory 1) (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1 1) + (memory 1 1) + (memory 0 0) + (data (memory 2) (i32.const 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 1 1) + (memory 0 1) + (memory 1 1) + (data (memory 1) (i32.const 0) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 1) + (memory 1) + (memory 0) + (data (memory 2) (i32.const 1)) + ) + "out of bounds memory access" +) +(assert_trap + (module + (memory 1 1) + (memory 1 1) + (memory 0 1) + (data (memory 2) (i32.const 1)) + ) + "out of bounds memory access" +) + +;; This seems to cause a time-out on Travis. +(;assert_unlinkable + (module + (memory 0x10000) + (data (i32.const 0xffffffff) "ab") + ) + "" ;; either out of memory or out of bounds +;) + +(assert_trap + (module + (global (import "spectest" "global_i32") i32) + (memory 3) + (memory 0) + (memory 3) + (data (memory 1) (global.get 0) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2 2) + (memory 1 2) + (memory 2 2) + (data (memory 1) (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (data (i32.const 0x1_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 3) + (memory 3) + (memory 2) + (data (memory 2) (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 3 3) + (memory 2 3) + (memory 3 3) + (data (memory 1) (i32.const 0x2_0000) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 0) + (memory 0) + (memory 1) + (data (memory 2) (i32.const -1) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 2) (i32.const -1) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory 2) + (memory 2) + (memory 2) + (data (memory 2) (i32.const -100) "a") + ) + "out of bounds memory access" +) +(assert_trap + (module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 1)) + (data (memory 3) (i32.const -100) "a") + ) + "out of bounds memory access" +) + diff --git a/proposals/wasm-3.0/data_drop0.wast b/proposals/wasm-3.0/data_drop0.wast new file mode 100644 index 0000000..b617b10 --- /dev/null +++ b/proposals/wasm-3.0/data_drop0.wast @@ -0,0 +1,28 @@ +;; data.drop +(module + (memory $mem0 0) + (memory $mem1 1) + (memory $mem2 0) + (data $p "x") + (data $a (memory 1) (i32.const 0) "x") + + (func (export "drop_passive") (data.drop $p)) + (func (export "init_passive") (param $len i32) + (memory.init $mem1 $p (i32.const 0) (i32.const 0) (local.get $len))) + + (func (export "drop_active") (data.drop $a)) + (func (export "init_active") (param $len i32) + (memory.init $mem1 $a (i32.const 0) (i32.const 0) (local.get $len))) +) + +(invoke "init_passive" (i32.const 1)) +(invoke "drop_passive") +(invoke "drop_passive") +(assert_return (invoke "init_passive" (i32.const 0))) +(assert_trap (invoke "init_passive" (i32.const 1)) "out of bounds memory access") +(invoke "init_passive" (i32.const 0)) +(invoke "drop_active") +(assert_return (invoke "init_active" (i32.const 0))) +(assert_trap (invoke "init_active" (i32.const 1)) "out of bounds memory access") +(invoke "init_active" (i32.const 0)) + diff --git a/proposals/wasm-3.0/elem.wast b/proposals/wasm-3.0/elem.wast new file mode 100644 index 0000000..1722a30 --- /dev/null +++ b/proposals/wasm-3.0/elem.wast @@ -0,0 +1,1110 @@ +;; Test the element section + +;; Syntax +(module + (table $t 10 funcref) + (func $f) + (func $g) + + ;; Passive + (elem funcref) + (elem funcref (ref.func $f) (item ref.func $f) (item (ref.null func)) (ref.func $g)) + (elem func) + (elem func $f $f $g $g) + + (elem $p1 funcref) + (elem $p2 funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) + (elem $p3 func) + (elem $p4 func $f $f $g $g) + + ;; Active + (elem (table $t) (i32.const 0) funcref) + (elem (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) + (elem (table $t) (i32.const 0) func) + (elem (table $t) (i32.const 0) func $f $g) + (elem (table $t) (offset (i32.const 0)) funcref) + (elem (table $t) (offset (i32.const 0)) func $f $g) + (elem (table 0) (i32.const 0) func) + (elem (table 0x0) (i32.const 0) func $f $f) + (elem (table 0x000) (offset (i32.const 0)) func) + (elem (table 0) (offset (i32.const 0)) func $f $f) + (elem (table $t) (i32.const 0) func) + (elem (table $t) (i32.const 0) func $f $f) + (elem (table $t) (offset (i32.const 0)) func) + (elem (table $t) (offset (i32.const 0)) func $f $f) + (elem (offset (i32.const 0))) + (elem (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) + (elem (offset (i32.const 0)) func $f $f) + (elem (offset (i32.const 0)) $f $f) + (elem (i32.const 0)) + (elem (i32.const 0) funcref (ref.func $f) (ref.null func)) + (elem (i32.const 0) func $f $f) + (elem (i32.const 0) $f $f) + (elem (i32.const 0) funcref (item (ref.func $f)) (item (ref.null func))) + + (elem $a1 (table $t) (i32.const 0) funcref) + (elem $a2 (table $t) (i32.const 0) funcref (ref.func $f) (ref.null func)) + (elem $a3 (table $t) (i32.const 0) func) + (elem $a4 (table $t) (i32.const 0) func $f $g) + (elem $a9 (table $t) (offset (i32.const 0)) funcref) + (elem $a10 (table $t) (offset (i32.const 0)) func $f $g) + (elem $a11 (table 0) (i32.const 0) func) + (elem $a12 (table 0x0) (i32.const 0) func $f $f) + (elem $a13 (table 0x000) (offset (i32.const 0)) func) + (elem $a14 (table 0) (offset (i32.const 0)) func $f $f) + (elem $a15 (table $t) (i32.const 0) func) + (elem $a16 (table $t) (i32.const 0) func $f $f) + (elem $a17 (table $t) (offset (i32.const 0)) func) + (elem $a18 (table $t) (offset (i32.const 0)) func $f $f) + (elem $a19 (offset (i32.const 0))) + (elem $a20 (offset (i32.const 0)) funcref (ref.func $f) (ref.null func)) + (elem $a21 (offset (i32.const 0)) func $f $f) + (elem $a22 (offset (i32.const 0)) $f $f) + (elem $a23 (i32.const 0)) + (elem $a24 (i32.const 0) funcref (ref.func $f) (ref.null func)) + (elem $a25 (i32.const 0) func $f $f) + (elem $a26 (i32.const 0) $f $f) + + ;; Declarative + (elem declare funcref) + (elem declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) + (elem declare func) + (elem declare func $f $f $g $g) + + (elem $d1 declare funcref) + (elem $d2 declare funcref (ref.func $f) (ref.func $f) (ref.null func) (ref.func $g)) + (elem $d3 declare func) + (elem $d4 declare func $f $f $g $g) +) + +(module + (func $f) + (func $g) + + (table $t funcref (elem (ref.func $f) (ref.null func) (ref.func $g))) +) + +(module + (func $f) + (func $g) + + (table $t 10 (ref func) (ref.func $f)) + (elem (i32.const 3) $g) +) + + +;; Basic use + +(module + (table 10 funcref) + (func $f) + (elem (i32.const 0) $f) +) +(module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const 0) $f) +) + +(module + (table 10 funcref) + (func $f) + (elem (i32.const 0) $f) + (elem (i32.const 3) $f) + (elem (i32.const 7) $f) + (elem (i32.const 5) $f) + (elem (i32.const 3) $f) +) +(module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const 9) $f) + (elem (i32.const 3) $f) + (elem (i32.const 7) $f) + (elem (i32.const 3) $f) + (elem (i32.const 5) $f) +) + +(module + (global (import "spectest" "global_i32") i32) + (table 1000 funcref) + (func $f) + (elem (global.get 0) $f) +) + +(module + (global $g (import "spectest" "global_i32") i32) + (table 1000 funcref) + (func $f) + (elem (global.get $g) $f) +) + +(module + (type $out-i32 (func (result i32))) + (table 10 funcref) + (elem (i32.const 7) $const-i32-a) + (elem (i32.const 9) $const-i32-b) + (func $const-i32-a (type $out-i32) (i32.const 65)) + (func $const-i32-b (type $out-i32) (i32.const 66)) + (func (export "call-7") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 7)) + ) + (func (export "call-9") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 9)) + ) +) +(assert_return (invoke "call-7") (i32.const 65)) +(assert_return (invoke "call-9") (i32.const 66)) + +;; Same as the above, but use ref.null to ensure the elements use exprs. +;; Note: some tools like wast2json avoid using exprs when possible. +(module + (type $out-i32 (func (result i32))) + (table 11 funcref) + (elem (i32.const 6) funcref (ref.null func) (ref.func $const-i32-a)) + (elem (i32.const 9) funcref (ref.func $const-i32-b) (ref.null func)) + (func $const-i32-a (type $out-i32) (i32.const 65)) + (func $const-i32-b (type $out-i32) (i32.const 66)) + (func (export "call-7") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 7)) + ) + (func (export "call-9") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 9)) + ) +) +(assert_return (invoke "call-7") (i32.const 65)) +(assert_return (invoke "call-9") (i32.const 66)) + +(module + (global i32 (i32.const 0)) + (table 1 funcref) (elem (global.get 0) $f) (func $f) +) +(module + (global $g i32 (i32.const 0)) + (table 1 funcref) (elem (global.get $g) $f) (func $f) +) + + +;; Corner cases + +(module + (table 10 funcref) + (func $f) + (elem (i32.const 9) $f) +) +(module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const 9) $f) +) + +(module + (table 0 funcref) + (elem (i32.const 0)) +) +(module + (import "spectest" "table" (table 0 funcref)) + (elem (i32.const 0)) +) + +(module + (table 0 0 funcref) + (elem (i32.const 0)) +) + +(module + (table 20 funcref) + (elem (i32.const 20)) +) + +(module + (import "spectest" "table" (table 0 funcref)) + (func $f) + (elem (i32.const 0) $f) +) + +(module + (import "spectest" "table" (table 0 100 funcref)) + (func $f) + (elem (i32.const 0) $f) +) + +(module + (import "spectest" "table" (table 0 funcref)) + (func $f) + (elem (i32.const 1) $f) +) + +(module + (import "spectest" "table" (table 0 30 funcref)) + (func $f) + (elem (i32.const 1) $f) +) + + +;; Binary format variations + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\00\41\00\0b\01\00" ;; Segment 0: (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\05\01" ;; Elem section: 1 element segment + "\01\00\01\00" ;; Segment 0: func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\02\00\41\00\0b\00\01\00" ;; Segment 0: (table 0) (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem declare func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\05\01" ;; Elem section: 1 element segment + "\03\00\01\00" ;; Segment 0: declare func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) (;;)(ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d2\00\0b" ;; Segment 0: (i32.const 0) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d0\70\0b" ;; Segment 0: (i32.const 0) (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\05\70\01\d2\00\0b" ;; Segment 0: funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\05\70\01\d0\70\0b" ;; Segment 0: funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\0b\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\70\01\d2\00\0b" ;; Segment 0: (table 0) (i32.const 0) funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem (table 0) (i32.const 0) funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\0b\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\70\01\d0\70\0b" ;; Segment 0: (table 0) (i32.const 0) funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 funcref) + (elem declare funcref (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\07\70\01\d2\00\0b" ;; Segment 0: declare funcref (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) +(module + (func) + (table 1 funcref) + (elem declare funcref (ref.null func)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\04\01" ;; Table section: 1 table + "\70\00\01" ;; Table 0: [1..] funcref + "\09\07\01" ;; Elem section: 1 element segment + "\07\70\01\d0\70\0b" ;; Segment 0: declare funcref (ref.null func) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\07\01" ;; Elem section: 1 element segment + "\00\41\00\0b\01\00" ;; Segment 0: (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\05\01" ;; Elem section: 1 element segment + "\01\00\01\00" ;; Segment 0: func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (table 0) (i32.const 0) func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\09\01" ;; Elem section: 1 element segment + "\02\00\41\00\0b\00\01\00" ;; Segment 0: (table 0) (i32.const 0) func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem declare func 0) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\05\01" ;; Elem section: 1 element segment + "\03\00\01\00" ;; Segment 0: declare func 0 + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(assert_invalid + (module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (i32.const 0) funcref (ref.func 0)) + ) + "type mismatch" +) +(assert_invalid + (module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\09\01" ;; Elem section: 1 element segment + "\04\41\00\0b\01\d2\00\0b" ;; Segment 0: (i32.const 0) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty + ) + "type mismatch" +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\08\01" ;; Elem section: 1 element segment + "\05\64\70\01\d2\00\0b" ;; Segment 0: (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem (table 0) (i32.const 0) (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\0c\01" ;; Elem section: 1 element segment + "\06\00\41\00\0b\64\70\01\d2\00\0b" ;; Segment 0: (table 0) (i32.const 0) (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + +(module + (func) + (table 1 (ref func) (ref.func 0)) + (elem declare (ref func) (ref.func 0)) +) +(module binary + "\00asm" "\01\00\00\00" ;; Magic + "\01\04\01\60\00\00" ;; Type section: 1 type + "\03\02\01\00" ;; Function section: 1 function + "\04\0a\01" ;; Table section: 1 table + "\40\00\64\70\00\01\d2\00\0b" ;; Table 0: [1..] (ref func) (ref.func 0) + "\09\08\01" ;; Elem section: 1 element segment + "\07\64\70\01\d2\00\0b" ;; Segment 0: declare (ref func) (ref.func 0) + "\0a\04\01" ;; Code section: 1 function + "\02\00\0b" ;; Function 0: empty +) + + +;; Invalid bounds for elements + +(assert_trap + (module + (table 0 funcref) + (func $f) + (elem (i32.const 0) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 0 0 funcref) + (func $f) + (elem (i32.const 0) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 0 1 funcref) + (func $f) + (elem (i32.const 0) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 0 funcref) + (elem (i32.const 1)) + ) + "out of bounds table access" +) +(assert_trap + (module + (table 10 funcref) + (func $f) + (elem (i32.const 10) $f) + ) + "out of bounds table access" +) +(assert_trap + (module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const 10) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 10 20 funcref) + (func $f) + (elem (i32.const 10) $f) + ) + "out of bounds table access" +) +(assert_trap + (module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const 10) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 10 funcref) + (func $f) + (elem (i32.const -1) $f) + ) + "out of bounds table access" +) +(assert_trap + (module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const -1) $f) + ) + "out of bounds table access" +) + +(assert_trap + (module + (table 10 funcref) + (func $f) + (elem (i32.const -10) $f) + ) + "out of bounds table access" +) +(assert_trap + (module + (import "spectest" "table" (table 10 funcref)) + (func $f) + (elem (i32.const -10) $f) + ) + "out of bounds table access" +) + + +;; Implicitly dropped elements + +(module + (table 10 funcref) + (elem $e (i32.const 0) func $f) + (func $f) + (func (export "init") + (table.init $e (i32.const 0) (i32.const 0) (i32.const 1)) + ) +) +(assert_trap (invoke "init") "out of bounds table access") + +(module + (table 10 funcref) + (elem $e declare func $f) + (func $f) + (func (export "init") + (table.init $e (i32.const 0) (i32.const 0) (i32.const 1)) + ) +) +(assert_trap (invoke "init") "out of bounds table access") + + +;; Element without table + +(assert_invalid + (module + (func $f) + (elem (i32.const 0) $f) + ) + "unknown table" +) + + +;; Invalid offsets + +(assert_invalid + (module + (table 1 funcref) + (elem (i64.const 0)) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (ref.null func)) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (offset (;empty instruction sequence;))) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (offset (i32.const 0) (i32.const 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (table 1 funcref) + (elem (offset (global.get 0) (global.get 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (table 1 funcref) + (elem (offset (global.get 0) (i32.const 0))) + ) + "type mismatch" +) + + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.ctz (i32.const 0))) + ) + "constant expression required" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (nop)) + ) + "constant expression required" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (offset (nop) (i32.const 0))) + ) + "constant expression required" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (offset (i32.const 0) (nop))) + ) + "constant expression required" +) + +(assert_invalid + (module + (global $g (import "test" "g") (mut i32)) + (table 1 funcref) + (elem (global.get $g)) + ) + "constant expression required" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (global.get 0)) + ) + "unknown global 0" +) + +(assert_invalid + (module + (global (import "test" "global-i32") i32) + (table 1 funcref) + (elem (global.get 1)) + ) + "unknown global 1" +) + +(assert_invalid + (module + (global (import "test" "global-mut-i32") (mut i32)) + (table 1 funcref) + (elem (global.get 0)) + ) + "constant expression required" +) + + +;; Invalid elements + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.const 0) funcref (ref.null extern)) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.const 0) funcref (item (ref.null func) (ref.null func))) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.const 0) funcref (i32.const 0)) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.const 0) funcref (item (i32.const 0))) + ) + "type mismatch" +) + +(assert_invalid + (module + (table 1 funcref) + (elem (i32.const 0) funcref (item (call $f))) + (func $f (result funcref) (ref.null func)) + ) + "constant expression required" +) + + +;; Two elements target the same slot + +(module + (type $out-i32 (func (result i32))) + (table 10 funcref) + (elem (i32.const 9) $const-i32-a) + (elem (i32.const 9) $const-i32-b) + (func $const-i32-a (type $out-i32) (i32.const 65)) + (func $const-i32-b (type $out-i32) (i32.const 66)) + (func (export "call-overwritten") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 9)) + ) +) +(assert_return (invoke "call-overwritten") (i32.const 66)) + +(module + (type $out-i32 (func (result i32))) + (import "spectest" "table" (table 10 funcref)) + (elem (i32.const 9) $const-i32-a) + (elem (i32.const 9) $const-i32-b) + (func $const-i32-a (type $out-i32) (i32.const 65)) + (func $const-i32-b (type $out-i32) (i32.const 66)) + (func (export "call-overwritten-element") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 9)) + ) +) +(assert_return (invoke "call-overwritten-element") (i32.const 66)) + + +;; Element sections across multiple modules change the same table + +(module $module1 + (type $out-i32 (func (result i32))) + (table (export "shared-table") 10 funcref) + (elem (i32.const 8) $const-i32-a) + (elem (i32.const 9) $const-i32-b) + (func $const-i32-a (type $out-i32) (i32.const 65)) + (func $const-i32-b (type $out-i32) (i32.const 66)) + (func (export "call-7") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 7)) + ) + (func (export "call-8") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 8)) + ) + (func (export "call-9") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 9)) + ) +) + +(register "module1" $module1) + +(assert_trap (invoke $module1 "call-7") "uninitialized element") +(assert_return (invoke $module1 "call-8") (i32.const 65)) +(assert_return (invoke $module1 "call-9") (i32.const 66)) + +(module $module2 + (type $out-i32 (func (result i32))) + (import "module1" "shared-table" (table 10 funcref)) + (elem (i32.const 7) $const-i32-c) + (elem (i32.const 8) $const-i32-d) + (func $const-i32-c (type $out-i32) (i32.const 67)) + (func $const-i32-d (type $out-i32) (i32.const 68)) +) + +(assert_return (invoke $module1 "call-7") (i32.const 67)) +(assert_return (invoke $module1 "call-8") (i32.const 68)) +(assert_return (invoke $module1 "call-9") (i32.const 66)) + +(module $module3 + (type $out-i32 (func (result i32))) + (import "module1" "shared-table" (table 10 funcref)) + (elem (i32.const 8) $const-i32-e) + (elem (i32.const 9) $const-i32-f) + (func $const-i32-e (type $out-i32) (i32.const 69)) + (func $const-i32-f (type $out-i32) (i32.const 70)) +) + +(assert_return (invoke $module1 "call-7") (i32.const 67)) +(assert_return (invoke $module1 "call-8") (i32.const 69)) +(assert_return (invoke $module1 "call-9") (i32.const 70)) + +;; Element segments must match element type of table + +(assert_invalid + (module (func $f) (table 1 externref) (elem (i32.const 0) $f)) + "type mismatch" +) + +(assert_invalid + (module (table 1 funcref) (elem (i32.const 0) externref (ref.null extern))) + "type mismatch" +) + +(assert_invalid + (module + (func $f) + (table $t 1 externref) + (elem $e funcref (ref.func $f)) + (func (table.init $t $e (i32.const 0) (i32.const 0) (i32.const 1)))) + "type mismatch" +) + +(assert_invalid + (module + (table $t 1 funcref) + (elem $e externref (ref.null extern)) + (func (table.init $t $e (i32.const 0) (i32.const 0) (i32.const 1)))) + "type mismatch" +) + +;; Initializing a table with an externref-type element segment + +(module $m + (table $t (export "table") 2 externref) + (func (export "get") (param $i i32) (result externref) + (table.get $t (local.get $i))) + (func (export "set") (param $i i32) (param $x externref) + (table.set $t (local.get $i) (local.get $x)))) + +(register "exporter" $m) + +(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern)) +(assert_return (invoke $m "get" (i32.const 1)) (ref.null extern)) + +(assert_return (invoke $m "set" (i32.const 0) (ref.extern 42))) +(assert_return (invoke $m "set" (i32.const 1) (ref.extern 137))) + +(assert_return (invoke $m "get" (i32.const 0)) (ref.extern 42)) +(assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137)) + +(module + (import "exporter" "table" (table $t 2 externref)) + (elem (i32.const 0) externref (ref.null extern))) + +(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern)) +(assert_return (invoke $m "get" (i32.const 1)) (ref.extern 137)) + +;; Initializing a table with imported funcref global + +(module $module4 + (func (result i32) + i32.const 42 + ) + (global (export "f") funcref (ref.func 0)) +) + +(register "module4" $module4) + +(module + (import "module4" "f" (global funcref)) + (type $out-i32 (func (result i32))) + (table 10 funcref) + (elem (offset (i32.const 0)) funcref (global.get 0)) + (func (export "call_imported_elem") (type $out-i32) + (call_indirect (type $out-i32) (i32.const 0)) + ) +) + +(assert_return (invoke "call_imported_elem") (i32.const 42)) + +;; Extended contant expressions + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.add (i32.const 1) (i32.const 2))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 3)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.sub (i32.const 2) (i32.const 1))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 1)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +(module + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) (offset (i32.mul (i32.const 2) (i32.const 2))) funcref (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 4)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") + +;; Combining add, sub, mul and global.get + +(module + (global (import "spectest" "global_i32") i32) + (table 10 funcref) + (func (result i32) (i32.const 42)) + (func (export "call_in_table") (param i32) (result i32) + (call_indirect (type 0) (local.get 0))) + (elem (table 0) + (offset + (i32.mul + (i32.const 2) + (i32.add + (i32.sub (global.get 0) (i32.const 665)) + (i32.const 2)))) + funcref + (ref.func 0)) +) + +(assert_return (invoke "call_in_table" (i32.const 6)) (i32.const 42)) +(assert_trap (invoke "call_in_table" (i32.const 0)) "uninitialized element") diff --git a/proposals/memory64/endianness64.wast b/proposals/wasm-3.0/endianness64.wast similarity index 100% rename from proposals/memory64/endianness64.wast rename to proposals/wasm-3.0/endianness64.wast diff --git a/proposals/wasm-3.0/exports.wast b/proposals/wasm-3.0/exports.wast new file mode 100644 index 0000000..f27b10a --- /dev/null +++ b/proposals/wasm-3.0/exports.wast @@ -0,0 +1,242 @@ +;; Functions + +(module (func) (export "a" (func 0))) +(module (func) (export "a" (func 0)) (export "b" (func 0))) +(module (func) (func) (export "a" (func 0)) (export "b" (func 1))) + +(module (func (export "a"))) +(module (func (export "a") (export "b") (export "c"))) +(module (func (export "a") (export "b") (param i32))) +(module (func) (export "a" (func 0))) +(module (func $a (export "a"))) +(module (func $a) (export "a" (func $a))) +(module (export "a" (func 0)) (func)) +(module (export "a" (func $a)) (func $a)) + +(module $Func + (export "e" (func $f)) + (func $f (param $n i32) (result i32) + (return (i32.add (local.get $n) (i32.const 1))) + ) +) +(assert_return (invoke "e" (i32.const 42)) (i32.const 43)) +(assert_return (invoke $Func "e" (i32.const 42)) (i32.const 43)) +(module) +(module $Other1) +(assert_return (invoke $Func "e" (i32.const 42)) (i32.const 43)) + +(module + (type (;0;) (func (result i32))) + (func (;0;) (type 0) (result i32) i32.const 42) + (export "a" (func 0)) + (export "b" (func 0)) + (export "c" (func 0))) +(assert_return (invoke "a") (i32.const 42)) +(assert_return (invoke "b") (i32.const 42)) +(assert_return (invoke "c") (i32.const 42)) + +(assert_invalid + (module (export "a" (func 0))) + "unknown function" +) +(assert_invalid + (module (func) (export "a" (func 1))) + "unknown function" +) +(assert_invalid + (module (import "spectest" "print_i32" (func (param i32))) (export "a" (func 1))) + "unknown function" +) +(assert_invalid + (module (func) (export "a" (func 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (func) (func) (export "a" (func 0)) (export "a" (func 1))) + "duplicate export name" +) +(assert_invalid + (module (func) (global i32 (i32.const 0)) (export "a" (func 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (func) (table 0 funcref) (export "a" (func 0)) (export "a" (table 0))) + "duplicate export name" +) +(assert_invalid + (module (func) (memory 0) (export "a" (func 0)) (export "a" (memory 0))) + "duplicate export name" +) +(assert_invalid + (module (tag $t0 (export "t0")) (tag $t1 (export "t0"))) + "duplicate export name" +) + + +;; Globals + +(module (global i32 (i32.const 0)) (export "a" (global 0))) +(module (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 0))) +(module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 1))) + +(module (global (export "a") i32 (i32.const 0))) +(module (global i32 (i32.const 0)) (export "a" (global 0))) +(module (global $a (export "a") i32 (i32.const 0))) +(module (global $a i32 (i32.const 0)) (export "a" (global $a))) +(module (export "a" (global 0)) (global i32 (i32.const 0))) +(module (export "a" (global $a)) (global $a i32 (i32.const 0))) + +(module $Global + (export "e" (global $g)) + (global $g i32 (i32.const 42)) +) +(assert_return (get "e") (i32.const 42)) +(assert_return (get $Global "e") (i32.const 42)) +(module) +(module $Other2) +(assert_return (get $Global "e") (i32.const 42)) + +(assert_invalid + (module (export "a" (global 0))) + "unknown global" +) +(assert_invalid + (module (global i32 (i32.const 0)) (export "a" (global 1))) + "unknown global" +) +(assert_invalid + (module (import "spectest" "global_i32" (global i32)) (export "a" (global 1))) + "unknown global" +) +(assert_invalid + (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 1))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (func) (export "a" (global 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (table 0 funcref) (export "a" (global 0)) (export "a" (table 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (memory 0) (export "a" (global 0)) (export "a" (memory 0))) + "duplicate export name" +) + + +;; Tables + +(module (table 0 funcref) (export "a" (table 0))) +(module (table 0 funcref) (export "a" (table 0)) (export "b" (table 0))) +(module (table 0 funcref) (table 0 funcref) (export "a" (table 0)) (export "b" (table 1))) + +(module (table (export "a") 0 funcref)) +(module (table (export "a") 0 1 funcref)) +(module (table 0 funcref) (export "a" (table 0))) +(module (table 0 1 funcref) (export "a" (table 0))) +(module (table $a (export "a") 0 funcref)) +(module (table $a (export "a") 0 1 funcref)) +(module (table $a 0 funcref) (export "a" (table $a))) +(module (table $a 0 1 funcref) (export "a" (table $a))) +(module (export "a" (table 0)) (table 0 funcref)) +(module (export "a" (table 0)) (table 0 1 funcref)) +(module (export "a" (table $a)) (table $a 0 funcref)) +(module (export "a" (table $a)) (table $a 0 1 funcref)) + +(; TODO: access table ;) + +(assert_invalid + (module (export "a" (table 0))) + "unknown table" +) +(assert_invalid + (module (table 0 funcref) (export "a" (table 1))) + "unknown table" +) +(assert_invalid + (module (import "spectest" "table" (table 10 20 funcref)) (export "a" (table 1))) + "unknown table" +) +(assert_invalid + (module (table 0 funcref) (export "a" (table 0)) (export "a" (table 0))) + "duplicate export name" +) +(assert_invalid + (module (table 0 funcref) (table 0 funcref) (export "a" (table 0)) (export "a" (table 1))) + "duplicate export name" +) +(assert_invalid + (module (table 0 funcref) (func) (export "a" (table 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (table 0 funcref) (global i32 (i32.const 0)) (export "a" (table 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (table 0 funcref) (memory 0) (export "a" (table 0)) (export "a" (memory 0))) + "duplicate export name" +) + + +;; Memories + +(module (memory 0) (export "a" (memory 0))) +(module (memory 0) (export "a" (memory 0)) (export "b" (memory 0))) +;; No multiple memories yet. +;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1))) + +(module (memory (export "a") 0)) +(module (memory (export "a") 0 1)) +(module (memory 0) (export "a" (memory 0))) +(module (memory 0 1) (export "a" (memory 0))) +(module (memory $a (export "a") 0)) +(module (memory $a (export "a") 0 1)) +(module (memory $a 0) (export "a" (memory $a))) +(module (memory $a 0 1) (export "a" (memory $a))) +(module (export "a" (memory 0)) (memory 0)) +(module (export "a" (memory 0)) (memory 0 1)) +(module (export "a" (memory $a)) (memory $a 0)) +(module (export "a" (memory $a)) (memory $a 0 1)) + +(; TODO: access memory ;) + +(assert_invalid + (module (export "a" (memory 0))) + "unknown memory" +) +(assert_invalid + (module (memory 0) (export "a" (memory 1))) + "unknown memory" +) +(assert_invalid + (module (import "spectest" "memory" (memory 1 2)) (export "a" (memory 1))) + "unknown memory" +) +(assert_invalid + (module (memory 0) (export "a" (memory 0)) (export "a" (memory 0))) + "duplicate export name" +) +;; No multiple memories yet. +;; (assert_invalid +;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "a" (memory 1))) +;; "duplicate export name" +;; ) +(assert_invalid + (module (memory 0) (func) (export "a" (memory 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (memory 0) (global i32 (i32.const 0)) (export "a" (memory 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (memory 0) (table 0 funcref) (export "a" (memory 0)) (export "a" (table 0))) + "duplicate export name" +) diff --git a/proposals/wasm-3.0/exports0.wast b/proposals/wasm-3.0/exports0.wast new file mode 100644 index 0000000..6eb94d1 --- /dev/null +++ b/proposals/wasm-3.0/exports0.wast @@ -0,0 +1,51 @@ +;; Memories + +(module (memory 0) (export "a" (memory 0))) +(module (memory 0) (export "a" (memory 0)) (export "b" (memory 0))) +(module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1))) +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 0) + (memory $mem3 0) + (memory $mem4 0) + (memory $mem5 0) + (memory $mem6 0) + + (export "a" (memory $mem0)) + (export "b" (memory $mem1)) + (export "ac" (memory $mem2)) + (export "bc" (memory $mem3)) + (export "ad" (memory $mem4)) + (export "bd" (memory $mem5)) + (export "be" (memory $mem6)) + + (export "za" (memory $mem0)) + (export "zb" (memory $mem1)) + (export "zac" (memory $mem2)) + (export "zbc" (memory $mem3)) + (export "zad" (memory $mem4)) + (export "zbd" (memory $mem5)) + (export "zbe" (memory $mem6)) +) + +(module + (export "a" (memory 0)) + (memory 6) + + (export "b" (memory 1)) + (memory 3) +) + +(module + (export "a" (memory 0)) + (memory 0 1) + (memory 0 1) + (memory 0 1) + (memory 0 1) + + (export "b" (memory 3)) +) +(module (export "a" (memory $a)) (memory $a 0)) +(module (export "a" (memory $a)) (memory $a 0 1)) + diff --git a/proposals/wasm-3.0/extern.wast b/proposals/wasm-3.0/extern.wast new file mode 100644 index 0000000..abf3166 --- /dev/null +++ b/proposals/wasm-3.0/extern.wast @@ -0,0 +1,54 @@ +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (ref.i31 (i32.const 7))) + (table.set (i32.const 2) (struct.new_default $st)) + (table.set (i32.const 3) (array.new_default $at (i32.const 0))) + (table.set (i32.const 4) (any.convert_extern (local.get $x))) + ) + + (func (export "internalize") (param externref) (result anyref) + (any.convert_extern (local.get 0)) + ) + (func (export "externalize") (param anyref) (result externref) + (extern.convert_any (local.get 0)) + ) + + (func (export "externalize-i") (param i32) (result externref) + (extern.convert_any (table.get (local.get 0))) + ) + (func (export "externalize-ii") (param i32) (result anyref) + (any.convert_extern (extern.convert_any (table.get (local.get 0)))) + ) +) + +(invoke "init" (ref.extern 0)) + +(assert_return (invoke "internalize" (ref.extern 1)) (ref.host 1)) +(assert_return (invoke "internalize" (ref.null extern)) (ref.null any)) + +(assert_return (invoke "externalize" (ref.host 2)) (ref.extern 2)) +(assert_return (invoke "externalize" (ref.null any)) (ref.null extern)) + +(assert_return (invoke "externalize-i" (i32.const 0)) (ref.null extern)) +(assert_return (invoke "externalize-i" (i32.const 1)) (ref.extern)) +(assert_return (invoke "externalize-i" (i32.const 2)) (ref.extern)) +(assert_return (invoke "externalize-i" (i32.const 3)) (ref.extern)) +(assert_return (invoke "externalize-i" (i32.const 4)) (ref.extern)) +(assert_return (invoke "externalize-i" (i32.const 5)) (ref.null extern)) + +(assert_return (invoke "externalize-ii" (i32.const 0)) (ref.null any)) +(assert_return (invoke "externalize-ii" (i32.const 1)) (ref.i31)) +(assert_return (invoke "externalize-ii" (i32.const 2)) (ref.struct)) +(assert_return (invoke "externalize-ii" (i32.const 3)) (ref.array)) +(assert_return (invoke "externalize-ii" (i32.const 4)) (ref.host 0)) +(assert_return (invoke "externalize-ii" (i32.const 5)) (ref.null any)) diff --git a/proposals/wasm-3.0/float_exprs0.wast b/proposals/wasm-3.0/float_exprs0.wast new file mode 100644 index 0000000..8b40b34 --- /dev/null +++ b/proposals/wasm-3.0/float_exprs0.wast @@ -0,0 +1,38 @@ +(module + (memory 0 0) + (memory $m 1 1) + (memory 0 0) + (func (export "init") (param $i i32) (param $x f64) + (f64.store $m (local.get $i) (local.get $x))) + + (func (export "run") (param $n i32) (param $z f64) + (local $i i32) + (block $exit + (loop $cont + (f64.store $m + (local.get $i) + (f64.div (f64.load $m (local.get $i)) (local.get $z)) + ) + (local.set $i (i32.add (local.get $i) (i32.const 8))) + (br_if $cont (i32.lt_u (local.get $i) (local.get $n))) + ) + ) + ) + + (func (export "check") (param $i i32) (result f64) (f64.load $m (local.get $i))) +) + +(invoke "init" (i32.const 0) (f64.const 15.1)) +(invoke "init" (i32.const 8) (f64.const 15.2)) +(invoke "init" (i32.const 16) (f64.const 15.3)) +(invoke "init" (i32.const 24) (f64.const 15.4)) +(assert_return (invoke "check" (i32.const 0)) (f64.const 15.1)) +(assert_return (invoke "check" (i32.const 8)) (f64.const 15.2)) +(assert_return (invoke "check" (i32.const 16)) (f64.const 15.3)) +(assert_return (invoke "check" (i32.const 24)) (f64.const 15.4)) +(invoke "run" (i32.const 32) (f64.const 3.0)) +(assert_return (invoke "check" (i32.const 0)) (f64.const 0x1.4222222222222p+2)) +(assert_return (invoke "check" (i32.const 8)) (f64.const 0x1.4444444444444p+2)) +(assert_return (invoke "check" (i32.const 16)) (f64.const 0x1.4666666666667p+2)) +(assert_return (invoke "check" (i32.const 24)) (f64.const 0x1.4888888888889p+2)) + diff --git a/proposals/wasm-3.0/float_exprs1.wast b/proposals/wasm-3.0/float_exprs1.wast new file mode 100644 index 0000000..834696a --- /dev/null +++ b/proposals/wasm-3.0/float_exprs1.wast @@ -0,0 +1,105 @@ +;; Test that plain summation is not reassociated, and that Kahan summation +;; isn't optimized into plain summation. + +(module + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory $m (data + "\c4\c5\57\24\a5\84\c8\0b\6d\b8\4b\2e\f2\76\17\1c\ca\4a\56\1e\1b\6e\71\22" + "\5d\17\1e\6e\bf\cd\14\5c\c7\21\55\51\39\9c\1f\b2\51\f0\a3\93\d7\c1\2c\ae" + "\7e\a8\28\3a\01\21\f4\0a\58\93\f8\42\77\9f\83\39\6a\5f\ba\f7\0a\d8\51\6a" + "\34\ca\ad\c6\34\0e\d8\26\dc\4c\33\1c\ed\29\90\a8\78\0f\d1\ce\76\31\23\83" + "\b8\35\e8\f2\44\b0\d3\a1\fc\bb\32\e1\b0\ba\69\44\09\d6\d9\7d\ff\2e\c0\5a" + "\36\14\33\14\3e\a9\fa\87\6d\8b\bc\ce\9d\a7\fd\c4\e9\85\3f\dd\d7\e1\18\a6" + "\50\26\72\6e\3f\73\0f\f8\12\93\23\34\61\76\12\48\c0\9b\05\93\eb\ac\86\de" + "\94\3e\55\e8\8c\e8\dd\e4\fc\95\47\be\56\03\21\20\4c\e6\bf\7b\f6\7f\d5\ba" + "\73\1c\c1\14\8f\c4\27\96\b3\bd\33\ff\78\41\5f\c0\5a\ce\f6\67\6e\73\9a\17" + "\66\70\03\f8\ce\27\a3\52\b2\9f\3b\bf\fb\ae\ed\d3\5a\f8\37\57\f0\f5\6e\ef" + "\b1\4d\70\3d\54\a7\01\9a\85\08\48\91\f5\9d\0c\60\87\5b\d9\54\1e\51\6d\88" + "\8e\08\8c\a5\71\3a\56\08\67\46\8f\8f\13\2a\2c\ec\2c\1f\b4\62\2b\6f\41\0a" + "\c4\65\42\a2\31\6b\2c\7d\3e\bb\75\ac\86\97\30\d9\48\cd\9a\1f\56\c4\c6\e4" + "\12\c0\9d\fb\ee\02\8c\ce\1c\f2\1e\a1\78\23\db\c4\1e\49\03\d3\71\cc\08\50" + "\c5\d8\5c\ed\d5\b5\65\ac\b5\c9\21\d2\c9\29\76\de\f0\30\1a\5b\3c\f2\3b\db" + "\3a\39\82\3a\16\08\6f\a8\f1\be\69\69\99\71\a6\05\d3\14\93\2a\16\f2\2f\11" + "\c7\7e\20\bb\91\44\ee\f8\e4\01\53\c0\b9\7f\f0\bf\f0\03\9c\6d\b1\df\a2\44" + "\01\6d\6b\71\2b\5c\b3\21\19\46\5e\8f\db\91\d3\7c\78\6b\b7\12\00\8f\eb\bd" + "\8a\f5\d4\2e\c4\c1\1e\df\73\63\59\47\49\03\0a\b7\cf\24\cf\9c\0e\44\7a\9e" + "\14\fb\42\bf\9d\39\30\9e\a0\ab\2f\d1\ae\9e\6a\83\43\e3\55\7d\85\bf\63\8a" + "\f8\96\10\1f\fe\6d\e7\22\1b\e1\69\46\8a\44\c8\c8\f9\0c\2b\19\07\a5\02\3e" + "\f2\30\10\9a\85\8a\5f\ef\81\45\a0\77\b1\03\10\73\4b\ae\98\9d\47\bf\9a\2d" + "\3a\d5\0f\03\66\e3\3d\53\d9\40\ce\1f\6f\32\2f\21\2b\23\21\6c\62\d4\a7\3e" + "\a8\ce\28\31\2d\00\3d\67\5e\af\a0\cf\2e\d2\b9\6b\84\eb\69\08\3c\62\36\be" + "\12\fd\36\7f\88\3e\ad\bc\0b\c0\41\c4\50\b6\e3\50\31\e8\ce\e2\96\65\55\9c" + "\16\46\e6\b0\2d\3a\e8\81\05\b0\bf\34\f7\bc\10\1c\fb\cc\3c\f1\85\97\42\9f" + "\eb\14\8d\3c\bf\d7\17\88\49\9d\8b\2b\b2\3a\83\d1\4f\04\9e\a1\0f\ad\08\9d" + "\54\af\d1\82\c3\ec\32\2f\02\8f\05\21\2d\a2\b7\e4\f4\6f\2e\81\2b\0b\9c\fc" + "\cb\fe\74\02\f9\db\f4\f3\ea\00\a8\ec\d1\99\74\26\dd\d6\34\d5\25\b1\46\dd" + "\9c\aa\71\f5\60\b0\88\c8\e0\0b\59\5a\25\4f\29\66\f9\e3\2e\fe\e9\da\e5\18" + "\4f\27\62\f4\ce\a4\21\95\74\c7\57\64\27\9a\4c\fd\54\7d\61\ce\c3\ac\87\46" + "\9c\fa\ff\09\ca\79\97\67\24\74\ca\d4\21\83\26\25\19\12\37\64\19\e5\65\e0" + "\74\75\8e\dd\c8\ef\74\c7\d8\21\2b\79\04\51\46\65\60\03\5d\fa\d8\f4\65\a4" + "\9e\5d\23\da\d7\8a\92\80\a4\de\78\3c\f1\57\42\6d\cd\c9\2f\d5\a4\9e\ab\40" + "\f4\cb\1b\d7\a3\ca\fc\eb\a7\01\b2\9a\69\4e\46\9b\18\4e\dd\79\a7\aa\a6\52" + "\39\1e\ef\30\cc\9b\bd\5b\ee\4c\21\6d\30\00\72\b0\46\5f\08\cf\c5\b9\e0\3e" + "\c2\b3\0c\dc\8e\64\de\19\42\79\cf\43\ea\43\5d\8e\88\f7\ab\15\dc\3f\c8\67" + "\20\db\b8\64\b1\47\1f\de\f2\cb\3f\59\9f\d8\46\90\dc\ae\2f\22\f9\e2\31\89" + "\d9\9c\1c\4c\d3\a9\4a\57\84\9c\9f\ea\2c\3c\ae\3c\c3\1e\8b\e5\4e\17\01\25" + "\db\34\46\5f\15\ea\05\0c\7c\d9\45\8c\19\d0\73\8a\96\16\dd\44\f9\05\b7\5b" + "\71\b0\e6\21\36\5f\75\89\91\73\75\ab\7d\ae\d3\73\ec\37\c6\ea\55\75\ef\ea" + "\ab\8b\7b\11\dc\6d\1a\b2\6a\c4\25\cf\aa\e3\9f\49\49\89\cb\37\9b\0a\a7\01" + "\60\70\dc\b7\c8\83\e1\42\f5\be\ad\62\94\ad\8d\a1" + )) + (memory 0 0) + (memory 0 0) + (memory 0 0) + + (func (export "f32.kahan_sum") (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (local $c f32) + (local $t f32) + (block $exit + (loop $top + (local.set $t + (f32.sub + (f32.sub + (local.tee $sum + (f32.add + (local.get $c) + (local.tee $t + (f32.sub (f32.load $m (local.get $p)) (local.get $t)) + ) + ) + ) + (local.get $c) + ) + (local.get $t) + ) + ) + (local.set $p (i32.add (local.get $p) (i32.const 4))) + (local.set $c (local.get $sum)) + (br_if $top (local.tee $n (i32.add (local.get $n) (i32.const -1)))) + ) + ) + (local.get $sum) + ) + + (func (export "f32.plain_sum") (param $p i32) (param $n i32) (result f32) + (local $sum f32) + (block $exit + (loop $top + (local.set $sum (f32.add (local.get $sum) (f32.load $m (local.get $p)))) + (local.set $p (i32.add (local.get $p) (i32.const 4))) + (local.set $n (i32.add (local.get $n) (i32.const -1))) + (br_if $top (local.get $n)) + ) + ) + (local.get $sum) + ) +) + +(assert_return (invoke "f32.kahan_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.101a1ap+104)) +(assert_return (invoke "f32.plain_sum" (i32.const 0) (i32.const 256)) (f32.const -0x1.a0343ap+103)) + diff --git a/proposals/wasm-3.0/float_memory0.wast b/proposals/wasm-3.0/float_memory0.wast new file mode 100644 index 0000000..00e22df --- /dev/null +++ b/proposals/wasm-3.0/float_memory0.wast @@ -0,0 +1,60 @@ +;; Test that floating-point load and store are bit-preserving. + +;; Test that load and store do not canonicalize NaNs as x87 does. + +(module + (memory 0 0) + (memory 0 0) + (memory 0 0) + (memory $m (data "\00\00\a0\7f")) + (memory 0 0) + (memory 0 0) + + (func (export "f32.load") (result f32) (f32.load $m (i32.const 0))) + (func (export "i32.load") (result i32) (i32.load $m (i32.const 0))) + (func (export "f32.store") (f32.store $m (i32.const 0) (f32.const nan:0x200000))) + (func (export "i32.store") (i32.store $m (i32.const 0) (i32.const 0x7fa00000))) + (func (export "reset") (i32.store $m (i32.const 0) (i32.const 0))) +) + +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "f32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) +(invoke "reset") +(assert_return (invoke "i32.load") (i32.const 0x0)) +(assert_return (invoke "f32.load") (f32.const 0.0)) +(invoke "i32.store") +(assert_return (invoke "i32.load") (i32.const 0x7fa00000)) +(assert_return (invoke "f32.load") (f32.const nan:0x200000)) + +(module + (memory 0 0) + (memory $m (data "\00\00\00\00\00\00\f4\7f")) + + (func (export "f64.load") (result f64) (f64.load $m (i32.const 0))) + (func (export "i64.load") (result i64) (i64.load $m (i32.const 0))) + (func (export "f64.store") (f64.store $m (i32.const 0) (f64.const nan:0x4000000000000))) + (func (export "i64.store") (i64.store $m (i32.const 0) (i64.const 0x7ff4000000000000))) + (func (export "reset") (i64.store $m (i32.const 0) (i64.const 0))) +) + +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "f64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) +(invoke "reset") +(assert_return (invoke "i64.load") (i64.const 0x0)) +(assert_return (invoke "f64.load") (f64.const 0.0)) +(invoke "i64.store") +(assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) +(assert_return (invoke "f64.load") (f64.const nan:0x4000000000000)) + diff --git a/proposals/memory64/float_memory64.wast b/proposals/wasm-3.0/float_memory64.wast similarity index 100% rename from proposals/memory64/float_memory64.wast rename to proposals/wasm-3.0/float_memory64.wast diff --git a/proposals/wasm-3.0/func.wast b/proposals/wasm-3.0/func.wast new file mode 100644 index 0000000..f2d18cc --- /dev/null +++ b/proposals/wasm-3.0/func.wast @@ -0,0 +1,988 @@ +;; Test `func` declarations, i.e. functions + +(module + ;; Auxiliary definition + (type $sig (func)) + (func $dummy) + + ;; Syntax + + (func) + (func (export "f")) + (func $f) + (func $h (export "g")) + + (func (local)) + (func (local) (local)) + (func (local i32)) + (func (local $x i32)) + (func (local i32 f64 i64)) + (func (local i32) (local f64)) + (func (local i32 f32) (local $x i64) (local) (local i32 f64)) + + (func (param)) + (func (param) (param)) + (func (param i32)) + (func (param $x i32)) + (func (param i32 f64 i64)) + (func (param i32) (param f64)) + (func (param i32 f32) (param $x i64) (param) (param i32 f64)) + + (func (result)) + (func (result) (result)) + (func (result i32) (unreachable)) + (func (result i32 f64 f32) (unreachable)) + (func (result i32) (result f64) (unreachable)) + (func (result i32 f32) (result i64) (result) (result i32 f64) (unreachable)) + + (type $sig-1 (func)) + (type $sig-2 (func (result i32))) + (type $sig-3 (func (param $x i32))) + (type $sig-4 (func (param i32 f64 i32) (result i32))) + + (func (export "type-use-1") (type $sig-1)) + (func (export "type-use-2") (type $sig-2) (i32.const 0)) + (func (export "type-use-3") (type $sig-3)) + (func (export "type-use-4") (type $sig-4) (i32.const 0)) + (func (export "type-use-5") (type $sig-2) (result i32) (i32.const 0)) + (func (export "type-use-6") (type $sig-3) (param i32)) + (func (export "type-use-7") + (type $sig-4) (param i32) (param f64 i32) (result i32) (i32.const 0) + ) + + (func (type $sig)) + (func (type $forward)) ;; forward reference + + (func $complex + (param i32 f32) (param $x i64) (param) (param i32) + (result) (result i32) (result) (result i64 i32) + (local f32) (local $y i32) (local i64 i32) (local) (local f64 i32) + (unreachable) (unreachable) + ) + (func $complex-sig + (type $sig) + (local f32) (local $y i32) (local i64 i32) (local) (local f64 i32) + (unreachable) (unreachable) + ) + + (type $forward (func)) + + ;; Typing of locals + + (func (export "local-first-i32") (result i32) (local i32 i32) (local.get 0)) + (func (export "local-first-i64") (result i64) (local i64 i64) (local.get 0)) + (func (export "local-first-f32") (result f32) (local f32 f32) (local.get 0)) + (func (export "local-first-f64") (result f64) (local f64 f64) (local.get 0)) + (func (export "local-second-i32") (result i32) (local i32 i32) (local.get 1)) + (func (export "local-second-i64") (result i64) (local i64 i64) (local.get 1)) + (func (export "local-second-f32") (result f32) (local f32 f32) (local.get 1)) + (func (export "local-second-f64") (result f64) (local f64 f64) (local.get 1)) + (func (export "local-mixed") (result f64) + (local f32) (local $x i32) (local i64 i32) (local) (local f64 i32) + (drop (f32.neg (local.get 0))) + (drop (i32.eqz (local.get 1))) + (drop (i64.eqz (local.get 2))) + (drop (i32.eqz (local.get 3))) + (drop (f64.neg (local.get 4))) + (drop (i32.eqz (local.get 5))) + (local.get 4) + ) + + ;; Typing of parameters + + (func (export "param-first-i32") (param i32 i32) (result i32) (local.get 0)) + (func (export "param-first-i64") (param i64 i64) (result i64) (local.get 0)) + (func (export "param-first-f32") (param f32 f32) (result f32) (local.get 0)) + (func (export "param-first-f64") (param f64 f64) (result f64) (local.get 0)) + (func (export "param-second-i32") (param i32 i32) (result i32) (local.get 1)) + (func (export "param-second-i64") (param i64 i64) (result i64) (local.get 1)) + (func (export "param-second-f32") (param f32 f32) (result f32) (local.get 1)) + (func (export "param-second-f64") (param f64 f64) (result f64) (local.get 1)) + (func (export "param-mixed") (param f32 i32) (param) (param $x i64) (param i32 f64 i32) + (result f64) + (drop (f32.neg (local.get 0))) + (drop (i32.eqz (local.get 1))) + (drop (i64.eqz (local.get 2))) + (drop (i32.eqz (local.get 3))) + (drop (f64.neg (local.get 4))) + (drop (i32.eqz (local.get 5))) + (local.get 4) + ) + + ;; Typing of results + + (func (export "empty")) + (func (export "value-void") (call $dummy)) + (func (export "value-i32") (result i32) (i32.const 77)) + (func (export "value-i64") (result i64) (i64.const 7777)) + (func (export "value-f32") (result f32) (f32.const 77.7)) + (func (export "value-f64") (result f64) (f64.const 77.77)) + (func (export "value-i32-f64") (result i32 f64) (i32.const 77) (f64.const 7)) + (func (export "value-i32-i32-i32") (result i32 i32 i32) + (i32.const 1) (i32.const 2) (i32.const 3) + ) + (func (export "value-block-void") (block (call $dummy) (call $dummy))) + (func (export "value-block-i32") (result i32) + (block (result i32) (call $dummy) (i32.const 77)) + ) + (func (export "value-block-i32-i64") (result i32 i64) + (block (result i32 i64) (call $dummy) (i32.const 1) (i64.const 2)) + ) + + (func (export "return-empty") (return)) + (func (export "return-i32") (result i32) (return (i32.const 78))) + (func (export "return-i64") (result i64) (return (i64.const 7878))) + (func (export "return-f32") (result f32) (return (f32.const 78.7))) + (func (export "return-f64") (result f64) (return (f64.const 78.78))) + (func (export "return-i32-f64") (result i32 f64) + (return (i32.const 78) (f64.const 78.78)) + ) + (func (export "return-i32-i32-i32") (result i32 i32 i32) + (return (i32.const 1) (i32.const 2) (i32.const 3)) + ) + (func (export "return-block-i32") (result i32) + (return (block (result i32) (call $dummy) (i32.const 77))) + ) + (func (export "return-block-i32-i64") (result i32 i64) + (return (block (result i32 i64) (call $dummy) (i32.const 1) (i64.const 2))) + ) + + (func (export "break-empty") (br 0)) + (func (export "break-i32") (result i32) (br 0 (i32.const 79))) + (func (export "break-i64") (result i64) (br 0 (i64.const 7979))) + (func (export "break-f32") (result f32) (br 0 (f32.const 79.9))) + (func (export "break-f64") (result f64) (br 0 (f64.const 79.79))) + (func (export "break-i32-f64") (result i32 f64) + (br 0 (i32.const 79) (f64.const 79.79)) + ) + (func (export "break-i32-i32-i32") (result i32 i32 i32) + (br 0 (i32.const 1) (i32.const 2) (i32.const 3)) + ) + (func (export "break-block-i32") (result i32) + (br 0 (block (result i32) (call $dummy) (i32.const 77))) + ) + (func (export "break-block-i32-i64") (result i32 i64) + (br 0 (block (result i32 i64) (call $dummy) (i32.const 1) (i64.const 2))) + ) + + (func (export "break-br_if-empty") (param i32) + (br_if 0 (local.get 0)) + ) + (func (export "break-br_if-num") (param i32) (result i32) + (drop (br_if 0 (i32.const 50) (local.get 0))) (i32.const 51) + ) + (func (export "break-br_if-num-num") (param i32) (result i32 i64) + (drop (drop (br_if 0 (i32.const 50) (i64.const 51) (local.get 0)))) + (i32.const 51) (i64.const 52) + ) + + (func (export "break-br_table-empty") (param i32) + (br_table 0 0 0 (local.get 0)) + ) + (func (export "break-br_table-num") (param i32) (result i32) + (br_table 0 0 (i32.const 50) (local.get 0)) (i32.const 51) + ) + (func (export "break-br_table-num-num") (param i32) (result f32 i64) + (br_table 0 0 (f32.const 50) (i64.const 51) (local.get 0)) + (f32.const 51) (i64.const 52) + ) + (func (export "break-br_table-nested-empty") (param i32) + (block (br_table 0 1 0 (local.get 0))) + ) + (func (export "break-br_table-nested-num") (param i32) (result i32) + (i32.add + (block (result i32) + (br_table 0 1 0 (i32.const 50) (local.get 0)) (i32.const 51) + ) + (i32.const 2) + ) + ) + (func (export "break-br_table-nested-num-num") (param i32) (result i32 i32) + (i32.add + (block (result i32 i32) + (br_table 0 1 0 (i32.const 50) (i32.const 51) (local.get 0)) + (i32.const 51) (i32.const -3) + ) + ) + (i32.const 52) + ) + + ;; Large signatures + + (func (export "large-sig") + (param i32 i64 f32 f32 i32 f64 f32 i32 i32 i32 f32 f64 f64 f64 i32 i32 f32) + (result f64 f32 i32 i32 i32 i64 f32 i32 i32 f32 f64 f64 i32 f32 i32 f64) + (local.get 5) + (local.get 2) + (local.get 0) + (local.get 8) + (local.get 7) + (local.get 1) + (local.get 3) + (local.get 9) + (local.get 4) + (local.get 6) + (local.get 13) + (local.get 11) + (local.get 15) + (local.get 16) + (local.get 14) + (local.get 12) + ) + + ;; Default initialization of locals + + (func (export "init-local-i32") (result i32) (local i32) (local.get 0)) + (func (export "init-local-i64") (result i64) (local i64) (local.get 0)) + (func (export "init-local-f32") (result f32) (local f32) (local.get 0)) + (func (export "init-local-f64") (result f64) (local f64) (local.get 0)) +) + +(assert_return (invoke "type-use-1")) +(assert_return (invoke "type-use-2") (i32.const 0)) +(assert_return (invoke "type-use-3" (i32.const 1))) +(assert_return + (invoke "type-use-4" (i32.const 1) (f64.const 1) (i32.const 1)) + (i32.const 0) +) +(assert_return (invoke "type-use-5") (i32.const 0)) +(assert_return (invoke "type-use-6" (i32.const 1))) +(assert_return + (invoke "type-use-7" (i32.const 1) (f64.const 1) (i32.const 1)) + (i32.const 0) +) + +(assert_return (invoke "local-first-i32") (i32.const 0)) +(assert_return (invoke "local-first-i64") (i64.const 0)) +(assert_return (invoke "local-first-f32") (f32.const 0)) +(assert_return (invoke "local-first-f64") (f64.const 0)) +(assert_return (invoke "local-second-i32") (i32.const 0)) +(assert_return (invoke "local-second-i64") (i64.const 0)) +(assert_return (invoke "local-second-f32") (f32.const 0)) +(assert_return (invoke "local-second-f64") (f64.const 0)) +(assert_return (invoke "local-mixed") (f64.const 0)) + +(assert_return + (invoke "param-first-i32" (i32.const 2) (i32.const 3)) (i32.const 2) +) +(assert_return + (invoke "param-first-i64" (i64.const 2) (i64.const 3)) (i64.const 2) +) +(assert_return + (invoke "param-first-f32" (f32.const 2) (f32.const 3)) (f32.const 2) +) +(assert_return + (invoke "param-first-f64" (f64.const 2) (f64.const 3)) (f64.const 2) +) +(assert_return + (invoke "param-second-i32" (i32.const 2) (i32.const 3)) (i32.const 3) +) +(assert_return + (invoke "param-second-i64" (i64.const 2) (i64.const 3)) (i64.const 3) +) +(assert_return + (invoke "param-second-f32" (f32.const 2) (f32.const 3)) (f32.const 3) +) +(assert_return + (invoke "param-second-f64" (f64.const 2) (f64.const 3)) (f64.const 3) +) + +(assert_return + (invoke "param-mixed" + (f32.const 1) (i32.const 2) (i64.const 3) + (i32.const 4) (f64.const 5.5) (i32.const 6) + ) + (f64.const 5.5) +) + +(assert_return (invoke "empty")) +(assert_return (invoke "value-void")) +(assert_return (invoke "value-i32") (i32.const 77)) +(assert_return (invoke "value-i64") (i64.const 7777)) +(assert_return (invoke "value-f32") (f32.const 77.7)) +(assert_return (invoke "value-f64") (f64.const 77.77)) +(assert_return (invoke "value-i32-f64") (i32.const 77) (f64.const 7)) +(assert_return (invoke "value-i32-i32-i32") + (i32.const 1) (i32.const 2) (i32.const 3) +) +(assert_return (invoke "value-block-void")) +(assert_return (invoke "value-block-i32") (i32.const 77)) +(assert_return (invoke "value-block-i32-i64") (i32.const 1) (i64.const 2)) + +(assert_return (invoke "return-empty")) +(assert_return (invoke "return-i32") (i32.const 78)) +(assert_return (invoke "return-i64") (i64.const 7878)) +(assert_return (invoke "return-f32") (f32.const 78.7)) +(assert_return (invoke "return-f64") (f64.const 78.78)) +(assert_return (invoke "return-i32-f64") (i32.const 78) (f64.const 78.78)) +(assert_return (invoke "return-i32-i32-i32") + (i32.const 1) (i32.const 2) (i32.const 3) +) +(assert_return (invoke "return-block-i32") (i32.const 77)) +(assert_return (invoke "return-block-i32-i64") (i32.const 1) (i64.const 2)) + +(assert_return (invoke "break-empty")) +(assert_return (invoke "break-i32") (i32.const 79)) +(assert_return (invoke "break-i64") (i64.const 7979)) +(assert_return (invoke "break-f32") (f32.const 79.9)) +(assert_return (invoke "break-f64") (f64.const 79.79)) +(assert_return (invoke "break-i32-f64") (i32.const 79) (f64.const 79.79)) +(assert_return (invoke "break-i32-i32-i32") + (i32.const 1) (i32.const 2) (i32.const 3) +) +(assert_return (invoke "break-block-i32") (i32.const 77)) +(assert_return (invoke "break-block-i32-i64") (i32.const 1) (i64.const 2)) + +(assert_return (invoke "break-br_if-empty" (i32.const 0))) +(assert_return (invoke "break-br_if-empty" (i32.const 2))) +(assert_return (invoke "break-br_if-num" (i32.const 0)) (i32.const 51)) +(assert_return (invoke "break-br_if-num" (i32.const 1)) (i32.const 50)) +(assert_return (invoke "break-br_if-num-num" (i32.const 0)) + (i32.const 51) (i64.const 52) +) +(assert_return (invoke "break-br_if-num-num" (i32.const 1)) + (i32.const 50) (i64.const 51) +) + +(assert_return (invoke "break-br_table-empty" (i32.const 0))) +(assert_return (invoke "break-br_table-empty" (i32.const 1))) +(assert_return (invoke "break-br_table-empty" (i32.const 5))) +(assert_return (invoke "break-br_table-empty" (i32.const -1))) +(assert_return (invoke "break-br_table-num" (i32.const 0)) (i32.const 50)) +(assert_return (invoke "break-br_table-num" (i32.const 1)) (i32.const 50)) +(assert_return (invoke "break-br_table-num" (i32.const 10)) (i32.const 50)) +(assert_return (invoke "break-br_table-num" (i32.const -100)) (i32.const 50)) +(assert_return (invoke "break-br_table-num-num" (i32.const 0)) + (f32.const 50) (i64.const 51) +) +(assert_return (invoke "break-br_table-num-num" (i32.const 1)) + (f32.const 50) (i64.const 51) +) +(assert_return (invoke "break-br_table-num-num" (i32.const 10)) + (f32.const 50) (i64.const 51) +) +(assert_return (invoke "break-br_table-num-num" (i32.const -100)) + (f32.const 50) (i64.const 51) +) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 0))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 1))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 3))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const -2))) +(assert_return + (invoke "break-br_table-nested-num" (i32.const 0)) (i32.const 52) +) +(assert_return + (invoke "break-br_table-nested-num" (i32.const 1)) (i32.const 50) +) +(assert_return + (invoke "break-br_table-nested-num" (i32.const 2)) (i32.const 52) +) +(assert_return + (invoke "break-br_table-nested-num" (i32.const -3)) (i32.const 52) +) +(assert_return + (invoke "break-br_table-nested-num-num" (i32.const 0)) + (i32.const 101) (i32.const 52) +) +(assert_return + (invoke "break-br_table-nested-num-num" (i32.const 1)) + (i32.const 50) (i32.const 51) +) +(assert_return + (invoke "break-br_table-nested-num-num" (i32.const 2)) + (i32.const 101) (i32.const 52) +) +(assert_return + (invoke "break-br_table-nested-num-num" (i32.const -3)) + (i32.const 101) (i32.const 52) +) + +(assert_return + (invoke "large-sig" + (i32.const 0) (i64.const 1) (f32.const 2) (f32.const 3) + (i32.const 4) (f64.const 5) (f32.const 6) (i32.const 7) + (i32.const 8) (i32.const 9) (f32.const 10) (f64.const 11) + (f64.const 12) (f64.const 13) (i32.const 14) (i32.const 15) + (f32.const 16) + ) + (f64.const 5) (f32.const 2) (i32.const 0) (i32.const 8) + (i32.const 7) (i64.const 1) (f32.const 3) (i32.const 9) + (i32.const 4) (f32.const 6) (f64.const 13) (f64.const 11) + (i32.const 15) (f32.const 16) (i32.const 14) (f64.const 12) +) + +(assert_return (invoke "init-local-i32") (i32.const 0)) +(assert_return (invoke "init-local-i64") (i64.const 0)) +(assert_return (invoke "init-local-f32") (f32.const 0)) +(assert_return (invoke "init-local-f64") (f64.const 0)) + + +;; Expansion of inline function types + +(module + (func $f (result f64) (f64.const 0)) ;; adds implicit type definition + (func $g (param i32)) ;; reuses explicit type definition + (type $t (func (param i32))) + + (func $i32->void (type 0)) ;; (param i32) + (func $void->f64 (type 1) (f64.const 0)) ;; (result f64) + (func $check + (call $i32->void (i32.const 0)) + (drop (call $void->f64)) + ) +) + +(assert_invalid + (module + (func $f (result f64) (f64.const 0)) ;; adds implicit type definition + (func $g (param i32)) ;; reuses explicit type definition + (func $h (result f64) (f64.const 1)) ;; reuses implicit type definition + (type $t (func (param i32))) + + (func (type 2)) ;; does not exist + ) + "unknown type" +) + +(assert_malformed + (module quote + "(func $f (result f64) (f64.const 0))" ;; adds implicit type definition + "(func $g (param i32))" ;; reuses explicit type definition + "(func $h (result f64) (f64.const 1))" ;; reuses implicit type definition + "(type $t (func (param i32)))" + + "(func (type 2) (param i32))" ;; does not exist + ) + "unknown type" +) + +(module + (type $proc (func (result i32))) + (type $sig (func (param i32) (result i32))) + + (func (export "f") (type $sig) + (local $var i32) + (local.get $var) + ) + + (func $g (type $sig) + (local $var i32) + (local.get $var) + ) + (func (export "g") (type $sig) + (call $g (local.get 0)) + ) + + (func (export "p") (type $proc) + (local $var i32) + (local.set 0 (i32.const 42)) + (local.get $var) + ) +) + +(assert_return (invoke "f" (i32.const 42)) (i32.const 0)) +(assert_return (invoke "g" (i32.const 42)) (i32.const 0)) +(assert_return (invoke "p") (i32.const 42)) + + +(module + (type $sig (func)) + + (func $empty-sig-1) ;; should be assigned type $sig + (func $complex-sig-1 (param f64 i64 f64 i64 f64 i64 f32 i32)) + (func $empty-sig-2) ;; should be assigned type $sig + (func $complex-sig-2 (param f64 i64 f64 i64 f64 i64 f32 i32)) + (func $complex-sig-3 (param f64 i64 f64 i64 f64 i64 f32 i32)) + (func $complex-sig-4 (param i64 i64 f64 i64 f64 i64 f32 i32)) + (func $complex-sig-5 (param i64 i64 f64 i64 f64 i64 f32 i32)) + + (type $empty-sig-duplicate (func)) + (type $complex-sig-duplicate (func (param i64 i64 f64 i64 f64 i64 f32 i32))) + (table funcref + (elem + $complex-sig-3 $empty-sig-2 $complex-sig-1 $complex-sig-3 $empty-sig-1 + $complex-sig-4 $complex-sig-5 + ) + ) + + (func (export "signature-explicit-reused") + (call_indirect (type $sig) (i32.const 1)) + (call_indirect (type $sig) (i32.const 4)) + ) + + (func (export "signature-implicit-reused") + ;; The implicit index 3 in this test depends on the function and + ;; type definitions, and may need adapting if they change. + (call_indirect (type 3) + (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) + (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) + (i32.const 0) + ) + (call_indirect (type 3) + (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) + (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) + (i32.const 2) + ) + (call_indirect (type 3) + (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) + (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) + (i32.const 3) + ) + ) + + (func (export "signature-explicit-duplicate") + (call_indirect (type $empty-sig-duplicate) (i32.const 1)) + ) + + (func (export "signature-implicit-duplicate") + (call_indirect (type $complex-sig-duplicate) + (i64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) + (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) + (i32.const 5) + ) + (call_indirect (type $complex-sig-duplicate) + (i64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) + (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) + (i32.const 6) + ) + ) +) + +(assert_return (invoke "signature-explicit-reused")) +(assert_return (invoke "signature-implicit-reused")) +(assert_return (invoke "signature-explicit-duplicate")) +(assert_return (invoke "signature-implicit-duplicate")) + + +;; Malformed type use + +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (type $sig) (result i32) (param i32) (i32.const 0))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (param i32) (type $sig) (result i32) (i32.const 0))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (param i32) (result i32) (type $sig) (i32.const 0))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (result i32) (type $sig) (param i32) (i32.const 0))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (result i32) (param i32) (type $sig) (i32.const 0))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func (result i32) (param i32) (i32.const 0))" + ) + "unexpected token" +) + +(assert_malformed + (module quote + "(type $sig (func))" + "(func (type $sig) (result i32) (i32.const 0))" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (type $sig) (result i32) (i32.const 0))" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (type $sig) (param i32) (i32.const 0))" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32 i32) (result i32)))" + "(func (type $sig) (param i32) (result i32) (unreachable))" + ) + "inline function type" +) + +(assert_invalid + (module (func $g (type 4))) + "unknown type" +) +(assert_invalid + (module + (func $f (drop (ref.func $g))) + (func $g (type 4)) + (elem declare func $g) + ) + "unknown type" +) + + +;; Invalid typing of locals + +(assert_invalid + (module (func $type-local-num-vs-num (result i64) (local i32) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f32) (i32.eqz (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (local.get 1)))) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $type-local-uninitialized (local $x (ref $t)) (drop (local.get $x))) + ) + "uninitialized local" +) + + +;; Invalid typing of parameters + +(assert_invalid + (module (func $type-param-num-vs-num (param i32) (result i64) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f32) (i32.eqz (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (local.get 1)))) + "type mismatch" +) + + +;; Invalid typing of result + +(assert_invalid + (module (func $type-empty-i32 (result i32))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-i64 (result i64))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f32 (result f32))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f64 (result f64))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f64-i32 (result f64 i32))) + "type mismatch" +) + +(assert_invalid + (module (func $type-value-void-vs-num (result i32) + (nop) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-void-vs-nums (result i32 i32) + (nop) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-num-vs-void + (i32.const 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-nums-vs-void + (i32.const 0) (i64.const 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-num-vs-num (result i32) + (f32.const 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-num-vs-nums (result f32 f32) + (f32.const 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-value-nums-vs-num (result f32) + (f32.const 0) (f32.const 0) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-return-last-empty-vs-num (result i32) + (return) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-last-empty-vs-nums (result i32 i32) + (return) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-last-void-vs-num (result i32) + (return (nop)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-last-void-vs-nums (result i32 i64) + (return (nop)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-last-num-vs-num (result i32) + (return (i64.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-last-num-vs-nums (result i64 i64) + (return (i64.const 0)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-return-empty-vs-num (result i32) + (return) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-empty-vs-nums (result i32 i32) + (return) (i32.const 1) (i32.const 2) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-partial-vs-nums (result i32 i32) + (i32.const 1) (return) (i32.const 2) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-void-vs-num (result i32) + (return (nop)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-void-vs-nums (result i32 i32) + (return (nop)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-num-vs-num (result i32) + (return (i64.const 1)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-num-vs-nums (result i32 i32) + (return (i64.const 1)) (i32.const 1) (i32.const 2) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-first-num-vs-num (result i32) + (return (i64.const 1)) (return (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-first-num-vs-nums (result i32 i32) + (return (i32.const 1)) (return (i32.const 1) (i32.const 2)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-break-last-void-vs-num (result i32) + (br 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-last-void-vs-nums (result i32 i32) + (br 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-last-num-vs-num (result i32) + (br 0 (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-last-num-vs-nums (result i32 i32) + (br 0 (i32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-void-vs-num (result i32) + (br 0) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-void-vs-nums (result i32 i32) + (br 0) (i32.const 1) (i32.const 2) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-num (result i32) + (br 0 (i64.const 1)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-nums (result i32 i32) + (br 0 (i32.const 1)) (i32.const 1) (i32.const 2) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-first-num-vs-num (result i32) + (br 0 (i64.const 1)) (br 0 (i32.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-break-nested-empty-vs-num (result i32) + (block (br 1)) (br 0 (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-nested-empty-vs-nums (result i32 i32) + (block (br 1)) (br 0 (i32.const 1) (i32.const 2)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-nested-void-vs-num (result i32) + (block (br 1 (nop))) (br 0 (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-nested-void-vs-nums (result i32 i32) + (block (br 1 (nop))) (br 0 (i32.const 1) (i32.const 2)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-nested-num-vs-num (result i32) + (block (br 1 (i64.const 1))) (br 0 (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-nested-num-vs-nums (result i32 i32) + (block (result i32) (br 1 (i32.const 1))) (br 0 (i32.const 1) (i32.const 2)) + )) + "type mismatch" +) + + +;; Syntax errors + +(assert_malformed + (module quote "(func (nop) (local i32))") + "unexpected token" +) +(assert_malformed + (module quote "(func (nop) (param i32))") + "unexpected token" +) +(assert_malformed + (module quote "(func (nop) (result i32))") + "unexpected token" +) +(assert_malformed + (module quote "(func (local i32) (param i32))") + "unexpected token" +) +(assert_malformed + (module quote "(func (local i32) (result i32) (local.get 0))") + "unexpected token" +) +(assert_malformed + (module quote "(func (result i32) (param i32) (local.get 0))") + "unexpected token" +) + +;; Duplicate name errors + +(assert_malformed + (module quote "(func $foo)" "(func $foo)") + "duplicate func" +) +(assert_malformed + (module quote "(import \"\" \"\" (func $foo))" "(func $foo)") + "duplicate func" +) +(assert_malformed + (module quote "(import \"\" \"\" (func $foo))" "(import \"\" \"\" (func $foo))") + "duplicate func" +) + +(assert_malformed + (module quote "(func (param $foo i32) (param $foo i32))") + "duplicate local" +) +(assert_malformed + (module quote "(func (param $foo i32) (local $foo i32))") + "duplicate local" +) +(assert_malformed + (module quote "(func (local $foo i32) (local $foo i32))") + "duplicate local" +) diff --git a/proposals/wasm-3.0/global.wast b/proposals/wasm-3.0/global.wast new file mode 100644 index 0000000..370d755 --- /dev/null +++ b/proposals/wasm-3.0/global.wast @@ -0,0 +1,705 @@ +;; Test globals + +(module + (global (import "spectest" "global_i32") i32) + (global (import "spectest" "global_i64") i64) + + (global $a i32 (i32.const -2)) + (global (;3;) f32 (f32.const -3)) + (global (;4;) f64 (f64.const -4)) + (global $b i64 (i64.const -5)) + + (global $x (mut i32) (i32.const -12)) + (global (;7;) (mut f32) (f32.const -13)) + (global (;8;) (mut f64) (f64.const -14)) + (global $y (mut i64) (i64.const -15)) + + (global $z1 i32 (global.get 0)) + (global $z2 i64 (global.get 1)) + (global $z3 i32 (i32.add (i32.sub (i32.mul (i32.const 20) (i32.const 2)) (i32.const 2)) (i32.const 4))) + (global $z4 i64 (i64.add (i64.sub (i64.mul (i64.const 20) (i64.const 2)) (i64.const 2)) (i64.const 5))) + (global $z5 i32 (i32.add (global.get 0) (i32.const 42))) + (global $z6 i64 (i64.add (global.get 1) (i64.const 42))) + + (global $r externref (ref.null extern)) + (global $mr (mut externref) (ref.null extern)) + (global funcref (ref.null func)) + + (func (export "get-a") (result i32) (global.get $a)) + (func (export "get-b") (result i64) (global.get $b)) + (func (export "get-r") (result externref) (global.get $r)) + (func (export "get-mr") (result externref) (global.get $mr)) + (func (export "get-x") (result i32) (global.get $x)) + (func (export "get-y") (result i64) (global.get $y)) + (func (export "get-z1") (result i32) (global.get $z1)) + (func (export "get-z2") (result i64) (global.get $z2)) + (func (export "get-z3") (result i32) (global.get $z3)) + (func (export "get-z4") (result i64) (global.get $z4)) + (func (export "get-z5") (result i32) (global.get $z5)) + (func (export "get-z6") (result i64) (global.get $z6)) + (func (export "set-x") (param i32) (global.set $x (local.get 0))) + (func (export "set-y") (param i64) (global.set $y (local.get 0))) + (func (export "set-mr") (param externref) (global.set $mr (local.get 0))) + + (func (export "get-3") (result f32) (global.get 3)) + (func (export "get-4") (result f64) (global.get 4)) + (func (export "get-7") (result f32) (global.get 7)) + (func (export "get-8") (result f64) (global.get 8)) + (func (export "set-7") (param f32) (global.set 7 (local.get 0))) + (func (export "set-8") (param f64) (global.set 8 (local.get 0))) + + ;; As the argument of control constructs and instructions + + (memory 1) + + (func $dummy) + + (func (export "as-select-first") (result i32) + (select (global.get $x) (i32.const 2) (i32.const 3)) + ) + (func (export "as-select-mid") (result i32) + (select (i32.const 2) (global.get $x) (i32.const 3)) + ) + (func (export "as-select-last") (result i32) + (select (i32.const 2) (i32.const 3) (global.get $x)) + ) + + (func (export "as-loop-first") (result i32) + (loop (result i32) + (global.get $x) (call $dummy) (call $dummy) + ) + ) + (func (export "as-loop-mid") (result i32) + (loop (result i32) + (call $dummy) (global.get $x) (call $dummy) + ) + ) + (func (export "as-loop-last") (result i32) + (loop (result i32) + (call $dummy) (call $dummy) (global.get $x) + ) + ) + + (func (export "as-if-condition") (result i32) + (if (result i32) (global.get $x) + (then (call $dummy) (i32.const 2)) + (else (call $dummy) (i32.const 3)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (global.get $x)) (else (i32.const 2)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 2)) (else (global.get $x)) + ) + ) + + (func (export "as-br_if-first") (result i32) + (block (result i32) + (br_if 0 (global.get $x) (i32.const 2)) + (return (i32.const 3)) + ) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) + (br_if 0 (i32.const 2) (global.get $x)) + (return (i32.const 3)) + ) + ) + + (func (export "as-br_table-first") (result i32) + (block (result i32) + (global.get $x) (i32.const 2) (br_table 0 0) + ) + ) + (func (export "as-br_table-last") (result i32) + (block (result i32) + (i32.const 2) (global.get $x) (br_table 0 0) + ) + ) + + (func $func (param i32 i32) (result i32) (local.get 0)) + (type $check (func (param i32 i32) (result i32))) + (table funcref (elem $func)) + (func (export "as-call_indirect-first") (result i32) + (block (result i32) + (call_indirect (type $check) + (global.get $x) (i32.const 2) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 2) (global.get $x) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 2) (i32.const 0) (global.get $x) + ) + ) + ) + + (func (export "as-store-first") + (global.get $x) (i32.const 1) (i32.store) + ) + (func (export "as-store-last") + (i32.const 0) (global.get $x) (i32.store) + ) + (func (export "as-load-operand") (result i32) + (i32.load (global.get $x)) + ) + (func (export "as-memory.grow-value") (result i32) + (memory.grow (global.get $x)) + ) + + (func $f (param i32) (result i32) (local.get 0)) + (func (export "as-call-value") (result i32) + (call $f (global.get $x)) + ) + + (func (export "as-return-value") (result i32) + (global.get $x) (return) + ) + (func (export "as-drop-operand") + (drop (global.get $x)) + ) + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (global.get $x))) + ) + + (func (export "as-local.set-value") (param i32) (result i32) + (local.set 0 (global.get $x)) + (local.get 0) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 (global.get $x)) + ) + (func (export "as-global.set-value") (result i32) + (global.set $x (global.get $x)) + (global.get $x) + ) + + (func (export "as-unary-operand") (result i32) + (i32.eqz (global.get $x)) + ) + (func (export "as-binary-operand") (result i32) + (i32.mul + (global.get $x) (global.get $x) + ) + ) + (func (export "as-compare-operand") (result i32) + (i32.gt_u + (global.get 0) (i32.const 1) + ) + ) +) + +(assert_return (invoke "get-a") (i32.const -2)) +(assert_return (invoke "get-b") (i64.const -5)) +(assert_return (invoke "get-r") (ref.null extern)) +(assert_return (invoke "get-mr") (ref.null extern)) +(assert_return (invoke "get-x") (i32.const -12)) +(assert_return (invoke "get-y") (i64.const -15)) +(assert_return (invoke "get-z1") (i32.const 666)) +(assert_return (invoke "get-z2") (i64.const 666)) +(assert_return (invoke "get-z3") (i32.const 42)) +(assert_return (invoke "get-z4") (i64.const 43)) +(assert_return (invoke "get-z5") (i32.const 708)) +(assert_return (invoke "get-z6") (i64.const 708)) + +(assert_return (invoke "get-3") (f32.const -3)) +(assert_return (invoke "get-4") (f64.const -4)) +(assert_return (invoke "get-7") (f32.const -13)) +(assert_return (invoke "get-8") (f64.const -14)) + +(assert_return (invoke "set-x" (i32.const 6))) +(assert_return (invoke "set-y" (i64.const 7))) + +(assert_return (invoke "set-7" (f32.const 8))) +(assert_return (invoke "set-8" (f64.const 9))) + +(assert_return (invoke "get-x") (i32.const 6)) +(assert_return (invoke "get-y") (i64.const 7)) +(assert_return (invoke "get-7") (f32.const 8)) +(assert_return (invoke "get-8") (f64.const 9)) + +(assert_return (invoke "set-7" (f32.const 8))) +(assert_return (invoke "set-8" (f64.const 9))) +(assert_return (invoke "set-mr" (ref.extern 10))) + +(assert_return (invoke "get-x") (i32.const 6)) +(assert_return (invoke "get-y") (i64.const 7)) +(assert_return (invoke "get-7") (f32.const 8)) +(assert_return (invoke "get-8") (f64.const 9)) +(assert_return (invoke "get-mr") (ref.extern 10)) + +(assert_return (invoke "as-select-first") (i32.const 6)) +(assert_return (invoke "as-select-mid") (i32.const 2)) +(assert_return (invoke "as-select-last") (i32.const 2)) + +(assert_return (invoke "as-loop-first") (i32.const 6)) +(assert_return (invoke "as-loop-mid") (i32.const 6)) +(assert_return (invoke "as-loop-last") (i32.const 6)) + +(assert_return (invoke "as-if-condition") (i32.const 2)) +(assert_return (invoke "as-if-then") (i32.const 6)) +(assert_return (invoke "as-if-else") (i32.const 6)) + +(assert_return (invoke "as-br_if-first") (i32.const 6)) +(assert_return (invoke "as-br_if-last") (i32.const 2)) + +(assert_return (invoke "as-br_table-first") (i32.const 6)) +(assert_return (invoke "as-br_table-last") (i32.const 2)) + +(assert_return (invoke "as-call_indirect-first") (i32.const 6)) +(assert_return (invoke "as-call_indirect-mid") (i32.const 2)) +(assert_trap (invoke "as-call_indirect-last") "undefined element") + +(assert_return (invoke "as-store-first")) +(assert_return (invoke "as-store-last")) +(assert_return (invoke "as-load-operand") (i32.const 1)) +(assert_return (invoke "as-memory.grow-value") (i32.const 1)) + +(assert_return (invoke "as-call-value") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 6)) +(assert_return (invoke "as-drop-operand")) +(assert_return (invoke "as-br-value") (i32.const 6)) + +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 6)) +(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 6)) +(assert_return (invoke "as-global.set-value") (i32.const 6)) + +(assert_return (invoke "as-unary-operand") (i32.const 0)) +(assert_return (invoke "as-binary-operand") (i32.const 36)) +(assert_return (invoke "as-compare-operand") (i32.const 1)) + +(assert_invalid + (module (global f32 (f32.const 0)) (func (global.set 0 (f32.const 1)))) + "immutable global" +) + +(assert_invalid + (module (import "spectest" "global_i32" (global i32)) (func (global.set 0 (i32.const 1)))) + "immutable global" +) + +;; mutable globals can be exported +(module (global (mut f32) (f32.const 0)) (export "a" (global 0))) +(module (global (export "a") (mut f32) (f32.const 0))) + +(assert_invalid + (module (global f32 (f32.neg (f32.const 0)))) + "constant expression required" +) + +(assert_invalid + (module (global f32 (local.get 0))) + "constant expression required" +) + +(assert_invalid + (module (global f32 (f32.neg (f32.const 1)))) + "constant expression required" +) + +(assert_invalid + (module (global i32 (i32.const 0) (nop))) + "constant expression required" +) + +(assert_invalid + (module (global i32 (i32.ctz (i32.const 0)))) + "constant expression required" +) + +(assert_invalid + (module (global i32 (nop))) + "constant expression required" +) + +(assert_invalid + (module (global i32 (f32.const 0))) + "type mismatch" +) + +(assert_invalid + (module (global i32 (i32.const 0) (i32.const 0))) + "type mismatch" +) + +(assert_invalid + (module (global i32 (;empty instruction sequence;))) + "type mismatch" +) + +(assert_invalid + (module (global (import "" "") externref) (global funcref (global.get 0))) + "type mismatch" +) + +(assert_invalid + (module (global (import "test" "global-i32") i32) (global i32 (global.get 0) (global.get 0))) + "type mismatch" +) + +(assert_invalid + (module (global (import "test" "global-i32") i32) (global i32 (i32.const 0) (global.get 0))) + "type mismatch" +) + +(assert_invalid + (module (global i32 (global.get 0))) + "unknown global" +) + +(assert_invalid + (module (global i32 (global.get 1)) (global i32 (i32.const 0))) + "unknown global" +) + +(assert_invalid + (module (global (import "test" "global-i32") i32) (global i32 (global.get 2))) + "unknown global" +) + +(module (global i32 (i32.const 0)) (global i32 (global.get 0))) +(module (global $g i32 (i32.const 0)) (global i32 (global.get $g))) + +(assert_invalid + (module (global (import "test" "global-mut-i32") (mut i32)) (global i32 (global.get 0))) + "constant expression required" +) + +(module + (import "spectest" "global_i32" (global i32)) +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\02\98\80\80\80\00" ;; import section + "\01" ;; length 1 + "\08\73\70\65\63\74\65\73\74" ;; "spectest" + "\0a\67\6c\6f\62\61\6c\5f\69\33\32" ;; "global_i32" + "\03" ;; GlobalImport + "\7f" ;; i32 + "\02" ;; malformed mutability + ) + "malformed mutability" +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\02\98\80\80\80\00" ;; import section + "\01" ;; length 1 + "\08\73\70\65\63\74\65\73\74" ;; "spectest" + "\0a\67\6c\6f\62\61\6c\5f\69\33\32" ;; "global_i32" + "\03" ;; GlobalImport + "\7f" ;; i32 + "\ff" ;; malformed mutability + ) + "malformed mutability" +) + +(module + (global i32 (i32.const 0)) +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\06\86\80\80\80\00" ;; global section + "\01" ;; length 1 + "\7f" ;; i32 + "\02" ;; malformed mutability + "\41\00" ;; i32.const 0 + "\0b" ;; end + ) + "malformed mutability" +) +(assert_malformed + (module binary + "\00asm" "\01\00\00\00" + "\06\86\80\80\80\00" ;; global section + "\01" ;; length 1 + "\7f" ;; i32 + "\ff" ;; malformed mutability + "\41\00" ;; i32.const 0 + "\0b" ;; end + ) + "malformed mutability" +) + +;; global.get with invalid index +(assert_invalid + (module (func (result i32) (global.get 0))) + "unknown global" +) + +(assert_invalid + (module + (global i32 (i32.const 0)) + (func (result i32) (global.get 1)) + ) + "unknown global" +) + +(assert_invalid + (module + (import "spectest" "global_i32" (global i32)) + (func (result i32) (global.get 1)) + ) + "unknown global" +) + +(assert_invalid + (module + (import "spectest" "global_i32" (global i32)) + (global i32 (i32.const 0)) + (func (result i32) (global.get 2)) + ) + "unknown global" +) + +;; global.set with invalid index +(assert_invalid + (module (func (i32.const 0) (global.set 0))) + "unknown global" +) + +(assert_invalid + (module + (global i32 (i32.const 0)) + (func (i32.const 0) (global.set 1)) + ) + "unknown global" +) + +(assert_invalid + (module + (import "spectest" "global_i32" (global i32)) + (func (i32.const 0) (global.set 1)) + ) + "unknown global" +) + +(assert_invalid + (module + (import "spectest" "global_i32" (global i32)) + (global i32 (i32.const 0)) + (func (i32.const 0) (global.set 2)) + ) + "unknown global" +) + + +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty + (global.set $x) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-block + (i32.const 0) + (block (global.set $x)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-loop + (i32.const 0) + (loop (global.set $x)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-then + (i32.const 0) (i32.const 0) + (if (then (global.set $x))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-else + (i32.const 0) (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (global.set $x))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-br + (i32.const 0) + (block (br 0 (global.set $x))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-br_if + (i32.const 0) + (block (br_if 0 (global.set $x))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-br_table + (i32.const 0) + (block (br_table 0 (global.set $x))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-return + (return (global.set $x)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-select + (select (global.set $x) (i32.const 1) (i32.const 2)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-global.set-value-empty-in-call + (call 1 (global.set $x)) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-global.set-value-empty-in-call_indirect + (block (result i32) + (call_indirect (type $sig) + (global.set $x) (i32.const 0) + ) + ) + ) + ) + "type mismatch" +) + + +;; Definition order + +(module + (global (export "g") i32 (i32.const 4)) +) +(register "G") + +(module + (global $g0 (import "G" "g") i32) + (global $g1 i32 (i32.const 8)) + (global $g2 i32 (global.get $g0)) + (global $g3 i32 (global.get $g1)) + + (global $gf funcref (ref.func $f)) + (func $f) + + (table $t 10 funcref (ref.null func)) + (elem (table $t) (global.get $g2) funcref (ref.func $f)) + (elem (table $t) (global.get $g3) funcref (global.get $gf)) + + (memory $m 1) + (data (global.get $g2) "\44\44\44\44") + (data (global.get $g3) "\88\88\88\88") + + (func (export "get-elem") (param $i i32) (result funcref) + (table.get $t (local.get $i)) + ) + (func (export "get-data") (param $i i32) (result i32) + (i32.load (local.get $i)) + ) +) + +(assert_return (invoke "get-elem" (i32.const 0)) (ref.null)) +(assert_return (invoke "get-elem" (i32.const 4)) (ref.func)) +(assert_return (invoke "get-elem" (i32.const 8)) (ref.func)) + +(assert_return (invoke "get-data" (i32.const 4)) (i32.const 0x44444444)) +(assert_return (invoke "get-data" (i32.const 8)) (i32.const 0x88888888)) + +(assert_invalid + (module + (global $g1 i32 (global.get $g2)) + (global $g2 i32 (i32.const 0)) + ) + "unknown global" +) + +(assert_invalid + (module + (global $g funcref (ref.null func)) + (table $t 10 funcref (global.get $g)) + ) + "unknown global" +) + + +;; Duplicate identifier errors + +(assert_malformed + (module quote + "(global $foo i32 (i32.const 0))" + "(global $foo i32 (i32.const 0))" + ) + "duplicate global" +) +(assert_malformed + (module quote + "(import \"\" \"\" (global $foo i32))" + "(global $foo i32 (i32.const 0))" + ) + "duplicate global" +) +(assert_malformed + (module quote + "(import \"\" \"\" (global $foo i32))" + "(import \"\" \"\" (global $foo i32))" + ) + "duplicate global" +) diff --git a/proposals/wasm-3.0/i16x8_relaxed_q15mulr_s.wast b/proposals/wasm-3.0/i16x8_relaxed_q15mulr_s.wast new file mode 100644 index 0000000..00f901c --- /dev/null +++ b/proposals/wasm-3.0/i16x8_relaxed_q15mulr_s.wast @@ -0,0 +1,28 @@ +;; Tests for i16x8.relaxed_q15mulr_s. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "i16x8.relaxed_q15mulr_s") (param v128 v128) (result v128) (i16x8.relaxed_q15mulr_s (local.get 0) (local.get 1))) + + (func (export "i16x8.relaxed_q15mulr_s_cmp") (param v128 v128) (result v128) + (i16x8.eq + (i16x8.relaxed_q15mulr_s (local.get 0) (local.get 1)) + (i16x8.relaxed_q15mulr_s (local.get 0) (local.get 1)))) +) + +;; INT16_MIN = -32768 +(assert_return (invoke "i16x8.relaxed_q15mulr_s" + (v128.const i16x8 -32768 -32767 32767 0 0 0 0 0) + (v128.const i16x8 -32768 -32768 32767 0 0 0 0 0)) + ;; overflows, return either INT16_MIN or INT16_MAX + (either (v128.const i16x8 -32768 32767 32766 0 0 0 0 0) + (v128.const i16x8 32767 32767 32766 0 0 0 0 0))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +(assert_return (invoke "i16x8.relaxed_q15mulr_s_cmp" + (v128.const i16x8 -32768 -32767 32767 0 0 0 0 0) + (v128.const i16x8 -32768 -32768 32767 0 0 0 0 0)) + ;; overflows, return either INT16_MIN or INT16_MAX + (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) + diff --git a/proposals/wasm-3.0/i31.wast b/proposals/wasm-3.0/i31.wast new file mode 100644 index 0000000..7485650 --- /dev/null +++ b/proposals/wasm-3.0/i31.wast @@ -0,0 +1,228 @@ +(module + (func (export "new") (param $i i32) (result (ref i31)) + (ref.i31 (local.get $i)) + ) + + (func (export "get_u") (param $i i32) (result i32) + (i31.get_u (ref.i31 (local.get $i))) + ) + (func (export "get_s") (param $i i32) (result i32) + (i31.get_s (ref.i31 (local.get $i))) + ) + + (func (export "get_u-null") (result i32) + (i31.get_u (ref.null i31)) + ) + (func (export "get_s-null") (result i32) + (i31.get_u (ref.null i31)) + ) + + (global $i (ref i31) (ref.i31 (i32.const 2))) + (global $m (mut (ref i31)) (ref.i31 (i32.const 3))) + + (func (export "get_globals") (result i32 i32) + (i31.get_u (global.get $i)) + (i31.get_u (global.get $m)) + ) + + (func (export "set_global") (param i32) + (global.set $m (ref.i31 (local.get 0))) + ) +) + +(assert_return (invoke "new" (i32.const 1)) (ref.i31)) + +(assert_return (invoke "get_u" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "get_u" (i32.const 100)) (i32.const 100)) +(assert_return (invoke "get_u" (i32.const -1)) (i32.const 0x7fff_ffff)) +(assert_return (invoke "get_u" (i32.const 0x3fff_ffff)) (i32.const 0x3fff_ffff)) +(assert_return (invoke "get_u" (i32.const 0x4000_0000)) (i32.const 0x4000_0000)) +(assert_return (invoke "get_u" (i32.const 0x7fff_ffff)) (i32.const 0x7fff_ffff)) +(assert_return (invoke "get_u" (i32.const 0xaaaa_aaaa)) (i32.const 0x2aaa_aaaa)) +(assert_return (invoke "get_u" (i32.const 0xcaaa_aaaa)) (i32.const 0x4aaa_aaaa)) + +(assert_return (invoke "get_s" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "get_s" (i32.const 100)) (i32.const 100)) +(assert_return (invoke "get_s" (i32.const -1)) (i32.const -1)) +(assert_return (invoke "get_s" (i32.const 0x3fff_ffff)) (i32.const 0x3fff_ffff)) +(assert_return (invoke "get_s" (i32.const 0x4000_0000)) (i32.const -0x4000_0000)) +(assert_return (invoke "get_s" (i32.const 0x7fff_ffff)) (i32.const -1)) +(assert_return (invoke "get_s" (i32.const 0xaaaa_aaaa)) (i32.const 0x2aaa_aaaa)) +(assert_return (invoke "get_s" (i32.const 0xcaaa_aaaa)) (i32.const 0xcaaa_aaaa)) + +(assert_trap (invoke "get_u-null") "null i31 reference") +(assert_trap (invoke "get_s-null") "null i31 reference") + +(assert_return (invoke "get_globals") (i32.const 2) (i32.const 3)) + +(invoke "set_global" (i32.const 1234)) +(assert_return (invoke "get_globals") (i32.const 2) (i32.const 1234)) + +(module $tables_of_i31ref + (table $table 3 10 i31ref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + (i31.get_u (table.get $table (local.get 0))) + ) + + (func (export "grow") (param i32 i32) (result i32) + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) + ) + + (func (export "fill") (param i32 i32 i32) + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) + ) + + (func (export "copy") (param i32 i32 i32) + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) + +(module $env + (global (export "g") i32 (i32.const 42)) +) +(register "env") + +(module $i31ref_of_global_table_initializer + (global $g (import "env" "g") i32) + (table $t 3 3 (ref i31) (ref.i31 (global.get $g))) + (func (export "get") (param i32) (result i32) + (i31.get_u (local.get 0) (table.get $t)) + ) +) + +(assert_return (invoke "get" (i32.const 0)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 42)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 42)) + +(module $i31ref_of_global_global_initializer + (global $g0 (import "env" "g") i32) + (global $g1 i31ref (ref.i31 (global.get $g0))) + (func (export "get") (result i32) + (i31.get_u (global.get $g1)) + ) +) + +(assert_return (invoke "get") (i32.const 42)) + +(module $anyref_global_of_i31ref + (global $c anyref (ref.i31 (i32.const 1234))) + (global $m (mut anyref) (ref.i31 (i32.const 5678))) + + (func (export "get_globals") (result i32 i32) + (i31.get_u (ref.cast i31ref (global.get $c))) + (i31.get_u (ref.cast i31ref (global.get $m))) + ) + + (func (export "set_global") (param i32) + (global.set $m (ref.i31 (local.get 0))) + ) +) + +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 5678)) +(invoke "set_global" (i32.const 0)) +(assert_return (invoke "get_globals") (i32.const 1234) (i32.const 0)) + +(module $anyref_table_of_i31ref + (table $table 3 10 anyref) + (elem (table $table) (i32.const 0) i31ref (item (ref.i31 (i32.const 999))) + (item (ref.i31 (i32.const 888))) + (item (ref.i31 (i32.const 777)))) + + (func (export "size") (result i32) + table.size $table + ) + + (func (export "get") (param i32) (result i32) + (i31.get_u (ref.cast i31ref (table.get $table (local.get 0)))) + ) + + (func (export "grow") (param i32 i32) (result i32) + (table.grow $table (ref.i31 (local.get 1)) (local.get 0)) + ) + + (func (export "fill") (param i32 i32 i32) + (table.fill $table (local.get 0) (ref.i31 (local.get 1)) (local.get 2)) + ) + + (func (export "copy") (param i32 i32 i32) + (table.copy $table $table (local.get 0) (local.get 1) (local.get 2)) + ) + + (elem $elem i31ref (item (ref.i31 (i32.const 123))) + (item (ref.i31 (i32.const 456))) + (item (ref.i31 (i32.const 789)))) + (func (export "init") (param i32 i32 i32) + (table.init $table $elem (local.get 0) (local.get 1) (local.get 2)) + ) +) + +;; Initial state. +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "get" (i32.const 0)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 888)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 777)) + +;; Grow from size 3 to size 5. +(assert_return (invoke "grow" (i32.const 2) (i32.const 333)) (i32.const 3)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 333)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 333)) + +;; Fill table[2..4] = 111. +(invoke "fill" (i32.const 2) (i32.const 111) (i32.const 2)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 111)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 111)) + +;; Copy from table[0..2] to table[3..5]. +(invoke "copy" (i32.const 3) (i32.const 0) (i32.const 2)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 999)) +(assert_return (invoke "get" (i32.const 4)) (i32.const 888)) + +;; Initialize the passive element at table[1..4]. +(invoke "init" (i32.const 1) (i32.const 0) (i32.const 3)) +(assert_return (invoke "get" (i32.const 1)) (i32.const 123)) +(assert_return (invoke "get" (i32.const 2)) (i32.const 456)) +(assert_return (invoke "get" (i32.const 3)) (i32.const 789)) diff --git a/proposals/wasm-3.0/i32x4_relaxed_trunc.wast b/proposals/wasm-3.0/i32x4_relaxed_trunc.wast new file mode 100644 index 0000000..cca3ecb --- /dev/null +++ b/proposals/wasm-3.0/i32x4_relaxed_trunc.wast @@ -0,0 +1,124 @@ +;; Tests for i32x4.relaxed_trunc_f32x4_s, i32x4.relaxed_trunc_f32x4_u, i32x4.relaxed_trunc_f64x2_s_zero, and i32x4.relaxed_trunc_f64x2_u_zero. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "i32x4.relaxed_trunc_f32x4_s") (param v128) (result v128) (i32x4.relaxed_trunc_f32x4_s (local.get 0))) + (func (export "i32x4.relaxed_trunc_f32x4_u") (param v128) (result v128) (i32x4.relaxed_trunc_f32x4_u (local.get 0))) + (func (export "i32x4.relaxed_trunc_f64x2_s_zero") (param v128) (result v128) (i32x4.relaxed_trunc_f64x2_s_zero (local.get 0))) + (func (export "i32x4.relaxed_trunc_f64x2_u_zero") (param v128) (result v128) (i32x4.relaxed_trunc_f64x2_u_zero (local.get 0))) + + (func (export "i32x4.relaxed_trunc_f32x4_s_cmp") (param v128) (result v128) + (i32x4.eq + (i32x4.relaxed_trunc_f32x4_s (local.get 0)) + (i32x4.relaxed_trunc_f32x4_s (local.get 0)))) + (func (export "i32x4.relaxed_trunc_f32x4_u_cmp") (param v128) (result v128) + (i32x4.eq + (i32x4.relaxed_trunc_f32x4_u (local.get 0)) + (i32x4.relaxed_trunc_f32x4_u (local.get 0)))) + (func (export "i32x4.relaxed_trunc_f64x2_s_zero_cmp") (param v128) (result v128) + (i32x4.eq + (i32x4.relaxed_trunc_f64x2_s_zero (local.get 0)) + (i32x4.relaxed_trunc_f64x2_s_zero (local.get 0)))) + (func (export "i32x4.relaxed_trunc_f64x2_u_zero_cmp") (param v128) (result v128) + (i32x4.eq + (i32x4.relaxed_trunc_f64x2_u_zero (local.get 0)) + (i32x4.relaxed_trunc_f64x2_u_zero (local.get 0)))) +) + +;; Test some edge cases around min/max to ensure that the instruction either +;; saturates correctly or returns INT_MIN. +;; +;; Note, though, that INT_MAX itself is not tested. The value for INT_MAX is +;; 2147483647 but that is not representable in a `f32` since it requires 31 bits +;; when a f32 has only 24 bits available. This means that the closest integers +;; to INT_MAX which can be represented are 2147483520 and 2147483648, meaning +;; that the INT_MAX test case cannot be tested. +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s" + ;; INT32_MIN INT32_MAX + (v128.const f32x4 -2147483648.0 -2147483904.0 2.0 2147483904.0)) + ;; out of range -> saturate or INT32_MIN + (either (v128.const i32x4 -2147483648 -2147483648 2 2147483647) + (v128.const i32x4 -2147483648 -2147483648 2 -2147483648))) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s" + (v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444)) + ;; nans -> 0 or INT32_MIN + (either (v128.const i32x4 0 0 0 0) + (v128.const i32x4 0x80000000 0x80000000 0x80000000 0x80000000))) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u" + ;; UINT32_MIN UINT32_MIN-1 saturate or UINT32_MAX + (either (v128.const i32x4 0 0 4294967040 0xffffffff) + (v128.const i32x4 0 0xffffffff 4294967040 0xffffffff))) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u" + (v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444)) + ;; nans -> 0 or UINT32_MAX + (either (v128.const i32x4 0 0 0 0) + (v128.const i32x4 0xffffffff 0xffffffff 0xffffffff 0xffffffff))) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero" + (v128.const f64x2 -2147483904.0 2147483904.0)) + ;; out of range -> saturate or INT32_MIN + (either (v128.const i32x4 -2147483648 2147483647 0 0) + (v128.const i32x4 -2147483648 -2147483648 0 0))) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero" + (v128.const f64x2 nan -nan)) + (either (v128.const i32x4 0 0 0 0) + (v128.const i32x4 0x80000000 0x80000000 0 0))) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero" + (v128.const f64x2 -1.0 4294967296.0)) + ;; out of range -> saturate or UINT32_MAX + (either (v128.const i32x4 0 0xffffffff 0 0) + (v128.const i32x4 0xffffffff 0xffffffff 0 0))) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero" + (v128.const f64x2 nan -nan)) + (either (v128.const i32x4 0 0 0 0) + (v128.const i32x4 0 0 0xffffffff 0xffffffff))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s_cmp" + ;; INT32_MIN INT32_MAX + (v128.const f32x4 -2147483648.0 -2147483904.0 2147483647.0 2147483904.0)) + ;; out of range -> saturate or INT32_MIN + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_s_cmp" + (v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444)) + ;; nans -> 0 or INT32_MIN + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u_cmp" + ;; UINT32_MIN UINT32_MIN-1 saturate or UINT32_MAX + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f32x4_u_cmp" + (v128.const f32x4 nan -nan nan:0x444444 -nan:0x444444)) + ;; nans -> 0 or UINT32_MAX + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero_cmp" + (v128.const f64x2 -2147483904.0 2147483904.0)) + ;; out of range -> saturate or INT32_MIN + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_s_zero_cmp" + (v128.const f64x2 nan -nan)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero_cmp" + (v128.const f64x2 -1.0 4294967296.0)) + ;; out of range -> saturate or UINT32_MAX + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_trunc_f64x2_u_zero_cmp" + (v128.const f64x2 nan -nan)) + (v128.const i32x4 -1 -1 -1 -1)) diff --git a/proposals/wasm-3.0/i8x16_relaxed_swizzle.wast b/proposals/wasm-3.0/i8x16_relaxed_swizzle.wast new file mode 100644 index 0000000..f1bcb45 --- /dev/null +++ b/proposals/wasm-3.0/i8x16_relaxed_swizzle.wast @@ -0,0 +1,45 @@ +;; Tests for relaxed i8x16 swizzle. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "i8x16.relaxed_swizzle") (param v128 v128) (result v128) (i8x16.relaxed_swizzle (local.get 0) (local.get 1))) + + (func (export "i8x16.relaxed_swizzle_cmp") (param v128 v128) (result v128) + (i8x16.eq + (i8x16.relaxed_swizzle (local.get 0) (local.get 1)) + (i8x16.relaxed_swizzle (local.get 0) (local.get 1)))) +) + +(assert_return (invoke "i8x16.relaxed_swizzle" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (either (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))) + +;; out of range, returns 0 or modulo 15 if < 128 +(assert_return (invoke "i8x16.relaxed_swizzle" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)) + (either (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))) + +;; out of range, returns 0 if >= 128 +(assert_return (invoke "i8x16.relaxed_swizzle" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 128 129 130 131 132 133 134 135 248 249 250 251 252 253 254 255)) + (either (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +;; out of range, returns 0 or modulo 15 if < 128 +(assert_return (invoke "i8x16.relaxed_swizzle_cmp" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)) + (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) + +;; out of range, returns 0 if >= 128 +(assert_return (invoke "i8x16.relaxed_swizzle_cmp" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 128 129 130 131 132 133 134 135 248 249 250 251 252 253 254 255)) + (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) diff --git a/proposals/wasm-3.0/id.wast b/proposals/wasm-3.0/id.wast new file mode 100644 index 0000000..dcf151f --- /dev/null +++ b/proposals/wasm-3.0/id.wast @@ -0,0 +1,31 @@ +(module + (func $fg) (func (call $fg)) + (func $03) (func (call $03)) + (func $!?@#a$%^&*b-+_.:9'`|/\<=>~) (func (call $!?@#a$%^&*b-+_.:9'`|/\<=>~)) + (func $" random \t \n stuff ") (func (call $" random \t \n stuff ")) + (func $" ") (func (call $" ")) + + (func $fh) (func (call $"fh")) + (func $"fi") (func (call $fi)) + (func $!?@#a$%^&*-+_.:9'`|/\<=>~) (func (call $"!?@#a$%^&*-+_.:9'`|/\\<=>~")) + + (func $"\41B") (func (call $"AB") (call $"A\42") (call $"\41\42") (call $"\u{41}\u{42}")) + (func $"\t") (func (call $"\09") (call $"\u{09}")) + (func $"") (func (call $"\ef\98\9a\ef\92\a9") (call $"\u{f61a}\u{f4a9}")) + + (func + block $l1 (br $"l1") end $"l1" + block $007 (br $"007") end $"007" + block $!?@#a$%^&*-+_.:9'`|/\<=>~ end $"!?@#a$%^&*-+_.:9'`|/\\<=>~" + (i32.const 0) if $"\41B" (br $AB) else $"A\42" end $"\u{41}\u{42}" + (i32.const 0) if $"\t" else $"\09" end $"\u{09}" + (i32.const 0) if $" " else $"\ef\98\9a\ef\92\a9 " end $"\u{f61a}\u{f4a9} " + ) +) + +(assert_malformed (module quote "(func $)") "empty identifier") +(assert_malformed (module quote "(func $\"\")") "empty identifier") +(assert_malformed (module quote "(func $ \"a\")") "empty identifier") +(assert_malformed (module quote "(func $\"a\nb\")") "empty identifier") +(assert_malformed (module quote "(func $\"a\tb\")") "empty identifier") +(assert_malformed (module quote "(func $\"\\ef\")") "malformed UTF-8") diff --git a/proposals/wasm-3.0/if.wast b/proposals/wasm-3.0/if.wast new file mode 100644 index 0000000..35a4cf6 --- /dev/null +++ b/proposals/wasm-3.0/if.wast @@ -0,0 +1,1564 @@ +;; Test `if` operator + +(module + ;; Auxiliary definition + (memory 1) + + (func $dummy) + + (func (export "empty") (param i32) + (if (local.get 0) (then)) + (if (local.get 0) (then) (else)) + (if $l (local.get 0) (then)) + (if $l (local.get 0) (then) (else)) + ) + + (func (export "singular") (param i32) (result i32) + (if (local.get 0) (then (nop))) + (if (local.get 0) (then (nop)) (else (nop))) + (if (result i32) (local.get 0) (then (i32.const 7)) (else (i32.const 8))) + ) + + (func (export "multi") (param i32) (result i32 i32) + (if (local.get 0) (then (call $dummy) (call $dummy) (call $dummy))) + (if (local.get 0) (then) (else (call $dummy) (call $dummy) (call $dummy))) + (if (result i32) (local.get 0) + (then (call $dummy) (call $dummy) (i32.const 8) (call $dummy)) + (else (call $dummy) (call $dummy) (i32.const 9) (call $dummy)) + ) + (if (result i32 i64 i32) (local.get 0) + (then + (call $dummy) (call $dummy) (i32.const 1) (call $dummy) + (call $dummy) (call $dummy) (i64.const 2) (call $dummy) + (call $dummy) (call $dummy) (i32.const 3) (call $dummy) + ) + (else + (call $dummy) (call $dummy) (i32.const -1) (call $dummy) + (call $dummy) (call $dummy) (i64.const -2) (call $dummy) + (call $dummy) (call $dummy) (i32.const -3) (call $dummy) + ) + ) + (drop) (drop) + ) + + (func (export "nested") (param i32 i32) (result i32) + (if (result i32) (local.get 0) + (then + (if (local.get 1) (then (call $dummy) (block) (nop))) + (if (local.get 1) (then) (else (call $dummy) (block) (nop))) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 9)) + (else (call $dummy) (i32.const 10)) + ) + ) + (else + (if (local.get 1) (then (call $dummy) (block) (nop))) + (if (local.get 1) (then) (else (call $dummy) (block) (nop))) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 10)) + (else (call $dummy) (i32.const 11)) + ) + ) + ) + ) + + (func (export "as-select-first") (param i32) (result i32) + (select + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) (i32.const 3) + ) + ) + (func (export "as-select-mid") (param i32) (result i32) + (select + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 3) + ) + ) + (func (export "as-select-last") (param i32) (result i32) + (select + (i32.const 2) (i32.const 3) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (loop (result i32) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (call $dummy) (call $dummy) + ) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (loop (result i32) + (call $dummy) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (call $dummy) + ) + ) + (func (export "as-loop-last") (param i32) (result i32) + (loop (result i32) + (call $dummy) (call $dummy) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + + (func (export "as-if-condition") (param i32) (result i32) + (if (result i32) + (if (result i32) (local.get 0) + (then (i32.const 1)) (else (i32.const 0)) + ) + (then (call $dummy) (i32.const 2)) + (else (call $dummy) (i32.const 3)) + ) + ) + + (func (export "as-br_if-first") (param i32) (result i32) + (block (result i32) + (br_if 0 + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) + ) + (return (i32.const 3)) + ) + ) + (func (export "as-br_if-last") (param i32) (result i32) + (block (result i32) + (br_if 0 + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + (return (i32.const 3)) + ) + ) + + (func (export "as-br_table-first") (param i32) (result i32) + (block (result i32) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) + (br_table 0 0) + ) + ) + (func (export "as-br_table-last") (param i32) (result i32) + (block (result i32) + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (br_table 0 0) + ) + ) + + (func $func (param i32 i32) (result i32) (local.get 0)) + (type $check (func (param i32 i32) (result i32))) + (table funcref (elem $func)) + (func (export "as-call_indirect-first") (param i32) (result i32) + (block (result i32) + (call_indirect (type $check) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-mid") (param i32) (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-last") (param i32) (result i32) + (block (result i32) + (call_indirect (type $check) + (i32.const 2) (i32.const 0) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + ) + + (func (export "as-store-first") (param i32) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.const 2) + (i32.store) + ) + (func (export "as-store-last") (param i32) + (i32.const 2) + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 1)) + (else (call $dummy) (i32.const 0)) + ) + (i32.store) + ) + + (func (export "as-memory.grow-value") (param i32) (result i32) + (memory.grow + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "as-call-value") (param i32) (result i32) + (call $f + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + (func (export "as-return-value") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0))) + (return) + ) + (func (export "as-drop-operand") (param i32) + (drop + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) + (br 0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + ) + (func (export "as-local.set-value") (param i32) (result i32) + (local i32) + (local.set 0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + (local.get 0) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) + ) + (global $a (mut i32) (i32.const 10)) + (func (export "as-global.set-value") (param i32) (result i32) + (global.set $a + (if (result i32) (local.get 0) + (then (i32.const 1)) + (else (i32.const 0)) + ) + ) (global.get $a) + ) + (func (export "as-load-operand") (param i32) (result i32) + (i32.load + (if (result i32) (local.get 0) + (then (i32.const 11)) + (else (i32.const 10)) + ) + ) + ) + + (func (export "as-unary-operand") (param i32) (result i32) + (i32.ctz + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 13)) + (else (call $dummy) (i32.const -13)) + ) + ) + ) + (func (export "as-binary-operand") (param i32 i32) (result i32) + (i32.mul + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 3)) + (else (call $dummy) (i32.const -3)) + ) + (if (result i32) (local.get 1) + (then (call $dummy) (i32.const 4)) + (else (call $dummy) (i32.const -5)) + ) + ) + ) + (func (export "as-test-operand") (param i32) (result i32) + (i32.eqz + (if (result i32) (local.get 0) + (then (call $dummy) (i32.const 13)) + (else (call $dummy) (i32.const 0)) + ) + ) + ) + (func (export "as-compare-operand") (param i32 i32) (result i32) + (f32.gt + (if (result f32) (local.get 0) + (then (call $dummy) (f32.const 3)) + (else (call $dummy) (f32.const -3)) + ) + (if (result f32) (local.get 1) + (then (call $dummy) (f32.const 4)) + (else (call $dummy) (f32.const -4)) + ) + ) + ) + (func (export "as-binary-operands") (param i32) (result i32) + (i32.mul + (if (result i32 i32) (local.get 0) + (then (call $dummy) (i32.const 3) (call $dummy) (i32.const 4)) + (else (call $dummy) (i32.const 3) (call $dummy) (i32.const -4)) + ) + ) + ) + (func (export "as-compare-operands") (param i32) (result i32) + (f32.gt + (if (result f32 f32) (local.get 0) + (then (call $dummy) (f32.const 3) (call $dummy) (f32.const 3)) + (else (call $dummy) (f32.const -2) (call $dummy) (f32.const -3)) + ) + ) + ) + (func (export "as-mixed-operands") (param i32) (result i32) + (if (result i32 i32) (local.get 0) + (then (call $dummy) (i32.const 3) (call $dummy) (i32.const 4)) + (else (call $dummy) (i32.const -3) (call $dummy) (i32.const -4)) + ) + (i32.const 5) + (i32.add) + (i32.mul) + ) + + (func (export "break-bare") (result i32) + (if (i32.const 1) (then (br 0) (unreachable))) + (if (i32.const 1) (then (br 0) (unreachable)) (else (unreachable))) + (if (i32.const 0) (then (unreachable)) (else (br 0) (unreachable))) + (if (i32.const 1) (then (br_if 0 (i32.const 1)) (unreachable))) + (if (i32.const 1) (then (br_if 0 (i32.const 1)) (unreachable)) (else (unreachable))) + (if (i32.const 0) (then (unreachable)) (else (br_if 0 (i32.const 1)) (unreachable))) + (if (i32.const 1) (then (br_table 0 (i32.const 0)) (unreachable))) + (if (i32.const 1) (then (br_table 0 (i32.const 0)) (unreachable)) (else (unreachable))) + (if (i32.const 0) (then (unreachable)) (else (br_table 0 (i32.const 0)) (unreachable))) + (i32.const 19) + ) + + (func (export "break-value") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (br 0 (i32.const 18)) (i32.const 19)) + (else (br 0 (i32.const 21)) (i32.const 20)) + ) + ) + (func (export "break-multi-value") (param i32) (result i32 i32 i64) + (if (result i32 i32 i64) (local.get 0) + (then + (br 0 (i32.const 18) (i32.const -18) (i64.const 18)) + (i32.const 19) (i32.const -19) (i64.const 19) + ) + (else + (br 0 (i32.const -18) (i32.const 18) (i64.const -18)) + (i32.const -19) (i32.const 19) (i64.const -19) + ) + ) + ) + + (func (export "param") (param i32) (result i32) + (i32.const 1) + (if (param i32) (result i32) (local.get 0) + (then (i32.const 2) (i32.add)) + (else (i32.const -2) (i32.add)) + ) + ) + (func (export "params") (param i32) (result i32) + (i32.const 1) + (i32.const 2) + (if (param i32 i32) (result i32) (local.get 0) + (then (i32.add)) + (else (i32.sub)) + ) + ) + (func (export "params-id") (param i32) (result i32) + (i32.const 1) + (i32.const 2) + (if (param i32 i32) (result i32 i32) (local.get 0) (then)) + (i32.add) + ) + (func (export "param-break") (param i32) (result i32) + (i32.const 1) + (if (param i32) (result i32) (local.get 0) + (then (i32.const 2) (i32.add) (br 0)) + (else (i32.const -2) (i32.add) (br 0)) + ) + ) + (func (export "params-break") (param i32) (result i32) + (i32.const 1) + (i32.const 2) + (if (param i32 i32) (result i32) (local.get 0) + (then (i32.add) (br 0)) + (else (i32.sub) (br 0)) + ) + ) + (func (export "params-id-break") (param i32) (result i32) + (i32.const 1) + (i32.const 2) + (if (param i32 i32) (result i32 i32) (local.get 0) (then (br 0))) + (i32.add) + ) + + (func (export "effects") (param i32) (result i32) + (local i32) + (if + (block (result i32) (local.set 1 (i32.const 1)) (local.get 0)) + (then + (local.set 1 (i32.mul (local.get 1) (i32.const 3))) + (local.set 1 (i32.sub (local.get 1) (i32.const 5))) + (local.set 1 (i32.mul (local.get 1) (i32.const 7))) + (br 0) + (local.set 1 (i32.mul (local.get 1) (i32.const 100))) + ) + (else + (local.set 1 (i32.mul (local.get 1) (i32.const 5))) + (local.set 1 (i32.sub (local.get 1) (i32.const 7))) + (local.set 1 (i32.mul (local.get 1) (i32.const 3))) + (br 0) + (local.set 1 (i32.mul (local.get 1) (i32.const 1000))) + ) + ) + (local.get 1) + ) + + ;; Examples + + (func $add64_u_with_carry (export "add64_u_with_carry") + (param $i i64) (param $j i64) (param $c i32) (result i64 i32) + (local $k i64) + (local.set $k + (i64.add + (i64.add (local.get $i) (local.get $j)) + (i64.extend_i32_u (local.get $c)) + ) + ) + (return (local.get $k) (i64.lt_u (local.get $k) (local.get $i))) + ) + + (func $add64_u_saturated (export "add64_u_saturated") + (param i64 i64) (result i64) + (call $add64_u_with_carry (local.get 0) (local.get 1) (i32.const 0)) + (if (param i64) (result i64) + (then (drop) (i64.const -1)) + ) + ) + + ;; Block signature syntax + + (type $block-sig-1 (func)) + (type $block-sig-2 (func (result i32))) + (type $block-sig-3 (func (param $x i32))) + (type $block-sig-4 (func (param i32 f64 i32) (result i32 f64 i32))) + + (func (export "type-use") + (if (type $block-sig-1) (i32.const 1) (then)) + (if (type $block-sig-2) (i32.const 1) + (then (i32.const 0)) (else (i32.const 2)) + ) + (if (type $block-sig-3) (i32.const 1) (then (drop)) (else (drop))) + (i32.const 0) (f64.const 0) (i32.const 0) + (if (type $block-sig-4) (i32.const 1) (then)) + (drop) (drop) (drop) + (if (type $block-sig-2) (result i32) (i32.const 1) + (then (i32.const 0)) (else (i32.const 2)) + ) + (if (type $block-sig-3) (param i32) (i32.const 1) + (then (drop)) (else (drop)) + ) + (i32.const 0) (f64.const 0) (i32.const 0) + (if (type $block-sig-4) + (param i32) (param f64 i32) (result i32 f64) (result i32) + (i32.const 1) (then) + ) + (drop) (drop) (drop) + ) + + ;; Atypical folded condition syntax + + (func (export "atypical-condition") + i32.const 0 + (if (then) (else)) + (if (i32.const 1) (i32.eqz) (then) (else)) + ) +) + +(assert_return (invoke "empty" (i32.const 0))) +(assert_return (invoke "empty" (i32.const 1))) +(assert_return (invoke "empty" (i32.const 100))) +(assert_return (invoke "empty" (i32.const -2))) + +(assert_return (invoke "singular" (i32.const 0)) (i32.const 8)) +(assert_return (invoke "singular" (i32.const 1)) (i32.const 7)) +(assert_return (invoke "singular" (i32.const 10)) (i32.const 7)) +(assert_return (invoke "singular" (i32.const -10)) (i32.const 7)) + +(assert_return (invoke "multi" (i32.const 0)) (i32.const 9) (i32.const -1)) +(assert_return (invoke "multi" (i32.const 1)) (i32.const 8) (i32.const 1)) +(assert_return (invoke "multi" (i32.const 13)) (i32.const 8) (i32.const 1)) +(assert_return (invoke "multi" (i32.const -5)) (i32.const 8) (i32.const 1)) + +(assert_return (invoke "nested" (i32.const 0) (i32.const 0)) (i32.const 11)) +(assert_return (invoke "nested" (i32.const 1) (i32.const 0)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 0) (i32.const 1)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 3) (i32.const 2)) (i32.const 9)) +(assert_return (invoke "nested" (i32.const 0) (i32.const -100)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const 10) (i32.const 10)) (i32.const 9)) +(assert_return (invoke "nested" (i32.const 0) (i32.const -1)) (i32.const 10)) +(assert_return (invoke "nested" (i32.const -111) (i32.const -2)) (i32.const 9)) + +(assert_return (invoke "as-select-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-select-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-select-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-select-mid" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-select-last" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-select-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loop-last" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-if-condition" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-if-condition" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-br_if-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-br_if-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-br_if-last" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-br_if-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-br_table-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-br_table-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-br_table-last" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-br_table-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-call_indirect-first" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-call_indirect-first" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-call_indirect-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-call_indirect-mid" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-call_indirect-last" (i32.const 0)) (i32.const 2)) +(assert_trap (invoke "as-call_indirect-last" (i32.const 1)) "undefined element") + +(assert_return (invoke "as-store-first" (i32.const 0))) +(assert_return (invoke "as-store-first" (i32.const 1))) +(assert_return (invoke "as-store-last" (i32.const 0))) +(assert_return (invoke "as-store-last" (i32.const 1))) + +(assert_return (invoke "as-memory.grow-value" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-memory.grow-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-call-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-call-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-return-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-drop-operand" (i32.const 0))) +(assert_return (invoke "as-drop-operand" (i32.const 1))) + +(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-br-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-global.set-value" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-global.set-value" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-load-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-load-operand" (i32.const 1)) (i32.const 0)) + +(assert_return (invoke "as-unary-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-unary-operand" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-unary-operand" (i32.const -1)) (i32.const 0)) + +(assert_return (invoke "as-binary-operand" (i32.const 0) (i32.const 0)) (i32.const 15)) +(assert_return (invoke "as-binary-operand" (i32.const 0) (i32.const 1)) (i32.const -12)) +(assert_return (invoke "as-binary-operand" (i32.const 1) (i32.const 0)) (i32.const -15)) +(assert_return (invoke "as-binary-operand" (i32.const 1) (i32.const 1)) (i32.const 12)) + +(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-test-operand" (i32.const 1)) (i32.const 0)) + +(assert_return (invoke "as-compare-operand" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-compare-operand" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-compare-operand" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-compare-operand" (i32.const 1) (i32.const 1)) (i32.const 0)) + +(assert_return (invoke "as-binary-operands" (i32.const 0)) (i32.const -12)) +(assert_return (invoke "as-binary-operands" (i32.const 1)) (i32.const 12)) + +(assert_return (invoke "as-compare-operands" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-compare-operands" (i32.const 1)) (i32.const 0)) + +(assert_return (invoke "as-mixed-operands" (i32.const 0)) (i32.const -3)) +(assert_return (invoke "as-mixed-operands" (i32.const 1)) (i32.const 27)) + +(assert_return (invoke "break-bare") (i32.const 19)) +(assert_return (invoke "break-value" (i32.const 1)) (i32.const 18)) +(assert_return (invoke "break-value" (i32.const 0)) (i32.const 21)) +(assert_return (invoke "break-multi-value" (i32.const 0)) + (i32.const -18) (i32.const 18) (i64.const -18) +) +(assert_return (invoke "break-multi-value" (i32.const 1)) + (i32.const 18) (i32.const -18) (i64.const 18) +) + +(assert_return (invoke "param" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "param" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "params" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "params" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "params-id" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "params-id" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "param-break" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "param-break" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "params-break" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "params-break" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "params-id-break" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "params-id-break" (i32.const 1)) (i32.const 3)) + +(assert_return (invoke "effects" (i32.const 1)) (i32.const -14)) +(assert_return (invoke "effects" (i32.const 0)) (i32.const -6)) + +(assert_return + (invoke "add64_u_with_carry" (i64.const 0) (i64.const 0) (i32.const 0)) + (i64.const 0) (i32.const 0) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const 100) (i64.const 124) (i32.const 0)) + (i64.const 224) (i32.const 0) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const -1) (i64.const 0) (i32.const 0)) + (i64.const -1) (i32.const 0) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const -1) (i64.const 1) (i32.const 0)) + (i64.const 0) (i32.const 1) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const -1) (i64.const -1) (i32.const 0)) + (i64.const -2) (i32.const 1) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const -1) (i64.const 0) (i32.const 1)) + (i64.const 0) (i32.const 1) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const -1) (i64.const 1) (i32.const 1)) + (i64.const 1) (i32.const 1) +) +(assert_return + (invoke "add64_u_with_carry" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000) (i32.const 0)) + (i64.const 0) (i32.const 1) +) + +(assert_return + (invoke "add64_u_saturated" (i64.const 0) (i64.const 0)) (i64.const 0) +) +(assert_return + (invoke "add64_u_saturated" (i64.const 1230) (i64.const 23)) (i64.const 1253) +) +(assert_return + (invoke "add64_u_saturated" (i64.const -1) (i64.const 0)) (i64.const -1) +) +(assert_return + (invoke "add64_u_saturated" (i64.const -1) (i64.const 1)) (i64.const -1) +) +(assert_return + (invoke "add64_u_saturated" (i64.const -1) (i64.const -1)) (i64.const -1) +) +(assert_return + (invoke "add64_u_saturated" (i64.const 0x8000000000000000) (i64.const 0x8000000000000000)) (i64.const -1) +) + +(assert_return (invoke "type-use")) + +(assert_return (invoke "atypical-condition")) + +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0)" + " (if (type $sig) (result i32) (param i32) (i32.const 1) (then))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0)" + " (if (param i32) (type $sig) (result i32) (i32.const 1) (then))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0)" + " (if (param i32) (result i32) (type $sig) (i32.const 1) (then))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0)" + " (if (result i32) (type $sig) (param i32) (i32.const 1) (then))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0)" + " (if (result i32) (param i32) (type $sig) (i32.const 1) (then))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func (i32.const 0) (if (result i32) (param i32) (i32.const 1) (then)))" + ) + "unexpected token" +) + +(assert_malformed + (module quote + "(func (i32.const 0) (i32.const 1)" + " (if (param $x i32) (then (drop)) (else (drop)))" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func))" + "(func (i32.const 1)" + " (if (type $sig) (result i32) (then (i32.const 0)) (else (i32.const 2)))" + " (unreachable)" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 1)" + " (if (type $sig) (result i32) (then (i32.const 0)) (else (i32.const 2)))" + " (unreachable)" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(func (i32.const 0) (i32.const 1)" + " (if (type $sig) (param i32) (then (drop)) (else (drop)))" + " (unreachable)" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32 i32) (result i32)))" + "(func (i32.const 0) (i32.const 1)" + " (if (type $sig) (param i32) (result i32) (then)) (unreachable)" + ")" + ) + "inline function type" +) + +(assert_invalid + (module + (type $sig (func)) + (func (i32.const 1) (if (type $sig) (i32.const 0) (then))) + ) + "type mismatch" +) + +(assert_invalid + (module (func $type-empty-i32 (result i32) (if (i32.const 0) (then)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-i64 (result i64) (if (i32.const 0) (then)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f32 (result f32) (if (i32.const 0) (then)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f64 (result f64) (if (i32.const 0) (then)))) + "type mismatch" +) + +(assert_invalid + (module (func $type-empty-i32 (result i32) (if (i32.const 0) (then) (else)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-i64 (result i64) (if (i32.const 0) (then) (else)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f32 (result f32) (if (i32.const 0) (then) (else)))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-f64 (result f64) (if (i32.const 0) (then) (else)))) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-num-vs-void + (if (i32.const 1) (then (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-value-num-vs-void-else + (if (i32.const 1) (then (i32.const 1)) (else)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-num-vs-void + (if (i32.const 1) (then) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-num-vs-void + (if (i32.const 1) (then (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-nums-vs-void + (if (i32.const 1) (then (i32.const 1) (i32.const 2))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-value-nums-vs-void-else + (if (i32.const 1) (then (i32.const 1) (i32.const 2)) (else)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-nums-vs-void + (if (i32.const 1) (then) (else (i32.const 1) (i32.const 2))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-nums-vs-void + (if (i32.const 1) (then (i32.const 1) (i32.const 2)) (else (i32.const 2) (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-empty-vs-num (result i32) + (if (result i32) (i32.const 1) (then) (else (i32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-empty-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 0)) (else)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-empty-vs-num (result i32) + (if (result i32) (i32.const 1) (then) (else)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-empty-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then) (else (i32.const 0) (i32.const 2))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-empty-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 0) (i32.const 1)) (else)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-empty-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then) (else)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-no-else-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-no-else-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-void-vs-num (result i32) + (if (result i32) (i32.const 1) (then (nop)) (else (i32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-void-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 0)) (else (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-void-vs-num (result i32) + (if (result i32) (i32.const 1) (then (nop)) (else (nop))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (nop)) (else (i32.const 0) (i32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 0) (i32.const 0)) (else (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (nop)) (else (nop))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-num-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i64.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-num-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1)) (else (i64.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-num-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i64.const 1)) (else (i64.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-num-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-num-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1) (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-num-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-partial-vs-nums (result i32 i32) + (i32.const 0) + (if (result i32 i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-partial-vs-nums (result i32 i32) + (i32.const 0) + (if (result i32 i32) (i32.const 1) (then (i32.const 1) (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-partial-vs-nums (result i32 i32) + (i32.const 0) + (if (result i32 i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-nums-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1) (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-nums-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1)) (else (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-value-nums-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1) (i32.const 1)) (else (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-both-different-value-num-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i64.const 1)) (else (f64.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-both-different-value-nums-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1) (i32.const 1) (i32.const 1)) (else (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-value-unreached-select (result i32) + (if (result i64) + (i32.const 0) + (then (select (unreachable) (unreachable) (unreachable))) + (else (i64.const 0)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-unreached-select (result i32) + (if (result i64) + (i32.const 1) + (then (i64.const 0)) + (else (select (unreachable) (unreachable) (unreachable))) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-value-unreached-select (result i32) + (if (result i64) + (i32.const 1) + (then (select (unreachable) (unreachable) (unreachable))) + (else (select (unreachable) (unreachable) (unreachable))) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-break-last-void-vs-num (result i32) + (if (result i32) (i32.const 1) (then (br 0)) (else (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-last-void-vs-num (result i32) + (if (result i32) (i32.const 1) (then (i32.const 1)) (else (br 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-break-last-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (br 0)) (else (i32.const 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-last-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) (then (i32.const 1) (i32.const 1)) (else (br 0))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-break-empty-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (br 0) (i32.const 1)) + (else (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-empty-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (i32.const 1)) + (else (br 0) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-break-empty-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (br 0) (i32.const 1) (i32.const 1)) + (else (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-empty-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (i32.const 1) (i32.const 1)) + (else (br 0) (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-break-void-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (br 0 (nop)) (i32.const 1)) + (else (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-void-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (i32.const 1)) + (else (br 0 (nop)) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-break-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (br 0 (nop)) (i32.const 1) (i32.const 1)) + (else (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-void-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (i32.const 1) (i32.const 1)) + (else (br 0 (nop)) (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-then-break-num-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (br 0 (i64.const 1)) (i32.const 1)) + (else (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-num-vs-num (result i32) + (if (result i32) (i32.const 1) + (then (i32.const 1)) + (else (br 0 (i64.const 1)) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-break-num-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (br 0 (i64.const 1)) (i32.const 1) (i32.const 1)) + (else (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-num-vs-nums (result i32 i32) + (if (result i32 i32) (i32.const 1) + (then (i32.const 1) (i32.const 1)) + (else (br 0 (i64.const 1)) (i32.const 1) (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-then-break-partial-vs-nums (result i32 i32) + (i32.const 1) + (if (result i32 i32) (i32.const 1) + (then (br 0 (i64.const 1)) (i32.const 1)) + (else (i32.const 1)) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-else-break-partial-vs-nums (result i32 i32) + (i32.const 1) + (if (result i32 i32) (i32.const 1) + (then (i32.const 1)) + (else (br 0 (i64.const 1)) (i32.const 1)) + ) + )) + "type mismatch" +) + +(assert_invalid + (module + (func $type-condition-empty + (if (then)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-block + (i32.const 0) + (block (if (then))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-loop + (i32.const 0) + (loop (if (then))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-then + (i32.const 0) (i32.const 0) + (if (then (if (then)))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-else + (i32.const 0) (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (if (then)) (i32.const 0))) + (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-br + (i32.const 0) + (block (br 0 (if(then))) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-br_if + (i32.const 0) + (block (br_if 0 (if(then)) (i32.const 1)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-br_table + (i32.const 0) + (block (br_table 0 (if(then))) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-return + (return (if(then))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-select + (select (if(then)) (i32.const 1) (i32.const 2)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-call + (call 1 (if(then))) (drop) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-condition-empty-in-call_indirect + (block (result i32) + (call_indirect (type $sig) + (if(then)) (i32.const 0) + ) + (drop) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-local.set + (local i32) + (local.set 0 (if(then))) (local.get 0) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-condition-empty-in-local.tee + (local i32) + (local.tee 0 (if(then))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-condition-empty-in-global.set + (global.set $x (if(then))) (global.get $x) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-condition-empty-in-memory.grow + (memory.grow (if(then))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-condition-empty-in-load + (i32.load (if(then))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-condition-empty-in-store + (i32.store (if(then)) (i32.const 1)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module (func $type-param-void-vs-num + (if (param i32) (i32.const 1) (then (drop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-void-vs-nums + (if (param i32 f64) (i32.const 1) (then (drop) (drop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num + (f32.const 0) (if (param i32) (i32.const 1) (then (drop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-nums + (f32.const 0) (if (param f32 i32) (i32.const 1) (then (drop) (drop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-nested-void-vs-num + (block (if (param i32) (i32.const 1) (then (drop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-void-vs-nums + (block (if (param i32 f64) (i32.const 1) (then (drop) (drop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num + (block (f32.const 0) (if (param i32) (i32.const 1) (then (drop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-nums + (block (f32.const 0) (if (param f32 i32) (i32.const 1) (then (drop) (drop)))) + )) + "type mismatch" +) + +(assert_malformed + (module quote "(func (param i32) (result i32) if (param $x i32) end)") + "unexpected token" +) +(assert_malformed + (module quote "(func (param i32) (result i32) (if (param $x i32) (then)))") + "unexpected token" +) + +(assert_malformed + (module quote "(func i32.const 0 if end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if $a end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if else $l end)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if $a else $l end)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if else end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if else $l end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if else $l1 end $l2)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if $a else end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if $a else $a end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func i32.const 0 if $a else $l end $l)") + "mismatching label" +) +(assert_malformed + (module quote "(func (if i32.const 0 (then) (else)))") + "unexpected token" +) diff --git a/proposals/memory64/imports.wast b/proposals/wasm-3.0/imports.wast similarity index 100% rename from proposals/memory64/imports.wast rename to proposals/wasm-3.0/imports.wast diff --git a/proposals/wasm-3.0/imports0.wast b/proposals/wasm-3.0/imports0.wast new file mode 100644 index 0000000..ce827a2 --- /dev/null +++ b/proposals/wasm-3.0/imports0.wast @@ -0,0 +1,45 @@ +(module + (func (export "func")) + (func (export "func-i32") (param i32)) + (func (export "func-f32") (param f32)) + (func (export "func->i32") (result i32) (i32.const 22)) + (func (export "func->f32") (result f32) (f32.const 11)) + (func (export "func-i32->i32") (param i32) (result i32) (local.get 0)) + (func (export "func-i64->i64") (param i64) (result i64) (local.get 0)) + (global (export "global-i32") i32 (i32.const 55)) + (global (export "global-f32") f32 (f32.const 44)) + (global (export "global-mut-i64") (mut i64) (i64.const 66)) + (table (export "table-10-inf") 10 funcref) + (table (export "table-10-20") 10 20 funcref) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(assert_unlinkable + (module (import "test" "memory-2-inf" (func))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (func))) + "incompatible import type" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (global i32))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (global i32))) + "incompatible import type" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (table 10 funcref))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-4" (table 10 funcref))) + "incompatible import type" +) diff --git a/proposals/wasm-3.0/imports1.wast b/proposals/wasm-3.0/imports1.wast new file mode 100644 index 0000000..bae0f80 --- /dev/null +++ b/proposals/wasm-3.0/imports1.wast @@ -0,0 +1,16 @@ +(module + (import "spectest" "memory" (memory 1 2)) + (import "spectest" "memory" (memory 1 2)) + (memory $m (import "spectest" "memory") 1 2) + (import "spectest" "memory" (memory 1 2)) + + (data (memory 2) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load $m (local.get 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + diff --git a/proposals/wasm-3.0/imports2.wast b/proposals/wasm-3.0/imports2.wast new file mode 100644 index 0000000..314bc13 --- /dev/null +++ b/proposals/wasm-3.0/imports2.wast @@ -0,0 +1,73 @@ +(module + (memory (export "z") 0 0) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(module + (import "test" "z" (memory 0)) + (memory $m (import "spectest" "memory") 1 2) + (data (memory 1) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load $m (local.get 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + +(module + (memory (import "spectest" "memory") 1 2) + (data (memory 0) (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load (local.get 0))) +) +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + +(module + (import "test" "memory-2-inf" (memory 2)) + (import "test" "memory-2-inf" (memory 1)) + (import "test" "memory-2-inf" (memory 0)) +) + +(module + (import "spectest" "memory" (memory 1)) + (import "spectest" "memory" (memory 0)) + (import "spectest" "memory" (memory 1 2)) + (import "spectest" "memory" (memory 0 2)) + (import "spectest" "memory" (memory 1 3)) + (import "spectest" "memory" (memory 0 3)) +) + +(assert_unlinkable + (module (import "test" "unknown" (memory 1))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "unknown" (memory 1))) + "unknown import" +) + +(assert_unlinkable + (module (import "test" "memory-2-inf" (memory 3))) + "incompatible import type" +) +(assert_unlinkable + (module (import "test" "memory-2-inf" (memory 2 3))) + "incompatible import type" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 2))) + "incompatible import type" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 1 1))) + "incompatible import type" +) + diff --git a/proposals/wasm-3.0/imports3.wast b/proposals/wasm-3.0/imports3.wast new file mode 100644 index 0000000..37cc4eb --- /dev/null +++ b/proposals/wasm-3.0/imports3.wast @@ -0,0 +1,75 @@ +(module + (func (export "func")) + (func (export "func-i32") (param i32)) + (func (export "func-f32") (param f32)) + (func (export "func->i32") (result i32) (i32.const 22)) + (func (export "func->f32") (result f32) (f32.const 11)) + (func (export "func-i32->i32") (param i32) (result i32) (local.get 0)) + (func (export "func-i64->i64") (param i64) (result i64) (local.get 0)) + (global (export "global-i32") i32 (i32.const 55)) + (global (export "global-f32") f32 (f32.const 44)) + (global (export "global-mut-i64") (mut i64) (i64.const 66)) + (table (export "table-10-inf") 10 funcref) + (table (export "table-10-20") 10 20 funcref) + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "func-i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "global-i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "test" "table-10-inf" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "print_i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "global_i32" (memory 1)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "table" (memory 1)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "memory" (memory 2)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (import "test" "memory-2-4" (memory 1)) + (import "spectest" "memory" (memory 1 1)) + ) + "incompatible import type" +) diff --git a/proposals/wasm-3.0/imports4.wast b/proposals/wasm-3.0/imports4.wast new file mode 100644 index 0000000..411b1c0 --- /dev/null +++ b/proposals/wasm-3.0/imports4.wast @@ -0,0 +1,47 @@ +(module + (memory (export "memory-2-inf") 2) + (memory (export "memory-2-4") 2 4) +) + +(register "test") + +(module + (import "test" "memory-2-4" (memory 1)) + (memory $m (import "spectest" "memory") 0 3) ;; actual has max size 2 + (func (export "grow") (param i32) (result i32) (memory.grow $m (local.get 0))) +) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) + +(module $Mgm + (memory 0) + (memory 0) + (memory $m (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow $m (i32.const 1))) +) +(register "grown-memory" $Mgm) +(assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 + +(module $Mgim1 + ;; imported memory limits should match, because external memory size is 2 now + (import "test" "memory-2-4" (memory 1)) + (memory $m (export "memory") (import "grown-memory" "memory") 2) + (memory 0) + (memory 0) + (func (export "grow") (result i32) (memory.grow $m (i32.const 1))) +) +(register "grown-imported-memory" $Mgim1) +(assert_return (invoke $Mgim1 "grow") (i32.const 2)) ;; now size is 3 + +(module $Mgim2 + ;; imported memory limits should match, because external memory size is 3 now + (import "test" "memory-2-4" (memory 1)) + (memory $m (import "grown-imported-memory" "memory") 3) + (memory 0) + (memory 0) + (func (export "size") (result i32) (memory.size $m)) +) +(assert_return (invoke $Mgim2 "size") (i32.const 3)) diff --git a/proposals/wasm-3.0/instance.wast b/proposals/wasm-3.0/instance.wast new file mode 100644 index 0000000..b88025d --- /dev/null +++ b/proposals/wasm-3.0/instance.wast @@ -0,0 +1,170 @@ +;; Instantiation is generative + +(module definition $M + (global (export "glob") (mut i32) (i32.const 0)) + (table (export "tab") 10 funcref (ref.null func)) + (memory (export "mem") 1) + (tag (export "tag")) +) + +(module instance $I1 $M) +(module instance $I2 $M) +(register "I1" $I1) +(register "I2" $I2) + +(module + (import "I1" "glob" (global $glob1 (mut i32))) + (import "I2" "glob" (global $glob2 (mut i32))) + (import "I1" "tab" (table $tab1 10 funcref)) + (import "I2" "tab" (table $tab2 10 funcref)) + (import "I1" "mem" (memory $mem1 1)) + (import "I2" "mem" (memory $mem2 1)) + (import "I1" "tag" (tag $tag1)) + (import "I2" "tag" (tag $tag2)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) + (func (export "tag") (result i32) + (block $on_tag1 + (block $on_other + (try_table (catch $tag1 $on_tag1) (catch_all $on_other) + (throw $tag2) + ) + (unreachable) + ) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) +) + +(assert_return (invoke "glob") (i32.const 0)) +(assert_return (invoke "tab") (ref.null)) +(assert_return (invoke "mem") (i32.const 0)) +(assert_return (invoke "tag") (i32.const 0)) + + +;; Import is not generative + +(module + (import "I1" "glob" (global $glob1 (mut i32))) + (import "I1" "glob" (global $glob2 (mut i32))) + (import "I1" "tab" (table $tab1 10 funcref)) + (import "I1" "tab" (table $tab2 10 funcref)) + (import "I1" "mem" (memory $mem1 1)) + (import "I1" "mem" (memory $mem2 1)) + (import "I1" "tag" (tag $tag1)) + (import "I1" "tag" (tag $tag2)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) + (func (export "tag") (result i32) + (block $on_tag1 + (block $on_other + (try_table (catch $tag1 $on_tag1) (catch_all $on_other) + (throw $tag2) + ) + (unreachable) + ) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) +) + +(assert_return (invoke "glob") (i32.const 1)) +(assert_return (invoke "tab") (ref.func)) +(assert_return (invoke "mem") (i32.const 1)) +(assert_return (invoke "tag") (i32.const 1)) + + +;; Export is not generative + +(module definition $N + (global $glob (mut i32) (i32.const 0)) + (table $tab 10 funcref (ref.null func)) + (memory $mem 1) + (tag $tag) + + (export "glob1" (global $glob)) + (export "glob2" (global $glob)) + (export "tab1" (table $tab)) + (export "tab2" (table $tab)) + (export "mem1" (memory $mem)) + (export "mem2" (memory $mem)) + (export "tag1" (tag $tag)) + (export "tag2" (tag $tag)) +) + +(module instance $I $N) +(register "I" $I) + +(module + (import "I" "glob1" (global $glob1 (mut i32))) + (import "I" "glob2" (global $glob2 (mut i32))) + (import "I" "tab1" (table $tab1 10 funcref)) + (import "I" "tab2" (table $tab2 10 funcref)) + (import "I" "mem1" (memory $mem1 1)) + (import "I" "mem2" (memory $mem2 1)) + (import "I" "tag1" (tag $tag1)) + (import "I" "tag2" (tag $tag2)) + + (func $f) + (elem declare func $f) + + (func (export "glob") (result i32) + (global.set $glob1 (i32.const 1)) + (global.get $glob2) + ) + (func (export "tab") (result funcref) + (table.set $tab1 (i32.const 0) (ref.func $f)) + (table.get $tab2 (i32.const 0)) + ) + (func (export "mem") (result i32) + (i32.store $mem1 (i32.const 0) (i32.const 1)) + (i32.load $mem2 (i32.const 0)) + ) + (func (export "tag") (result i32) + (block $on_tag1 + (block $on_other + (try_table (catch $tag1 $on_tag1) (catch_all $on_other) + (throw $tag2) + ) + (unreachable) + ) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) +) + +(assert_return (invoke "glob") (i32.const 1)) +(assert_return (invoke "tab") (ref.func)) +(assert_return (invoke "mem") (i32.const 1)) +(assert_return (invoke "tag") (i32.const 1)) diff --git a/proposals/wasm-3.0/legacy/rethrow.wast b/proposals/wasm-3.0/legacy/rethrow.wast new file mode 100644 index 0000000..e41d94b --- /dev/null +++ b/proposals/wasm-3.0/legacy/rethrow.wast @@ -0,0 +1,96 @@ +;; Test rethrow instruction. + +(module + (tag $e0) + (tag $e1) + + (func (export "catch-rethrow-0") + (try + (do (throw $e0)) + (catch $e0 (rethrow 0)) + ) + ) + + (func (export "catch-rethrow-1") (param i32) (result i32) + (try (result i32) + (do (throw $e0)) + (catch $e0 + (if (i32.eqz (local.get 0)) (then (rethrow 1))) (i32.const 23) + ) + ) + ) + + (func (export "catchall-rethrow-0") + (try + (do (throw $e0)) + (catch_all (rethrow 0)) + ) + ) + + (func (export "catchall-rethrow-1") (param i32) (result i32) + (try (result i32) + (do (throw $e0)) + (catch_all + (if (i32.eqz (local.get 0)) (then (rethrow 1))) (i32.const 23) + ) + ) + ) + + (func (export "rethrow-nested") (param i32) (result i32) + (try (result i32) + (do (throw $e1)) + (catch $e1 + (try (result i32) + (do (throw $e0)) + (catch $e0 + (if (i32.eq (local.get 0) (i32.const 0)) (then (rethrow 1))) + (if (i32.eq (local.get 0) (i32.const 1)) (then (rethrow 2))) + (i32.const 23) + ) + ) + ) + ) + ) + + (func (export "rethrow-recatch") (param i32) (result i32) + (try (result i32) + (do (throw $e0)) + (catch $e0 + (try (result i32) + (do (if (i32.eqz (local.get 0)) (then (rethrow 2))) (i32.const 42)) + (catch $e0 (i32.const 23)) + ) + ) + ) + ) + + (func (export "rethrow-stack-polymorphism") + (try + (do (throw $e0)) + (catch $e0 (i32.const 1) (rethrow 0)) + ) + ) +) + +(assert_exception (invoke "catch-rethrow-0")) + +(assert_exception (invoke "catch-rethrow-1" (i32.const 0))) +(assert_return (invoke "catch-rethrow-1" (i32.const 1)) (i32.const 23)) + +(assert_exception (invoke "catchall-rethrow-0")) + +(assert_exception (invoke "catchall-rethrow-1" (i32.const 0))) +(assert_return (invoke "catchall-rethrow-1" (i32.const 1)) (i32.const 23)) +(assert_exception (invoke "rethrow-nested" (i32.const 0))) +(assert_exception (invoke "rethrow-nested" (i32.const 1))) +(assert_return (invoke "rethrow-nested" (i32.const 2)) (i32.const 23)) + +(assert_return (invoke "rethrow-recatch" (i32.const 0)) (i32.const 23)) +(assert_return (invoke "rethrow-recatch" (i32.const 1)) (i32.const 42)) + +(assert_exception (invoke "rethrow-stack-polymorphism")) + +(assert_invalid (module (func (rethrow 0))) "invalid rethrow label") +(assert_invalid (module (func (block (rethrow 0)))) "invalid rethrow label") +(assert_invalid (module (func (try (do (rethrow 0)) (delegate 0)))) + "invalid rethrow label") diff --git a/proposals/wasm-3.0/legacy/throw.wast b/proposals/wasm-3.0/legacy/throw.wast new file mode 100644 index 0000000..d53b5b5 --- /dev/null +++ b/proposals/wasm-3.0/legacy/throw.wast @@ -0,0 +1,51 @@ +;; Test throw instruction. + +(module + (tag $e0) + (tag $e-i32 (param i32)) + (tag $e-f32 (param f32)) + (tag $e-i64 (param i64)) + (tag $e-f64 (param f64)) + (tag $e-i32-i32 (param i32 i32)) + + (func $throw-if (export "throw-if") (param i32) (result i32) + (local.get 0) + (i32.const 0) (if (i32.ne) (then (throw $e0))) + (i32.const 0) + ) + + (func (export "throw-param-f32") (param f32) (local.get 0) (throw $e-f32)) + + (func (export "throw-param-i64") (param i64) (local.get 0) (throw $e-i64)) + + (func (export "throw-param-f64") (param f64) (local.get 0) (throw $e-f64)) + + (func $throw-1-2 (i32.const 1) (i32.const 2) (throw $e-i32-i32)) + (func (export "test-throw-1-2") + (try + (do (call $throw-1-2)) + (catch $e-i32-i32 + (i32.const 2) + (if (i32.ne) (then (unreachable))) + (i32.const 1) + (if (i32.ne) (then (unreachable))) + ) + ) + ) +) + +(assert_return (invoke "throw-if" (i32.const 0)) (i32.const 0)) +(assert_exception (invoke "throw-if" (i32.const 10))) +(assert_exception (invoke "throw-if" (i32.const -1))) + +(assert_exception (invoke "throw-param-f32" (f32.const 5.0))) +(assert_exception (invoke "throw-param-i64" (i64.const 5))) +(assert_exception (invoke "throw-param-f64" (f64.const 5.0))) + +(assert_return (invoke "test-throw-1-2")) + +(assert_invalid (module (func (throw 0))) "unknown tag 0") +(assert_invalid (module (tag (param i32)) (func (throw 0))) + "type mismatch: instruction requires [i32] but stack has []") +(assert_invalid (module (tag (param i32)) (func (i64.const 5) (throw 0))) + "type mismatch: instruction requires [i32] but stack has [i64]") diff --git a/proposals/wasm-3.0/legacy/try_catch.wast b/proposals/wasm-3.0/legacy/try_catch.wast new file mode 100644 index 0000000..07399f3 --- /dev/null +++ b/proposals/wasm-3.0/legacy/try_catch.wast @@ -0,0 +1,276 @@ +;; Test try-catch blocks. + +(module + (tag $e0 (export "e0")) + (func (export "throw") (throw $e0)) +) + +(register "test") + +(module + (tag $imported-e0 (import "test" "e0")) + (func $imported-throw (import "test" "throw")) + (tag $e0) + (tag $e1) + (tag $e2) + (tag $e-i32 (param i32)) + (tag $e-f32 (param f32)) + (tag $e-i64 (param i64)) + (tag $e-f64 (param f64)) + + (func $throw-if (param i32) (result i32) + (local.get 0) + (i32.const 0) (if (i32.ne) (then (throw $e0))) + (i32.const 0) + ) + + (func (export "empty-catch") (try (do) (catch $e0))) + + (func (export "simple-throw-catch") (param i32) (result i32) + (try (result i32) + (do (local.get 0) (i32.eqz) (if (then (throw $e0)) (else)) (i32.const 42)) + (catch $e0 (i32.const 23)) + ) + ) + + (func (export "unreachable-not-caught") (try (do (unreachable)) (catch_all))) + + (func $div (param i32 i32) (result i32) + (local.get 0) (local.get 1) (i32.div_u) + ) + (func (export "trap-in-callee") (param i32 i32) (result i32) + (try (result i32) + (do (local.get 0) (local.get 1) (call $div)) + (catch_all (i32.const 11)) + ) + ) + + (func (export "catch-complex-1") (param i32) (result i32) + (try (result i32) + (do + (try (result i32) + (do + (local.get 0) + (i32.eqz) + (if + (then (throw $e0)) + (else + (local.get 0) + (i32.const 1) + (i32.eq) + (if (then (throw $e1)) (else (throw $e2))) + ) + ) + (i32.const 2) + ) + (catch $e0 (i32.const 3)) + ) + ) + (catch $e1 (i32.const 4)) + ) + ) + + (func (export "catch-complex-2") (param i32) (result i32) + (try (result i32) + (do + (local.get 0) + (i32.eqz) + (if + (then (throw $e0)) + (else + (local.get 0) + (i32.const 1) + (i32.eq) + (if (then (throw $e1)) (else (throw $e2))) + ) + ) + (i32.const 2) + ) + (catch $e0 (i32.const 3)) + (catch $e1 (i32.const 4)) + ) + ) + + (func (export "throw-catch-param-i32") (param i32) (result i32) + (try (result i32) + (do (local.get 0) (throw $e-i32) (i32.const 2)) + (catch $e-i32 (return)) + ) + ) + + (func (export "throw-catch-param-f32") (param f32) (result f32) + (try (result f32) + (do (local.get 0) (throw $e-f32) (f32.const 0)) + (catch $e-f32 (return)) + ) + ) + + (func (export "throw-catch-param-i64") (param i64) (result i64) + (try (result i64) + (do (local.get 0) (throw $e-i64) (i64.const 2)) + (catch $e-i64 (return)) + ) + ) + + (func (export "throw-catch-param-f64") (param f64) (result f64) + (try (result f64) + (do (local.get 0) (throw $e-f64) (f64.const 0)) + (catch $e-f64 (return)) + ) + ) + + (func $throw-param-i32 (param i32) (local.get 0) (throw $e-i32)) + (func (export "catch-param-i32") (param i32) (result i32) + (try (result i32) + (do (i32.const 0) (local.get 0) (call $throw-param-i32)) + (catch $e-i32) + ) + ) + + (func (export "catch-imported") (result i32) + (try (result i32) + (do + (i32.const 1) + (call $imported-throw) + ) + (catch $imported-e0 (i32.const 2)) + ) + ) + + (func (export "catchless-try") (param i32) (result i32) + (try (result i32) + (do + (try (result i32) + (do (local.get 0) (call $throw-if)) + ) + ) + (catch $e0 (i32.const 1)) + ) + ) + + (func $throw-void (throw $e0)) + (func (export "return-call-in-try-catch") + (try + (do + (return_call $throw-void) + ) + (catch $e0) + ) + ) + + (table funcref (elem $throw-void)) + (func (export "return-call-indirect-in-try-catch") + (try + (do + (return_call_indirect (param) (i32.const 0)) + ) + (catch $e0) + ) + ) + + (func (export "break-try-catch") + (try (do (br 0)) (catch $e0)) + ) + + (func (export "break-try-catch_all") + (try (do (br 0)) (catch_all)) + ) +) + +(assert_return (invoke "empty-catch")) + +(assert_return (invoke "simple-throw-catch" (i32.const 0)) (i32.const 23)) +(assert_return (invoke "simple-throw-catch" (i32.const 1)) (i32.const 42)) + +(assert_trap (invoke "unreachable-not-caught") "unreachable") + +(assert_return (invoke "trap-in-callee" (i32.const 7) (i32.const 2)) (i32.const 3)) +(assert_trap (invoke "trap-in-callee" (i32.const 1) (i32.const 0)) "integer divide by zero") + +(assert_return (invoke "catch-complex-1" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "catch-complex-1" (i32.const 1)) (i32.const 4)) +(assert_exception (invoke "catch-complex-1" (i32.const 2))) + +(assert_return (invoke "catch-complex-2" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "catch-complex-2" (i32.const 1)) (i32.const 4)) +(assert_exception (invoke "catch-complex-2" (i32.const 2))) + +(assert_return (invoke "throw-catch-param-i32" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "throw-catch-param-i32" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "throw-catch-param-i32" (i32.const 10)) (i32.const 10)) + +(assert_return (invoke "throw-catch-param-f32" (f32.const 5.0)) (f32.const 5.0)) +(assert_return (invoke "throw-catch-param-f32" (f32.const 10.5)) (f32.const 10.5)) + +(assert_return (invoke "throw-catch-param-i64" (i64.const 5)) (i64.const 5)) +(assert_return (invoke "throw-catch-param-i64" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "throw-catch-param-i64" (i64.const -1)) (i64.const -1)) + +(assert_return (invoke "throw-catch-param-f64" (f64.const 5.0)) (f64.const 5.0)) +(assert_return (invoke "throw-catch-param-f64" (f64.const 10.5)) (f64.const 10.5)) + +(assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5)) + +(assert_return (invoke "catch-imported") (i32.const 2)) + +(assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1)) + +(assert_exception (invoke "return-call-in-try-catch")) +(assert_exception (invoke "return-call-indirect-in-try-catch")) + +(assert_return (invoke "break-try-catch")) +(assert_return (invoke "break-try-catch_all")) + +(module + (func $imported-throw (import "test" "throw")) + (tag $e0) + + (func (export "imported-mismatch") (result i32) + (try (result i32) + (do + (try (result i32) + (do + (i32.const 1) + (call $imported-throw) + ) + (catch $e0 (i32.const 2)) + ) + ) + (catch_all (i32.const 3)) + ) + ) +) + +(assert_return (invoke "imported-mismatch") (i32.const 3)) + +(assert_malformed + (module quote "(module (func (catch_all)))") + "unexpected token" +) + +(assert_malformed + (module quote "(module (tag $e) (func (catch $e)))") + "unexpected token" +) + +(assert_malformed + (module quote + "(module (func (try (do) (catch_all) (catch_all))))" + ) + "unexpected token" +) + +(assert_invalid (module (func (result i32) (try (result i32) (do)))) + "type mismatch: instruction requires [i32] but stack has []") +(assert_invalid (module (func (result i32) (try (result i32) (do (i64.const 42))))) + "type mismatch: instruction requires [i32] but stack has [i64]") +(assert_invalid (module (tag) (func (try (do) (catch 0 (i32.const 42))))) + "type mismatch: block requires [] but stack has [i32]") +(assert_invalid (module + (tag (param i64)) + (func (result i32) + (try (result i32) (do (i32.const 42)) (catch 0)))) + "type mismatch: instruction requires [i32] but stack has [i64]") +(assert_invalid (module (func (try (do) (catch_all (i32.const 42))))) + "type mismatch: block requires [] but stack has [i32]") diff --git a/proposals/wasm-3.0/legacy/try_delegate.wast b/proposals/wasm-3.0/legacy/try_delegate.wast new file mode 100644 index 0000000..39ee09a --- /dev/null +++ b/proposals/wasm-3.0/legacy/try_delegate.wast @@ -0,0 +1,244 @@ +;; Test try-delegate blocks. + +(module + (tag $e0) + (tag $e1) + + (func (export "delegate-no-throw") (result i32) + (try $t (result i32) + (do (try (result i32) (do (i32.const 1)) (delegate $t))) + (catch $e0 (i32.const 2)) + ) + ) + + (func $throw-if (param i32) + (local.get 0) + (if (then (throw $e0)) (else)) + ) + + (func (export "delegate-throw") (param i32) (result i32) + (try $t (result i32) + (do + (try (result i32) + (do (local.get 0) (call $throw-if) (i32.const 1)) + (delegate $t) + ) + ) + (catch $e0 (i32.const 2)) + ) + ) + + (func (export "delegate-skip") (result i32) + (try $t (result i32) + (do + (try (result i32) + (do + (try (result i32) + (do (throw $e0) (i32.const 1)) + (delegate $t) + ) + ) + (catch $e0 (i32.const 2)) + ) + ) + (catch $e0 (i32.const 3)) + ) + ) + + (func (export "delegate-to-block") (result i32) + (try (result i32) + (do (block (try (do (throw $e0)) (delegate 0))) + (i32.const 0)) + (catch_all (i32.const 1))) + ) + + (func (export "delegate-to-catch") (result i32) + (try (result i32) + (do (try + (do (throw $e0)) + (catch $e0 + (try (do (rethrow 1)) (delegate 0)))) + (i32.const 0)) + (catch_all (i32.const 1))) + ) + + (func (export "delegate-to-caller-trivial") + (try + (do (throw $e0)) + (delegate 0))) + + (func (export "delegate-to-caller-skipping") + (try (do (try (do (throw $e0)) (delegate 1))) (catch_all)) + ) + + (func $select-tag (param i32) + (block (block (block (local.get 0) (br_table 0 1 2)) (return)) (throw $e0)) + (throw $e1) + ) + + (func (export "delegate-merge") (param i32 i32) (result i32) + (try $t (result i32) + (do + (local.get 0) + (call $select-tag) + (try + (result i32) + (do (local.get 1) (call $select-tag) (i32.const 1)) + (delegate $t) + ) + ) + (catch $e0 (i32.const 2)) + ) + ) + + (func (export "delegate-throw-no-catch") (result i32) + (try (result i32) + (do (try (result i32) (do (throw $e0) (i32.const 1)) (delegate 0))) + (catch $e1 (i32.const 2)) + ) + ) + + (func (export "delegate-correct-targets") (result i32) + (try (result i32) + (do (try $l3 + (do (try $l2 + (do (try $l1 + (do (try $l0 + (do (try + (do (throw $e0)) + (delegate $l1))) + (catch_all unreachable))) + (delegate $l3))) + (catch_all unreachable))) + (catch_all (try + (do (throw $e0)) + (delegate $l3)))) + unreachable) + (catch_all (i32.const 1)))) + + (func $throw-void (throw $e0)) + (func (export "return-call-in-try-delegate") + (try $l + (do + (try + (do + (return_call $throw-void) + ) + (delegate $l) + ) + ) + (catch $e0) + ) + ) + + (table funcref (elem $throw-void)) + (func (export "return-call-indirect-in-try-delegate") + (try $l + (do + (try + (do + (return_call_indirect (param) (i32.const 0)) + ) + (delegate $l) + ) + ) + (catch $e0) + ) + ) + + (func (export "break-try-delegate") + (try (do (br 0)) (delegate 0)) + ) + + (func (export "break-and-call-throw") (result i32) + (try $outer (result i32) + (do + (try (result i32) + (do + (block $a + (try (do (br $a)) (delegate $outer)) + ) + (call $throw-void) + (i32.const 0) + ) + (catch $e0 (i32.const 1)) + ) + ) + (catch $e0 (i32.const 2)) + ) + ) + + (func (export "break-and-throw") (result i32) + (try $outer (result i32) + (do + (try (result i32) + (do + (block $a + (try (do (br $a)) (delegate $outer)) + ) + (throw $e0) + (i32.const 0) + ) + (catch $e0 (i32.const 1)) + ) + ) + (catch $e0 (i32.const 2)) + ) + ) +) + +(assert_return (invoke "delegate-no-throw") (i32.const 1)) + +(assert_return (invoke "delegate-throw" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "delegate-throw" (i32.const 1)) (i32.const 2)) + +(assert_exception (invoke "delegate-throw-no-catch")) + +(assert_return (invoke "delegate-merge" (i32.const 1) (i32.const 0)) (i32.const 2)) +(assert_exception (invoke "delegate-merge" (i32.const 2) (i32.const 0))) +(assert_return (invoke "delegate-merge" (i32.const 0) (i32.const 1)) (i32.const 2)) +(assert_exception (invoke "delegate-merge" (i32.const 0) (i32.const 2))) +(assert_return (invoke "delegate-merge" (i32.const 0) (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "delegate-skip") (i32.const 3)) + +(assert_return (invoke "delegate-to-block") (i32.const 1)) +(assert_return (invoke "delegate-to-catch") (i32.const 1)) + +(assert_exception (invoke "delegate-to-caller-trivial")) +(assert_exception (invoke "delegate-to-caller-skipping")) + +(assert_return (invoke "delegate-correct-targets") (i32.const 1)) + +(assert_exception (invoke "return-call-in-try-delegate")) +(assert_exception (invoke "return-call-indirect-in-try-delegate")) + +(assert_return (invoke "break-try-delegate")) + +(assert_return (invoke "break-and-call-throw") (i32.const 1)) +(assert_return (invoke "break-and-throw") (i32.const 1)) + +(assert_malformed + (module quote "(module (func (delegate 0)))") + "unexpected token" +) + +(assert_malformed + (module quote "(module (tag $e) (func (try (do) (catch $e) (delegate 0))))") + "unexpected token" +) + +(assert_malformed + (module quote "(module (func (try (do) (catch_all) (delegate 0))))") + "unexpected token" +) + +(assert_malformed + (module quote "(module (func (try (do) (delegate) (delegate 0))))") + "unexpected token" +) + +(assert_invalid + (module (func (try (do) (delegate 1)))) + "unknown label" +) diff --git a/proposals/wasm-3.0/linking.wast b/proposals/wasm-3.0/linking.wast new file mode 100644 index 0000000..6a8ba1d --- /dev/null +++ b/proposals/wasm-3.0/linking.wast @@ -0,0 +1,610 @@ +;; Functions + +(module $Mf + (func (export "call") (result i32) (call $g)) + (func $g (result i32) (i32.const 2)) +) +(register "Mf" $Mf) + +(module $Nf + (func $f (import "Mf" "call") (result i32)) + (export "Mf.call" (func $f)) + (func (export "call Mf.call") (result i32) (call $f)) + (func (export "call") (result i32) (call $g)) + (func $g (result i32) (i32.const 3)) +) + +(assert_return (invoke $Mf "call") (i32.const 2)) +(assert_return (invoke $Nf "Mf.call") (i32.const 2)) +(assert_return (invoke $Nf "call") (i32.const 3)) +(assert_return (invoke $Nf "call Mf.call") (i32.const 2)) + +(module + (import "spectest" "print_i32" (func $f (param i32))) + (export "print" (func $f)) +) +(register "reexport_f") +(assert_unlinkable + (module (import "reexport_f" "print" (func (param i64)))) + "incompatible import type" +) +(assert_unlinkable + (module (import "reexport_f" "print" (func (param i32) (result i32)))) + "incompatible import type" +) + + +;; Globals + +(module $Mg + (global $glob (export "glob") i32 (i32.const 42)) + (func (export "get") (result i32) (global.get $glob)) + + ;; export mutable globals + (global $mut_glob (export "mut_glob") (mut i32) (i32.const 142)) + (func (export "get_mut") (result i32) (global.get $mut_glob)) + (func (export "set_mut") (param i32) (global.set $mut_glob (local.get 0))) +) +(register "Mg" $Mg) + +(module $Ng + (global $x (import "Mg" "glob") i32) + (global $mut_glob (import "Mg" "mut_glob") (mut i32)) + (func $f (import "Mg" "get") (result i32)) + (func $get_mut (import "Mg" "get_mut") (result i32)) + (func $set_mut (import "Mg" "set_mut") (param i32)) + + (export "Mg.glob" (global $x)) + (export "Mg.get" (func $f)) + (global $glob (export "glob") i32 (i32.const 43)) + (func (export "get") (result i32) (global.get $glob)) + + (export "Mg.mut_glob" (global $mut_glob)) + (export "Mg.get_mut" (func $get_mut)) + (export "Mg.set_mut" (func $set_mut)) +) + +(assert_return (get $Mg "glob") (i32.const 42)) +(assert_return (get $Ng "Mg.glob") (i32.const 42)) +(assert_return (get $Ng "glob") (i32.const 43)) +(assert_return (invoke $Mg "get") (i32.const 42)) +(assert_return (invoke $Ng "Mg.get") (i32.const 42)) +(assert_return (invoke $Ng "get") (i32.const 43)) + +(assert_return (get $Mg "mut_glob") (i32.const 142)) +(assert_return (get $Ng "Mg.mut_glob") (i32.const 142)) +(assert_return (invoke $Mg "get_mut") (i32.const 142)) +(assert_return (invoke $Ng "Mg.get_mut") (i32.const 142)) + +(assert_return (invoke $Mg "set_mut" (i32.const 241))) +(assert_return (get $Mg "mut_glob") (i32.const 241)) +(assert_return (get $Ng "Mg.mut_glob") (i32.const 241)) +(assert_return (invoke $Mg "get_mut") (i32.const 241)) +(assert_return (invoke $Ng "Mg.get_mut") (i32.const 241)) + + +(assert_unlinkable + (module (import "Mg" "mut_glob" (global i32))) + "incompatible import type" +) +(assert_unlinkable + (module (import "Mg" "glob" (global (mut i32)))) + "incompatible import type" +) + + +(module $Mref_ex + (type $t (func)) + (func $f) (elem declare func $f) + (global (export "g-const-funcnull") (ref null func) (ref.null func)) + (global (export "g-const-func") (ref func) (ref.func $f)) + (global (export "g-const-refnull") (ref null $t) (ref.null $t)) + (global (export "g-const-ref") (ref $t) (ref.func $f)) + (global (export "g-const-extern") externref (ref.null extern)) + (global (export "g-var-funcnull") (mut (ref null func)) (ref.null func)) + (global (export "g-var-func") (mut (ref func)) (ref.func $f)) + (global (export "g-var-refnull") (mut (ref null $t)) (ref.null $t)) + (global (export "g-var-ref") (mut (ref $t)) (ref.func $f)) + (global (export "g-var-extern") (mut externref) (ref.null extern)) +) +(register "Mref_ex" $Mref_ex) + +(module $Mref_im + (type $t (func)) + (global (import "Mref_ex" "g-const-funcnull") (ref null func)) + (global (import "Mref_ex" "g-const-func") (ref null func)) + (global (import "Mref_ex" "g-const-refnull") (ref null func)) + (global (import "Mref_ex" "g-const-ref") (ref null func)) + (global (import "Mref_ex" "g-const-func") (ref func)) + (global (import "Mref_ex" "g-const-ref") (ref func)) + (global (import "Mref_ex" "g-const-refnull") (ref null $t)) + (global (import "Mref_ex" "g-const-ref") (ref null $t)) + (global (import "Mref_ex" "g-const-ref") (ref $t)) + (global (import "Mref_ex" "g-const-extern") externref) + + (global (import "Mref_ex" "g-var-funcnull") (mut (ref null func))) + (global (import "Mref_ex" "g-var-func") (mut (ref func))) + (global (import "Mref_ex" "g-var-refnull") (mut (ref null $t))) + (global (import "Mref_ex" "g-var-ref") (mut (ref $t))) + (global (import "Mref_ex" "g-var-extern") (mut externref)) +) + +(assert_unlinkable + (module (global (import "Mref_ex" "g-const-extern") (ref null func))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-funcnull") (ref func))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-refnull") (ref func))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-extern") (ref func))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-funcnull") (ref null $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-func") (ref null $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-extern") (ref null $t))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-funcnull") (ref $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-func") (ref $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-refnull") (ref $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-const-extern") (ref $t))) + "incompatible import type" +) + + +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-func") (mut (ref null func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-refnull") (mut (ref null func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-ref") (mut (ref null func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-extern") (mut (ref null func)))) + "incompatible import type" +) + +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-funcnull") (mut (ref func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-refnull") (mut (ref func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-ref") (mut (ref func)))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-extern") (mut (ref func)))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-funcnull") (mut (ref null $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-func") (mut (ref null $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-ref") (mut (ref null $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-extern") (mut (ref null $t)))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-funcnull") (mut (ref $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-func") (mut (ref $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-refnull") (mut (ref $t)))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (global (import "Mref_ex" "g-var-extern") (mut (ref $t)))) + "incompatible import type" +) + +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-funcnull") (mut externref))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-func") (mut externref))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-refnull") (mut externref))) + "incompatible import type" +) +(assert_unlinkable + (module (global (import "Mref_ex" "g-var-ref") (mut externref))) + "incompatible import type" +) + + +;; Tables + +(module $Mt + (type (func (result i32))) + (type (func)) + + (table (export "tab") 10 funcref) + (elem (i32.const 2) $g $g $g $g) + (func $g (result i32) (i32.const 4)) + (func (export "h") (result i32) (i32.const -4)) + + (func (export "call") (param i32) (result i32) + (call_indirect (type 0) (local.get 0)) + ) +) +(register "Mt" $Mt) + +(module $Nt + (type (func)) + (type (func (result i32))) + + (func $f (import "Mt" "call") (param i32) (result i32)) + (func $h (import "Mt" "h") (result i32)) + + (table funcref (elem $g $g $g $h $f)) + (func $g (result i32) (i32.const 5)) + + (export "Mt.call" (func $f)) + (func (export "call Mt.call") (param i32) (result i32) + (call $f (local.get 0)) + ) + (func (export "call") (param i32) (result i32) + (call_indirect (type 1) (local.get 0)) + ) +) + +(assert_return (invoke $Mt "call" (i32.const 2)) (i32.const 4)) +(assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const 4)) +(assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5)) +(assert_return (invoke $Nt "call Mt.call" (i32.const 2)) (i32.const 4)) + +(assert_trap (invoke $Mt "call" (i32.const 1)) "uninitialized element") +(assert_trap (invoke $Nt "Mt.call" (i32.const 1)) "uninitialized element") +(assert_return (invoke $Nt "call" (i32.const 1)) (i32.const 5)) +(assert_trap (invoke $Nt "call Mt.call" (i32.const 1)) "uninitialized element") + +(assert_trap (invoke $Mt "call" (i32.const 0)) "uninitialized element") +(assert_trap (invoke $Nt "Mt.call" (i32.const 0)) "uninitialized element") +(assert_return (invoke $Nt "call" (i32.const 0)) (i32.const 5)) +(assert_trap (invoke $Nt "call Mt.call" (i32.const 0)) "uninitialized element") + +(assert_trap (invoke $Mt "call" (i32.const 20)) "undefined element") +(assert_trap (invoke $Nt "Mt.call" (i32.const 20)) "undefined element") +(assert_trap (invoke $Nt "call" (i32.const 7)) "undefined element") +(assert_trap (invoke $Nt "call Mt.call" (i32.const 20)) "undefined element") + +(assert_return (invoke $Nt "call" (i32.const 3)) (i32.const -4)) +(assert_trap (invoke $Nt "call" (i32.const 4)) "indirect call type mismatch") + +(module $Ot + (type (func (result i32))) + + (func $h (import "Mt" "h") (result i32)) + (table (import "Mt" "tab") 5 funcref) + (elem (i32.const 1) $i $h) + (func $i (result i32) (i32.const 6)) + + (func (export "call") (param i32) (result i32) + (call_indirect (type 0) (local.get 0)) + ) +) + +(assert_return (invoke $Mt "call" (i32.const 3)) (i32.const 4)) +(assert_return (invoke $Nt "Mt.call" (i32.const 3)) (i32.const 4)) +(assert_return (invoke $Nt "call Mt.call" (i32.const 3)) (i32.const 4)) +(assert_return (invoke $Ot "call" (i32.const 3)) (i32.const 4)) + +(assert_return (invoke $Mt "call" (i32.const 2)) (i32.const -4)) +(assert_return (invoke $Nt "Mt.call" (i32.const 2)) (i32.const -4)) +(assert_return (invoke $Nt "call" (i32.const 2)) (i32.const 5)) +(assert_return (invoke $Nt "call Mt.call" (i32.const 2)) (i32.const -4)) +(assert_return (invoke $Ot "call" (i32.const 2)) (i32.const -4)) + +(assert_return (invoke $Mt "call" (i32.const 1)) (i32.const 6)) +(assert_return (invoke $Nt "Mt.call" (i32.const 1)) (i32.const 6)) +(assert_return (invoke $Nt "call" (i32.const 1)) (i32.const 5)) +(assert_return (invoke $Nt "call Mt.call" (i32.const 1)) (i32.const 6)) +(assert_return (invoke $Ot "call" (i32.const 1)) (i32.const 6)) + +(assert_trap (invoke $Mt "call" (i32.const 0)) "uninitialized element") +(assert_trap (invoke $Nt "Mt.call" (i32.const 0)) "uninitialized element") +(assert_return (invoke $Nt "call" (i32.const 0)) (i32.const 5)) +(assert_trap (invoke $Nt "call Mt.call" (i32.const 0)) "uninitialized element") +(assert_trap (invoke $Ot "call" (i32.const 0)) "uninitialized element") + +(assert_trap (invoke $Ot "call" (i32.const 20)) "undefined element") + +(module + (table (import "Mt" "tab") 0 funcref) + (elem (i32.const 9) $f) + (func $f) +) + +(module $G1 (global (export "g") i32 (i32.const 5))) +(register "G1" $G1) +(module $G2 + (global (import "G1" "g") i32) + (global (export "g") i32 (global.get 0)) +) +(assert_return (get $G2 "g") (i32.const 5)) + +(assert_trap + (module + (table (import "Mt" "tab") 0 funcref) + (elem (i32.const 10) $f) + (func $f) + ) + "out of bounds table access" +) + +(assert_unlinkable + (module + (table (import "Mt" "tab") 10 funcref) + (memory (import "Mt" "mem") 1) ;; does not exist + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (elem (i32.const 9) $f) + ) + "unknown import" +) +(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") + +;; Unlike in the v1 spec, active element segments stored before an +;; out-of-bounds access persist after the instantiation failure. +(assert_trap + (module + (table (import "Mt" "tab") 10 funcref) + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (elem (i32.const 8) $f $f $f $f $f) ;; (partially) out of bounds + ) + "out of bounds table access" +) +(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) +(assert_trap (invoke $Mt "call" (i32.const 8)) "uninitialized element") + +(assert_trap + (module + (table (import "Mt" "tab") 10 funcref) + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (memory 1) + (data (i32.const 0x10000) "d") ;; out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) + + +(module $Mtable_ex + (type $t (func)) + (table (export "t-funcnull") 1 (ref null func)) + (table (export "t-refnull") 1 (ref null $t)) + (table (export "t-extern") 1 externref) +) +(register "Mtable_ex" $Mtable_ex) + +(module + (type $t (func)) + (table (import "Mtable_ex" "t-funcnull") 1 (ref null func)) + (table (import "Mtable_ex" "t-refnull") 1 (ref null $t)) + (table (import "Mtable_ex" "t-extern") 1 externref) +) + +(assert_unlinkable + (module (table (import "Mtable_ex" "t-refnull") 1 (ref null func))) + "incompatible import type" +) +(assert_unlinkable + (module (table (import "Mtable_ex" "t-extern") 1 (ref null func))) + "incompatible import type" +) + +(assert_unlinkable + (module (type $t (func)) (table (import "Mtable_ex" "t-funcnull") 1 (ref null $t))) + "incompatible import type" +) +(assert_unlinkable + (module (type $t (func)) (table (import "Mtable_ex" "t-extern") 1 (ref null $t))) + "incompatible import type" +) + +(assert_unlinkable + (module (table (import "Mtable_ex" "t-funcnull") 1 externref)) + "incompatible import type" +) +(assert_unlinkable + (module (table (import "Mtable_ex" "t-refnull") 1 externref)) + "incompatible import type" +) + + +;; Memories + +(module $Mm + (memory (export "mem") 1 5) + (data (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) +(register "Mm" $Mm) + +(module $Nm + (func $loadM (import "Mm" "load") (param i32) (result i32)) + + (memory 1) + (data (i32.const 10) "\f0\f1\f2\f3\f4\f5") + + (export "Mm.load" (func $loadM)) + (func (export "load") (param $a i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) + +(module $Om + (memory (import "Mm" "mem") 1) + (data (i32.const 5) "\a0\a1\a2\a3\a4\a5\a6\a7") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) +(assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) + +(module + (memory (import "Mm" "mem") 0) + (data (i32.const 0xffff) "a") +) + +(assert_trap + (module + (memory (import "Mm" "mem") 0) + (data (i32.const 0x10000) "a") + ) + "out of bounds memory access" +) + +(module $Pm + (memory (import "Mm" "mem") 1 8) + + (func (export "grow") (param $a i32) (result i32) + (memory.grow (local.get 0)) + ) +) + +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 4)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) + +(assert_unlinkable + (module + (func $host (import "spectest" "print")) + (memory (import "Mm" "mem") 1) + (table (import "Mm" "tab") 0 funcref) ;; does not exist + (data (i32.const 0) "abc") + ) + "unknown import" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0)) + +;; Unlike in v1 spec, active data segments written before an +;; out-of-bounds access persist after the instantiation failure. +(assert_trap + (module + ;; Note: the memory is 5 pages large by the time we get here. + (memory (import "Mm" "mem") 1) + (data (i32.const 0) "abc") + (data (i32.const 327670) "zzzzzzzzzzzzzzzzzz") ;; (partially) out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) +(assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) + +(assert_trap + (module + (memory (import "Mm" "mem") 1) + (data (i32.const 0) "abc") + (table 0 funcref) + (func) + (elem (i32.const 0) 0) ;; out of bounds + ) + "out of bounds table access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + +;; Store is modified if the start function traps. +(module $Ms + (type $t (func (result i32))) + (memory (export "memory") 1) + (table (export "table") 1 funcref) + (func (export "get memory[0]") (type $t) + (i32.load8_u (i32.const 0)) + ) + (func (export "get table[0]") (type $t) + (call_indirect (type $t) (i32.const 0)) + ) +) +(register "Ms" $Ms) + +(assert_trap + (module + (import "Ms" "memory" (memory 1)) + (import "Ms" "table" (table 1 funcref)) + (data (i32.const 0) "hello") + (elem (i32.const 0) $f) + (func $f (result i32) + (i32.const 0xdead) + ) + (func $main + (unreachable) + ) + (start $main) + ) + "unreachable" +) + +(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' +(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) diff --git a/proposals/wasm-3.0/linking0.wast b/proposals/wasm-3.0/linking0.wast new file mode 100644 index 0000000..b09c69f --- /dev/null +++ b/proposals/wasm-3.0/linking0.wast @@ -0,0 +1,42 @@ +(module $Mt + (type (func (result i32))) + (type (func)) + + (table (export "tab") 10 funcref) + (elem (i32.const 2) $g $g $g $g) + (func $g (result i32) (i32.const 4)) + (func (export "h") (result i32) (i32.const -4)) + + (func (export "call") (param i32) (result i32) + (call_indirect (type 0) (local.get 0)) + ) +) +(register "Mt" $Mt) + +(assert_unlinkable + (module + (table (import "Mt" "tab") 10 funcref) + (memory (import "spectest" "memory") 1) + (memory (import "Mt" "mem") 1) ;; does not exist + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (elem (i32.const 9) $f) + ) + "unknown import" +) +(assert_trap (invoke $Mt "call" (i32.const 7)) "uninitialized element") + + +(assert_trap + (module + (table (import "Mt" "tab") 10 funcref) + (func $f (result i32) (i32.const 0)) + (elem (i32.const 7) $f) + (memory 0) + (memory $m 1) + (memory 0) + (data $m (i32.const 0x10000) "d") ;; out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mt "call" (i32.const 7)) (i32.const 0)) diff --git a/proposals/wasm-3.0/linking1.wast b/proposals/wasm-3.0/linking1.wast new file mode 100644 index 0000000..39eabb0 --- /dev/null +++ b/proposals/wasm-3.0/linking1.wast @@ -0,0 +1,65 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(module $Nm + (func $loadM (import "Mm" "load") (param i32) (result i32)) + (memory (import "Mm" "mem0") 0) + + (memory $m 1) + (data (memory 1) (i32.const 10) "\f0\f1\f2\f3\f4\f5") + + (export "Mm.load" (func $loadM)) + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $m (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 2)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) + +(module $Om + (memory (import "Mm" "mem1") 1) + (data (i32.const 5) "\a0\a1\a2\a3\a4\a5\a6\a7") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) + +(assert_return (invoke $Mm "load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "Mm.load" (i32.const 12)) (i32.const 0xa7)) +(assert_return (invoke $Nm "load" (i32.const 12)) (i32.const 0xf2)) +(assert_return (invoke $Om "load" (i32.const 12)) (i32.const 0xa7)) + +(module + (memory (import "Mm" "mem1") 0) + (data (i32.const 0xffff) "a") +) + +(assert_trap + (module + (memory (import "Mm" "mem0") 0) + (data (i32.const 0xffff) "a") + ) + "out of bounds memory access" +) + +(assert_trap + (module + (memory (import "Mm" "mem1") 0) + (data (i32.const 0x10000) "a") + ) + "out of bounds memory access" +) + diff --git a/proposals/wasm-3.0/linking2.wast b/proposals/wasm-3.0/linking2.wast new file mode 100644 index 0000000..26bf3cc --- /dev/null +++ b/proposals/wasm-3.0/linking2.wast @@ -0,0 +1,30 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 1 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(module $Pm + (memory (import "Mm" "mem1") 1 8) + + (func (export "grow") (param $a i32) (result i32) + (memory.grow (local.get 0)) + ) +) + +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 2)) (i32.const 1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 3)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const 4)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) +(assert_return (invoke $Pm "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke $Pm "grow" (i32.const 0)) (i32.const 5)) + diff --git a/proposals/wasm-3.0/linking3.wast b/proposals/wasm-3.0/linking3.wast new file mode 100644 index 0000000..e23fbe4 --- /dev/null +++ b/proposals/wasm-3.0/linking3.wast @@ -0,0 +1,83 @@ +(module $Mm + (memory $mem0 (export "mem0") 0 0) + (memory $mem1 (export "mem1") 5 5) + (memory $mem2 (export "mem2") 0 0) + + (data (memory 1) (i32.const 10) "\00\01\02\03\04\05\06\07\08\09") + + (func (export "load") (param $a i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) +) +(register "Mm" $Mm) + +(assert_unlinkable + (module + (func $host (import "spectest" "print")) + (memory (import "Mm" "mem1") 1) + (table (import "Mm" "tab") 0 funcref) ;; does not exist + (data (i32.const 0) "abc") + ) + "unknown import" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 0)) + +;; Unlike in v1 spec, active data segments written before an +;; out-of-bounds access persist after the instantiation failure. +(assert_trap + (module + ;; Note: the memory is 5 pages large by the time we get here. + (memory (import "Mm" "mem1") 1) + (data (i32.const 0) "abc") + (data (i32.const 327670) "zzzzzzzzzzzzzzzzzz") ;; (partially) out of bounds + ) + "out of bounds memory access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) +(assert_return (invoke $Mm "load" (i32.const 327670)) (i32.const 0)) + +(assert_trap + (module + (memory (import "Mm" "mem1") 1) + (data (i32.const 0) "abc") + (table 0 funcref) + (func) + (elem (i32.const 0) 0) ;; out of bounds + ) + "out of bounds table access" +) +(assert_return (invoke $Mm "load" (i32.const 0)) (i32.const 97)) + +;; Store is modified if the start function traps. +(module $Ms + (type $t (func (result i32))) + (memory (export "memory") 1) + (table (export "table") 1 funcref) + (func (export "get memory[0]") (type $t) + (i32.load8_u (i32.const 0)) + ) + (func (export "get table[0]") (type $t) + (call_indirect (type $t) (i32.const 0)) + ) +) +(register "Ms" $Ms) + +(assert_trap + (module + (import "Ms" "memory" (memory 1)) + (import "Ms" "table" (table 1 funcref)) + (data (i32.const 0) "hello") + (elem (i32.const 0) $f) + (func $f (result i32) + (i32.const 0xdead) + ) + (func $main + (unreachable) + ) + (start $main) + ) + "unreachable" +) + +(assert_return (invoke $Ms "get memory[0]") (i32.const 104)) ;; 'h' +(assert_return (invoke $Ms "get table[0]") (i32.const 0xdead)) diff --git a/proposals/wasm-3.0/load.wast b/proposals/wasm-3.0/load.wast new file mode 100644 index 0000000..9fe48e2 --- /dev/null +++ b/proposals/wasm-3.0/load.wast @@ -0,0 +1,631 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (data (memory $mem1) (i32.const 0) "\01") + (data (memory $mem2) (i32.const 0) "\02") +) + +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + +(module $M + (memory (export "mem") 2) + + (func (export "read") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) +) + +(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read1" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read1" (i32.const 23)) (i32.const 4)) +(assert_return (invoke "read1" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read2" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read2" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read2" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read2" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read2" (i32.const 54)) (i32.const 14)) + + +;; Load operator as the argument of control constructs and instructions + +(module + (memory 1) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (i32.load (i32.const 0)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (i32.load (i32.const 0)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (i32.load (i32.const 0)) (i32.const 1))) (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (i32.load (i32.const 0)))) (i32.const 7) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (i32.load (i32.const 0)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (i32.load (i32.const 0)) (i32.const 1)) (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (i32.load (i32.const 0))) (i32.const 7) + ) + ) + + (func (export "as-return-value") (result i32) + (return (i32.load (i32.const 0))) + ) + + (func (export "as-if-cond") (result i32) + (if (result i32) (i32.load (i32.const 0)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (i32.load (i32.const 0))) (else (i32.const 0)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 0)) (else (i32.load (i32.const 0))) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (select (i32.load (i32.const 0)) (local.get 0) (local.get 1)) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (select (local.get 0) (i32.load (i32.const 0)) (local.get 1)) + ) + (func (export "as-select-cond") (result i32) + (select (i32.const 0) (i32.const 1) (i32.load (i32.const 0))) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (call $f (i32.load (i32.const 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (result i32) + (call $f (i32.const 1) (i32.load (i32.const 0)) (i32.const 3)) + ) + (func (export "as-call-last") (result i32) + (call $f (i32.const 1) (i32.const 2) (i32.load (i32.const 0))) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (result i32) + (call_indirect (type $sig) + (i32.load (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.load (i32.const 0)) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.load (i32.const 0)) (i32.const 0) + ) + ) + (func (export "as-call_indirect-index") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.const 3) (i32.load (i32.const 0)) + ) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (i32.load (i32.const 0))) + ) + (func (export "as-local.tee-value") (result i32) (local i32) + (local.tee 0 (i32.load (i32.const 0))) + ) + (global $g (mut i32) (i32.const 0)) + (func (export "as-global.set-value") (local i32) + (global.set $g (i32.load (i32.const 0))) + ) + + (func (export "as-load-address") (result i32) + (i32.load (i32.load (i32.const 0))) + ) + (func (export "as-loadN-address") (result i32) + (i32.load8_s (i32.load (i32.const 0))) + ) + + (func (export "as-store-address") + (i32.store (i32.load (i32.const 0)) (i32.const 7)) + ) + (func (export "as-store-value") + (i32.store (i32.const 2) (i32.load (i32.const 0))) + ) + + (func (export "as-storeN-address") + (i32.store8 (i32.load8_s (i32.const 0)) (i32.const 7)) + ) + (func (export "as-storeN-value") + (i32.store16 (i32.const 2) (i32.load (i32.const 0))) + ) + + (func (export "as-unary-operand") (result i32) + (i32.clz (i32.load (i32.const 100))) + ) + + (func (export "as-binary-left") (result i32) + (i32.add (i32.load (i32.const 100)) (i32.const 10)) + ) + (func (export "as-binary-right") (result i32) + (i32.sub (i32.const 10) (i32.load (i32.const 100))) + ) + + (func (export "as-test-operand") (result i32) + (i32.eqz (i32.load (i32.const 100))) + ) + + (func (export "as-compare-left") (result i32) + (i32.le_s (i32.load (i32.const 100)) (i32.const 10)) + ) + (func (export "as-compare-right") (result i32) + (i32.ne (i32.const 10) (i32.load (i32.const 100))) + ) + + (func (export "as-memory.grow-size") (result i32) + (memory.grow (i32.load (i32.const 100))) + ) +) + +(assert_return (invoke "as-br-value") (i32.const 0)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 0)) +(assert_return (invoke "as-br_if-value-cond") (i32.const 7)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 0)) +(assert_return (invoke "as-br_table-value-index") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 0)) + +(assert_return (invoke "as-if-cond") (i32.const 1)) +(assert_return (invoke "as-if-then") (i32.const 0)) +(assert_return (invoke "as-if-else") (i32.const 0)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-select-cond") (i32.const 1)) + +(assert_return (invoke "as-call-first") (i32.const -1)) +(assert_return (invoke "as-call-mid") (i32.const -1)) +(assert_return (invoke "as-call-last") (i32.const -1)) + +(assert_return (invoke "as-call_indirect-first") (i32.const -1)) +(assert_return (invoke "as-call_indirect-mid") (i32.const -1)) +(assert_return (invoke "as-call_indirect-last") (i32.const -1)) +(assert_return (invoke "as-call_indirect-index") (i32.const -1)) + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value") (i32.const 0)) +(assert_return (invoke "as-global.set-value")) + +(assert_return (invoke "as-load-address") (i32.const 0)) +(assert_return (invoke "as-loadN-address") (i32.const 0)) +(assert_return (invoke "as-store-address")) +(assert_return (invoke "as-store-value")) +(assert_return (invoke "as-storeN-address")) +(assert_return (invoke "as-storeN-value")) + +(assert_return (invoke "as-unary-operand") (i32.const 32)) + +(assert_return (invoke "as-binary-left") (i32.const 10)) +(assert_return (invoke "as-binary-right") (i32.const 10)) + +(assert_return (invoke "as-test-operand") (i32.const 1)) + +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) + +(assert_return (invoke "as-memory.grow-size") (i32.const 1)) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load32 (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load32_u (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load32_s (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load64 (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load64_u (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i32) (i32.load64_s (local.get 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i64) (i64.load64 (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i64) (i64.load64_u (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result i64) (i64.load64_s (local.get 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result f32) (f32.load32 (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result f32) (f32.load64 (local.get 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result f64) (f64.load32 (local.get 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (result f64) (f64.load64 (local.get 0)))" + ) + "unknown operator" +) + + +;; load should have retval + +(assert_invalid + (module (memory 1) (func $load_i32 (i32.load (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load8_s_i32 (i32.load8_s (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load8_u_i32 (i32.load8_u (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load16_s_i32 (i32.load16_s (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load16_u_i32 (i32.load16_u (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load_i64 (i64.load (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load8_s_i64 (i64.load8_s (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load8_u_i64 (i64.load8_u (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load16_s_i64 (i64.load16_s (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load16_u_i64 (i64.load16_u (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load32_s_i64 (i64.load32_s (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load32_u_i64 (i64.load32_u (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load_f32 (f32.load (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func $load_f64 (f64.load (i32.const 0)))) + "type mismatch" +) + + +;; Type check + +(assert_invalid (module (memory 1) (func (result i32) (i32.load (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i32) (i32.load8_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i32) (i32.load8_u (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i32) (i32.load16_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i32) (i32.load16_u (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load8_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load8_u (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load16_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load16_u (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load32_s (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result i64) (i64.load32_u (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result f32) (f32.load (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (result f64) (f64.load (f32.const 0)))) "type mismatch") + + +(assert_invalid + (module + (memory 0) + (func $type-address-empty + (i32.load) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-block + (i32.const 0) + (block (i32.load) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-loop + (i32.const 0) + (loop (i32.load) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-then + (i32.const 0) (i32.const 0) + (if (then (i32.load) (drop))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-else + (i32.const 0) (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (i32.load))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-br + (i32.const 0) + (block (br 0 (i32.load)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-br_if + (i32.const 0) + (block (br_if 0 (i32.load) (i32.const 1)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-br_table + (i32.const 0) + (block (br_table 0 (i32.load)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-return + (return (i32.load)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-select + (select (i32.load) (i32.const 1) (i32.const 2)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-call + (call 1 (i32.load)) (drop) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-address-empty-in-call_indirect + (block (result i32) + (call_indirect (type $sig) + (i32.load) (i32.const 0) + ) + (drop) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-local.set + (local i32) + (local.set 0 (i32.load)) (local.get 0) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-local.tee + (local i32) + (local.tee 0 (i32.load)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (global $x (mut i32) (i32.const 0)) + (func $type-address-empty-in-global.set + (global.set $x (i32.load)) (global.get $x) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-memory.grow + (memory.grow (i32.load)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-address-empty-in-load + (i32.load (i32.load)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-store + (i32.store (i32.load) (i32.const 1)) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/load0.wast b/proposals/wasm-3.0/load0.wast new file mode 100644 index 0000000..2332a20 --- /dev/null +++ b/proposals/wasm-3.0/load0.wast @@ -0,0 +1,19 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (data (memory $mem1) (i32.const 0) "\01") + (data (memory $mem2) (i32.const 0) "\02") +) + +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/proposals/wasm-3.0/load1.wast b/proposals/wasm-3.0/load1.wast new file mode 100644 index 0000000..be309c3 --- /dev/null +++ b/proposals/wasm-3.0/load1.wast @@ -0,0 +1,41 @@ +(module $M + (memory (export "mem") 2) + + (func (export "read") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) +) + +(assert_return (invoke $M "read" (i32.const 20)) (i32.const 1)) +(assert_return (invoke $M "read" (i32.const 21)) (i32.const 2)) +(assert_return (invoke $M "read" (i32.const 22)) (i32.const 3)) +(assert_return (invoke $M "read" (i32.const 23)) (i32.const 4)) +(assert_return (invoke $M "read" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read1" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read1" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read1" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read1" (i32.const 23)) (i32.const 4)) +(assert_return (invoke "read1" (i32.const 24)) (i32.const 5)) + +(assert_return (invoke "read2" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read2" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read2" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read2" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read2" (i32.const 54)) (i32.const 14)) diff --git a/proposals/wasm-3.0/load2.wast b/proposals/wasm-3.0/load2.wast new file mode 100644 index 0000000..dfe6fed --- /dev/null +++ b/proposals/wasm-3.0/load2.wast @@ -0,0 +1,213 @@ +(module + (memory 0) + (memory 0) + (memory 0) + (memory $m 1) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (i32.load $m (i32.const 0)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (i32.load $m (i32.const 0)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (i32.load $m (i32.const 0)) (i32.const 1))) (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (i32.load $m (i32.const 0)))) (i32.const 7) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (i32.load $m (i32.const 0)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (i32.load $m (i32.const 0)) (i32.const 1)) (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (i32.load $m (i32.const 0))) (i32.const 7) + ) + ) + + (func (export "as-return-value") (result i32) + (return (i32.load $m (i32.const 0))) + ) + + (func (export "as-if-cond") (result i32) + (if (result i32) (i32.load $m (i32.const 0)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (i32.load $m (i32.const 0))) (else (i32.const 0)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 0)) (else (i32.load $m (i32.const 0))) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (select (i32.load $m (i32.const 0)) (local.get 0) (local.get 1)) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (select (local.get 0) (i32.load $m (i32.const 0)) (local.get 1)) + ) + (func (export "as-select-cond") (result i32) + (select (i32.const 0) (i32.const 1) (i32.load $m (i32.const 0))) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (call $f (i32.load $m (i32.const 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (result i32) + (call $f (i32.const 1) (i32.load $m (i32.const 0)) (i32.const 3)) + ) + (func (export "as-call-last") (result i32) + (call $f (i32.const 1) (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (result i32) + (call_indirect (type $sig) + (i32.load $m (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.load $m (i32.const 0)) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.load $m (i32.const 0)) (i32.const 0) + ) + ) + (func (export "as-call_indirect-index") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.const 3) (i32.load $m (i32.const 0)) + ) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (i32.load $m (i32.const 0))) + ) + (func (export "as-local.tee-value") (result i32) (local i32) + (local.tee 0 (i32.load $m (i32.const 0))) + ) + (global $g (mut i32) (i32.const 0)) + (func (export "as-global.set-value") (local i32) + (global.set $g (i32.load $m (i32.const 0))) + ) + + (func (export "as-load-address") (result i32) + (i32.load $m (i32.load $m (i32.const 0))) + ) + (func (export "as-loadN-address") (result i32) + (i32.load8_s $m (i32.load $m (i32.const 0))) + ) + + (func (export "as-store-address") + (i32.store $m (i32.load $m (i32.const 0)) (i32.const 7)) + ) + (func (export "as-store-value") + (i32.store $m (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (func (export "as-storeN-address") + (i32.store8 $m (i32.load8_s $m (i32.const 0)) (i32.const 7)) + ) + (func (export "as-storeN-value") + (i32.store16 $m (i32.const 2) (i32.load $m (i32.const 0))) + ) + + (func (export "as-unary-operand") (result i32) + (i32.clz (i32.load $m (i32.const 100))) + ) + + (func (export "as-binary-left") (result i32) + (i32.add (i32.load $m (i32.const 100)) (i32.const 10)) + ) + (func (export "as-binary-right") (result i32) + (i32.sub (i32.const 10) (i32.load $m (i32.const 100))) + ) + + (func (export "as-test-operand") (result i32) + (i32.eqz (i32.load $m (i32.const 100))) + ) + + (func (export "as-compare-left") (result i32) + (i32.le_s (i32.load $m (i32.const 100)) (i32.const 10)) + ) + (func (export "as-compare-right") (result i32) + (i32.ne (i32.const 10) (i32.load $m (i32.const 100))) + ) + + (func (export "as-memory.grow-size") (result i32) + (memory.grow $m (i32.load $m (i32.const 100))) + ) +) + +(assert_return (invoke "as-br-value") (i32.const 0)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 0)) +(assert_return (invoke "as-br_if-value-cond") (i32.const 7)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 0)) +(assert_return (invoke "as-br_table-value-index") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 0)) + +(assert_return (invoke "as-if-cond") (i32.const 1)) +(assert_return (invoke "as-if-then") (i32.const 0)) +(assert_return (invoke "as-if-else") (i32.const 0)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-select-cond") (i32.const 1)) + +(assert_return (invoke "as-call-first") (i32.const -1)) +(assert_return (invoke "as-call-mid") (i32.const -1)) +(assert_return (invoke "as-call-last") (i32.const -1)) + +(assert_return (invoke "as-call_indirect-first") (i32.const -1)) +(assert_return (invoke "as-call_indirect-mid") (i32.const -1)) +(assert_return (invoke "as-call_indirect-last") (i32.const -1)) +(assert_return (invoke "as-call_indirect-index") (i32.const -1)) + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value") (i32.const 0)) +(assert_return (invoke "as-global.set-value")) + +(assert_return (invoke "as-load-address") (i32.const 0)) +(assert_return (invoke "as-loadN-address") (i32.const 0)) +(assert_return (invoke "as-store-address")) +(assert_return (invoke "as-store-value")) +(assert_return (invoke "as-storeN-address")) +(assert_return (invoke "as-storeN-value")) + +(assert_return (invoke "as-unary-operand") (i32.const 32)) + +(assert_return (invoke "as-binary-left") (i32.const 10)) +(assert_return (invoke "as-binary-right") (i32.const 10)) + +(assert_return (invoke "as-test-operand") (i32.const 1)) + +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) + +(assert_return (invoke "as-memory.grow-size") (i32.const 1)) + diff --git a/proposals/memory64/load64.wast b/proposals/wasm-3.0/load64.wast similarity index 100% rename from proposals/memory64/load64.wast rename to proposals/wasm-3.0/load64.wast diff --git a/proposals/wasm-3.0/local_get.wast b/proposals/wasm-3.0/local_get.wast new file mode 100644 index 0000000..45dbcae --- /dev/null +++ b/proposals/wasm-3.0/local_get.wast @@ -0,0 +1,225 @@ +;; Test `local.get` operator + +(module + ;; Typing + + (func (export "type-local-i32") (result i32) (local i32) (local.get 0)) + (func (export "type-local-i64") (result i64) (local i64) (local.get 0)) + (func (export "type-local-f32") (result f32) (local f32) (local.get 0)) + (func (export "type-local-f64") (result f64) (local f64) (local.get 0)) + + (func (export "type-param-i32") (param i32) (result i32) (local.get 0)) + (func (export "type-param-i64") (param i64) (result i64) (local.get 0)) + (func (export "type-param-f32") (param f32) (result f32) (local.get 0)) + (func (export "type-param-f64") (param f64) (result f64) (local.get 0)) + + (func (export "type-mixed") (param i64 f32 f64 i32 i32) + (local f32 i64 i64 f64) + (drop (i64.eqz (local.get 0))) + (drop (f32.neg (local.get 1))) + (drop (f64.neg (local.get 2))) + (drop (i32.eqz (local.get 3))) + (drop (i32.eqz (local.get 4))) + (drop (f32.neg (local.get 5))) + (drop (i64.eqz (local.get 6))) + (drop (i64.eqz (local.get 7))) + (drop (f64.neg (local.get 8))) + ) + + ;; Reading + + (func (export "read") (param i64 f32 f64 i32 i32) (result f64) + (local f32 i64 i64 f64) + (local.set 5 (f32.const 5.5)) + (local.set 6 (i64.const 6)) + (local.set 8 (f64.const 8)) + (f64.add + (f64.convert_i64_u (local.get 0)) + (f64.add + (f64.promote_f32 (local.get 1)) + (f64.add + (local.get 2) + (f64.add + (f64.convert_i32_u (local.get 3)) + (f64.add + (f64.convert_i32_s (local.get 4)) + (f64.add + (f64.promote_f32 (local.get 5)) + (f64.add + (f64.convert_i64_u (local.get 6)) + (f64.add + (f64.convert_i64_u (local.get 7)) + (local.get 8) + ) + ) + ) + ) + ) + ) + ) + ) + ) + + ;; As parameter of control constructs and instructions + + (func (export "as-block-value") (param i32) (result i32) + (block (result i32) (local.get 0)) + ) + (func (export "as-loop-value") (param i32) (result i32) + (loop (result i32) (local.get 0)) + ) + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) (br 0 (local.get 0))) + ) + (func (export "as-br_if-value") (param i32) (result i32) + (block $l0 (result i32) (br_if $l0 (local.get 0) (i32.const 1))) + ) + + (func (export "as-br_if-value-cond") (param i32) (result i32) + (block (result i32) + (br_if 0 (local.get 0) (local.get 0)) + ) + ) + (func (export "as-br_table-value") (param i32) (result i32) + (block + (block + (block + (br_table 0 1 2 (local.get 0)) + (return (i32.const 0)) + ) + (return (i32.const 1)) + ) + (return (i32.const 2)) + ) + (i32.const 3) + ) + + (func (export "as-return-value") (param i32) (result i32) + (return (local.get 0)) + ) + + (func (export "as-if-then") (param i32) (result i32) + (if (result i32) (local.get 0) (then (local.get 0)) (else (i32.const 0))) + ) + (func (export "as-if-else") (param i32) (result i32) + (if (result i32) (local.get 0) (then (i32.const 1)) (else (local.get 0))) + ) +) + +(assert_return (invoke "type-local-i32") (i32.const 0)) +(assert_return (invoke "type-local-i64") (i64.const 0)) +(assert_return (invoke "type-local-f32") (f32.const 0)) +(assert_return (invoke "type-local-f64") (f64.const 0)) + +(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 2)) +(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 3)) +(assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 4.4)) +(assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 5.5)) + +(assert_return (invoke "as-block-value" (i32.const 6)) (i32.const 6)) +(assert_return (invoke "as-loop-value" (i32.const 7)) (i32.const 7)) + +(assert_return (invoke "as-br-value" (i32.const 8)) (i32.const 8)) +(assert_return (invoke "as-br_if-value" (i32.const 9)) (i32.const 9)) +(assert_return (invoke "as-br_if-value-cond" (i32.const 10)) (i32.const 10)) +(assert_return (invoke "as-br_table-value" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 0)) + +(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 0)) + +(assert_return + (invoke "type-mixed" + (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) +) + +(assert_return + (invoke "read" + (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) + (f64.const 34.8) +) + + +;; Invalid typing of access to locals + +(assert_invalid + (module (func $type-local-num-vs-num (result i64) (local i32) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (result i32) (local f32) (i32.eqz (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (result f64) (local f64 i64) (f64.neg (local.get 1)))) + "type mismatch" +) + + +;; Invalid typing of access to parameters + +(assert_invalid + (module (func $type-param-num-vs-num (param i32) (result i64) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f32) (result i32) (i32.eqz (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f64 i64) (result f64) (f64.neg (local.get 1)))) + "type mismatch" +) + + +;; Invalid result type + +(assert_invalid + (module (func $type-empty-vs-i32 (local i32) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-vs-i64 (local i64) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-vs-f32 (local f32) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-empty-vs-f64 (local f64) (local.get 0))) + "type mismatch" +) + + +;; Invalid local index + +(assert_invalid + (module (func $unbound-local (local i32 i64) (local.get 3) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-local (local i32 i64) (local.get 14324343) drop)) + "unknown local" +) + +(assert_invalid + (module (func $unbound-param (param i32 i64) (local.get 2) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-param (param i32 i64) (local.get 714324343) drop)) + "unknown local" +) + +(assert_invalid + (module (func $unbound-mixed (param i32) (local i32 i64) (local.get 3) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-mixed (param i64) (local i32 i64) (local.get 214324343) drop)) + "unknown local" +) diff --git a/proposals/wasm-3.0/local_init.wast b/proposals/wasm-3.0/local_init.wast new file mode 100644 index 0000000..176ccc6 --- /dev/null +++ b/proposals/wasm-3.0/local_init.wast @@ -0,0 +1,74 @@ +;; Uninitialized undefaulted locals + +(module + (func (export "get-after-set") (param $p (ref extern)) (result (ref extern)) + (local $x (ref extern)) + (local.set $x (local.get $p)) + (local.get $x) + ) + (func (export "get-after-tee") (param $p (ref extern)) (result (ref extern)) + (local $x (ref extern)) + (drop (local.tee $x (local.get $p))) + (local.get $x) + ) + (func (export "get-in-block-after-set") (param $p (ref extern)) (result (ref extern)) + (local $x (ref extern)) + (local.set $x (local.get $p)) + (block (result (ref extern)) (local.get $x)) + ) +) + +(assert_return (invoke "get-after-set" (ref.extern 1)) (ref.extern 1)) +(assert_return (invoke "get-after-tee" (ref.extern 2)) (ref.extern 2)) +(assert_return (invoke "get-in-block-after-set" (ref.extern 3)) (ref.extern 3)) + +(assert_invalid + (module (func $uninit (local $x (ref extern)) (drop (local.get $x)))) + "uninitialized local" +) +(assert_invalid + (module + (func $uninit-after-end (param $p (ref extern)) + (local $x (ref extern)) + (block (local.set $x (local.get $p)) (drop (local.tee $x (local.get $p)))) + (drop (local.get $x)) + ) + ) + "uninitialized local" +) +(assert_invalid + (module + (func $uninit-in-else (param $p (ref extern)) + (local $x (ref extern)) + (if (i32.const 0) + (then (local.set $x (local.get $p))) + (else (local.get $x)) + ) + ) + ) + "uninitialized local" +) + +(assert_invalid + (module + (func $uninit-from-if (param $p (ref extern)) + (local $x (ref extern)) + (if (i32.const 0) + (then (local.set $x (local.get $p))) + (else (local.set $x (local.get $p))) + ) + (drop (local.get $x)) + ) + ) + "uninitialized local" +) + +(module + (func (export "tee-init") (param $p (ref extern)) (result (ref extern)) + (local $x (ref extern)) + (drop (local.tee $x (local.get $p))) + (local.get $x) + ) +) + +(assert_return (invoke "tee-init" (ref.extern 1)) (ref.extern 1)) diff --git a/proposals/wasm-3.0/local_tee.wast b/proposals/wasm-3.0/local_tee.wast new file mode 100644 index 0000000..eeb26e6 --- /dev/null +++ b/proposals/wasm-3.0/local_tee.wast @@ -0,0 +1,654 @@ +;; Test `local.tee` operator + +(module + ;; Typing + + (func (export "type-local-i32") (result i32) (local i32) (local.tee 0 (i32.const 0))) + (func (export "type-local-i64") (result i64) (local i64) (local.tee 0 (i64.const 0))) + (func (export "type-local-f32") (result f32) (local f32) (local.tee 0 (f32.const 0))) + (func (export "type-local-f64") (result f64) (local f64) (local.tee 0 (f64.const 0))) + + (func (export "type-param-i32") (param i32) (result i32) (local.tee 0 (i32.const 10))) + (func (export "type-param-i64") (param i64) (result i64) (local.tee 0 (i64.const 11))) + (func (export "type-param-f32") (param f32) (result f32) (local.tee 0 (f32.const 11.1))) + (func (export "type-param-f64") (param f64) (result f64) (local.tee 0 (f64.const 12.2))) + + (func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) + (drop (i64.eqz (local.tee 0 (i64.const 0)))) + (drop (f32.neg (local.tee 1 (f32.const 0)))) + (drop (f64.neg (local.tee 2 (f64.const 0)))) + (drop (i32.eqz (local.tee 3 (i32.const 0)))) + (drop (i32.eqz (local.tee 4 (i32.const 0)))) + (drop (f32.neg (local.tee 5 (f32.const 0)))) + (drop (i64.eqz (local.tee 6 (i64.const 0)))) + (drop (i64.eqz (local.tee 7 (i64.const 0)))) + (drop (f64.neg (local.tee 8 (f64.const 0)))) + ) + + ;; Writing + + (func (export "write") (param i64 f32 f64 i32 i32) (result i64) (local f32 i64 i64 f64) + (drop (local.tee 1 (f32.const -0.3))) + (drop (local.tee 3 (i32.const 40))) + (drop (local.tee 4 (i32.const -7))) + (drop (local.tee 5 (f32.const 5.5))) + (drop (local.tee 6 (i64.const 6))) + (drop (local.tee 8 (f64.const 8))) + (i64.trunc_f64_s + (f64.add + (f64.convert_i64_u (local.get 0)) + (f64.add + (f64.promote_f32 (local.get 1)) + (f64.add + (local.get 2) + (f64.add + (f64.convert_i32_u (local.get 3)) + (f64.add + (f64.convert_i32_s (local.get 4)) + (f64.add + (f64.promote_f32 (local.get 5)) + (f64.add + (f64.convert_i64_u (local.get 6)) + (f64.add + (f64.convert_i64_u (local.get 7)) + (local.get 8) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + + ;; Result + + (func (export "result") (param i64 f32 f64 i32 i32) (result f64) + (local f32 i64 i64 f64) + (f64.add + (f64.convert_i64_u (local.tee 0 (i64.const 1))) + (f64.add + (f64.promote_f32 (local.tee 1 (f32.const 2))) + (f64.add + (local.tee 2 (f64.const 3.3)) + (f64.add + (f64.convert_i32_u (local.tee 3 (i32.const 4))) + (f64.add + (f64.convert_i32_s (local.tee 4 (i32.const 5))) + (f64.add + (f64.promote_f32 (local.tee 5 (f32.const 5.5))) + (f64.add + (f64.convert_i64_u (local.tee 6 (i64.const 6))) + (f64.add + (f64.convert_i64_u (local.tee 7 (i64.const 0))) + (local.tee 8 (f64.const 8)) + ) + ) + ) + ) + ) + ) + ) + ) + ) + + (func $dummy) + + (func (export "as-block-first") (param i32) (result i32) + (block (result i32) (local.tee 0 (i32.const 1)) (call $dummy)) + ) + (func (export "as-block-mid") (param i32) (result i32) + (block (result i32) (call $dummy) (local.tee 0 (i32.const 1)) (call $dummy)) + ) + (func (export "as-block-last") (param i32) (result i32) + (block (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 1))) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (loop (result i32) (local.tee 0 (i32.const 3)) (call $dummy)) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (loop (result i32) (call $dummy) (local.tee 0 (i32.const 4)) (call $dummy)) + ) + (func (export "as-loop-last") (param i32) (result i32) + (loop (result i32) (call $dummy) (call $dummy) (local.tee 0 (i32.const 5))) + ) + + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) (br 0 (local.tee 0 (i32.const 9)))) + ) + + (func (export "as-br_if-cond") (param i32) + (block (br_if 0 (local.tee 0 (i32.const 1)))) + ) + (func (export "as-br_if-value") (param i32) (result i32) + (block (result i32) + (drop (br_if 0 (local.tee 0 (i32.const 8)) (i32.const 1))) (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (param i32) (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (local.tee 0 (i32.const 9)))) (i32.const 7) + ) + ) + + (func (export "as-br_table-index") (param i32) + (block (br_table 0 0 0 (local.tee 0 (i32.const 0)))) + ) + (func (export "as-br_table-value") (param i32) (result i32) + (block (result i32) + (br_table 0 0 0 (local.tee 0 (i32.const 10)) (i32.const 1)) (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (param i32) (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (local.tee 0 (i32.const 11))) (i32.const 7) + ) + ) + + (func (export "as-return-value") (param i32) (result i32) + (return (local.tee 0 (i32.const 7))) + ) + + (func (export "as-if-cond") (param i32) (result i32) + (if (result i32) (local.tee 0 (i32.const 2)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (local.tee 0 (i32.const 3))) (else (local.get 0)) + ) + ) + (func (export "as-if-else") (param i32) (result i32) + (if (result i32) (local.get 0) + (then (local.get 0)) (else (local.tee 0 (i32.const 4))) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (select (local.tee 0 (i32.const 5)) (local.get 0) (local.get 1)) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (select (local.get 0) (local.tee 0 (i32.const 6)) (local.get 1)) + ) + (func (export "as-select-cond") (param i32) (result i32) + (select (i32.const 0) (i32.const 1) (local.tee 0 (i32.const 7))) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (param i32) (result i32) + (call $f (local.tee 0 (i32.const 12)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (param i32) (result i32) + (call $f (i32.const 1) (local.tee 0 (i32.const 13)) (i32.const 3)) + ) + (func (export "as-call-last") (param i32) (result i32) + (call $f (i32.const 1) (i32.const 2) (local.tee 0 (i32.const 14))) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (param i32) (result i32) + (call_indirect (type $sig) + (local.tee 0 (i32.const 1)) (i32.const 2) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-mid") (param i32) (result i32) + (call_indirect (type $sig) + (i32.const 1) (local.tee 0 (i32.const 2)) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-last") (param i32) (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (local.tee 0 (i32.const 3)) (i32.const 0) + ) + ) + (func (export "as-call_indirect-index") (param i32) (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.const 3) (local.tee 0 (i32.const 0)) + ) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (local.tee 0 (i32.const 1))) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 (local.tee 0 (i32.const 1))) + ) + (global $g (mut i32) (i32.const 0)) + (func (export "as-global.set-value") (local i32) + (global.set $g (local.tee 0 (i32.const 1))) + ) + + (memory 1) + (func (export "as-load-address") (param i32) (result i32) + (i32.load (local.tee 0 (i32.const 1))) + ) + (func (export "as-loadN-address") (param i32) (result i32) + (i32.load8_s (local.tee 0 (i32.const 3))) + ) + + (func (export "as-store-address") (param i32) + (i32.store (local.tee 0 (i32.const 30)) (i32.const 7)) + ) + (func (export "as-store-value") (param i32) + (i32.store (i32.const 2) (local.tee 0 (i32.const 1))) + ) + + (func (export "as-storeN-address") (param i32) + (i32.store8 (local.tee 0 (i32.const 1)) (i32.const 7)) + ) + (func (export "as-storeN-value") (param i32) + (i32.store16 (i32.const 2) (local.tee 0 (i32.const 1))) + ) + + (func (export "as-unary-operand") (param f32) (result f32) + (f32.neg (local.tee 0 (f32.const nan:0x0f1e2))) + ) + + (func (export "as-binary-left") (param i32) (result i32) + (i32.add (local.tee 0 (i32.const 3)) (i32.const 10)) + ) + (func (export "as-binary-right") (param i32) (result i32) + (i32.sub (i32.const 10) (local.tee 0 (i32.const 4))) + ) + + (func (export "as-test-operand") (param i32) (result i32) + (i32.eqz (local.tee 0 (i32.const 0))) + ) + + (func (export "as-compare-left") (param i32) (result i32) + (i32.le_s (local.tee 0 (i32.const 43)) (i32.const 10)) + ) + (func (export "as-compare-right") (param i32) (result i32) + (i32.ne (i32.const 10) (local.tee 0 (i32.const 42))) + ) + + (func (export "as-convert-operand") (param i64) (result i32) + (i32.wrap_i64 (local.tee 0 (i64.const 41))) + ) + + (func (export "as-memory.grow-size") (param i32) (result i32) + (memory.grow (local.tee 0 (i32.const 40))) + ) + +) + +(assert_return (invoke "type-local-i32") (i32.const 0)) +(assert_return (invoke "type-local-i64") (i64.const 0)) +(assert_return (invoke "type-local-f32") (f32.const 0)) +(assert_return (invoke "type-local-f64") (f64.const 0)) + +(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10)) +(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11)) +(assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1)) +(assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2)) + +(assert_return (invoke "as-block-first" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-block-mid" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-block-last" (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 4)) +(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 5)) + +(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 9)) + +(assert_return (invoke "as-br_if-cond" (i32.const 0))) +(assert_return (invoke "as-br_if-value" (i32.const 0)) (i32.const 8)) +(assert_return (invoke "as-br_if-value-cond" (i32.const 0)) (i32.const 6)) + +(assert_return (invoke "as-br_table-index" (i32.const 0))) +(assert_return (invoke "as-br_table-value" (i32.const 0)) (i32.const 10)) +(assert_return (invoke "as-br_table-value-index" (i32.const 0)) (i32.const 6)) + +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 7)) + +(assert_return (invoke "as-if-cond" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 4)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 5)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 6)) +(assert_return (invoke "as-select-cond" (i32.const 0)) (i32.const 0)) + +(assert_return (invoke "as-call-first" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call-mid" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call-last" (i32.const 0)) (i32.const -1)) + +(assert_return (invoke "as-call_indirect-first" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call_indirect-mid" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call_indirect-last" (i32.const 0)) (i32.const -1)) +(assert_return (invoke "as-call_indirect-index" (i32.const 0)) (i32.const -1)) + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-global.set-value")) + +(assert_return (invoke "as-load-address" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-loadN-address" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-store-address" (i32.const 0))) +(assert_return (invoke "as-store-value" (i32.const 0))) +(assert_return (invoke "as-storeN-address" (i32.const 0))) +(assert_return (invoke "as-storeN-value" (i32.const 0))) + +(assert_return (invoke "as-unary-operand" (f32.const 0)) (f32.const -nan:0x0f1e2)) +(assert_return (invoke "as-binary-left" (i32.const 0)) (i32.const 13)) +(assert_return (invoke "as-binary-right" (i32.const 0)) (i32.const 6)) +(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-compare-left" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-compare-right" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-convert-operand" (i64.const 0)) (i32.const 41)) +(assert_return (invoke "as-memory.grow-size" (i32.const 0)) (i32.const 1)) + +(assert_return + (invoke "type-mixed" + (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) +) + +(assert_return + (invoke "write" + (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) + (i64.const 56) +) + +(assert_return + (invoke "result" + (i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5) + ) + (f64.const 34.8) +) + + +;; Invalid typing of access to locals + +(assert_invalid + (module (func $type-local-num-vs-num (result i64) (local i32) (local.tee 0 (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f32) (i32.eqz (local.tee 0 (f32.const 0))))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (local.tee 1 (i64.const 0))))) + "type mismatch" +) + +(assert_invalid + (module (func $type-local-arg-void-vs-num (local i32) (local.tee 0 (nop)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local i32) (local.tee 0 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local f32) (local.tee 0 (f64.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local f64 i64) (local.tee 1 (f64.const 0)))) + "type mismatch" +) + + +;; Invalid typing of access to parameters + +(assert_invalid + (module (func $type-param-num-vs-num (param i32) (result i64) (local.get 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f32) (i32.eqz (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (local.get 1)))) + "type mismatch" +) + +(assert_invalid + (module (func $type-param-arg-void-vs-num (param i32) (local.tee 0 (nop)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param i32) (local.tee 0 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param f32) (local.tee 0 (f64.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param f64 i64) (local.tee 1 (f64.const 0)))) + "type mismatch" +) + +(assert_invalid + (module + (func $type-param-arg-empty-vs-num (param i32) + (local.tee 0) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-block (param i32) + (i32.const 0) + (block (local.tee 0) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-loop (param i32) + (i32.const 0) + (loop (local.tee 0) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-then (param i32) + (i32.const 0) (i32.const 0) + (if (then (local.tee 0) (drop))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-else (param i32) + (i32.const 0) (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (local.tee 0))) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-br (param i32) + (i32.const 0) + (block (br 0 (local.tee 0)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-br_if (param i32) + (i32.const 0) + (block (br_if 0 (local.tee 0) (i32.const 1)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-br_table (param i32) + (i32.const 0) + (block (br_table 0 (local.tee 0)) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-return (param i32) + (return (local.tee 0)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-select (param i32) + (select (local.tee 0) (i32.const 1) (i32.const 2)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-call (param i32) + (call 1 (local.tee 0)) (drop) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-param-arg-empty-vs-num-in-call_indirect (param i32) + (block (result i32) + (call_indirect (type $sig) + (local.tee 0) (i32.const 0) + ) + (drop) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-local.set (param i32) + (local.set 0 (local.tee 0)) (local.get 0) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-param-arg-empty-vs-num-in-local.tee (param i32) + (local.tee 0 (local.tee 0)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (global $x (mut i32) (i32.const 0)) + (func $type-param-arg-empty-vs-num-in-global.set (param i32) + (global.set $x (local.tee 0)) (global.get $x) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-param-arg-empty-vs-num-in-memory.grow (param i32) + (memory.grow (local.tee 0)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-param-arg-empty-vs-num-in-load (param i32) + (i32.load (local.tee 0)) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-param-arg-empty-vs-num-in-store (param i32) + (i32.store (local.tee 0) (i32.const 1)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (local.tee 1 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (local.tee 1 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (local.tee 1 (i64.const 0)))) + "type mismatch" +) + +;; https://github.com/WebAssembly/gc/issues/516 +(assert_invalid + (module + (type $t (func)) + (func $f (param (ref null $t))) + (func + (local $x funcref) + (ref.null $t) + (local.tee $x) ;; leaves only a funcref on the stack + (call $f) + ) + ) + "type mismatch" +) + + +;; Invalid local index + +(assert_invalid + (module (func $unbound-local (local i32 i64) (local.tee 3 (i32.const 0)) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-local (local i32 i64) (local.tee 14324343 (i32.const 0)) drop)) + "unknown local" +) + +(assert_invalid + (module (func $unbound-param (param i32 i64) (local.tee 2 (i32.const 0)) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-param (param i32 i64) (local.tee 714324343 (i32.const 0)) drop)) + "unknown local" +) + +(assert_invalid + (module (func $unbound-mixed (param i32) (local i32 i64) (local.tee 3 (i32.const 0)) drop)) + "unknown local" +) +(assert_invalid + (module (func $large-mixed (param i64) (local i32 i64) (local.tee 214324343 (i32.const 0)) drop)) + "unknown local" +) diff --git a/proposals/wasm-3.0/memory-multi.wast b/proposals/wasm-3.0/memory-multi.wast new file mode 100644 index 0000000..b5b71fd --- /dev/null +++ b/proposals/wasm-3.0/memory-multi.wast @@ -0,0 +1,42 @@ +;; From wasmtime misc_testsuite/multi-memory/simple.wast + +;; Should be replaced with suitable extensions to ../meta/generate_memory_*.js + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "init1") (result i32) + (memory.init $mem1 $d (i32.const 1) (i32.const 0) (i32.const 4)) + (i32.load $mem1 (i32.const 1)) + ) + + (func (export "init2") (result i32) + (memory.init $mem2 $d (i32.const 1) (i32.const 4) (i32.const 4)) + (i32.load $mem2 (i32.const 1)) + ) + + (data $d "\01\00\00\00" "\02\00\00\00") +) + +(assert_return (invoke "init1") (i32.const 1)) +(assert_return (invoke "init2") (i32.const 2)) + + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "fill1") (result i32) + (memory.fill $mem1 (i32.const 1) (i32.const 0x01) (i32.const 4)) + (i32.load $mem1 (i32.const 1)) + ) + + (func (export "fill2") (result i32) + (memory.fill $mem2 (i32.const 1) (i32.const 0x02) (i32.const 2)) + (i32.load $mem2 (i32.const 1)) + ) +) + +(assert_return (invoke "fill1") (i32.const 0x01010101)) +(assert_return (invoke "fill2") (i32.const 0x0202)) diff --git a/proposals/wasm-3.0/memory.wast b/proposals/wasm-3.0/memory.wast new file mode 100644 index 0000000..e01170a --- /dev/null +++ b/proposals/wasm-3.0/memory.wast @@ -0,0 +1,277 @@ +;; Test memory section structure + +(module (memory 0)) +(module (memory 1)) +(module (memory 0 0)) +(module (memory 0 1)) +(module (memory 1 256)) +(module (memory 0 65536)) + +(module (memory (data)) (func (export "memsize") (result i32) (memory.size))) +(assert_return (invoke "memsize") (i32.const 0)) +(module (memory (data "")) (func (export "memsize") (result i32) (memory.size))) +(assert_return (invoke "memsize") (i32.const 0)) +(module (memory (data "x")) (func (export "memsize") (result i32) (memory.size))) +(assert_return (invoke "memsize") (i32.const 1)) + +(assert_invalid (module (data (i32.const 0))) "unknown memory") +(assert_invalid (module (data (i32.const 0) "")) "unknown memory") +(assert_invalid (module (data (i32.const 0) "x")) "unknown memory") + +(assert_invalid + (module (func (drop (f32.load (i32.const 0))))) + "unknown memory" +) +(assert_invalid + (module (func (f32.store (i32.const 0) (f32.const 0)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (i32.load8_s (i32.const 0))))) + "unknown memory" +) +(assert_invalid + (module (func (i32.store8 (i32.const 0) (i32.const 0)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (memory.size)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (memory.grow (i32.const 0))))) + "unknown memory" +) + + +(assert_invalid + (module (memory 1 0)) + "size minimum must not be greater than maximum" +) +(assert_invalid + (module (memory 65537)) + "memory size" +) +(assert_invalid + (module (memory 2147483648)) + "memory size" +) +(assert_invalid + (module (memory 4294967295)) + "memory size" +) +(assert_invalid + (module (memory 0 65537)) + "memory size" +) +(assert_invalid + (module (memory 0 2147483648)) + "memory size" +) +(assert_invalid + (module (memory 0 4294967295)) + "memory size" +) + +(assert_invalid + (module (memory 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory 0x1_0000_0000 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory 0 0x1_0000_0000)) + "memory size" +) + +(assert_invalid + (module (memory (import "M" "m") 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") 0x1_0000_0000 0x1_0000_0000)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") 0 0x1_0000_0000)) + "memory size" +) + +(module + (memory 1) + (data (i32.const 0) "ABC\a7D") (data (i32.const 20) "WASM") + + ;; Data section + (func (export "data") (result i32) + (i32.and + (i32.and + (i32.and + (i32.eq (i32.load8_u (i32.const 0)) (i32.const 65)) + (i32.eq (i32.load8_u (i32.const 3)) (i32.const 167)) + ) + (i32.and + (i32.eq (i32.load8_u (i32.const 6)) (i32.const 0)) + (i32.eq (i32.load8_u (i32.const 19)) (i32.const 0)) + ) + ) + (i32.and + (i32.and + (i32.eq (i32.load8_u (i32.const 20)) (i32.const 87)) + (i32.eq (i32.load8_u (i32.const 23)) (i32.const 77)) + ) + (i32.and + (i32.eq (i32.load8_u (i32.const 24)) (i32.const 0)) + (i32.eq (i32.load8_u (i32.const 1023)) (i32.const 0)) + ) + ) + ) + ) + + ;; Memory cast + (func (export "cast") (result f64) + (i64.store (i32.const 8) (i64.const -12345)) + (if + (f64.eq + (f64.load (i32.const 8)) + (f64.reinterpret_i64 (i64.const -12345)) + ) + (then (return (f64.const 0))) + ) + (i64.store align=1 (i32.const 9) (i64.const 0)) + (i32.store16 align=1 (i32.const 15) (i32.const 16453)) + (f64.load align=1 (i32.const 9)) + ) + + ;; Sign and zero extending memory loads + (func (export "i32_load8_s") (param $i i32) (result i32) + (i32.store8 (i32.const 8) (local.get $i)) + (i32.load8_s (i32.const 8)) + ) + (func (export "i32_load8_u") (param $i i32) (result i32) + (i32.store8 (i32.const 8) (local.get $i)) + (i32.load8_u (i32.const 8)) + ) + (func (export "i32_load16_s") (param $i i32) (result i32) + (i32.store16 (i32.const 8) (local.get $i)) + (i32.load16_s (i32.const 8)) + ) + (func (export "i32_load16_u") (param $i i32) (result i32) + (i32.store16 (i32.const 8) (local.get $i)) + (i32.load16_u (i32.const 8)) + ) + (func (export "i64_load8_s") (param $i i64) (result i64) + (i64.store8 (i32.const 8) (local.get $i)) + (i64.load8_s (i32.const 8)) + ) + (func (export "i64_load8_u") (param $i i64) (result i64) + (i64.store8 (i32.const 8) (local.get $i)) + (i64.load8_u (i32.const 8)) + ) + (func (export "i64_load16_s") (param $i i64) (result i64) + (i64.store16 (i32.const 8) (local.get $i)) + (i64.load16_s (i32.const 8)) + ) + (func (export "i64_load16_u") (param $i i64) (result i64) + (i64.store16 (i32.const 8) (local.get $i)) + (i64.load16_u (i32.const 8)) + ) + (func (export "i64_load32_s") (param $i i64) (result i64) + (i64.store32 (i32.const 8) (local.get $i)) + (i64.load32_s (i32.const 8)) + ) + (func (export "i64_load32_u") (param $i i64) (result i64) + (i64.store32 (i32.const 8) (local.get $i)) + (i64.load32_u (i32.const 8)) + ) +) + +(assert_return (invoke "data") (i32.const 1)) +(assert_return (invoke "cast") (f64.const 42.0)) + +(assert_return (invoke "i32_load8_s" (i32.const -1)) (i32.const -1)) +(assert_return (invoke "i32_load8_u" (i32.const -1)) (i32.const 255)) +(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1)) +(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 65535)) + +(assert_return (invoke "i32_load8_s" (i32.const 100)) (i32.const 100)) +(assert_return (invoke "i32_load8_u" (i32.const 200)) (i32.const 200)) +(assert_return (invoke "i32_load16_s" (i32.const 20000)) (i32.const 20000)) +(assert_return (invoke "i32_load16_u" (i32.const 40000)) (i32.const 40000)) + +(assert_return (invoke "i32_load8_s" (i32.const 0xfedc6543)) (i32.const 0x43)) +(assert_return (invoke "i32_load8_s" (i32.const 0x3456cdef)) (i32.const 0xffffffef)) +(assert_return (invoke "i32_load8_u" (i32.const 0xfedc6543)) (i32.const 0x43)) +(assert_return (invoke "i32_load8_u" (i32.const 0x3456cdef)) (i32.const 0xef)) +(assert_return (invoke "i32_load16_s" (i32.const 0xfedc6543)) (i32.const 0x6543)) +(assert_return (invoke "i32_load16_s" (i32.const 0x3456cdef)) (i32.const 0xffffcdef)) +(assert_return (invoke "i32_load16_u" (i32.const 0xfedc6543)) (i32.const 0x6543)) +(assert_return (invoke "i32_load16_u" (i32.const 0x3456cdef)) (i32.const 0xcdef)) + +(assert_return (invoke "i64_load8_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load8_u" (i64.const -1)) (i64.const 255)) +(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 65535)) +(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 4294967295)) + +(assert_return (invoke "i64_load8_s" (i64.const 100)) (i64.const 100)) +(assert_return (invoke "i64_load8_u" (i64.const 200)) (i64.const 200)) +(assert_return (invoke "i64_load16_s" (i64.const 20000)) (i64.const 20000)) +(assert_return (invoke "i64_load16_u" (i64.const 40000)) (i64.const 40000)) +(assert_return (invoke "i64_load32_s" (i64.const 20000)) (i64.const 20000)) +(assert_return (invoke "i64_load32_u" (i64.const 40000)) (i64.const 40000)) + +(assert_return (invoke "i64_load8_s" (i64.const 0xfedcba9856346543)) (i64.const 0x43)) +(assert_return (invoke "i64_load8_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffffef)) +(assert_return (invoke "i64_load8_u" (i64.const 0xfedcba9856346543)) (i64.const 0x43)) +(assert_return (invoke "i64_load8_u" (i64.const 0x3456436598bacdef)) (i64.const 0xef)) +(assert_return (invoke "i64_load16_s" (i64.const 0xfedcba9856346543)) (i64.const 0x6543)) +(assert_return (invoke "i64_load16_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffcdef)) +(assert_return (invoke "i64_load16_u" (i64.const 0xfedcba9856346543)) (i64.const 0x6543)) +(assert_return (invoke "i64_load16_u" (i64.const 0x3456436598bacdef)) (i64.const 0xcdef)) +(assert_return (invoke "i64_load32_s" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543)) +(assert_return (invoke "i64_load32_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffff98bacdef)) +(assert_return (invoke "i64_load32_u" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543)) +(assert_return (invoke "i64_load32_u" (i64.const 0x3456436598bacdef)) (i64.const 0x98bacdef)) + +;; Duplicate identifier errors + +(assert_malformed (module quote + "(memory $foo 1)" + "(memory $foo 1)") + "duplicate memory") +(assert_malformed (module quote + "(import \"\" \"\" (memory $foo 1))" + "(memory $foo 1)") + "duplicate memory") +(assert_malformed (module quote + "(import \"\" \"\" (memory $foo 1))" + "(import \"\" \"\" (memory $foo 1))") + "duplicate memory") + +;; Test that exporting random globals does not change a memory's semantics. + +(module + (memory (export "memory") 1 1) + + ;; These should not change the behavior of memory accesses. + (global (export "__data_end") i32 (i32.const 10000)) + (global (export "__stack_top") i32 (i32.const 10000)) + (global (export "__heap_base") i32 (i32.const 10000)) + + (func (export "load") (param i32) (result i32) + (i32.load8_u (local.get 0)) + ) +) + +;; None of these memory accesses should trap. +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 20000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 30000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 40000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 50000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 60000)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 65535)) (i32.const 0)) diff --git a/proposals/wasm-3.0/memory64.wast b/proposals/wasm-3.0/memory64.wast new file mode 100644 index 0000000..ba3b242 --- /dev/null +++ b/proposals/wasm-3.0/memory64.wast @@ -0,0 +1,204 @@ +;; Test memory section structure +;; Largely duplicated from memory, but with all memories using a 64-bit index. + +(module (memory i64 0 0)) +(module (memory i64 0 1)) +(module (memory i64 1 256)) +(module (memory i64 0 65536)) + +(module (memory i64 (data)) (func (export "memsize") (result i64) (memory.size))) +(assert_return (invoke "memsize") (i64.const 0)) +(module (memory i64 (data "")) (func (export "memsize") (result i64) (memory.size))) +(assert_return (invoke "memsize") (i64.const 0)) +(module (memory i64 (data "x")) (func (export "memsize") (result i64) (memory.size))) +(assert_return (invoke "memsize") (i64.const 1)) + +(assert_invalid (module (data (i64.const 0))) "unknown memory") +(assert_invalid (module (data (i64.const 0) "")) "unknown memory") +(assert_invalid (module (data (i64.const 0) "x")) "unknown memory") + +(assert_invalid + (module (func (drop (f32.load (i64.const 0))))) + "unknown memory" +) +(assert_invalid + (module (func (f32.store (i64.const 0) (f32.const 0)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (i32.load8_s (i64.const 0))))) + "unknown memory" +) +(assert_invalid + (module (func (i32.store8 (i64.const 0) (i32.const 0)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (memory.size)))) + "unknown memory" +) +(assert_invalid + (module (func (drop (memory.grow (i64.const 0))))) + "unknown memory" +) + + +(assert_invalid + (module (memory i64 1 0)) + "size minimum must not be greater than maximum" +) + +(assert_invalid + (module (memory i64 0x1_0000_0000_0001)) + "memory size" +) +(assert_invalid + (module (memory i64 0 0x1_0000_0000_0001)) + "memory size" +) + +(assert_invalid + (module (memory (import "M" "m") i64 0x1_0000_0000_0001)) + "memory size" +) +(assert_invalid + (module (memory (import "M" "m") i64 0 0x1_0000_0000_0001)) + "memory size" +) + +(module + (memory i64 1) + (data (i64.const 0) "ABC\a7D") (data (i64.const 20) "WASM") + + ;; Data section + (func (export "data") (result i32) + (i32.and + (i32.and + (i32.and + (i32.eq (i32.load8_u (i64.const 0)) (i32.const 65)) + (i32.eq (i32.load8_u (i64.const 3)) (i32.const 167)) + ) + (i32.and + (i32.eq (i32.load8_u (i64.const 6)) (i32.const 0)) + (i32.eq (i32.load8_u (i64.const 19)) (i32.const 0)) + ) + ) + (i32.and + (i32.and + (i32.eq (i32.load8_u (i64.const 20)) (i32.const 87)) + (i32.eq (i32.load8_u (i64.const 23)) (i32.const 77)) + ) + (i32.and + (i32.eq (i32.load8_u (i64.const 24)) (i32.const 0)) + (i32.eq (i32.load8_u (i64.const 1023)) (i32.const 0)) + ) + ) + ) + ) + + ;; Memory cast + (func (export "cast") (result f64) + (i64.store (i64.const 8) (i64.const -12345)) + (if + (f64.eq + (f64.load (i64.const 8)) + (f64.reinterpret_i64 (i64.const -12345)) + ) + (then (return (f64.const 0))) + ) + (i64.store align=1 (i64.const 9) (i64.const 0)) + (i32.store16 align=1 (i64.const 15) (i32.const 16453)) + (f64.load align=1 (i64.const 9)) + ) + + ;; Sign and zero extending memory loads + (func (export "i32_load8_s") (param $i i32) (result i32) + (i32.store8 (i64.const 8) (local.get $i)) + (i32.load8_s (i64.const 8)) + ) + (func (export "i32_load8_u") (param $i i32) (result i32) + (i32.store8 (i64.const 8) (local.get $i)) + (i32.load8_u (i64.const 8)) + ) + (func (export "i32_load16_s") (param $i i32) (result i32) + (i32.store16 (i64.const 8) (local.get $i)) + (i32.load16_s (i64.const 8)) + ) + (func (export "i32_load16_u") (param $i i32) (result i32) + (i32.store16 (i64.const 8) (local.get $i)) + (i32.load16_u (i64.const 8)) + ) + (func (export "i64_load8_s") (param $i i64) (result i64) + (i64.store8 (i64.const 8) (local.get $i)) + (i64.load8_s (i64.const 8)) + ) + (func (export "i64_load8_u") (param $i i64) (result i64) + (i64.store8 (i64.const 8) (local.get $i)) + (i64.load8_u (i64.const 8)) + ) + (func (export "i64_load16_s") (param $i i64) (result i64) + (i64.store16 (i64.const 8) (local.get $i)) + (i64.load16_s (i64.const 8)) + ) + (func (export "i64_load16_u") (param $i i64) (result i64) + (i64.store16 (i64.const 8) (local.get $i)) + (i64.load16_u (i64.const 8)) + ) + (func (export "i64_load32_s") (param $i i64) (result i64) + (i64.store32 (i64.const 8) (local.get $i)) + (i64.load32_s (i64.const 8)) + ) + (func (export "i64_load32_u") (param $i i64) (result i64) + (i64.store32 (i64.const 8) (local.get $i)) + (i64.load32_u (i64.const 8)) + ) +) + +(assert_return (invoke "data") (i32.const 1)) +(assert_return (invoke "cast") (f64.const 42.0)) + +(assert_return (invoke "i32_load8_s" (i32.const -1)) (i32.const -1)) +(assert_return (invoke "i32_load8_u" (i32.const -1)) (i32.const 255)) +(assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1)) +(assert_return (invoke "i32_load16_u" (i32.const -1)) (i32.const 65535)) + +(assert_return (invoke "i32_load8_s" (i32.const 100)) (i32.const 100)) +(assert_return (invoke "i32_load8_u" (i32.const 200)) (i32.const 200)) +(assert_return (invoke "i32_load16_s" (i32.const 20000)) (i32.const 20000)) +(assert_return (invoke "i32_load16_u" (i32.const 40000)) (i32.const 40000)) + +(assert_return (invoke "i32_load8_s" (i32.const 0xfedc6543)) (i32.const 0x43)) +(assert_return (invoke "i32_load8_s" (i32.const 0x3456cdef)) (i32.const 0xffffffef)) +(assert_return (invoke "i32_load8_u" (i32.const 0xfedc6543)) (i32.const 0x43)) +(assert_return (invoke "i32_load8_u" (i32.const 0x3456cdef)) (i32.const 0xef)) +(assert_return (invoke "i32_load16_s" (i32.const 0xfedc6543)) (i32.const 0x6543)) +(assert_return (invoke "i32_load16_s" (i32.const 0x3456cdef)) (i32.const 0xffffcdef)) +(assert_return (invoke "i32_load16_u" (i32.const 0xfedc6543)) (i32.const 0x6543)) +(assert_return (invoke "i32_load16_u" (i32.const 0x3456cdef)) (i32.const 0xcdef)) + +(assert_return (invoke "i64_load8_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load8_u" (i64.const -1)) (i64.const 255)) +(assert_return (invoke "i64_load16_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load16_u" (i64.const -1)) (i64.const 65535)) +(assert_return (invoke "i64_load32_s" (i64.const -1)) (i64.const -1)) +(assert_return (invoke "i64_load32_u" (i64.const -1)) (i64.const 4294967295)) + +(assert_return (invoke "i64_load8_s" (i64.const 100)) (i64.const 100)) +(assert_return (invoke "i64_load8_u" (i64.const 200)) (i64.const 200)) +(assert_return (invoke "i64_load16_s" (i64.const 20000)) (i64.const 20000)) +(assert_return (invoke "i64_load16_u" (i64.const 40000)) (i64.const 40000)) +(assert_return (invoke "i64_load32_s" (i64.const 20000)) (i64.const 20000)) +(assert_return (invoke "i64_load32_u" (i64.const 40000)) (i64.const 40000)) + +(assert_return (invoke "i64_load8_s" (i64.const 0xfedcba9856346543)) (i64.const 0x43)) +(assert_return (invoke "i64_load8_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffffef)) +(assert_return (invoke "i64_load8_u" (i64.const 0xfedcba9856346543)) (i64.const 0x43)) +(assert_return (invoke "i64_load8_u" (i64.const 0x3456436598bacdef)) (i64.const 0xef)) +(assert_return (invoke "i64_load16_s" (i64.const 0xfedcba9856346543)) (i64.const 0x6543)) +(assert_return (invoke "i64_load16_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffffffffcdef)) +(assert_return (invoke "i64_load16_u" (i64.const 0xfedcba9856346543)) (i64.const 0x6543)) +(assert_return (invoke "i64_load16_u" (i64.const 0x3456436598bacdef)) (i64.const 0xcdef)) +(assert_return (invoke "i64_load32_s" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543)) +(assert_return (invoke "i64_load32_s" (i64.const 0x3456436598bacdef)) (i64.const 0xffffffff98bacdef)) +(assert_return (invoke "i64_load32_u" (i64.const 0xfedcba9856346543)) (i64.const 0x56346543)) +(assert_return (invoke "i64_load32_u" (i64.const 0x3456436598bacdef)) (i64.const 0x98bacdef)) diff --git a/proposals/memory64/memory_copy.wast b/proposals/wasm-3.0/memory_copy.wast similarity index 100% rename from proposals/memory64/memory_copy.wast rename to proposals/wasm-3.0/memory_copy.wast diff --git a/proposals/wasm-3.0/memory_copy0.wast b/proposals/wasm-3.0/memory_copy0.wast new file mode 100644 index 0000000..5a5d910 --- /dev/null +++ b/proposals/wasm-3.0/memory_copy0.wast @@ -0,0 +1,60 @@ +;; memory.copy +(module + (memory $mem0 (data "\ff\11\44\ee")) + (memory $mem1 (data "\ee\22\55\ff")) + (memory $mem2 (data "\dd\33\66\00")) + (memory $mem3 (data "\aa\bb\cc\dd")) + + (func (export "copy") (param i32 i32 i32) + (memory.copy $mem3 $mem3 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem3 (local.get 0))) +) + +;; Non-overlapping copy. +(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) + +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) + +;; Overlap, source > dest +(invoke "copy" (i32.const 8) (i32.const 10) (i32.const 4)) +(assert_return (invoke "load8_u" (i32.const 8)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) + +;; Overlap, source < dest +(invoke "copy" (i32.const 10) (i32.const 7) (i32.const 6)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 15)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 16)) (i32.const 0)) + +;; Copy ending at memory limit is ok. +(invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) +(invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) + +;; Succeed when copying 0 bytes at the end of the region. +(invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) + +;; Copying 0 bytes outside the memory traps. +(assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) + "out of bounds memory access") + diff --git a/proposals/wasm-3.0/memory_copy1.wast b/proposals/wasm-3.0/memory_copy1.wast new file mode 100644 index 0000000..df9165f --- /dev/null +++ b/proposals/wasm-3.0/memory_copy1.wast @@ -0,0 +1,40 @@ +;; test memory.copy across different memories. +(module + (memory $mem0 (data "\ff\11\44\ee")) + (memory $mem1 (data "\ee\22\55\ff")) + (memory $mem2 (data "\dd\33\66\00")) + (memory $mem3 (data "\aa\bb\cc\dd")) + + (func (export "copy") (param i32 i32 i32) + (memory.copy $mem0 $mem3 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem0 (local.get 0))) +) + +;; Non-overlapping copy. +(invoke "copy" (i32.const 10) (i32.const 0) (i32.const 4)) + +(assert_return (invoke "load8_u" (i32.const 9)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 10)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 11)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 12)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 13)) (i32.const 0xdd)) +(assert_return (invoke "load8_u" (i32.const 14)) (i32.const 0)) + +;; Copy ending at memory limit is ok. +(invoke "copy" (i32.const 0xff00) (i32.const 0) (i32.const 0x100)) +(invoke "copy" (i32.const 0xfe00) (i32.const 0xff00) (i32.const 0x100)) + +;; Succeed when copying 0 bytes at the end of the region. +(invoke "copy" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "copy" (i32.const 0) (i32.const 0x10000) (i32.const 0)) + +;; Copying 0 bytes outside the memory traps. +(assert_trap (invoke "copy" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "copy" (i32.const 0) (i32.const 0x10001) (i32.const 0)) + "out of bounds memory access") diff --git a/proposals/memory64/memory_fill.wast b/proposals/wasm-3.0/memory_fill.wast similarity index 100% rename from proposals/memory64/memory_fill.wast rename to proposals/wasm-3.0/memory_fill.wast diff --git a/proposals/wasm-3.0/memory_fill0.wast b/proposals/wasm-3.0/memory_fill0.wast new file mode 100644 index 0000000..eaf15bf --- /dev/null +++ b/proposals/wasm-3.0/memory_fill0.wast @@ -0,0 +1,46 @@ +;; memory.fill +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 1) + + (func (export "fill") (param i32 i32 i32) + (memory.fill $mem2 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0))) +) + +;; Basic fill test. +(invoke "fill" (i32.const 1) (i32.const 0xff) (i32.const 3)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 3)) (i32.const 0xff)) +(assert_return (invoke "load8_u" (i32.const 4)) (i32.const 0)) + +;; Fill value is stored as a byte. +(invoke "fill" (i32.const 0) (i32.const 0xbbaa) (i32.const 2)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xaa)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xaa)) + +;; Fill all of memory +(invoke "fill" (i32.const 0) (i32.const 0) (i32.const 0x10000)) + +;; Out-of-bounds writes trap, and nothing is written +(assert_trap (invoke "fill" (i32.const 0xff00) (i32.const 1) (i32.const 0x101)) + "out of bounds memory access") +(assert_return (invoke "load8_u" (i32.const 0xff00)) (i32.const 0)) +(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0)) + +;; Succeed when writing 0 bytes at the end of the region. +(invoke "fill" (i32.const 0x10000) (i32.const 0) (i32.const 0)) + +;; Writing 0 bytes outside the memory traps. +(assert_trap (invoke "fill" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") + + diff --git a/proposals/wasm-3.0/memory_grow.wast b/proposals/wasm-3.0/memory_grow.wast new file mode 100644 index 0000000..195ef66 --- /dev/null +++ b/proposals/wasm-3.0/memory_grow.wast @@ -0,0 +1,535 @@ +(module + (memory 0) + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) +) + +(assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 800)) (i32.const 3)) +(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 64736)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 803)) + +(module + (memory 0 10) + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) +) + +(assert_return (invoke "grow" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 2)) (i32.const 2)) +(assert_return (invoke "grow" (i32.const 6)) (i32.const 4)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 10)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 0x10000)) (i32.const -1)) + + +;; Test that newly allocated memory (program start and memory.grow) is zeroed + +(module + (memory 1) + (func (export "grow") (param i32) (result i32) + (memory.grow (local.get 0)) + ) + (func (export "check-memory-zero") (param i32 i32) (result i32) + (local i32) + (local.set 2 (i32.const 1)) + (block + (loop + (local.set 2 (i32.load8_u (local.get 0))) + (br_if 1 (i32.ne (local.get 2) (i32.const 0))) + (br_if 1 (i32.ge_u (local.get 0) (local.get 1))) + (local.set 0 (i32.add (local.get 0) (i32.const 1))) + (br_if 0 (i32.le_u (local.get 0) (local.get 1))) + ) + ) + (local.get 2) + ) +) + +(assert_return (invoke "check-memory-zero" (i32.const 0) (i32.const 0xffff)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "check-memory-zero" (i32.const 0x10000) (i32.const 0x1_ffff)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "check-memory-zero" (i32.const 0x20000) (i32.const 0x2_ffff)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 3)) +(assert_return (invoke "check-memory-zero" (i32.const 0x30000) (i32.const 0x3_ffff)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 4)) +(assert_return (invoke "check-memory-zero" (i32.const 0x40000) (i32.const 0x4_ffff)) (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 5)) +(assert_return (invoke "check-memory-zero" (i32.const 0x50000) (i32.const 0x5_ffff)) (i32.const 0)) + + +;; Memory access at boundary + +(module + (memory 0) + + (func (export "load_at_zero") (result i32) (i32.load (i32.const 0))) + (func (export "store_at_zero") (i32.store (i32.const 0) (i32.const 2))) + + (func (export "load_at_page_size") (result i32) + (i32.load (i32.const 0x10000)) + ) + (func (export "store_at_page_size") + (i32.store (i32.const 0x10000) (i32.const 3)) + ) + + (func (export "grow") (param i32) (result i32) (memory.grow (local.get 0))) + (func (export "size") (result i32) (memory.size)) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_trap (invoke "store_at_zero") "out of bounds memory access") +(assert_trap (invoke "load_at_zero") "out of bounds memory access") +(assert_trap (invoke "store_at_page_size") "out of bounds memory access") +(assert_trap (invoke "load_at_page_size") "out of bounds memory access") +(assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "load_at_zero") (i32.const 0)) +(assert_return (invoke "store_at_zero")) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_trap (invoke "store_at_page_size") "out of bounds memory access") +(assert_trap (invoke "load_at_page_size") "out of bounds memory access") +(assert_return (invoke "grow" (i32.const 4)) (i32.const 1)) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_return (invoke "store_at_zero")) +(assert_return (invoke "load_at_zero") (i32.const 2)) +(assert_return (invoke "load_at_page_size") (i32.const 0)) +(assert_return (invoke "store_at_page_size")) +(assert_return (invoke "load_at_page_size") (i32.const 3)) + + +;; Multiple memories + +(module + (memory (export "mem1") 2 5) + (memory (export "mem2") 0) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem1") 1 6) + (memory $mem2 (import "M" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) + (func (export "size3") (result i32) (memory.size $mem3)) + (func (export "size4") (result i32) (memory.size $mem4)) + + (func (export "grow1") (param i32) (result i32) + (memory.grow $mem1 (local.get 0)) + ) + (func (export "grow2") (param i32) (result i32) + (memory.grow $mem2 (local.get 0)) + ) + (func (export "grow3") (param i32) (result i32) + (memory.grow $mem3 (local.get 0)) + ) + (func (export "grow4") (param i32) (result i32) + (memory.grow $mem4 (local.get 0)) + ) +) + +(assert_return (invoke "size1") (i32.const 2)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "size1") (i32.const 3)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 2)) (i32.const 3)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow1" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow2" (i32.const 10)) (i32.const 0)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow3" (i32.const 0x1000_0000)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow3" (i32.const 3)) (i32.const 3)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 6)) +(assert_return (invoke "size4") (i32.const 4)) + +(assert_return (invoke "grow4" (i32.const 1)) (i32.const 4)) +(assert_return (invoke "grow4" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "size1") (i32.const 5)) +(assert_return (invoke "size2") (i32.const 10)) +(assert_return (invoke "size3") (i32.const 6)) +(assert_return (invoke "size4") (i32.const 5)) + + +;; As the argument of control constructs and instructions + +(module + (memory 1) + + (func (export "as-br-value") (result i32) + (block (result i32) (br 0 (memory.grow (i32.const 0)))) + ) + + (func (export "as-br_if-cond") + (block (br_if 0 (memory.grow (i32.const 0)))) + ) + (func (export "as-br_if-value") (result i32) + (block (result i32) + (drop (br_if 0 (memory.grow (i32.const 0)) (i32.const 1))) (i32.const 7) + ) + ) + (func (export "as-br_if-value-cond") (result i32) + (block (result i32) + (drop (br_if 0 (i32.const 6) (memory.grow (i32.const 0)))) (i32.const 7) + ) + ) + + (func (export "as-br_table-index") + (block (br_table 0 0 0 (memory.grow (i32.const 0)))) + ) + (func (export "as-br_table-value") (result i32) + (block (result i32) + (br_table 0 0 0 (memory.grow (i32.const 0)) (i32.const 1)) (i32.const 7) + ) + ) + (func (export "as-br_table-value-index") (result i32) + (block (result i32) + (br_table 0 0 (i32.const 6) (memory.grow (i32.const 0))) (i32.const 7) + ) + ) + + (func (export "as-return-value") (result i32) + (return (memory.grow (i32.const 0))) + ) + + (func (export "as-if-cond") (result i32) + (if (result i32) (memory.grow (i32.const 0)) + (then (i32.const 0)) (else (i32.const 1)) + ) + ) + (func (export "as-if-then") (result i32) + (if (result i32) (i32.const 1) + (then (memory.grow (i32.const 0))) (else (i32.const 0)) + ) + ) + (func (export "as-if-else") (result i32) + (if (result i32) (i32.const 0) + (then (i32.const 0)) (else (memory.grow (i32.const 0))) + ) + ) + + (func (export "as-select-first") (param i32 i32) (result i32) + (select (memory.grow (i32.const 0)) (local.get 0) (local.get 1)) + ) + (func (export "as-select-second") (param i32 i32) (result i32) + (select (local.get 0) (memory.grow (i32.const 0)) (local.get 1)) + ) + (func (export "as-select-cond") (result i32) + (select (i32.const 0) (i32.const 1) (memory.grow (i32.const 0))) + ) + + (func $f (param i32 i32 i32) (result i32) (i32.const -1)) + (func (export "as-call-first") (result i32) + (call $f (memory.grow (i32.const 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-call-mid") (result i32) + (call $f (i32.const 1) (memory.grow (i32.const 0)) (i32.const 3)) + ) + (func (export "as-call-last") (result i32) + (call $f (i32.const 1) (i32.const 2) (memory.grow (i32.const 0))) + ) + + (type $sig (func (param i32 i32 i32) (result i32))) + (table funcref (elem $f)) + (func (export "as-call_indirect-first") (result i32) + (call_indirect (type $sig) + (memory.grow (i32.const 0)) (i32.const 2) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-mid") (result i32) + (call_indirect (type $sig) + (i32.const 1) (memory.grow (i32.const 0)) (i32.const 3) (i32.const 0) + ) + ) + (func (export "as-call_indirect-last") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (memory.grow (i32.const 0)) (i32.const 0) + ) + ) + (func (export "as-call_indirect-index") (result i32) + (call_indirect (type $sig) + (i32.const 1) (i32.const 2) (i32.const 3) (memory.grow (i32.const 0)) + ) + ) + + (func (export "as-local.set-value") (local i32) + (local.set 0 (memory.grow (i32.const 0))) + ) + (func (export "as-local.tee-value") (result i32) (local i32) + (local.tee 0 (memory.grow (i32.const 0))) + ) + (global $g (mut i32) (i32.const 0)) + (func (export "as-global.set-value") (local i32) + (global.set $g (memory.grow (i32.const 0))) + ) + + (func (export "as-load-address") (result i32) + (i32.load (memory.grow (i32.const 0))) + ) + (func (export "as-loadN-address") (result i32) + (i32.load8_s (memory.grow (i32.const 0))) + ) + + (func (export "as-store-address") + (i32.store (memory.grow (i32.const 0)) (i32.const 7)) + ) + (func (export "as-store-value") + (i32.store (i32.const 2) (memory.grow (i32.const 0))) + ) + + (func (export "as-storeN-address") + (i32.store8 (memory.grow (i32.const 0)) (i32.const 7)) + ) + (func (export "as-storeN-value") + (i32.store16 (i32.const 2) (memory.grow (i32.const 0))) + ) + + (func (export "as-unary-operand") (result i32) + (i32.clz (memory.grow (i32.const 0))) + ) + + (func (export "as-binary-left") (result i32) + (i32.add (memory.grow (i32.const 0)) (i32.const 10)) + ) + (func (export "as-binary-right") (result i32) + (i32.sub (i32.const 10) (memory.grow (i32.const 0))) + ) + + (func (export "as-test-operand") (result i32) + (i32.eqz (memory.grow (i32.const 0))) + ) + + (func (export "as-compare-left") (result i32) + (i32.le_s (memory.grow (i32.const 0)) (i32.const 10)) + ) + (func (export "as-compare-right") (result i32) + (i32.ne (i32.const 10) (memory.grow (i32.const 0))) + ) + + (func (export "as-memory.grow-size") (result i32) + (memory.grow (memory.grow (i32.const 0))) + ) +) + +(assert_return (invoke "as-br-value") (i32.const 1)) + +(assert_return (invoke "as-br_if-cond")) +(assert_return (invoke "as-br_if-value") (i32.const 1)) +(assert_return (invoke "as-br_if-value-cond") (i32.const 6)) + +(assert_return (invoke "as-br_table-index")) +(assert_return (invoke "as-br_table-value") (i32.const 1)) +(assert_return (invoke "as-br_table-value-index") (i32.const 6)) + +(assert_return (invoke "as-return-value") (i32.const 1)) + +(assert_return (invoke "as-if-cond") (i32.const 0)) +(assert_return (invoke "as-if-then") (i32.const 1)) +(assert_return (invoke "as-if-else") (i32.const 1)) + +(assert_return (invoke "as-select-first" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-select-second" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-select-cond") (i32.const 0)) + +(assert_return (invoke "as-call-first") (i32.const -1)) +(assert_return (invoke "as-call-mid") (i32.const -1)) +(assert_return (invoke "as-call-last") (i32.const -1)) + +(assert_return (invoke "as-call_indirect-first") (i32.const -1)) +(assert_return (invoke "as-call_indirect-mid") (i32.const -1)) +(assert_return (invoke "as-call_indirect-last") (i32.const -1)) +(assert_trap (invoke "as-call_indirect-index") "undefined element") + +(assert_return (invoke "as-local.set-value")) +(assert_return (invoke "as-local.tee-value") (i32.const 1)) +(assert_return (invoke "as-global.set-value")) + +(assert_return (invoke "as-load-address") (i32.const 0)) +(assert_return (invoke "as-loadN-address") (i32.const 0)) +(assert_return (invoke "as-store-address")) +(assert_return (invoke "as-store-value")) +(assert_return (invoke "as-storeN-address")) +(assert_return (invoke "as-storeN-value")) + +(assert_return (invoke "as-unary-operand") (i32.const 31)) + +(assert_return (invoke "as-binary-left") (i32.const 11)) +(assert_return (invoke "as-binary-right") (i32.const 9)) + +(assert_return (invoke "as-test-operand") (i32.const 0)) + +(assert_return (invoke "as-compare-left") (i32.const 1)) +(assert_return (invoke "as-compare-right") (i32.const 1)) + +(assert_return (invoke "as-memory.grow-size") (i32.const 1)) + +(module $Mgm + (memory (export "memory") 1) ;; initial size is 1 + (func (export "grow") (result i32) (memory.grow (i32.const 1))) +) +(register "grown-memory" $Mgm) +(assert_return (invoke $Mgm "grow") (i32.const 1)) ;; now size is 2 +(module $Mgim1 + ;; imported memory limits should match, because external memory size is 2 now + (memory (export "memory") (import "grown-memory" "memory") 2) + (func (export "grow") (result i32) (memory.grow (i32.const 1))) +) +(register "grown-imported-memory" $Mgim1) +(assert_return (invoke $Mgim1 "grow") (i32.const 2)) ;; now size is 3 +(module $Mgim2 + ;; imported memory limits should match, because external memory size is 3 now + (import "grown-imported-memory" "memory" (memory 3)) + (func (export "size") (result i32) (memory.size)) +) +(assert_return (invoke $Mgim2 "size") (i32.const 3)) + + +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 2) + + (func (export "grow1") (param i32) (result i32) + (memory.grow $mem1 (local.get 0)) + ) + (func (export "grow2") (param i32) (result i32) + (memory.grow $mem2 (local.get 0)) + ) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) +) + +(assert_return (invoke "size1") (i32.const 1)) +(assert_return (invoke "size2") (i32.const 2)) +(assert_return (invoke "grow1" (i32.const 3)) (i32.const 1)) +(assert_return (invoke "grow1" (i32.const 4)) (i32.const 4)) +(assert_return (invoke "grow1" (i32.const 1)) (i32.const 8)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "grow2" (i32.const 1)) (i32.const 3)) + + +;; Type mismatches + +(assert_invalid + (module + (memory 1) + (func $type-i32-vs-f32 (result i32) + (memory.grow (f32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-size-empty-vs-i32 (result i32) + (memory.grow) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-size-empty-vs-i32-in-block (result i32) + (i32.const 0) + (block (result i32) (memory.grow)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-size-empty-vs-i32-in-loop (result i32) + (i32.const 0) + (loop (result i32) (memory.grow)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (func $type-size-empty-vs-i32-in-then (result i32) + (i32.const 0) (i32.const 0) + (if (result i32) (then (memory.grow))) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-empty + (memory.grow (i32.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-size-f32-vs-i32 (result i32) + (memory.grow (f32.const 0)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-empty + (memory.grow (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-f32 (result f32) + (memory.grow (i32.const 0)) + ) + ) + "type mismatch" +) diff --git a/proposals/memory64/memory_grow64.wast b/proposals/wasm-3.0/memory_grow64.wast similarity index 100% rename from proposals/memory64/memory_grow64.wast rename to proposals/wasm-3.0/memory_grow64.wast diff --git a/proposals/memory64/memory_init.wast b/proposals/wasm-3.0/memory_init.wast similarity index 100% rename from proposals/memory64/memory_init.wast rename to proposals/wasm-3.0/memory_init.wast diff --git a/proposals/wasm-3.0/memory_init0.wast b/proposals/wasm-3.0/memory_init0.wast new file mode 100644 index 0000000..190da6b --- /dev/null +++ b/proposals/wasm-3.0/memory_init0.wast @@ -0,0 +1,42 @@ +;; memory.init +(module + (memory $mem0 0) + (memory $mem1 0) + (memory $mem2 1) + (memory $mem3 0) + (data $mem2 "\aa\bb\cc\dd") + + (func (export "init") (param i32 i32 i32) + (memory.init $mem2 0 + (local.get 0) + (local.get 1) + (local.get 2))) + + (func (export "load8_u") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0))) +) + +(invoke "init" (i32.const 0) (i32.const 1) (i32.const 2)) +(assert_return (invoke "load8_u" (i32.const 0)) (i32.const 0xbb)) +(assert_return (invoke "load8_u" (i32.const 1)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 2)) (i32.const 0)) + +;; Init ending at memory limit and segment limit is ok. +(invoke "init" (i32.const 0xfffc) (i32.const 0) (i32.const 4)) + +;; Out-of-bounds writes trap, and nothing is written. +(assert_trap (invoke "init" (i32.const 0xfffe) (i32.const 0) (i32.const 3)) + "out of bounds memory access") +(assert_return (invoke "load8_u" (i32.const 0xfffe)) (i32.const 0xcc)) +(assert_return (invoke "load8_u" (i32.const 0xffff)) (i32.const 0xdd)) + +;; Succeed when writing 0 bytes at the end of either region. +(invoke "init" (i32.const 0x10000) (i32.const 0) (i32.const 0)) +(invoke "init" (i32.const 0) (i32.const 4) (i32.const 0)) + +;; Writing 0 bytes outside the memory traps. +(assert_trap (invoke "init" (i32.const 0x10001) (i32.const 0) (i32.const 0)) + "out of bounds memory access") +(assert_trap (invoke "init" (i32.const 0) (i32.const 5) (i32.const 0)) + "out of bounds memory access") + diff --git a/proposals/memory64/memory_redundancy64.wast b/proposals/wasm-3.0/memory_redundancy64.wast similarity index 100% rename from proposals/memory64/memory_redundancy64.wast rename to proposals/wasm-3.0/memory_redundancy64.wast diff --git a/proposals/wasm-3.0/memory_size.wast b/proposals/wasm-3.0/memory_size.wast new file mode 100644 index 0000000..a1d6ea2 --- /dev/null +++ b/proposals/wasm-3.0/memory_size.wast @@ -0,0 +1,111 @@ +(module + (memory 0) + (func (export "size") (result i32) (memory.size)) + (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 5)) + +(module + (memory 1) + (func (export "size") (result i32) (memory.size)) + (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 2)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 6)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 6)) + +(module + (memory 0 2) + (func (export "size") (result i32) (memory.size)) + (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 3))) +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 2)) + +(module + (memory 3 8) + (func (export "size") (result i32) (memory.size)) + (func (export "grow") (param $sz i32) (drop (memory.grow (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 3)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 4)) +(assert_return (invoke "grow" (i32.const 3))) +(assert_return (invoke "size") (i32.const 7)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 7)) +(assert_return (invoke "grow" (i32.const 2))) +(assert_return (invoke "size") (i32.const 7)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 8)) + + +;; Multiple memories + +(module + (memory (export "mem1") 2 4) + (memory (export "mem2") 0) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem1") 1 5) + (memory $mem2 (import "M" "mem2") 0) + (memory $mem3 3) + (memory $mem4 4 5) + + (func (export "size1") (result i32) (memory.size $mem1)) + (func (export "size2") (result i32) (memory.size $mem2)) + (func (export "size3") (result i32) (memory.size $mem3)) + (func (export "size4") (result i32) (memory.size $mem4)) +) + +(assert_return (invoke "size1") (i32.const 2)) +(assert_return (invoke "size2") (i32.const 0)) +(assert_return (invoke "size3") (i32.const 3)) +(assert_return (invoke "size4") (i32.const 4)) + + +;; Type errors + +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-empty + (memory.size) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-result-i32-vs-f32 (result f32) + (memory.size) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/memory_size0.wast b/proposals/wasm-3.0/memory_size0.wast new file mode 100644 index 0000000..47ad9ec --- /dev/null +++ b/proposals/wasm-3.0/memory_size0.wast @@ -0,0 +1,19 @@ +(module + (memory 0) + (memory 0) + (memory 0) + (memory 0) + (memory $m 0) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 5)) + diff --git a/proposals/wasm-3.0/memory_size1.wast b/proposals/wasm-3.0/memory_size1.wast new file mode 100644 index 0000000..69026a6 --- /dev/null +++ b/proposals/wasm-3.0/memory_size1.wast @@ -0,0 +1,29 @@ +(module + (memory 0) + (memory 0) + (memory $n 0) + (memory 0) + (memory $m 0) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) + + (func (export "sizen") (result i32) (memory.size $n)) + (func (export "grown") (param $sz i32) (drop (memory.grow $n (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 0)) + +(assert_return (invoke "grown" (i32.const 1))) +(assert_return (invoke "size") (i32.const 5)) +(assert_return (invoke "sizen") (i32.const 1)) diff --git a/proposals/wasm-3.0/memory_size2.wast b/proposals/wasm-3.0/memory_size2.wast new file mode 100644 index 0000000..e59917e --- /dev/null +++ b/proposals/wasm-3.0/memory_size2.wast @@ -0,0 +1,34 @@ +(module + (memory 0 0) + (memory 0 0) + (memory $n 0 0) + (memory $m 0 2) + + (func (export "size") (result i32) (memory.size $m)) + (func (export "grow") (param $sz i32) (drop (memory.grow $m (local.get $sz)))) + + (func (export "sizen") (result i32) (memory.size $n)) + (func (export "grown") (param $sz i32) (drop (memory.grow $n (local.get $sz)))) +) + +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 3))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 0)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 4))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 2)) + +(assert_return (invoke "grown" (i32.const 1))) +(assert_return (invoke "sizen") (i32.const 0)) +(assert_return (invoke "size") (i32.const 2)) diff --git a/proposals/wasm-3.0/memory_size3.wast b/proposals/wasm-3.0/memory_size3.wast new file mode 100644 index 0000000..834aa1c --- /dev/null +++ b/proposals/wasm-3.0/memory_size3.wast @@ -0,0 +1,25 @@ +;; Type errors + +(assert_invalid + (module + (memory 0) + (memory $m 1) + (memory 0) + (func $type-result-i32-vs-empty + (memory.size $m) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 0) + (memory 0) + (memory 0) + (memory $m 1) + (func $type-result-i32-vs-f32 (result f32) + (memory.size $m) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/memory_trap0.wast b/proposals/wasm-3.0/memory_trap0.wast new file mode 100644 index 0000000..26ecdf8 --- /dev/null +++ b/proposals/wasm-3.0/memory_trap0.wast @@ -0,0 +1,36 @@ +(module + (memory 0) + (memory 0) + (memory $m 1) + + (func $addr_limit (result i32) + (i32.mul (memory.size $m) (i32.const 0x10000)) + ) + + (func (export "store") (param $i i32) (param $v i32) + (i32.store $m (i32.add (call $addr_limit) (local.get $i)) (local.get $v)) + ) + + (func (export "load") (param $i i32) (result i32) + (i32.load $m (i32.add (call $addr_limit) (local.get $i))) + ) + + (func (export "memory.grow") (param i32) (result i32) + (memory.grow $m (local.get 0)) + ) +) + +(assert_return (invoke "store" (i32.const -4) (i32.const 42))) +(assert_return (invoke "load" (i32.const -4)) (i32.const 42)) +(assert_trap (invoke "store" (i32.const -3) (i32.const 0x12345678)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const -2) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const -1) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const 0) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "store" (i32.const 0x80000000) (i32.const 13)) "out of bounds memory access") +(assert_trap (invoke "load" (i32.const 0x80000000)) "out of bounds memory access") +(assert_return (invoke "memory.grow" (i32.const 0x10001)) (i32.const -1)) + diff --git a/proposals/wasm-3.0/memory_trap1.wast b/proposals/wasm-3.0/memory_trap1.wast new file mode 100644 index 0000000..bd692d0 --- /dev/null +++ b/proposals/wasm-3.0/memory_trap1.wast @@ -0,0 +1,250 @@ +(module + (memory 0) + (memory 0) + (memory $m 1) + (data (memory 2) (i32.const 0) "abcdefgh") + (data (memory 2) (i32.const 0xfff8) "abcdefgh") + + (func (export "i32.load") (param $a i32) (result i32) + (i32.load $m (local.get $a)) + ) + (func (export "i64.load") (param $a i32) (result i64) + (i64.load $m (local.get $a)) + ) + (func (export "f32.load") (param $a i32) (result f32) + (f32.load $m (local.get $a)) + ) + (func (export "f64.load") (param $a i32) (result f64) + (f64.load $m (local.get $a)) + ) + (func (export "i32.load8_s") (param $a i32) (result i32) + (i32.load8_s $m (local.get $a)) + ) + (func (export "i32.load8_u") (param $a i32) (result i32) + (i32.load8_u $m (local.get $a)) + ) + (func (export "i32.load16_s") (param $a i32) (result i32) + (i32.load16_s $m (local.get $a)) + ) + (func (export "i32.load16_u") (param $a i32) (result i32) + (i32.load16_u $m (local.get $a)) + ) + (func (export "i64.load8_s") (param $a i32) (result i64) + (i64.load8_s $m (local.get $a)) + ) + (func (export "i64.load8_u") (param $a i32) (result i64) + (i64.load8_u $m (local.get $a)) + ) + (func (export "i64.load16_s") (param $a i32) (result i64) + (i64.load16_s $m (local.get $a)) + ) + (func (export "i64.load16_u") (param $a i32) (result i64) + (i64.load16_u $m (local.get $a)) + ) + (func (export "i64.load32_s") (param $a i32) (result i64) + (i64.load32_s $m (local.get $a)) + ) + (func (export "i64.load32_u") (param $a i32) (result i64) + (i64.load32_u $m (local.get $a)) + ) + (func (export "i32.store") (param $a i32) (param $v i32) + (i32.store $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store") (param $a i32) (param $v i64) + (i64.store $m (local.get $a) (local.get $v)) + ) + (func (export "f32.store") (param $a i32) (param $v f32) + (f32.store $m (local.get $a) (local.get $v)) + ) + (func (export "f64.store") (param $a i32) (param $v f64) + (f64.store $m (local.get $a) (local.get $v)) + ) + (func (export "i32.store8") (param $a i32) (param $v i32) + (i32.store8 $m (local.get $a) (local.get $v)) + ) + (func (export "i32.store16") (param $a i32) (param $v i32) + (i32.store16 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store8") (param $a i32) (param $v i64) + (i64.store8 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store16") (param $a i32) (param $v i64) + (i64.store16 $m (local.get $a) (local.get $v)) + ) + (func (export "i64.store32") (param $a i32) (param $v i64) + (i64.store32 $m (local.get $a) (local.get $v)) + ) +) + +(assert_trap (invoke "i32.store" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xfffe) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -2) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -3) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store" (i32.const -4) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffc) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffb) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfffa) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -3) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -4) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -5) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -6) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -7) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store" (i32.const -8) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0x10000) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xffff) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xfffe) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -1) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -2) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -3) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f32.store" (i32.const -4) (f32.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0x10000) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xffff) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffe) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffd) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffc) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffb) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfffa) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -1) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -2) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -3) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -4) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -5) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -6) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -7) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "f64.store" (i32.const -8) (f64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store8" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store8" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const 0x10000) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const 0xffff) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const -1) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.store16" (i32.const -2) (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store8" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store8" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store16" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0x10000) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xffff) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xfffe) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const 0xfffd) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -1) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -2) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -3) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i64.store32" (i32.const -4) (i64.const 0)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i32.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffc)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffb)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfffa)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const 0xfff9)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -5)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -6)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -7)) "out of bounds memory access") +(assert_trap (invoke "i64.load" (i32.const -8)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "f32.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffc)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffb)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfffa)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const 0xfff9)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -5)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -6)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -7)) "out of bounds memory access") +(assert_trap (invoke "f64.load" (i32.const -8)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load8_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i32.load16_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load8_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load16_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_s" (i32.const -4)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0x10000)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xffff)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xfffe)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const 0xfffd)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -1)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -2)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -3)) "out of bounds memory access") +(assert_trap (invoke "i64.load32_u" (i32.const -4)) "out of bounds memory access") + +;; No memory was changed +(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0x6867666564636261)) +(assert_return (invoke "i64.load" (i32.const 0)) (i64.const 0x6867666564636261)) + +;; Check that out of bounds store do not store partial data. +;; Zero last 8 bytes. +(assert_return (invoke "i64.store" (i32.const 0xfff8) (i64.const 0))) +(assert_trap (invoke "i32.store" (i32.const 0xfffd) (i32.const 0x12345678)) "out of bounds memory access") +(assert_return (invoke "i32.load" (i32.const 0xfffc)) (i32.const 0)) +(assert_trap (invoke "i64.store" (i32.const 0xfff9) (i64.const 0x1234567890abcdef)) "out of bounds memory access") +(assert_return (invoke "i64.load" (i32.const 0xfff8)) (i64.const 0)) +(assert_trap (invoke "f32.store" (i32.const 0xfffd) (f32.const 0x12345678)) "out of bounds memory access") +(assert_return (invoke "f32.load" (i32.const 0xfffc)) (f32.const 0)) +(assert_trap (invoke "f64.store" (i32.const 0xfff9) (f64.const 0x1234567890abcdef)) "out of bounds memory access") +(assert_return (invoke "f64.load" (i32.const 0xfff8)) (f64.const 0)) diff --git a/proposals/memory64/memory_trap64.wast b/proposals/wasm-3.0/memory_trap64.wast similarity index 100% rename from proposals/memory64/memory_trap64.wast rename to proposals/wasm-3.0/memory_trap64.wast diff --git a/proposals/wasm-3.0/ref.wast b/proposals/wasm-3.0/ref.wast new file mode 100644 index 0000000..aef1b39 --- /dev/null +++ b/proposals/wasm-3.0/ref.wast @@ -0,0 +1,80 @@ +;; Syntax + +(module + (type $t (func)) + + (func + (param + funcref + externref + (ref func) + (ref extern) + (ref 0) + (ref $t) + (ref 0) + (ref $t) + (ref null func) + (ref null extern) + (ref null 0) + (ref null $t) + ) + ) +) + + +;; Undefined type index. + +(assert_invalid + (module (type $type-func-param-invalid (func (param (ref 1))))) + "unknown type" +) +(assert_invalid + (module (type $type-func-result-invalid (func (result (ref 1))))) + "unknown type" +) + +(assert_invalid + (module (global $global-invalid (ref null 1) (ref.null 1))) + "unknown type" +) + +(assert_invalid + (module (table $table-invalid 10 (ref null 1))) + "unknown type" +) + +(assert_invalid + (module (elem $elem-invalid (ref 1))) + "unknown type" +) + +(assert_invalid + (module (func $func-param-invalid (param (ref 1)))) + "unknown type" +) +(assert_invalid + (module (func $func-result-invalid (result (ref 1)))) + "unknown type" +) +(assert_invalid + (module (func $func-local-invalid (local (ref null 1)))) + "unknown type" +) + +(assert_invalid + (module (func $block-result-invalid (drop (block (result (ref 1)) (unreachable))))) + "unknown type" +) +(assert_invalid + (module (func $loop-result-invalid (drop (loop (result (ref 1)) (unreachable))))) + "unknown type" +) +(assert_invalid + (module (func $if-invalid (drop (if (result (ref 1)) (then) (else))))) + "unknown type" +) + +(assert_invalid + (module (func $select-result-invalid (drop (select (result (ref 1)) (unreachable))))) + "unknown type" +) diff --git a/proposals/wasm-3.0/ref_as_non_null.wast b/proposals/wasm-3.0/ref_as_non_null.wast new file mode 100644 index 0000000..6b3380f --- /dev/null +++ b/proposals/wasm-3.0/ref_as_non_null.wast @@ -0,0 +1,46 @@ +(module + (type $t (func (result i32))) + + (func $nn (param $r (ref $t)) (result i32) + (call_ref $t (ref.as_non_null (local.get $r))) + ) + (func $n (param $r (ref null $t)) (result i32) + (call_ref $t (ref.as_non_null (local.get $r))) + ) + + (elem func $f) + (func $f (result i32) (i32.const 7)) + + (func (export "nullable-null") (result i32) (call $n (ref.null $t))) + (func (export "nonnullable-f") (result i32) (call $nn (ref.func $f))) + (func (export "nullable-f") (result i32) (call $n (ref.func $f))) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.as_non_null) + (call $nn) + ) +) + +(assert_trap (invoke "unreachable") "unreachable") + +(assert_trap (invoke "nullable-null") "null reference") +(assert_return (invoke "nonnullable-f") (i32.const 7)) +(assert_return (invoke "nullable-f") (i32.const 7)) + +(assert_invalid + (module + (type $t (func (result i32))) + (func $g (param $r (ref $t)) (drop (ref.as_non_null (local.get $r)))) + (func (call $g (ref.null $t))) + ) + "type mismatch" +) + + +(module + (type $t (func)) + (func (param $r (ref $t)) (drop (ref.as_non_null (local.get $r)))) + (func (param $r (ref func)) (drop (ref.as_non_null (local.get $r)))) + (func (param $r (ref extern)) (drop (ref.as_non_null (local.get $r)))) +) diff --git a/proposals/wasm-3.0/ref_cast.wast b/proposals/wasm-3.0/ref_cast.wast new file mode 100644 index 0000000..8e35431 --- /dev/null +++ b/proposals/wasm-3.0/ref_cast.wast @@ -0,0 +1,186 @@ +;; Abstract Types + +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table 10 anyref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set (i32.const 0) (ref.null any)) + (table.set (i32.const 1) (ref.i31 (i32.const 7))) + (table.set (i32.const 2) (struct.new_default $st)) + (table.set (i32.const 3) (array.new_default $at (i32.const 0))) + (table.set (i32.const 4) (any.convert_extern (local.get $x))) + (table.set (i32.const 5) (ref.null i31)) + (table.set (i32.const 6) (ref.null struct)) + (table.set (i32.const 7) (ref.null none)) + ) + + (func (export "ref_cast_non_null") (param $i i32) + (drop (ref.as_non_null (table.get (local.get $i)))) + (drop (ref.cast (ref null any) (table.get (local.get $i)))) + ) + (func (export "ref_cast_null") (param $i i32) + (drop (ref.cast anyref (table.get (local.get $i)))) + (drop (ref.cast structref (table.get (local.get $i)))) + (drop (ref.cast arrayref (table.get (local.get $i)))) + (drop (ref.cast i31ref (table.get (local.get $i)))) + (drop (ref.cast nullref (table.get (local.get $i)))) + ) + (func (export "ref_cast_i31") (param $i i32) + (drop (ref.cast (ref i31) (table.get (local.get $i)))) + (drop (ref.cast i31ref (table.get (local.get $i)))) + ) + (func (export "ref_cast_struct") (param $i i32) + (drop (ref.cast (ref struct) (table.get (local.get $i)))) + (drop (ref.cast structref (table.get (local.get $i)))) + ) + (func (export "ref_cast_array") (param $i i32) + (drop (ref.cast (ref array) (table.get (local.get $i)))) + (drop (ref.cast arrayref (table.get (local.get $i)))) + ) +) + +(invoke "init" (ref.extern 0)) + +(assert_trap (invoke "ref_cast_non_null" (i32.const 0)) "null reference") +(assert_return (invoke "ref_cast_non_null" (i32.const 1))) +(assert_return (invoke "ref_cast_non_null" (i32.const 2))) +(assert_return (invoke "ref_cast_non_null" (i32.const 3))) +(assert_return (invoke "ref_cast_non_null" (i32.const 4))) +(assert_trap (invoke "ref_cast_non_null" (i32.const 5)) "null reference") +(assert_trap (invoke "ref_cast_non_null" (i32.const 6)) "null reference") +(assert_trap (invoke "ref_cast_non_null" (i32.const 7)) "null reference") + +(assert_return (invoke "ref_cast_null" (i32.const 0))) +(assert_trap (invoke "ref_cast_null" (i32.const 1)) "cast failure") +(assert_trap (invoke "ref_cast_null" (i32.const 2)) "cast failure") +(assert_trap (invoke "ref_cast_null" (i32.const 3)) "cast failure") +(assert_trap (invoke "ref_cast_null" (i32.const 4)) "cast failure") +(assert_return (invoke "ref_cast_null" (i32.const 5))) +(assert_return (invoke "ref_cast_null" (i32.const 6))) +(assert_return (invoke "ref_cast_null" (i32.const 7))) + +(assert_trap (invoke "ref_cast_i31" (i32.const 0)) "cast failure") +(assert_return (invoke "ref_cast_i31" (i32.const 1))) +(assert_trap (invoke "ref_cast_i31" (i32.const 2)) "cast failure") +(assert_trap (invoke "ref_cast_i31" (i32.const 3)) "cast failure") +(assert_trap (invoke "ref_cast_i31" (i32.const 4)) "cast failure") +(assert_trap (invoke "ref_cast_i31" (i32.const 5)) "cast failure") +(assert_trap (invoke "ref_cast_i31" (i32.const 6)) "cast failure") +(assert_trap (invoke "ref_cast_i31" (i32.const 7)) "cast failure") + +(assert_trap (invoke "ref_cast_struct" (i32.const 0)) "cast failure") +(assert_trap (invoke "ref_cast_struct" (i32.const 1)) "cast failure") +(assert_return (invoke "ref_cast_struct" (i32.const 2))) +(assert_trap (invoke "ref_cast_struct" (i32.const 3)) "cast failure") +(assert_trap (invoke "ref_cast_struct" (i32.const 4)) "cast failure") +(assert_trap (invoke "ref_cast_struct" (i32.const 5)) "cast failure") +(assert_trap (invoke "ref_cast_struct" (i32.const 6)) "cast failure") +(assert_trap (invoke "ref_cast_struct" (i32.const 7)) "cast failure") + +(assert_trap (invoke "ref_cast_array" (i32.const 0)) "cast failure") +(assert_trap (invoke "ref_cast_array" (i32.const 1)) "cast failure") +(assert_trap (invoke "ref_cast_array" (i32.const 2)) "cast failure") +(assert_return (invoke "ref_cast_array" (i32.const 3))) +(assert_trap (invoke "ref_cast_array" (i32.const 4)) "cast failure") +(assert_trap (invoke "ref_cast_array" (i32.const 5)) "cast failure") +(assert_trap (invoke "ref_cast_array" (i32.const 6)) "cast failure") +(assert_trap (invoke "ref_cast_array" (i32.const 7)) "cast failure") + + +;; Concrete Types + +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_default $t0)) + (table.set (i32.const 10) (struct.new_default $t0)) + (table.set (i32.const 1) (struct.new_default $t1)) + (table.set (i32.const 11) (struct.new_default $t1')) + (table.set (i32.const 2) (struct.new_default $t2)) + (table.set (i32.const 12) (struct.new_default $t2')) + (table.set (i32.const 3) (struct.new_default $t3)) + (table.set (i32.const 4) (struct.new_default $t4)) + ) + + (func (export "test-sub") + (call $init) + + (drop (ref.cast (ref null $t0) (ref.null struct))) + (drop (ref.cast (ref null $t0) (table.get (i32.const 0)))) + (drop (ref.cast (ref null $t0) (table.get (i32.const 1)))) + (drop (ref.cast (ref null $t0) (table.get (i32.const 2)))) + (drop (ref.cast (ref null $t0) (table.get (i32.const 3)))) + (drop (ref.cast (ref null $t0) (table.get (i32.const 4)))) + + (drop (ref.cast (ref null $t0) (ref.null struct))) + (drop (ref.cast (ref null $t1) (table.get (i32.const 1)))) + (drop (ref.cast (ref null $t1) (table.get (i32.const 2)))) + + (drop (ref.cast (ref null $t0) (ref.null struct))) + (drop (ref.cast (ref null $t2) (table.get (i32.const 2)))) + + (drop (ref.cast (ref null $t0) (ref.null struct))) + (drop (ref.cast (ref null $t3) (table.get (i32.const 3)))) + + (drop (ref.cast (ref null $t4) (table.get (i32.const 4)))) + + (drop (ref.cast (ref $t0) (table.get (i32.const 0)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 1)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 2)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 3)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 4)))) + + (drop (ref.cast (ref $t1) (table.get (i32.const 1)))) + (drop (ref.cast (ref $t1) (table.get (i32.const 2)))) + + (drop (ref.cast (ref $t2) (table.get (i32.const 2)))) + + (drop (ref.cast (ref $t3) (table.get (i32.const 3)))) + + (drop (ref.cast (ref $t4) (table.get (i32.const 4)))) + ) + + (func (export "test-canon") + (call $init) + + (drop (ref.cast (ref $t0) (table.get (i32.const 0)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 1)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 2)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 3)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 4)))) + + (drop (ref.cast (ref $t0) (table.get (i32.const 10)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 11)))) + (drop (ref.cast (ref $t0) (table.get (i32.const 12)))) + + (drop (ref.cast (ref $t1') (table.get (i32.const 1)))) + (drop (ref.cast (ref $t1') (table.get (i32.const 2)))) + + (drop (ref.cast (ref $t1) (table.get (i32.const 11)))) + (drop (ref.cast (ref $t1) (table.get (i32.const 12)))) + + (drop (ref.cast (ref $t2') (table.get (i32.const 2)))) + + (drop (ref.cast (ref $t2) (table.get (i32.const 12)))) + ) +) + +(invoke "test-sub") +(invoke "test-canon") diff --git a/proposals/wasm-3.0/ref_eq.wast b/proposals/wasm-3.0/ref_eq.wast new file mode 100644 index 0000000..001efd6 --- /dev/null +++ b/proposals/wasm-3.0/ref_eq.wast @@ -0,0 +1,168 @@ +(module + (type $st (sub (struct))) + (type $st' (sub (struct (field i32)))) + (type $at (array i8)) + (type $st-sub1 (sub $st (struct))) + (type $st-sub2 (sub $st (struct))) + (type $st'-sub1 (sub $st' (struct (field i32)))) + (type $st'-sub2 (sub $st' (struct (field i32)))) + + (table 20 (ref null eq)) + + (func (export "init") + (table.set (i32.const 0) (ref.null eq)) + (table.set (i32.const 1) (ref.null i31)) + (table.set (i32.const 2) (ref.i31 (i32.const 7))) + (table.set (i32.const 3) (ref.i31 (i32.const 7))) + (table.set (i32.const 4) (ref.i31 (i32.const 8))) + (table.set (i32.const 5) (struct.new_default $st)) + (table.set (i32.const 6) (struct.new_default $st)) + (table.set (i32.const 7) (array.new_default $at (i32.const 0))) + (table.set (i32.const 8) (array.new_default $at (i32.const 0))) + ) + + (func (export "eq") (param $i i32) (param $j i32) (result i32) + (ref.eq (table.get (local.get $i)) (table.get (local.get $j))) + ) +) + +(invoke "init") + +(assert_return (invoke "eq" (i32.const 0) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 0) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 1) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 2) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 2)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 3)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 2) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 3) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 2)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 3)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 3) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 4) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 4)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 4) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 5) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 5)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 5) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 6) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 6)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 6) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 7) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 7)) (i32.const 1)) +(assert_return (invoke "eq" (i32.const 7) (i32.const 8)) (i32.const 0)) + +(assert_return (invoke "eq" (i32.const 8) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 1)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 2)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 3)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 4)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 5)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 6)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 7)) (i32.const 0)) +(assert_return (invoke "eq" (i32.const 8) (i32.const 8)) (i32.const 1)) + +(assert_invalid + (module + (func (export "eq") (param $r (ref any)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (export "eq") (param $r (ref null any)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (export "eq") (param $r (ref func)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (export "eq") (param $r (ref null func)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (export "eq") (param $r (ref extern)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func (export "eq") (param $r (ref null extern)) (result i32) + (ref.eq (local.get $r) (local.get $r)) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/ref_is_null.wast b/proposals/wasm-3.0/ref_is_null.wast new file mode 100644 index 0000000..730170d --- /dev/null +++ b/proposals/wasm-3.0/ref_is_null.wast @@ -0,0 +1,85 @@ +(module + (type $t (func)) + (func $dummy) + + (func $f1 (export "funcref") (param $x funcref) (result i32) + (ref.is_null (local.get $x)) + ) + (func $f2 (export "externref") (param $x externref) (result i32) + (ref.is_null (local.get $x)) + ) + (func $f3 (param $x (ref null $t)) (result i32) + (ref.is_null (local.get $x)) + ) + (func $f3' (export "ref-null") (result i32) + (call $f3 (ref.null $t)) + ) + + (table $t1 2 funcref) + (table $t2 2 externref) + (table $t3 2 (ref null $t)) + (elem (table $t1) (i32.const 1) func $dummy) + (elem (table $t3) (i32.const 1) (ref $t) (ref.func $dummy)) + + (func (export "init") (param $r externref) + (table.set $t2 (i32.const 1) (local.get $r)) + ) + (func (export "deinit") + (table.set $t1 (i32.const 1) (ref.null func)) + (table.set $t2 (i32.const 1) (ref.null extern)) + (table.set $t3 (i32.const 1) (ref.null $t)) + ) + + (func (export "funcref-elem") (param $x i32) (result i32) + (call $f1 (table.get $t1 (local.get $x))) + ) + (func (export "externref-elem") (param $x i32) (result i32) + (call $f2 (table.get $t2 (local.get $x))) + ) + (func (export "ref-elem") (param $x i32) (result i32) + (call $f3 (table.get $t3 (local.get $x))) + ) +) + +(assert_return (invoke "funcref" (ref.null func)) (i32.const 1)) +(assert_return (invoke "externref" (ref.null extern)) (i32.const 1)) +(assert_return (invoke "ref-null") (i32.const 1)) + +(assert_return (invoke "externref" (ref.extern 1)) (i32.const 0)) + +(invoke "init" (ref.extern 0)) + +(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref-elem" (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "ref-elem" (i32.const 1)) (i32.const 0)) + +(invoke "deinit") + +(assert_return (invoke "funcref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref-elem" (i32.const 0)) (i32.const 1)) + +(assert_return (invoke "funcref-elem" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "externref-elem" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref-elem" (i32.const 1)) (i32.const 1)) + + +(module + (type $t (func)) + (func (param $r (ref $t)) (drop (ref.is_null (local.get $r)))) + (func (param $r (ref func)) (drop (ref.is_null (local.get $r)))) + (func (param $r (ref extern)) (drop (ref.is_null (local.get $r)))) +) + +(assert_invalid + (module (func $ref-vs-num (param i32) (ref.is_null (local.get 0)))) + "type mismatch" +) +(assert_invalid + (module (func $ref-vs-empty (ref.is_null))) + "type mismatch" +) diff --git a/proposals/wasm-3.0/ref_null.wast b/proposals/wasm-3.0/ref_null.wast new file mode 100644 index 0000000..3faadaf --- /dev/null +++ b/proposals/wasm-3.0/ref_null.wast @@ -0,0 +1,81 @@ +(module + (type $t (func)) + (func (export "anyref") (result anyref) (ref.null any)) + (func (export "funcref") (result funcref) (ref.null func)) + (func (export "exnref") (result exnref) (ref.null exn)) + (func (export "externref") (result externref) (ref.null extern)) + (func (export "ref") (result (ref null $t)) (ref.null $t)) + + (global anyref (ref.null any)) + (global funcref (ref.null func)) + (global exnref (ref.null exn)) + (global externref (ref.null extern)) + (global (ref null $t) (ref.null $t)) +) + +(assert_return (invoke "anyref") (ref.null any)) +(assert_return (invoke "funcref") (ref.null func)) +(assert_return (invoke "exnref") (ref.null exn)) +(assert_return (invoke "externref") (ref.null extern)) +(assert_return (invoke "ref") (ref.null)) + + +(module + (type $t (func)) + (global $null nullref (ref.null none)) + (global $nullfunc nullfuncref (ref.null nofunc)) + (global $nullexn nullexnref (ref.null noexn)) + (global $nullextern nullexternref (ref.null noextern)) + (func (export "anyref") (result anyref) (global.get $null)) + (func (export "nullref") (result nullref) (global.get $null)) + (func (export "funcref") (result funcref) (global.get $nullfunc)) + (func (export "nullfuncref") (result nullfuncref) (global.get $nullfunc)) + (func (export "exnref") (result exnref) (global.get $nullexn)) + (func (export "nullexnref") (result nullexnref) (global.get $nullexn)) + (func (export "externref") (result externref) (global.get $nullextern)) + (func (export "nullexternref") (result nullexternref) (global.get $nullextern)) + (func (export "ref") (result (ref null $t)) (global.get $nullfunc)) + + (global anyref (ref.null any)) + (global anyref (ref.null none)) + (global funcref (ref.null func)) + (global funcref (ref.null nofunc)) + (global exnref (ref.null exn)) + (global exnref (ref.null noexn)) + (global externref (ref.null extern)) + (global externref (ref.null noextern)) + (global nullref (ref.null none)) + (global nullfuncref (ref.null nofunc)) + (global nullexnref (ref.null noexn)) + (global nullexternref (ref.null noextern)) + (global (ref null $t) (ref.null $t)) + (global (ref null $t) (ref.null nofunc)) +) + +(assert_return (invoke "anyref") (ref.null any)) +(assert_return (invoke "anyref") (ref.null none)) +(assert_return (invoke "anyref") (ref.null)) +(assert_return (invoke "nullref") (ref.null any)) +(assert_return (invoke "nullref") (ref.null none)) +(assert_return (invoke "nullref") (ref.null)) +(assert_return (invoke "funcref") (ref.null func)) +(assert_return (invoke "funcref") (ref.null nofunc)) +(assert_return (invoke "funcref") (ref.null)) +(assert_return (invoke "nullfuncref") (ref.null func)) +(assert_return (invoke "nullfuncref") (ref.null nofunc)) +(assert_return (invoke "nullfuncref") (ref.null)) +(assert_return (invoke "exnref") (ref.null exn)) +(assert_return (invoke "exnref") (ref.null noexn)) +(assert_return (invoke "exnref") (ref.null)) +(assert_return (invoke "nullexnref") (ref.null exn)) +(assert_return (invoke "nullexnref") (ref.null noexn)) +(assert_return (invoke "nullexnref") (ref.null)) +(assert_return (invoke "externref") (ref.null extern)) +(assert_return (invoke "externref") (ref.null noextern)) +(assert_return (invoke "externref") (ref.null)) +(assert_return (invoke "nullexternref") (ref.null extern)) +(assert_return (invoke "nullexternref") (ref.null noextern)) +(assert_return (invoke "nullexternref") (ref.null)) +(assert_return (invoke "ref") (ref.null func)) +(assert_return (invoke "ref") (ref.null nofunc)) +(assert_return (invoke "ref") (ref.null)) diff --git a/proposals/wasm-3.0/ref_test.wast b/proposals/wasm-3.0/ref_test.wast new file mode 100644 index 0000000..590b81b --- /dev/null +++ b/proposals/wasm-3.0/ref_test.wast @@ -0,0 +1,330 @@ +;; Abstract Types + +(module + (type $ft (func)) + (type $st (struct)) + (type $at (array i8)) + + (table $ta 10 anyref) + (table $tf 10 funcref) + (table $te 10 externref) + + (elem declare func $f) + (func $f) + + (func (export "init") (param $x externref) + (table.set $ta (i32.const 0) (ref.null any)) + (table.set $ta (i32.const 1) (ref.null struct)) + (table.set $ta (i32.const 2) (ref.null none)) + (table.set $ta (i32.const 3) (ref.i31 (i32.const 7))) + (table.set $ta (i32.const 4) (struct.new_default $st)) + (table.set $ta (i32.const 5) (array.new_default $at (i32.const 0))) + (table.set $ta (i32.const 6) (any.convert_extern (local.get $x))) + (table.set $ta (i32.const 7) (any.convert_extern (ref.null extern))) + + (table.set $tf (i32.const 0) (ref.null nofunc)) + (table.set $tf (i32.const 1) (ref.null func)) + (table.set $tf (i32.const 2) (ref.func $f)) + + (table.set $te (i32.const 0) (ref.null noextern)) + (table.set $te (i32.const 1) (ref.null extern)) + (table.set $te (i32.const 2) (local.get $x)) + (table.set $te (i32.const 3) (extern.convert_any (ref.i31 (i32.const 8)))) + (table.set $te (i32.const 4) (extern.convert_any (struct.new_default $st))) + (table.set $te (i32.const 5) (extern.convert_any (ref.null any))) + ) + + (func (export "ref_test_null_data") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $ta (local.get $i))) + (ref.test nullref (table.get $ta (local.get $i))) + ) + ) + (func (export "ref_test_any") (param $i i32) (result i32) + (i32.add + (ref.test (ref any) (table.get $ta (local.get $i))) + (ref.test anyref (table.get $ta (local.get $i))) + ) + ) + (func (export "ref_test_eq") (param $i i32) (result i32) + (i32.add + (ref.test (ref eq) (table.get $ta (local.get $i))) + (ref.test eqref (table.get $ta (local.get $i))) + ) + ) + (func (export "ref_test_i31") (param $i i32) (result i32) + (i32.add + (ref.test (ref i31) (table.get $ta (local.get $i))) + (ref.test i31ref (table.get $ta (local.get $i))) + ) + ) + (func (export "ref_test_struct") (param $i i32) (result i32) + (i32.add + (ref.test (ref struct) (table.get $ta (local.get $i))) + (ref.test structref (table.get $ta (local.get $i))) + ) + ) + (func (export "ref_test_array") (param $i i32) (result i32) + (i32.add + (ref.test (ref array) (table.get $ta (local.get $i))) + (ref.test arrayref (table.get $ta (local.get $i))) + ) + ) + + (func (export "ref_test_null_func") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $tf (local.get $i))) + (ref.test (ref null nofunc) (table.get $tf (local.get $i))) + ) + ) + (func (export "ref_test_func") (param $i i32) (result i32) + (i32.add + (ref.test (ref func) (table.get $tf (local.get $i))) + (ref.test funcref (table.get $tf (local.get $i))) + ) + ) + + (func (export "ref_test_null_extern") (param $i i32) (result i32) + (i32.add + (ref.is_null (table.get $te (local.get $i))) + (ref.test (ref null noextern) (table.get $te (local.get $i))) + ) + ) + (func (export "ref_test_extern") (param $i i32) (result i32) + (i32.add + (ref.test (ref extern) (table.get $te (local.get $i))) + (ref.test externref (table.get $te (local.get $i))) + ) + ) +) + +(invoke "init" (ref.extern 0)) + +(assert_return (invoke "ref_test_null_data" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "ref_test_null_data" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "ref_test_null_data" (i32.const 2)) (i32.const 2)) +(assert_return (invoke "ref_test_null_data" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "ref_test_null_data" (i32.const 4)) (i32.const 0)) +(assert_return (invoke "ref_test_null_data" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "ref_test_null_data" (i32.const 6)) (i32.const 0)) +(assert_return (invoke "ref_test_null_data" (i32.const 7)) (i32.const 2)) + +(assert_return (invoke "ref_test_any" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_any" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_any" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "ref_test_any" (i32.const 3)) (i32.const 2)) +(assert_return (invoke "ref_test_any" (i32.const 4)) (i32.const 2)) +(assert_return (invoke "ref_test_any" (i32.const 5)) (i32.const 2)) +(assert_return (invoke "ref_test_any" (i32.const 6)) (i32.const 2)) +(assert_return (invoke "ref_test_any" (i32.const 7)) (i32.const 1)) + +(assert_return (invoke "ref_test_eq" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_eq" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_eq" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "ref_test_eq" (i32.const 3)) (i32.const 2)) +(assert_return (invoke "ref_test_eq" (i32.const 4)) (i32.const 2)) +(assert_return (invoke "ref_test_eq" (i32.const 5)) (i32.const 2)) +(assert_return (invoke "ref_test_eq" (i32.const 6)) (i32.const 0)) +(assert_return (invoke "ref_test_eq" (i32.const 7)) (i32.const 1)) + +(assert_return (invoke "ref_test_i31" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_i31" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_i31" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "ref_test_i31" (i32.const 3)) (i32.const 2)) +(assert_return (invoke "ref_test_i31" (i32.const 4)) (i32.const 0)) +(assert_return (invoke "ref_test_i31" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "ref_test_i31" (i32.const 6)) (i32.const 0)) +(assert_return (invoke "ref_test_i31" (i32.const 7)) (i32.const 1)) + +(assert_return (invoke "ref_test_struct" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_struct" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_struct" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "ref_test_struct" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "ref_test_struct" (i32.const 4)) (i32.const 2)) +(assert_return (invoke "ref_test_struct" (i32.const 5)) (i32.const 0)) +(assert_return (invoke "ref_test_struct" (i32.const 6)) (i32.const 0)) +(assert_return (invoke "ref_test_struct" (i32.const 7)) (i32.const 1)) + +(assert_return (invoke "ref_test_array" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_array" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_array" (i32.const 2)) (i32.const 1)) +(assert_return (invoke "ref_test_array" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "ref_test_array" (i32.const 4)) (i32.const 0)) +(assert_return (invoke "ref_test_array" (i32.const 5)) (i32.const 2)) +(assert_return (invoke "ref_test_array" (i32.const 6)) (i32.const 0)) +(assert_return (invoke "ref_test_array" (i32.const 7)) (i32.const 1)) + +(assert_return (invoke "ref_test_null_func" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "ref_test_null_func" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "ref_test_null_func" (i32.const 2)) (i32.const 0)) + +(assert_return (invoke "ref_test_func" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_func" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_func" (i32.const 2)) (i32.const 2)) + +(assert_return (invoke "ref_test_null_extern" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "ref_test_null_extern" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "ref_test_null_extern" (i32.const 2)) (i32.const 0)) +(assert_return (invoke "ref_test_null_extern" (i32.const 3)) (i32.const 0)) +(assert_return (invoke "ref_test_null_extern" (i32.const 4)) (i32.const 0)) +(assert_return (invoke "ref_test_null_extern" (i32.const 5)) (i32.const 2)) + +(assert_return (invoke "ref_test_extern" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "ref_test_extern" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "ref_test_extern" (i32.const 2)) (i32.const 2)) +(assert_return (invoke "ref_test_extern" (i32.const 3)) (i32.const 2)) +(assert_return (invoke "ref_test_extern" (i32.const 4)) (i32.const 2)) +(assert_return (invoke "ref_test_extern" (i32.const 5)) (i32.const 1)) + + +;; Concrete Types + +(module + (type $t0 (sub (struct))) + (type $t1 (sub $t0 (struct (field i32)))) + (type $t1' (sub $t0 (struct (field i32)))) + (type $t2 (sub $t1 (struct (field i32 i32)))) + (type $t2' (sub $t1' (struct (field i32 i32)))) + (type $t3 (sub $t0 (struct (field i32 i32)))) + (type $t0' (sub $t0 (struct))) + (type $t4 (sub $t0' (struct (field i32 i32)))) + + (table 20 (ref null struct)) + + (func $init + (table.set (i32.const 0) (struct.new_default $t0)) + (table.set (i32.const 10) (struct.new_default $t0)) + (table.set (i32.const 1) (struct.new_default $t1)) + (table.set (i32.const 11) (struct.new_default $t1')) + (table.set (i32.const 2) (struct.new_default $t2)) + (table.set (i32.const 12) (struct.new_default $t2')) + (table.set (i32.const 3) (struct.new_default $t3)) + (table.set (i32.const 4) (struct.new_default $t4)) + ) + + (func (export "test-sub") + (call $init) + (block $l + ;; must hold + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null struct)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test (ref null $t0) (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null struct)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test (ref null $t1) (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null struct)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test (ref null $t2) (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null struct)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test (ref null $t3) (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null struct)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t0)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t1)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t2)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t3)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (ref.null $t4)))) + (br_if $l (i32.eqz (ref.test (ref null $t4) (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 4))))) + + (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 $t2) (table.get (i32.const 2))))) + + (br_if $l (i32.eqz (ref.test (ref $t3) (table.get (i32.const 3))))) + + (br_if $l (i32.eqz (ref.test (ref $t4) (table.get (i32.const 4))))) + + ;; must not hold + (br_if $l (ref.test (ref $t0) (ref.null struct))) + (br_if $l (ref.test (ref $t1) (ref.null struct))) + (br_if $l (ref.test (ref $t2) (ref.null struct))) + (br_if $l (ref.test (ref $t3) (ref.null struct))) + (br_if $l (ref.test (ref $t4) (ref.null struct))) + + (br_if $l (ref.test (ref $t1) (table.get (i32.const 0)))) + (br_if $l (ref.test (ref $t1) (table.get (i32.const 3)))) + (br_if $l (ref.test (ref $t1) (table.get (i32.const 4)))) + + (br_if $l (ref.test (ref $t2) (table.get (i32.const 0)))) + (br_if $l (ref.test (ref $t2) (table.get (i32.const 1)))) + (br_if $l (ref.test (ref $t2) (table.get (i32.const 3)))) + (br_if $l (ref.test (ref $t2) (table.get (i32.const 4)))) + + (br_if $l (ref.test (ref $t3) (table.get (i32.const 0)))) + (br_if $l (ref.test (ref $t3) (table.get (i32.const 1)))) + (br_if $l (ref.test (ref $t3) (table.get (i32.const 2)))) + (br_if $l (ref.test (ref $t3) (table.get (i32.const 4)))) + + (br_if $l (ref.test (ref $t4) (table.get (i32.const 0)))) + (br_if $l (ref.test (ref $t4) (table.get (i32.const 1)))) + (br_if $l (ref.test (ref $t4) (table.get (i32.const 2)))) + (br_if $l (ref.test (ref $t4) (table.get (i32.const 3)))) + + (return) + ) + (unreachable) + ) + + (func (export "test-canon") + (call $init) + (block $l + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 0))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 1))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 2))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 3))))) + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 4))))) + + (br_if $l (i32.eqz (ref.test (ref $t0) (table.get (i32.const 10))))) + (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))))) + + (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 12))))) + + (return) + ) + (unreachable) + ) +) + +(assert_return (invoke "test-sub")) +(assert_return (invoke "test-canon")) diff --git a/proposals/wasm-3.0/relaxed_dot_product.wast b/proposals/wasm-3.0/relaxed_dot_product.wast new file mode 100644 index 0000000..48714b8 --- /dev/null +++ b/proposals/wasm-3.0/relaxed_dot_product.wast @@ -0,0 +1,107 @@ +;; Tests for relaxed dot products. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "i16x8.relaxed_dot_i8x16_i7x16_s") (param v128 v128) (result v128) (i16x8.relaxed_dot_i8x16_i7x16_s (local.get 0) (local.get 1))) + (func (export "i32x4.relaxed_dot_i8x16_i7x16_add_s") (param v128 v128 v128) (result v128) (i32x4.relaxed_dot_i8x16_i7x16_add_s (local.get 0) (local.get 1) (local.get 2))) + + (func (export "i16x8.relaxed_dot_i8x16_i7x16_s_cmp") (param v128 v128) (result v128) + (i16x8.eq + (i16x8.relaxed_dot_i8x16_i7x16_s (local.get 0) (local.get 1)) + (i16x8.relaxed_dot_i8x16_i7x16_s (local.get 0) (local.get 1)))) + (func (export "i32x4.relaxed_dot_i8x16_i7x16_add_s_cmp") (param v128 v128 v128) (result v128) + (i16x8.eq + (i32x4.relaxed_dot_i8x16_i7x16_add_s (local.get 0) (local.get 1) (local.get 2)) + (i32x4.relaxed_dot_i8x16_i7x16_add_s (local.get 0) (local.get 1) (local.get 2)))) +) + +;; Simple values to ensure things are functional. +(assert_return (invoke "i16x8.relaxed_dot_i8x16_i7x16_s" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i16x8 1 13 41 85 145 221 313 421)) + +;; Test max and min i8 values; +(assert_return (invoke "i16x8.relaxed_dot_i8x16_i7x16_s" + (v128.const i8x16 -128 -128 127 127 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i16x8 -32512 32258 0 0 0 0 0 0)) + +;; signed * unsigned : -128 * 129 * 2 = -33,024 saturated to -32,768 +;; signed * signed : -128 * -127 * 2 = 32,512 +;; unsigned * unsigned : 128 * 129 * 2 = 33,024 +(assert_return (invoke "i16x8.relaxed_dot_i8x16_i7x16_s" + (v128.const i8x16 -128 -128 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 -127 -127 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (either + (v128.const i16x8 -32768 0 0 0 0 0 0 0) + (v128.const i16x8 32512 0 0 0 0 0 0 0) + (v128.const i16x8 33024 0 0 0 0 0 0 0))) + +;; Simple values to ensure things are functional. +(assert_return (invoke "i32x4.relaxed_dot_i8x16_i7x16_add_s" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i32x4 0 1 2 3)) + ;; intermediate result is [14, 126, 366, 734] + (v128.const i32x4 14 127 368 737)) + +;; Test max and min i8 values; +(assert_return (invoke "i32x4.relaxed_dot_i8x16_i7x16_add_s" + (v128.const i8x16 -128 -128 -128 -128 127 127 127 127 0 0 0 0 0 0 0 0) + (v128.const i8x16 127 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0) + (v128.const i32x4 1 2 3 4)) + ;; intermediate result is [-65024, 64516, 0, 0] + (v128.const i32x4 -65023 64518 3 4)) + +;; signed * unsigned : -128 * 129 * 4 = -66,048 (+ 1) VPDPBUSD AVX2-VNNI or AVX512-VNNI +;; signed * unsigned with intermediate saturation : +;; (-128 * 129) + (-128 * 129) = -33024 saturated to -32768 (PMADDUBSW) +;; -32768 + -32768 = -65536 (+ 1) +;; signed * signed : -128 * -127 * 4 = 65,024 (+ 1) +;; unsigned * unsigned : 128 * 129 * 2 = 66,048 (+ 1) +(assert_return (invoke "i32x4.relaxed_dot_i8x16_i7x16_add_s" + (v128.const i8x16 -128 -128 -128 -128 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 -127 -127 -127 -127 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i32x4 1 2 3 4)) + (either + (v128.const i32x4 -66047 2 3 4) + (v128.const i32x4 -65535 2 3 4) + (v128.const i32x4 65025 2 3 4) + (v128.const i32x4 66049 2 3 4))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +;; Test max and min i8 values; +(assert_return (invoke "i16x8.relaxed_dot_i8x16_i7x16_s_cmp" + (v128.const i8x16 -128 -128 127 127 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 127 127 127 127 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) + +;; Test max and min i8 values; +(assert_return (invoke "i32x4.relaxed_dot_i8x16_i7x16_add_s_cmp" + (v128.const i8x16 -128 -128 -128 -128 127 127 127 127 0 0 0 0 0 0 0 0) + (v128.const i8x16 127 127 127 127 127 127 127 127 0 0 0 0 0 0 0 0) + (v128.const i32x4 1 2 3 4)) + ;; intermediate result is [-65024, 64516, 0, 0] + (v128.const i32x4 -1 -1 -1 -1)) + +;; signed * unsigned : -128 * 129 * 2 = -33,024 saturated to -32,768 +;; signed * signed : -128 * -127 * 2 = 32,512 +;; unsigned * unsigned : 128 * 129 * 2 = 33,024 +(assert_return (invoke "i16x8.relaxed_dot_i8x16_i7x16_s_cmp" + (v128.const i8x16 -128 -128 0 0 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 -127 -127 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) + +;; signed * unsigned : -128 * 129 * 4 = -66,048 (+ 1) VPDPBUSD AVX2-VNNI or AVX512-VNNI +;; signed * unsigned with intermediate saturation : +;; (-128 * 129) + (-128 * 129) = -33024 saturated to -32768 (PMADDUBSW) +;; -32768 + -32768 = -65536 (+ 1) +;; signed * signed : -128 * -127 * 4 = 65,024 (+ 1) +;; unsigned * unsigned : 128 * 129 * 2 = 66,048 (+ 1) +(assert_return (invoke "i32x4.relaxed_dot_i8x16_i7x16_add_s_cmp" + (v128.const i8x16 -128 -128 -128 -128 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i8x16 -127 -127 -127 -127 0 0 0 0 0 0 0 0 0 0 0 0) + (v128.const i32x4 1 2 3 4)) + (v128.const i32x4 -1 -1 -1 -1)) diff --git a/proposals/wasm-3.0/relaxed_laneselect.wast b/proposals/wasm-3.0/relaxed_laneselect.wast new file mode 100644 index 0000000..1091381 --- /dev/null +++ b/proposals/wasm-3.0/relaxed_laneselect.wast @@ -0,0 +1,103 @@ +;; Tests for i8x16.relaxed_laneselect, i16x8.relaxed_laneselect, i32x4.relaxed_laneselect, and i64x2.relaxed_laneselect. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "i8x16.relaxed_laneselect") (param v128 v128 v128) (result v128) (i8x16.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2))) + (func (export "i16x8.relaxed_laneselect") (param v128 v128 v128) (result v128) (i16x8.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2))) + (func (export "i32x4.relaxed_laneselect") (param v128 v128 v128) (result v128) (i32x4.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2))) + (func (export "i64x2.relaxed_laneselect") (param v128 v128 v128) (result v128) (i64x2.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2))) + + (func (export "i8x16.relaxed_laneselect_cmp") (param v128 v128 v128) (result v128) + (i8x16.eq + (i8x16.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)) + (i8x16.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)))) + (func (export "i16x8.relaxed_laneselect_cmp") (param v128 v128 v128) (result v128) + (i16x8.eq + (i16x8.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)) + (i16x8.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)))) + (func (export "i32x4.relaxed_laneselect_cmp") (param v128 v128 v128) (result v128) + (i32x4.eq + (i32x4.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)) + (i32x4.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)))) + (func (export "i64x2.relaxed_laneselect_cmp") (param v128 v128 v128) (result v128) + (i64x2.eq + (i64x2.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)) + (i64x2.relaxed_laneselect (local.get 0) (local.get 1) (local.get 2)))) +) + +(assert_return (invoke "i8x16.relaxed_laneselect" + (v128.const i8x16 0 1 0x12 0x12 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 16 17 0x34 0x34 20 21 22 23 24 25 26 27 28 29 30 31) + (v128.const i8x16 0xff 0 0xf0 0x0f 0 0 0 0 0 0 0 0 0 0 0 0)) + (either (v128.const i8x16 0 17 0x14 0x32 20 21 22 23 24 25 26 27 28 29 30 31) + (v128.const i8x16 0 17 0x12 0x34 20 21 22 23 24 25 26 27 28 29 30 31))) + +(assert_return (invoke "i16x8.relaxed_laneselect" + (v128.const i16x8 0 1 0x1234 0x1234 4 5 6 7) + (v128.const i16x8 8 9 0x5678 0x5678 12 13 14 15) + (v128.const i16x8 0xffff 0 0xff00 0x00ff 0 0 0 0)) + (either (v128.const i16x8 0 9 0x1278 0x5634 12 13 14 15) + (v128.const i16x8 0 9 0x1234 0x5678 12 13 14 15))) + +;; special case for i16x8 to allow pblendvb +(assert_return (invoke "i16x8.relaxed_laneselect" + (v128.const i16x8 0 1 0x1234 0x1234 4 5 6 7) + (v128.const i16x8 8 9 0x5678 0x5678 12 13 14 15) + (v128.const i16x8 0xffff 0 0xff00 0x0080 0 0 0 0)) ;; 0x0080 is the special case + (either (v128.const i16x8 0 9 0x1278 0x5678 12 13 14 15) ;; bitselect + (v128.const i16x8 0 9 0x1234 0x5678 12 13 14 15) ;; top bit of i16 lane examined + (v128.const i16x8 0 9 0x1278 0x5634 12 13 14 15) ;; top bit of each byte + )) + +(assert_return (invoke "i32x4.relaxed_laneselect" + (v128.const i32x4 0 1 0x12341234 0x12341234) + (v128.const i32x4 4 5 0x56785678 0x56785678) + (v128.const i32x4 0xffffffff 0 0xffff0000 0x0000ffff)) + (either (v128.const i32x4 0 5 0x12345678 0x56781234) + (v128.const i32x4 0 5 0x12341234 0x56785678))) + +(assert_return (invoke "i64x2.relaxed_laneselect" + (v128.const i64x2 0 1) + (v128.const i64x2 2 3) + (v128.const i64x2 0xffffffffffffffff 0)) + (either (v128.const i64x2 0 3) + (v128.const i64x2 0 3))) + +(assert_return (invoke "i64x2.relaxed_laneselect" + (v128.const i64x2 0x1234123412341234 0x1234123412341234) + (v128.const i64x2 0x5678567856785678 0x5678567856785678) + (v128.const i64x2 0xffffffff00000000 0x00000000ffffffff)) + (either (v128.const i64x2 0x1234123456785678 0x5678567812341234) + (v128.const i64x2 0x1234123412341234 0x5678567856785678))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +(assert_return (invoke "i8x16.relaxed_laneselect_cmp" + (v128.const i8x16 0 1 0x12 0x12 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 16 17 0x34 0x34 20 21 22 23 24 25 26 27 28 29 30 31) + (v128.const i8x16 0xff 0 0xf0 0x0f 0 0 0 0 0 0 0 0 0 0 0 0)) + (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) + +(assert_return (invoke "i16x8.relaxed_laneselect_cmp" + (v128.const i16x8 0 1 0x1234 0x1234 4 5 6 7) + (v128.const i16x8 8 9 0x5678 0x5678 12 13 14 15) + (v128.const i16x8 0xffff 0 0xff00 0x00ff 0 0 0 0)) + (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) + +(assert_return (invoke "i32x4.relaxed_laneselect_cmp" + (v128.const i32x4 0 1 0x12341234 0x12341234) + (v128.const i32x4 4 5 0x56785678 0x56785678) + (v128.const i32x4 0xffffffff 0 0xffff0000 0x0000ffff)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "i64x2.relaxed_laneselect_cmp" + (v128.const i64x2 0 1) + (v128.const i64x2 2 3) + (v128.const i64x2 0xffffffffffffffff 0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "i64x2.relaxed_laneselect_cmp" + (v128.const i64x2 0x1234123412341234 0x1234123412341234) + (v128.const i64x2 0x5678567856785678 0x5678567856785678) + (v128.const i64x2 0xffffffff00000000 0x00000000ffffffff)) + (v128.const i64x2 -1 -1)) diff --git a/proposals/wasm-3.0/relaxed_madd_nmadd.wast b/proposals/wasm-3.0/relaxed_madd_nmadd.wast new file mode 100644 index 0000000..187b71d --- /dev/null +++ b/proposals/wasm-3.0/relaxed_madd_nmadd.wast @@ -0,0 +1,224 @@ +;; Tests for f32x4.relaxed_madd, f32x4.relaxed_nmadd, f64x2.relaxed_madd, and f64x2.relaxed_nmadd. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "f32x4.relaxed_madd") (param v128 v128 v128) (result v128) (f32x4.relaxed_madd (local.get 0) (local.get 1) (local.get 2))) + (func (export "f32x4.relaxed_nmadd") (param v128 v128 v128) (result v128) (f32x4.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2))) + (func (export "f64x2.relaxed_nmadd") (param v128 v128 v128) (result v128) (f64x2.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2))) + (func (export "f64x2.relaxed_madd") (param v128 v128 v128) (result v128) (f64x2.relaxed_madd (local.get 0) (local.get 1) (local.get 2))) + + (func (export "f32x4.relaxed_madd_cmp") (param v128 v128 v128) (result v128) + (f32x4.eq + (f32x4.relaxed_madd (local.get 0) (local.get 1) (local.get 2)) + (f32x4.relaxed_madd (local.get 0) (local.get 1) (local.get 2)))) + (func (export "f32x4.relaxed_nmadd_cmp") (param v128 v128 v128) (result v128) + (f32x4.eq + (f32x4.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2)) + (f32x4.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2)))) + (func (export "f64x2.relaxed_nmadd_cmp") (param v128 v128 v128) (result v128) + (f64x2.eq + (f64x2.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2)) + (f64x2.relaxed_nmadd (local.get 0) (local.get 1) (local.get 2)))) + (func (export "f64x2.relaxed_madd_cmp") (param v128 v128 v128) (result v128) + (f64x2.eq + (f64x2.relaxed_madd (local.get 0) (local.get 1) (local.get 2)) + (f64x2.relaxed_madd (local.get 0) (local.get 1) (local.get 2)))) +) + + +;; FLT_MAX == 0x1.fffffep+127 +;; FLT_MAX * 2 - FLT_MAX == +;; FLT_MAX (if fma) +;; 0 (if no fma) +;; from https://www.vinc17.net/software/fma-tests.c +(assert_return (invoke "f32x4.relaxed_madd" + (v128.const f32x4 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 ) + (v128.const f32x4 2.0 2.0 2.0 2.0) + (v128.const f32x4 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127)) + (either (v128.const f32x4 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127) + (v128.const f32x4 inf inf inf inf))) + +;; Special values for float: +;; x = 0x1.000004p+0 (1 + 2^-22) +;; y = 0x1.0002p+0 (1 + 2^-15) +;; z = -(1.0 + 0x0.0002p+0 + 0x0.000004p+0) +;; = -0x1.000204p+0 +;; x.y = 1.0 + 0x0.0002p+0 + 0x0.000004p+0 + 0x1p-37 (round bit) +;; x.y+z = 0 (2 roundings) +;; fma(x, y, z) = (0x1p-37) 2^-37 +;; from https://accurate-algorithms.readthedocs.io/en/latest/ch09appendix.html#test-system-information +(assert_return (invoke "f32x4.relaxed_madd" + (v128.const f32x4 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0) + (v128.const f32x4 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (either (v128.const f32x4 0x1p-37 0x1p-37 0x1p-37 0x1p-37) + (v128.const f32x4 0 0 0 0))) +;; nmadd tests with negated x, same answers are expected. +(assert_return (invoke "f32x4.relaxed_nmadd" + (v128.const f32x4 -0x1.000004p+0 -0x1.000004p+0 -0x1.000004p+0 -0x1.000004p+0) + (v128.const f32x4 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (either (v128.const f32x4 0x1p-37 0x1p-37 0x1p-37 0x1p-37) + (v128.const f32x4 0 0 0 0))) +;; nmadd tests with negated y, same answers are expected. +(assert_return (invoke "f32x4.relaxed_nmadd" + (v128.const f32x4 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0) + (v128.const f32x4 -0x1.0002p+0 -0x1.0002p+0 -0x1.0002p+0 -0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (either (v128.const f32x4 0x1p-37 0x1p-37 0x1p-37 0x1p-37) + (v128.const f32x4 0 0 0 0))) + +;; DBL_MAX = 0x1.fffffffffffffp+1023 +;; DLB_MAX * 2 - DLB_MAX == +;; DLB_MAX (if fma) +;; 0 (if no fma) +;; form https://www.vinc17.net/software/fma-tests.c +;; from https://www.vinc17.net/software/fma-tests.c +(assert_return (invoke "f64x2.relaxed_madd" + (v128.const f64x2 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023) + (v128.const f64x2 2.0 2.0) + (v128.const f64x2 -0x1.fffffffffffffp+1023 -0x1.fffffffffffffp+1023)) + (either (v128.const f64x2 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023) + (v128.const f64x2 inf inf))) + +;; Special values for double: +;; x = 0x1.00000004p+0 (1 + 2^-30) +;; y = 0x1.000002p+0 (1 + 2^-23) +;; z = -(1.0 + 0x0.000002p+0 + 0x0.00000004p+0) +;; = -0x1.00000204p+0 +;; x.y = 1.0 + 0x0.000002p+0 + 0x0.00000004p+0 + 0x1p-53 (round bit) +;; x.y+z = 0 (2 roundings) +;; fma(x, y, z) = 0x1p-53 +;; from https://accurate-algorithms.readthedocs.io/en/latest/ch09appendix.html#test-system-information +(assert_return (invoke "f64x2.relaxed_madd" + (v128.const f64x2 0x1.00000004p+0 0x1.00000004p+0) + (v128.const f64x2 0x1.000002p+0 0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (either (v128.const f64x2 0x1p-53 0x1p-53) + (v128.const f64x2 0 0))) +;; nmadd tests with negated x, same answers are expected. +(assert_return (invoke "f64x2.relaxed_nmadd" + (v128.const f64x2 -0x1.00000004p+0 -0x1.00000004p+0) + (v128.const f64x2 0x1.000002p+0 0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (either (v128.const f64x2 0x1p-53 0x1p-53) + (v128.const f64x2 0 0))) +;; nmadd tests with negated y, same answers are expected. +(assert_return (invoke "f64x2.relaxed_nmadd" + (v128.const f64x2 0x1.00000004p+0 0x1.00000004p+0) + (v128.const f64x2 -0x1.000002p+0 -0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (either (v128.const f64x2 0x1p-53 0x1p-53) + (v128.const f64x2 0 0))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +;; FLT_MAX == 0x1.fffffep+127 +;; FLT_MAX * 2 - FLT_MAX == +;; FLT_MAX (if fma) +;; 0 (if no fma) +;; from https://www.vinc17.net/software/fma-tests.c +(assert_return (invoke "f32x4.relaxed_madd_cmp" + (v128.const f32x4 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 ) + (v128.const f32x4 2.0 2.0 2.0 2.0) + (v128.const f32x4 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127)) + (v128.const i32x4 -1 -1 -1 -1)) + +;; Special values for float: +;; x = 0x1.000004p+0 (1 + 2^-22) +;; y = 0x1.0002p+0 (1 + 2^-15) +;; z = -(1.0 + 0x0.0002p+0 + 0x0.000004p+0) +;; = -0x1.000204p+0 +;; x.y = 1.0 + 0x0.0002p+0 + 0x0.000004p+0 + 0x1p-37 (round bit) +;; x.y+z = 0 (2 roundings) +;; fma(x, y, z) = (0x1p-37) 2^-37 +;; from https://accurate-algorithms.readthedocs.io/en/latest/ch09appendix.html#test-system-information +(assert_return (invoke "f32x4.relaxed_madd_cmp" + (v128.const f32x4 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0) + (v128.const f32x4 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (v128.const i32x4 -1 -1 -1 -1)) +;; nmadd tests with negated x, same answers are expected. +(assert_return (invoke "f32x4.relaxed_nmadd_cmp" + (v128.const f32x4 -0x1.000004p+0 -0x1.000004p+0 -0x1.000004p+0 -0x1.000004p+0) + (v128.const f32x4 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0 0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (v128.const i32x4 -1 -1 -1 -1)) +;; nmadd tests with negated y, same answers are expected. +(assert_return (invoke "f32x4.relaxed_nmadd_cmp" + (v128.const f32x4 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0 0x1.000004p+0) + (v128.const f32x4 -0x1.0002p+0 -0x1.0002p+0 -0x1.0002p+0 -0x1.0002p+0) + (v128.const f32x4 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0 -0x1.000204p+0)) + (v128.const i32x4 -1 -1 -1 -1)) + +;; DBL_MAX = 0x1.fffffffffffffp+1023 +;; DLB_MAX * 2 - DLB_MAX == +;; DLB_MAX (if fma) +;; 0 (if no fma) +;; form https://www.vinc17.net/software/fma-tests.c +;; from https://www.vinc17.net/software/fma-tests.c +(assert_return (invoke "f64x2.relaxed_madd_cmp" + (v128.const f64x2 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023) + (v128.const f64x2 2.0 2.0) + (v128.const f64x2 -0x1.fffffffffffffp+1023 -0x1.fffffffffffffp+1023)) + (v128.const i64x2 -1 -1)) + +;; Special values for double: +;; x = 0x1.00000004p+0 (1 + 2^-30) +;; y = 0x1.000002p+0 (1 + 2^-23) +;; z = -(1.0 + 0x0.000002p+0 + 0x0.00000004p+0) +;; = -0x1.00000204p+0 +;; x.y = 1.0 + 0x0.000002p+0 + 0x0.00000004p+0 + 0x1p-53 (round bit) +;; x.y+z = 0 (2 roundings) +;; fma(x, y, z) = 0x1p-53 +;; from https://accurate-algorithms.readthedocs.io/en/latest/ch09appendix.html#test-system-information +(assert_return (invoke "f64x2.relaxed_madd_cmp" + (v128.const f64x2 0x1.00000004p+0 0x1.00000004p+0) + (v128.const f64x2 0x1.000002p+0 0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (v128.const i64x2 -1 -1)) +;; nmadd tests with negated x, same answers are expected. +(assert_return (invoke "f64x2.relaxed_nmadd_cmp" + (v128.const f64x2 -0x1.00000004p+0 -0x1.00000004p+0) + (v128.const f64x2 0x1.000002p+0 0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (v128.const i64x2 -1 -1)) +;; nmadd tests with negated y, same answers are expected. +(assert_return (invoke "f64x2.relaxed_nmadd_cmp" + (v128.const f64x2 0x1.00000004p+0 0x1.00000004p+0) + (v128.const f64x2 -0x1.000002p+0 -0x1.000002p+0) + (v128.const f64x2 -0x1.00000204p+0 -0x1.00000204p+0)) + (v128.const i64x2 -1 -1)) + +;; Test that the non-deterministic choice of fusing and then rounding or +;; rounding multiple times in `relaxed_madd` is consistent throughout a +;; program's execution. +;; +;; This property is impossible to test exhaustively, so this is just a simple +;; smoke test for when the operands to a `relaxed_madd` are known statically +;; versus when they are dynamically supplied. This should, at least, catch +;; illegal constant-folding and -propagation by the compiler that leads to +;; inconsistent rounding behavior at compile time versus at run time. +;; +;; FLT_MAX == 0x1.fffffep+127 +;; FLT_MAX * 2 - FLT_MAX == +;; FLT_MAX (if fma) +;; 0 (if no fma) +;; from https://www.vinc17.net/software/fma-tests.c +(module + (func (export "test-consistent-nondeterminism") (param v128 v128 v128) (result v128) + (f32x4.eq + (f32x4.relaxed_madd (v128.const f32x4 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 ) + (v128.const f32x4 2.0 2.0 2.0 2.0) + (v128.const f32x4 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127)) + (f32x4.relaxed_madd (local.get 0) + (local.get 1) + (local.get 2)) + ) + ) +) +(assert_return (invoke "test-consistent-nondeterminism" + (v128.const f32x4 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 0x1.fffffep+127 ) + (v128.const f32x4 2.0 2.0 2.0 2.0) + (v128.const f32x4 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127 -0x1.fffffep+127)) + (v128.const i32x4 -1 -1 -1 -1)) diff --git a/proposals/wasm-3.0/relaxed_min_max.wast b/proposals/wasm-3.0/relaxed_min_max.wast new file mode 100644 index 0000000..ac3ebb0 --- /dev/null +++ b/proposals/wasm-3.0/relaxed_min_max.wast @@ -0,0 +1,184 @@ +;; Tests for f32x4.min, f32x4.max, f64x2.min, and f64x2.max. +;; `either` comes from https://github.com/WebAssembly/threads. + +(module + (func (export "f32x4.relaxed_min") (param v128 v128) (result v128) (f32x4.relaxed_min (local.get 0) (local.get 1))) + (func (export "f32x4.relaxed_max") (param v128 v128) (result v128) (f32x4.relaxed_max (local.get 0) (local.get 1))) + (func (export "f64x2.relaxed_min") (param v128 v128) (result v128) (f64x2.relaxed_min (local.get 0) (local.get 1))) + (func (export "f64x2.relaxed_max") (param v128 v128) (result v128) (f64x2.relaxed_max (local.get 0) (local.get 1))) + + (func (export "f32x4.relaxed_min_cmp") (param v128 v128) (result v128) + (i32x4.eq + (f32x4.relaxed_min (local.get 0) (local.get 1)) + (f32x4.relaxed_min (local.get 0) (local.get 1)))) + (func (export "f32x4.relaxed_max_cmp") (param v128 v128) (result v128) + (i32x4.eq + (f32x4.relaxed_max (local.get 0) (local.get 1)) + (f32x4.relaxed_max (local.get 0) (local.get 1)))) + (func (export "f64x2.relaxed_min_cmp") (param v128 v128) (result v128) + (i64x2.eq + (f64x2.relaxed_min (local.get 0) (local.get 1)) + (f64x2.relaxed_min (local.get 0) (local.get 1)))) + (func (export "f64x2.relaxed_max_cmp") (param v128 v128) (result v128) + (i64x2.eq + (f64x2.relaxed_max (local.get 0) (local.get 1)) + (f64x2.relaxed_max (local.get 0) (local.get 1)))) +) + +(assert_return (invoke "f32x4.relaxed_min" + (v128.const f32x4 -nan nan 0 0) + (v128.const f32x4 0 0 -nan nan)) + (either (v128.const f32x4 nan:canonical nan:canonical nan:canonical nan:canonical) + (v128.const f32x4 nan:canonical nan:canonical 0 0) + (v128.const f32x4 0 0 nan:canonical nan:canonical) + (v128.const f32x4 0 0 0 0))) + +(assert_return (invoke "f32x4.relaxed_min" + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0)) + (either (v128.const f32x4 -0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 -0.0 +0.0 -0.0))) + +(assert_return (invoke "f32x4.relaxed_max" + (v128.const f32x4 -nan nan 0 0) + (v128.const f32x4 0 0 -nan nan)) + (either (v128.const f32x4 nan:canonical nan:canonical nan:canonical nan:canonical) + (v128.const f32x4 nan:canonical nan:canonical 0 0) + (v128.const f32x4 0 0 nan:canonical nan:canonical) + (v128.const f32x4 0 0 0 0))) + +(assert_return (invoke "f32x4.relaxed_max" + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0)) + (either (v128.const f32x4 +0.0 +0.0 +0.0 -0.0) + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 -0.0 +0.0 -0.0))) + +(assert_return (invoke "f64x2.relaxed_min" + (v128.const f64x2 -nan nan) + (v128.const f64x2 0 0)) + (either (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0) + (v128.const f64x2 0 0))) + +(assert_return (invoke "f64x2.relaxed_min" + (v128.const f64x2 0 0) + (v128.const f64x2 -nan nan)) + (either (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0) + (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0))) + +(assert_return (invoke "f64x2.relaxed_min" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0)) + (either (v128.const f64x2 -0.0 -0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0) + (v128.const f64x2 -0.0 -0.0))) + +(assert_return (invoke "f64x2.relaxed_min" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0)) + (either (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0))) + +(assert_return (invoke "f64x2.relaxed_max" + (v128.const f64x2 -nan nan) + (v128.const f64x2 0 0)) + (either (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0) + (v128.const f64x2 0 0))) + +(assert_return (invoke "f64x2.relaxed_max" + (v128.const f64x2 0 0) + (v128.const f64x2 -nan nan)) + (either (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0) + (v128.const f64x2 nan:canonical nan:canonical) + (v128.const f64x2 0 0))) + +(assert_return (invoke "f64x2.relaxed_max" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0)) + (either (v128.const f64x2 +0.0 +0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0) + (v128.const f64x2 -0.0 -0.0))) + +(assert_return (invoke "f64x2.relaxed_max" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0)) + (either (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0))) + +;; Check that multiple calls to the relaxed instruction with same inputs returns same results. + +(assert_return (invoke "f32x4.relaxed_min_cmp" + (v128.const f32x4 -nan nan 0 0) + (v128.const f32x4 0 0 -nan nan)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "f32x4.relaxed_min_cmp" + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "f32x4.relaxed_max_cmp" + (v128.const f32x4 -nan nan 0 0) + (v128.const f32x4 0 0 -nan nan)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "f32x4.relaxed_max_cmp" + (v128.const f32x4 +0.0 -0.0 +0.0 -0.0) + (v128.const f32x4 -0.0 +0.0 +0.0 -0.0)) + (v128.const i32x4 -1 -1 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_min_cmp" + (v128.const f64x2 -nan nan) + (v128.const f64x2 0 0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_min_cmp" + (v128.const f64x2 0 0) + (v128.const f64x2 -nan nan)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_min_cmp" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_min_cmp" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_max_cmp" + (v128.const f64x2 -nan nan) + (v128.const f64x2 0 0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_max_cmp" + (v128.const f64x2 0 0) + (v128.const f64x2 -nan nan)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_max_cmp" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 -0.0 +0.0)) + (v128.const i64x2 -1 -1)) + +(assert_return (invoke "f64x2.relaxed_max_cmp" + (v128.const f64x2 +0.0 -0.0) + (v128.const f64x2 +0.0 -0.0)) + (v128.const i64x2 -1 -1)) diff --git a/proposals/wasm-3.0/return_call.wast b/proposals/wasm-3.0/return_call.wast new file mode 100644 index 0000000..b9e8f8f --- /dev/null +++ b/proposals/wasm-3.0/return_call.wast @@ -0,0 +1,210 @@ +;; Test `return_call` operator + +(module + ;; Auxiliary definitions + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + (func $const-f32 (result f32) (f32.const 0xf32)) + (func $const-f64 (result f64) (f64.const 0xf64)) + + (func $id-i32 (param i32) (result i32) (local.get 0)) + (func $id-i64 (param i64) (result i64) (local.get 0)) + (func $id-f32 (param f32) (result f32) (local.get 0)) + (func $id-f64 (param f64) (result f64) (local.get 0)) + + (func $f32-i32 (param f32 i32) (result i32) (local.get 1)) + (func $i32-i64 (param i32 i64) (result i64) (local.get 1)) + (func $f64-f32 (param f64 f32) (result f32) (local.get 1)) + (func $i64-f64 (param i64 f64) (result f64) (local.get 1)) + + ;; Typing + + (func (export "type-i32") (result i32) (return_call $const-i32)) + (func (export "type-i64") (result i64) (return_call $const-i64)) + (func (export "type-f32") (result f32) (return_call $const-f32)) + (func (export "type-f64") (result f64) (return_call $const-f64)) + + (func (export "type-first-i32") (result i32) (return_call $id-i32 (i32.const 32))) + (func (export "type-first-i64") (result i64) (return_call $id-i64 (i64.const 64))) + (func (export "type-first-f32") (result f32) (return_call $id-f32 (f32.const 1.32))) + (func (export "type-first-f64") (result f64) (return_call $id-f64 (f64.const 1.64))) + + (func (export "type-second-i32") (result i32) + (return_call $f32-i32 (f32.const 32.1) (i32.const 32)) + ) + (func (export "type-second-i64") (result i64) + (return_call $i32-i64 (i32.const 32) (i64.const 64)) + ) + (func (export "type-second-f32") (result f32) + (return_call $f64-f32 (f64.const 64) (f32.const 32)) + ) + (func (export "type-second-f64") (result f64) + (return_call $i64-f64 (i64.const 64) (f64.const 64.1)) + ) + + ;; Recursion + + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call $fac-acc + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + ) + ) + ) + ) + + (func $count (export "count") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 0)) + (else (return_call $count (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + + (func $even (export "even") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 44)) + (else (return_call $odd (i64.sub (local.get 0) (i64.const 1)))) + ) + ) + (func $odd (export "odd") (param i64) (result i32) + (if (result i32) (i64.eqz (local.get 0)) + (then (i32.const 99)) + (else (return_call $even (i64.sub (local.get 0) (i64.const 1)))) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "count" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0)) + +(assert_return (invoke "even" (i64.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i64.const 1_000_000)) (i32.const 44)) +(assert_return (invoke "even" (i64.const 1_000_001)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i64.const 1_000_000)) (i32.const 99)) +(assert_return (invoke "odd" (i64.const 999_999)) (i32.const 44)) + + +;; Invalid typing + +(assert_invalid + (module + (func $type-void-vs-num (result i32) (return_call 1) (i32.const 0)) + (func) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-num-vs-num (result i32) (return_call 1) (i32.const 0)) + (func (result i64) (i64.const 1)) + ) + "type mismatch" +) + +(assert_invalid + (module + (func $arity-0-vs-1 (return_call 1)) + (func (param i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $arity-0-vs-2 (return_call 1)) + (func (param f64 i32)) + ) + "type mismatch" +) + +(module + (func $arity-1-vs-0 (i32.const 1) (return_call 1)) + (func) +) + +(module + (func $arity-2-vs-0 (f64.const 2) (i32.const 1) (return_call 1)) + (func) +) + +(assert_invalid + (module + (func $type-first-void-vs-num (return_call 1 (nop) (i32.const 1))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-void-vs-num (return_call 1 (i32.const 1) (nop))) + (func (param i32 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-first-num-vs-num (return_call 1 (f64.const 1) (i32.const 1))) + (func (param i32 f64)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-second-num-vs-num (return_call 1 (i32.const 1) (f64.const 1))) + (func (param f64 i32)) + ) + "type mismatch" +) +(assert_invalid + (module + (func $f (result i32 i32) unreachable) + (func (result i32) + return_call $f + ) + ) + "type mismatch" +) + +;; Unbound function + +(assert_invalid + (module (func $unbound-func (return_call 1))) + "unknown function" +) +(assert_invalid + (module (func $large-func (return_call 1012321300))) + "unknown function" +) diff --git a/proposals/wasm-3.0/return_call_indirect.wast b/proposals/wasm-3.0/return_call_indirect.wast new file mode 100644 index 0000000..aa158be --- /dev/null +++ b/proposals/wasm-3.0/return_call_indirect.wast @@ -0,0 +1,546 @@ +;; Test `return_call_indirect` operator + +(module + ;; Auxiliary definitions + (type $proc (func)) + (type $out-i32 (func (result i32))) + (type $out-i64 (func (result i64))) + (type $out-f32 (func (result f32))) + (type $out-f64 (func (result f64))) + (type $over-i32 (func (param i32) (result i32))) + (type $over-i64 (func (param i64) (result i64))) + (type $over-f32 (func (param f32) (result f32))) + (type $over-f64 (func (param f64) (result f64))) + (type $f32-i32 (func (param f32 i32) (result i32))) + (type $i32-i64 (func (param i32 i64) (result i64))) + (type $f64-f32 (func (param f64 f32) (result f32))) + (type $i64-f64 (func (param i64 f64) (result f64))) + (type $over-i32-duplicate (func (param i32) (result i32))) + (type $over-i64-duplicate (func (param i64) (result i64))) + (type $over-f32-duplicate (func (param f32) (result f32))) + (type $over-f64-duplicate (func (param f64) (result f64))) + + (func $const-i32 (type $out-i32) (i32.const 0x132)) + (func $const-i64 (type $out-i64) (i64.const 0x164)) + (func $const-f32 (type $out-f32) (f32.const 0xf32)) + (func $const-f64 (type $out-f64) (f64.const 0xf64)) + + (func $id-i32 (type $over-i32) (local.get 0)) + (func $id-i64 (type $over-i64) (local.get 0)) + (func $id-f32 (type $over-f32) (local.get 0)) + (func $id-f64 (type $over-f64) (local.get 0)) + + (func $i32-i64 (type $i32-i64) (local.get 1)) + (func $i64-f64 (type $i64-f64) (local.get 1)) + (func $f32-i32 (type $f32-i32) (local.get 1)) + (func $f64-f32 (type $f64-f32) (local.get 1)) + + (func $over-i32-duplicate (type $over-i32-duplicate) (local.get 0)) + (func $over-i64-duplicate (type $over-i64-duplicate) (local.get 0)) + (func $over-f32-duplicate (type $over-f32-duplicate) (local.get 0)) + (func $over-f64-duplicate (type $over-f64-duplicate) (local.get 0)) + + (table funcref + (elem + $const-i32 $const-i64 $const-f32 $const-f64 + $id-i32 $id-i64 $id-f32 $id-f64 + $f32-i32 $i32-i64 $f64-f32 $i64-f64 + $fac $fac-acc $even $odd + $over-i32-duplicate $over-i64-duplicate + $over-f32-duplicate $over-f64-duplicate + ) + ) + + ;; Syntax + + (func + (return_call_indirect (i32.const 0)) + (return_call_indirect (param i64) (i64.const 0) (i32.const 0)) + (return_call_indirect (param i64) (param) (param f64 i32 i64) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + (return_call_indirect (result) (i32.const 0)) + ) + + (func (result i32) + (return_call_indirect (result i32) (i32.const 0)) + (return_call_indirect (result i32) (result) (i32.const 0)) + (return_call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0)) + (return_call_indirect + (param) (param i64) (param) (param f64 i32 i64) (param) (param) + (result) (result i32) (result) (result) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + ) + + (func (result i64) + (return_call_indirect (type $over-i64) (param i64) (result i64) + (i64.const 0) (i32.const 0) + ) + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (return_call_indirect (type $out-i32) (i32.const 0)) + ) + (func (export "type-i64") (result i64) + (return_call_indirect (type $out-i64) (i32.const 1)) + ) + (func (export "type-f32") (result f32) + (return_call_indirect (type $out-f32) (i32.const 2)) + ) + (func (export "type-f64") (result f64) + (return_call_indirect (type $out-f64) (i32.const 3)) + ) + + (func (export "type-index") (result i64) + (return_call_indirect (type $over-i64) (i64.const 100) (i32.const 5)) + ) + + (func (export "type-first-i32") (result i32) + (return_call_indirect (type $over-i32) (i32.const 32) (i32.const 4)) + ) + (func (export "type-first-i64") (result i64) + (return_call_indirect (type $over-i64) (i64.const 64) (i32.const 5)) + ) + (func (export "type-first-f32") (result f32) + (return_call_indirect (type $over-f32) (f32.const 1.32) (i32.const 6)) + ) + (func (export "type-first-f64") (result f64) + (return_call_indirect (type $over-f64) (f64.const 1.64) (i32.const 7)) + ) + + (func (export "type-second-i32") (result i32) + (return_call_indirect (type $f32-i32) + (f32.const 32.1) (i32.const 32) (i32.const 8) + ) + ) + (func (export "type-second-i64") (result i64) + (return_call_indirect (type $i32-i64) + (i32.const 32) (i64.const 64) (i32.const 9) + ) + ) + (func (export "type-second-f32") (result f32) + (return_call_indirect (type $f64-f32) + (f64.const 64) (f32.const 32) (i32.const 10) + ) + ) + (func (export "type-second-f64") (result f64) + (return_call_indirect (type $i64-f64) + (i64.const 64) (f64.const 64.1) (i32.const 11) + ) + ) + + ;; Dispatch + + (func (export "dispatch") (param i32 i64) (result i64) + (return_call_indirect (type $over-i64) (local.get 1) (local.get 0)) + ) + + (func (export "dispatch-structural") (param i32) (result i64) + (return_call_indirect (type $over-i64-duplicate) + (i64.const 9) (local.get 0) + ) + ) + + ;; Multiple tables + + (table $tab2 funcref (elem $tab-f1)) + (table $tab3 funcref (elem $tab-f2)) + + (func $tab-f1 (result i32) (i32.const 0x133)) + (func $tab-f2 (result i32) (i32.const 0x134)) + + (func (export "call-tab") (param $i i32) (result i32) + (if (i32.eq (local.get $i) (i32.const 0)) + (then (return_call_indirect (type $out-i32) (i32.const 0))) + ) + (if (i32.eq (local.get $i) (i32.const 1)) + (then (return_call_indirect 1 (type $out-i32) (i32.const 0))) + ) + (if (i32.eq (local.get $i) (i32.const 2)) + (then (return_call_indirect $tab3 (type $out-i32) (i32.const 0))) + ) + (i32.const 0) + ) + + ;; Recursion + + (func $fac (export "fac") (type $over-i64) + (return_call_indirect (param i64 i64) (result i64) + (local.get 0) (i64.const 1) (i32.const 13) + ) + ) + + (func $fac-acc (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call_indirect (param i64 i64) (result i64) + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (i32.const 13) + ) + ) + ) + ) + + (func $even (export "even") (param i32) (result i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 44)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 15) + ) + ) + ) + ) + (func $odd (export "odd") (param i32) (result i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 99)) + (else + (return_call_indirect (type $over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 14) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-index") (i64.const 100)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 2)) (i64.const 2)) +(assert_return (invoke "dispatch" (i32.const 5) (i64.const 5)) (i64.const 5)) +(assert_return (invoke "dispatch" (i32.const 12) (i64.const 5)) (i64.const 120)) +(assert_return (invoke "dispatch" (i32.const 17) (i64.const 2)) (i64.const 2)) +(assert_trap (invoke "dispatch" (i32.const 0) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 15) (i64.const 2)) "indirect call type mismatch") +(assert_trap (invoke "dispatch" (i32.const 20) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const -1) (i64.const 2)) "undefined element") +(assert_trap (invoke "dispatch" (i32.const 1213432423) (i64.const 2)) "undefined element") + +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 5)) (i64.const 9)) +(assert_return (invoke "dispatch-structural" (i32.const 12)) (i64.const 362880)) +(assert_return (invoke "dispatch-structural" (i32.const 17)) (i64.const 9)) +(assert_trap (invoke "dispatch-structural" (i32.const 11)) "indirect call type mismatch") +(assert_trap (invoke "dispatch-structural" (i32.const 16)) "indirect call type mismatch") + +(assert_return (invoke "call-tab" (i32.const 0)) (i32.const 0x132)) +(assert_return (invoke "call-tab" (i32.const 1)) (i32.const 0x133)) +(assert_return (invoke "call-tab" (i32.const 2)) (i32.const 0x134)) + +(assert_return (invoke "fac" (i64.const 0)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac" (i64.const 5)) (i64.const 120)) +(assert_return (invoke "fac" (i64.const 25)) (i64.const 7034535277573963776)) + +(assert_return (invoke "even" (i32.const 0)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 1)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 77)) (i32.const 99)) +(assert_return (invoke "even" (i32.const 100_000)) (i32.const 44)) +(assert_return (invoke "even" (i32.const 111_111)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 0)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 1)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 77)) (i32.const 44)) +(assert_return (invoke "odd" (i32.const 200_002)) (i32.const 99)) +(assert_return (invoke "odd" (i32.const 300_003)) (i32.const 44)) + + +;; Invalid syntax + +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (param i32) (type $sig) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (param i32) (result i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32) (type $sig)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (result i32) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "unexpected token" +) + +(assert_malformed + (module quote + "(table 0 funcref)" + "(func (return_call_indirect (param $x i32) (i32.const 0) (i32.const 0)))" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(type $sig (func))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (result i32) (i32.const 0))" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32) (result i32)))" + "(table 0 funcref)" + "(func" + " (return_call_indirect (type $sig) (param i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) +(assert_malformed + (module quote + "(type $sig (func (param i32 i32) (result i32)))" + "(table 0 funcref)" + "(func (result i32)" + " (return_call_indirect (type $sig) (param i32) (result i32)" + " (i32.const 0) (i32.const 0)" + " )" + ")" + ) + "inline function type" +) + +;; Invalid typing + +(assert_invalid + (module + (type (func)) + (func $no-table (return_call_indirect (type 0) (i32.const 0))) + ) + "unknown table" +) + +(assert_invalid + (module + (type (func)) + (table 0 funcref) + (func $type-void-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (result i64))) + (table 0 funcref) + (func $type-num-vs-num (i32.eqz (return_call_indirect (type 0) (i32.const 0)))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $arity-0-vs-1 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 funcref) + (func $arity-0-vs-2 (return_call_indirect (type 0) (i32.const 0))) + ) + "type mismatch" +) + +(module + (type (func)) + (table 0 funcref) + (func $arity-1-vs-0 (return_call_indirect (type 0) (i32.const 1) (i32.const 0))) +) + +(module + (type (func)) + (table 0 funcref) + (func $arity-2-vs-0 + (return_call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0)) + ) +) + +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $type-func-void-vs-i32 (return_call_indirect (type 0) (i32.const 1) (nop))) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32))) + (table 0 funcref) + (func $type-func-num-vs-i32 (return_call_indirect (type 0) (i32.const 0) (i64.const 1))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 funcref) + (func $type-first-void-vs-num + (return_call_indirect (type 0) (nop) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 i32))) + (table 0 funcref) + (func $type-second-void-vs-num + (return_call_indirect (type 0) (i32.const 1) (nop) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param i32 f64))) + (table 0 funcref) + (func $type-first-num-vs-num + (return_call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type (func (param f64 i32))) + (table 0 funcref) + (func $type-second-num-vs-num + (return_call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $ty (func (result i32 i32))) + (import "env" "table" (table $table 0 funcref)) + (func (param i32) (result i32) + local.get 0 + return_call_indirect $table (type $ty) + ) + ) + "type mismatch" +) + +;; Unbound type + +(assert_invalid + (module + (table 0 funcref) + (func $unbound-type (return_call_indirect (type 1) (i32.const 0))) + ) + "unknown type" +) +(assert_invalid + (module + (table 0 funcref) + (func $large-type (return_call_indirect (type 1012321300) (i32.const 0))) + ) + "unknown type" +) + + +;; Unbound function in table + +(assert_invalid + (module (table funcref (elem 0 0))) + "unknown function 0" +) diff --git a/proposals/wasm-3.0/return_call_ref.wast b/proposals/wasm-3.0/return_call_ref.wast new file mode 100644 index 0000000..5f5a7cb --- /dev/null +++ b/proposals/wasm-3.0/return_call_ref.wast @@ -0,0 +1,397 @@ +;; Test `return_call_ref` operator + +(module + ;; Auxiliary definitions + (type $proc (func)) + (type $-i32 (func (result i32))) + (type $-i64 (func (result i64))) + (type $-f32 (func (result f32))) + (type $-f64 (func (result f64))) + + (type $i32-i32 (func (param i32) (result i32))) + (type $i64-i64 (func (param i64) (result i64))) + (type $f32-f32 (func (param f32) (result f32))) + (type $f64-f64 (func (param f64) (result f64))) + + (type $f32-i32 (func (param f32 i32) (result i32))) + (type $i32-i64 (func (param i32 i64) (result i64))) + (type $f64-f32 (func (param f64 f32) (result f32))) + (type $i64-f64 (func (param i64 f64) (result f64))) + + (type $i64i64-i64 (func (param i64 i64) (result i64))) + + (func $const-i32 (result i32) (i32.const 0x132)) + (func $const-i64 (result i64) (i64.const 0x164)) + (func $const-f32 (result f32) (f32.const 0xf32)) + (func $const-f64 (result f64) (f64.const 0xf64)) + + (func $id-i32 (param i32) (result i32) (local.get 0)) + (func $id-i64 (param i64) (result i64) (local.get 0)) + (func $id-f32 (param f32) (result f32) (local.get 0)) + (func $id-f64 (param f64) (result f64) (local.get 0)) + + (func $f32-i32 (param f32 i32) (result i32) (local.get 1)) + (func $i32-i64 (param i32 i64) (result i64) (local.get 1)) + (func $f64-f32 (param f64 f32) (result f32) (local.get 1)) + (func $i64-f64 (param i64 f64) (result f64) (local.get 1)) + + (global $const-i32 (ref $-i32) (ref.func $const-i32)) + (global $const-i64 (ref $-i64) (ref.func $const-i64)) + (global $const-f32 (ref $-f32) (ref.func $const-f32)) + (global $const-f64 (ref $-f64) (ref.func $const-f64)) + + (global $id-i32 (ref $i32-i32) (ref.func $id-i32)) + (global $id-i64 (ref $i64-i64) (ref.func $id-i64)) + (global $id-f32 (ref $f32-f32) (ref.func $id-f32)) + (global $id-f64 (ref $f64-f64) (ref.func $id-f64)) + + (global $f32-i32 (ref $f32-i32) (ref.func $f32-i32)) + (global $i32-i64 (ref $i32-i64) (ref.func $i32-i64)) + (global $f64-f32 (ref $f64-f32) (ref.func $f64-f32)) + (global $i64-f64 (ref $i64-f64) (ref.func $i64-f64)) + + (elem declare func + $const-i32 $const-i64 $const-f32 $const-f64 + $id-i32 $id-i64 $id-f32 $id-f64 + $f32-i32 $i32-i64 $f64-f32 $i64-f64 + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (return_call_ref $-i32 (global.get $const-i32)) + ) + (func (export "type-i64") (result i64) + (return_call_ref $-i64 (global.get $const-i64)) + ) + (func (export "type-f32") (result f32) + (return_call_ref $-f32 (global.get $const-f32)) + ) + (func (export "type-f64") (result f64) + (return_call_ref $-f64 (global.get $const-f64)) + ) + + (func (export "type-first-i32") (result i32) + (return_call_ref $i32-i32 (i32.const 32) (global.get $id-i32)) + ) + (func (export "type-first-i64") (result i64) + (return_call_ref $i64-i64 (i64.const 64) (global.get $id-i64)) + ) + (func (export "type-first-f32") (result f32) + (return_call_ref $f32-f32 (f32.const 1.32) (global.get $id-f32)) + ) + (func (export "type-first-f64") (result f64) + (return_call_ref $f64-f64 (f64.const 1.64) (global.get $id-f64)) + ) + + (func (export "type-second-i32") (result i32) + (return_call_ref $f32-i32 (f32.const 32.1) (i32.const 32) (global.get $f32-i32)) + ) + (func (export "type-second-i64") (result i64) + (return_call_ref $i32-i64 (i32.const 32) (i64.const 64) (global.get $i32-i64)) + ) + (func (export "type-second-f32") (result f32) + (return_call_ref $f64-f32 (f64.const 64) (f32.const 32) (global.get $f64-f32)) + ) + (func (export "type-second-f64") (result f64) + (return_call_ref $i64-f64 (i64.const 64) (f64.const 64.1) (global.get $i64-f64)) + ) + + ;; Null + + (func (export "null") + (return_call_ref $proc (ref.null $proc)) + ) + + ;; Recursion + + (global $fac-acc (ref $i64i64-i64) (ref.func $fac-acc)) + + (elem declare func $fac-acc) + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 1)) + (else + (return_call_ref $i64i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (i64.mul (local.get 0) (local.get 1)) + (global.get $fac-acc) + ) + ) + ) + ) + + (global $count (ref $i64-i64) (ref.func $count)) + + (elem declare func $count) + (func $count (export "count") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (local.get 0)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $count) + ) + ) + ) + ) + + (global $even (ref $i64-i64) (ref.func $even)) + (global $odd (ref $i64-i64) (ref.func $odd)) + + (elem declare func $even) + (func $even (export "even") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 44)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $odd) + ) + ) + ) + ) + (elem declare func $odd) + (func $odd (export "odd") (param i64) (result i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 99)) + (else + (return_call_ref $i64-i64 + (i64.sub (local.get 0) (i64.const 1)) + (global.get $even) + ) + ) + ) + ) +) + +(assert_return (invoke "type-i32") (i32.const 0x132)) +(assert_return (invoke "type-i64") (i64.const 0x164)) +(assert_return (invoke "type-f32") (f32.const 0xf32)) +(assert_return (invoke "type-f64") (f64.const 0xf64)) + +(assert_return (invoke "type-first-i32") (i32.const 32)) +(assert_return (invoke "type-first-i64") (i64.const 64)) +(assert_return (invoke "type-first-f32") (f32.const 1.32)) +(assert_return (invoke "type-first-f64") (f64.const 1.64)) + +(assert_return (invoke "type-second-i32") (i32.const 32)) +(assert_return (invoke "type-second-i64") (i64.const 64)) +(assert_return (invoke "type-second-f32") (f32.const 32)) +(assert_return (invoke "type-second-f64") (f64.const 64.1)) + +(assert_trap (invoke "null") "null function reference") + +(assert_return (invoke "fac-acc" (i64.const 0) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 1) (i64.const 1)) (i64.const 1)) +(assert_return (invoke "fac-acc" (i64.const 5) (i64.const 1)) (i64.const 120)) +(assert_return + (invoke "fac-acc" (i64.const 25) (i64.const 1)) + (i64.const 7034535277573963776) +) + +(assert_return (invoke "count" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1000)) (i64.const 0)) +(assert_return (invoke "count" (i64.const 1_000_000)) (i64.const 0)) + +(assert_return (invoke "even" (i64.const 0)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 1)) (i64.const 99)) +(assert_return (invoke "even" (i64.const 100)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 77)) (i64.const 99)) +(assert_return (invoke "even" (i64.const 1_000_000)) (i64.const 44)) +(assert_return (invoke "even" (i64.const 1_000_001)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 0)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 1)) (i64.const 44)) +(assert_return (invoke "odd" (i64.const 200)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 77)) (i64.const 44)) +(assert_return (invoke "odd" (i64.const 1_000_000)) (i64.const 99)) +(assert_return (invoke "odd" (i64.const 999_999)) (i64.const 44)) + + +;; More typing + +(module + (type $t (func)) + (type $t1 (func (result (ref $t)))) + (type $t2 (func (result (ref null $t)))) + (type $t3 (func (result (ref func)))) + (type $t4 (func (result (ref null func)))) + (elem declare func $f11 $f22 $f33 $f44) + (func $f11 (result (ref $t)) (return_call_ref $t1 (ref.func $f11))) + (func $f21 (result (ref null $t)) (return_call_ref $t1 (ref.func $f11))) + (func $f22 (result (ref null $t)) (return_call_ref $t2 (ref.func $f22))) + (func $f31 (result (ref func)) (return_call_ref $t1 (ref.func $f11))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + (func $f41 (result (ref null func)) (return_call_ref $t1 (ref.func $f11))) + (func $f42 (result (ref null func)) (return_call_ref $t2 (ref.func $f22))) + (func $f43 (result (ref null func)) (return_call_ref $t3 (ref.func $f33))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) +) + +(assert_invalid + (module + (type $t (func)) + (type $t2 (func (result (ref null $t)))) + (elem declare func $f22) + (func $f12 (result (ref $t)) (return_call_ref $t2 (ref.func $f22))) + (func $f22 (result (ref null $t)) (return_call_ref $t2 (ref.func $f22))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t3 (func (result (ref func)))) + (elem declare func $f33) + (func $f13 (result (ref $t)) (return_call_ref $t3 (ref.func $f33))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f14 (result (ref $t)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t3 (func (result (ref func)))) + (elem declare func $f33) + (func $f23 (result (ref null $t)) (return_call_ref $t3 (ref.func $f33))) + (func $f33 (result (ref func)) (return_call_ref $t3 (ref.func $f33))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f24 (result (ref null $t)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t4 (func (result (ref null func)))) + (elem declare func $f44) + (func $f34 (result (ref func)) (return_call_ref $t4 (ref.func $f44))) + (func $f44 (result (ref null func)) (return_call_ref $t4 (ref.func $f44))) + ) + "type mismatch" +) + + +;; Unreachable typing. + +(module + (type $t (func (result i32))) + (func (export "unreachable") (result i32) + (unreachable) + (return_call_ref $t) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.func $f) + (return_call_ref $t) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (i32.const 0) + (ref.func $f) + (return_call_ref $t) + (i32.const 0) + ) +) +(assert_trap (invoke "unreachable") "unreachable") + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (i64.const 0) + (ref.func $f) + (return_call_ref $t) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (elem declare func $f) + (type $t (func (param i32) (result i32))) + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "unreachable") (result i32) + (unreachable) + (ref.func $f) + (return_call_ref $t) + (i64.const 0) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $f (param $r externref) + (return_call_ref $t (local.get $r)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $t (func)) + (func $f (param $r funcref) + (return_call_ref $t (local.get $r)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $ty (func (result i32 i32))) + (func (param (ref $ty)) (result i32) + local.get 0 + return_call_ref $ty + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/select.wast b/proposals/wasm-3.0/select.wast new file mode 100644 index 0000000..61e4dc2 --- /dev/null +++ b/proposals/wasm-3.0/select.wast @@ -0,0 +1,592 @@ +(module + ;; Auxiliary + (func $dummy) + (table $tab funcref (elem $dummy)) + (memory 1) + + (func (export "select-i32") (param i32 i32 i32) (result i32) + (select (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-i64") (param i64 i64 i32) (result i64) + (select (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-f32") (param f32 f32 i32) (result f32) + (select (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-f64") (param f64 f64 i32) (result f64) + (select (local.get 0) (local.get 1) (local.get 2)) + ) + + (func (export "select-i32-t") (param i32 i32 i32) (result i32) + (select (result i32) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-i64-t") (param i64 i64 i32) (result i64) + (select (result i64) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-f32-t") (param f32 f32 i32) (result f32) + (select (result f32) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-f64-t") (param f64 f64 i32) (result f64) + (select (result f64) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-funcref") (param funcref funcref i32) (result funcref) + (select (result funcref) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "select-externref") (param externref externref i32) (result externref) + (select (result externref) (local.get 0) (local.get 1) (local.get 2)) + ) + + (type $t (func)) + (func $tf) (elem declare func $tf) + (func (export "join-funcnull") (param i32) (result (ref null func)) + (select (result (ref null func)) + (ref.func $tf) + (ref.null func) + (local.get 0) + ) + ) + + ;; Check that both sides of the select are evaluated + (func (export "select-trap-left") (param $cond i32) (result i32) + (select (unreachable) (i32.const 0) (local.get $cond)) + ) + (func (export "select-trap-right") (param $cond i32) (result i32) + (select (i32.const 0) (unreachable) (local.get $cond)) + ) + + (func (export "select-unreached") + (unreachable) (select) + (unreachable) (i32.const 0) (select) + (unreachable) (i32.const 0) (i32.const 0) (select) + (unreachable) (i32.const 0) (i32.const 0) (i32.const 0) (select) + (unreachable) (f32.const 0) (i32.const 0) (select) + (unreachable) + ) + + (func (export "select_unreached_result_1") (result i32) + (unreachable) (i32.add (select)) + ) + + (func (export "select_unreached_result_2") (result i64) + (unreachable) (i64.add (select (i64.const 0) (i32.const 0))) + ) + + + ;; As the argument of control constructs and instructions + + (func (export "as-select-first") (param i32) (result i32) + (select (select (i32.const 0) (i32.const 1) (local.get 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-select-mid") (param i32) (result i32) + (select (i32.const 2) (select (i32.const 0) (i32.const 1) (local.get 0)) (i32.const 3)) + ) + (func (export "as-select-last") (param i32) (result i32) + (select (i32.const 2) (i32.const 3) (select (i32.const 0) (i32.const 1) (local.get 0))) + ) + + (func (export "as-loop-first") (param i32) (result i32) + (loop (result i32) (select (i32.const 2) (i32.const 3) (local.get 0)) (call $dummy) (call $dummy)) + ) + (func (export "as-loop-mid") (param i32) (result i32) + (loop (result i32) (call $dummy) (select (i32.const 2) (i32.const 3) (local.get 0)) (call $dummy)) + ) + (func (export "as-loop-last") (param i32) (result i32) + (loop (result i32) (call $dummy) (call $dummy) (select (i32.const 2) (i32.const 3) (local.get 0))) + ) + + (func (export "as-if-condition") (param i32) + (select (i32.const 2) (i32.const 3) (local.get 0)) (if (then (call $dummy))) + ) + (func (export "as-if-then") (param i32) (result i32) + (if (result i32) (i32.const 1) (then (select (i32.const 2) (i32.const 3) (local.get 0))) (else (i32.const 4))) + ) + (func (export "as-if-else") (param i32) (result i32) + (if (result i32) (i32.const 0) (then (i32.const 2)) (else (select (i32.const 2) (i32.const 3) (local.get 0)))) + ) + + (func (export "as-br_if-first") (param i32) (result i32) + (block (result i32) (br_if 0 (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 4))) + ) + (func (export "as-br_if-last") (param i32) (result i32) + (block (result i32) (br_if 0 (i32.const 2) (select (i32.const 2) (i32.const 3) (local.get 0)))) + ) + + (func (export "as-br_table-first") (param i32) (result i32) + (block (result i32) (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 2) (br_table 0 0)) + ) + (func (export "as-br_table-last") (param i32) (result i32) + (block (result i32) (i32.const 2) (select (i32.const 2) (i32.const 3) (local.get 0)) (br_table 0 0)) + ) + + (func $func (param i32 i32) (result i32) (local.get 0)) + (type $check (func (param i32 i32) (result i32))) + (table $t funcref (elem $func)) + (func (export "as-call_indirect-first") (param i32) (result i32) + (block (result i32) + (call_indirect $t (type $check) + (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 1) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-mid") (param i32) (result i32) + (block (result i32) + (call_indirect $t (type $check) + (i32.const 1) (select (i32.const 2) (i32.const 3) (local.get 0)) (i32.const 0) + ) + ) + ) + (func (export "as-call_indirect-last") (param i32) (result i32) + (block (result i32) + (call_indirect $t (type $check) + (i32.const 1) (i32.const 4) (select (i32.const 2) (i32.const 3) (local.get 0)) + ) + ) + ) + + (func (export "as-store-first") (param i32) + (select (i32.const 0) (i32.const 4) (local.get 0)) (i32.const 1) (i32.store) + ) + (func (export "as-store-last") (param i32) + (i32.const 8) (select (i32.const 1) (i32.const 2) (local.get 0)) (i32.store) + ) + + (func (export "as-memory.grow-value") (param i32) (result i32) + (memory.grow (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + + (func $f (param i32) (result i32) (local.get 0)) + + (func (export "as-call-value") (param i32) (result i32) + (call $f (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + (func (export "as-return-value") (param i32) (result i32) + (select (i32.const 1) (i32.const 2) (local.get 0)) (return) + ) + (func (export "as-drop-operand") (param i32) + (drop (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + (func (export "as-br-value") (param i32) (result i32) + (block (result i32) (br 0 (select (i32.const 1) (i32.const 2) (local.get 0)))) + ) + (func (export "as-local.set-value") (param i32) (result i32) + (local i32) (local.set 0 (select (i32.const 1) (i32.const 2) (local.get 0))) (local.get 0) + ) + (func (export "as-local.tee-value") (param i32) (result i32) + (local.tee 0 (select (i32.const 1) (i32.const 2) (local.get 0))) + ) + (global $a (mut i32) (i32.const 10)) + (func (export "as-global.set-value") (param i32) (result i32) + (global.set $a (select (i32.const 1) (i32.const 2) (local.get 0))) + (global.get $a) + ) + (func (export "as-load-operand") (param i32) (result i32) + (i32.load (select (i32.const 0) (i32.const 4) (local.get 0))) + ) + + (func (export "as-unary-operand") (param i32) (result i32) + (i32.eqz (select (i32.const 0) (i32.const 1) (local.get 0))) + ) + (func (export "as-binary-operand") (param i32) (result i32) + (i32.mul + (select (i32.const 1) (i32.const 2) (local.get 0)) + (select (i32.const 1) (i32.const 2) (local.get 0)) + ) + ) + (func (export "as-test-operand") (param i32) (result i32) + (block (result i32) + (i32.eqz (select (i32.const 0) (i32.const 1) (local.get 0))) + ) + ) + + (func (export "as-compare-left") (param i32) (result i32) + (block (result i32) + (i32.le_s (select (i32.const 1) (i32.const 2) (local.get 0)) (i32.const 1)) + ) + ) + (func (export "as-compare-right") (param i32) (result i32) + (block (result i32) + (i32.ne (i32.const 1) (select (i32.const 0) (i32.const 1) (local.get 0))) + ) + ) + + (func (export "as-convert-operand") (param i32) (result i32) + (block (result i32) + (i32.wrap_i64 (select (i64.const 1) (i64.const 0) (local.get 0))) + ) + ) +) + +(assert_return (invoke "select-i32" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2)) +(assert_return (invoke "select-f32" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1)) +(assert_return (invoke "select-f64" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1)) + +(assert_return (invoke "select-i32" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2)) +(assert_return (invoke "select-i32" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2)) +(assert_return (invoke "select-i64" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2)) + +(assert_return (invoke "select-f32" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan)) +(assert_return (invoke "select-f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304)) +(assert_return (invoke "select-f32" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1)) +(assert_return (invoke "select-f32" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1)) +(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2)) +(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2)) +(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan)) +(assert_return (invoke "select-f32" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304)) + +(assert_return (invoke "select-f64" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan)) +(assert_return (invoke "select-f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304)) +(assert_return (invoke "select-f64" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1)) +(assert_return (invoke "select-f64" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1)) +(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2)) +(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2)) +(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) +(assert_return (invoke "select-f64" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) + +(assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 1)) (i64.const 2)) +(assert_return (invoke "select-f32-t" (f32.const 1) (f32.const 2) (i32.const 1)) (f32.const 1)) +(assert_return (invoke "select-f64-t" (f64.const 1) (f64.const 2) (i32.const 1)) (f64.const 1)) +(assert_return (invoke "select-funcref" (ref.null func) (ref.null func) (i32.const 1)) (ref.null func)) +(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 1)) (ref.extern 1)) + +(assert_return (invoke "select-i32-t" (i32.const 1) (i32.const 2) (i32.const 0)) (i32.const 2)) +(assert_return (invoke "select-i32-t" (i32.const 2) (i32.const 1) (i32.const 0)) (i32.const 1)) +(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const -1)) (i64.const 2)) +(assert_return (invoke "select-i64-t" (i64.const 2) (i64.const 1) (i32.const 0xf0f0f0f0)) (i64.const 2)) +(assert_return (invoke "select-externref" (ref.extern 1) (ref.extern 2) (i32.const 0)) (ref.extern 2)) +(assert_return (invoke "select-externref" (ref.extern 2) (ref.extern 1) (i32.const 0)) (ref.extern 1)) + +(assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 1)) (f32.const nan)) +(assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 1)) (f32.const nan:0x20304)) +(assert_return (invoke "select-f32-t" (f32.const nan) (f32.const 1) (i32.const 0)) (f32.const 1)) +(assert_return (invoke "select-f32-t" (f32.const nan:0x20304) (f32.const 1) (i32.const 0)) (f32.const 1)) +(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan) (i32.const 1)) (f32.const 2)) +(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan:0x20304) (i32.const 1)) (f32.const 2)) +(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan) (i32.const 0)) (f32.const nan)) +(assert_return (invoke "select-f32-t" (f32.const 2) (f32.const nan:0x20304) (i32.const 0)) (f32.const nan:0x20304)) + +(assert_return (invoke "select-f64-t" (f64.const nan) (f64.const 1) (i32.const 1)) (f64.const nan)) +(assert_return (invoke "select-f64-t" (f64.const nan:0x20304) (f64.const 1) (i32.const 1)) (f64.const nan:0x20304)) +(assert_return (invoke "select-f64-t" (f64.const nan) (f64.const 1) (i32.const 0)) (f64.const 1)) +(assert_return (invoke "select-f64-t" (f64.const nan:0x20304) (f64.const 1) (i32.const 0)) (f64.const 1)) +(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 1)) (f64.const 2)) +(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 1)) (f64.const 2)) +(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan) (i32.const 0)) (f64.const nan)) +(assert_return (invoke "select-f64-t" (f64.const 2) (f64.const nan:0x20304) (i32.const 0)) (f64.const nan:0x20304)) + +(assert_return (invoke "join-funcnull" (i32.const 1)) (ref.func)) +(assert_return (invoke "join-funcnull" (i32.const 0)) (ref.null)) + +(assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable") +(assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable") +(assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable") +(assert_trap (invoke "select-trap-right" (i32.const 0)) "unreachable") + +(assert_return (invoke "as-select-first" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-select-first" (i32.const 1)) (i32.const 0)) +(assert_return (invoke "as-select-mid" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-select-mid" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-select-last" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-select-last" (i32.const 1)) (i32.const 3)) + +(assert_return (invoke "as-loop-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-loop-first" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-loop-mid" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-loop-mid" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-loop-last" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-loop-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-if-condition" (i32.const 0))) +(assert_return (invoke "as-if-condition" (i32.const 1))) +(assert_return (invoke "as-if-then" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-if-then" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-if-else" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-if-else" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-br_if-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-br_if-first" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-br_if-last" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-br_if-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-br_table-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-br_table-first" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-br_table-last" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-br_table-last" (i32.const 1)) (i32.const 2)) + +(assert_return (invoke "as-call_indirect-first" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "as-call_indirect-first" (i32.const 1)) (i32.const 2)) +(assert_return (invoke "as-call_indirect-mid" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-call_indirect-mid" (i32.const 1)) (i32.const 1)) +(assert_trap (invoke "as-call_indirect-last" (i32.const 0)) "undefined element") +(assert_trap (invoke "as-call_indirect-last" (i32.const 1)) "undefined element") + +(assert_return (invoke "as-store-first" (i32.const 0))) +(assert_return (invoke "as-store-first" (i32.const 1))) +(assert_return (invoke "as-store-last" (i32.const 0))) +(assert_return (invoke "as-store-last" (i32.const 1))) + +(assert_return (invoke "as-memory.grow-value" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-memory.grow-value" (i32.const 1)) (i32.const 3)) + +(assert_return (invoke "as-call-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-call-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-return-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-return-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-drop-operand" (i32.const 0))) +(assert_return (invoke "as-drop-operand" (i32.const 1))) +(assert_return (invoke "as-br-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-br-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-local.set-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-local.set-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-local.tee-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-local.tee-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-global.set-value" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "as-global.set-value" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-load-operand" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "as-load-operand" (i32.const 1)) (i32.const 1)) + +(assert_return (invoke "as-unary-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-unary-operand" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-binary-operand" (i32.const 0)) (i32.const 4)) +(assert_return (invoke "as-binary-operand" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-test-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-test-operand" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-compare-left" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-compare-left" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-compare-right" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-compare-right" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-convert-operand" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-convert-operand" (i32.const 1)) (i32.const 1)) + +(assert_invalid + (module (func $arity-0-implicit (select (nop) (nop) (i32.const 1)))) + "type mismatch" +) +(assert_invalid + (module (func $arity-0 (select (result) (nop) (nop) (i32.const 1)))) + "invalid result arity" +) +(assert_invalid + (module (func $arity-2 (result i32 i32) + (select (result i32 i32) + (i32.const 0) (i32.const 0) + (i32.const 0) (i32.const 0) + (i32.const 1) + ) + )) + "invalid result arity" +) + + +(assert_invalid + (module (type $t (func)) + (func $type-ref-implicit (param $r (ref $t)) + (drop (select (local.get $r) (local.get $r) (i32.const 1))) + ) + ) + "type mismatch" +) +(assert_invalid + (module (func $type-funcref-implicit (param $r funcref) + (drop (select (local.get $r) (local.get $r) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-externref-implicit (param $r externref) + (drop (select (local.get $r) (local.get $r) (i32.const 1))) + )) + "type mismatch" +) +(module (func $type-unreachable-ref-implicit + (drop (ref.is_null (select (unreachable) (i32.const 1)))) +)) + +(assert_invalid + (module (func $type-num-vs-num + (drop (select (i32.const 1) (i64.const 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num + (drop (select (i32.const 1) (f32.const 1.0) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num + (drop (select (i32.const 1) (f64.const 1.0) (i32.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-num-vs-num (select (i32.const 1) (i64.const 1) (i32.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num (select (i32.const 1) (f32.const 1.0) (i32.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num (select (i32.const 1) (i64.const 1) (i32.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num (select (i32.const 1) (f32.const 1.0) (i32.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func $type-num-vs-num (select (i32.const 1) (f64.const 1.0) (i32.const 1)) (drop))) + "type mismatch" +) + + +(assert_invalid + (module + (func $type-1st-operand-empty + (select) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-operand-empty + (i32.const 0) (select) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-3rd-operand-empty + (i32.const 0) (i32.const 0) (select) (drop) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-1st-operand-empty-in-block + (i32.const 0) (i32.const 0) (i32.const 0) + (block (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-operand-empty-in-block + (i32.const 0) (i32.const 0) + (block (i32.const 0) (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-3rd-operand-empty-in-block + (i32.const 0) + (block (i32.const 0) (i32.const 0) (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-1st-operand-empty-in-loop + (i32.const 0) (i32.const 0) (i32.const 0) + (loop (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-operand-empty-in-loop + (i32.const 0) (i32.const 0) + (loop (i32.const 0) (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-3rd-operand-empty-in-loop + (i32.const 0) + (loop (i32.const 0) (i32.const 0) (select) (drop)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-1st-operand-empty-in-then + (i32.const 0) (i32.const 0) (i32.const 0) + (if (then (select) (drop))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-2nd-operand-empty-in-then + (i32.const 0) (i32.const 0) + (if (then (i32.const 0) (select) (drop))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $type-3rd-operand-empty-in-then + (i32.const 0) + (if (then (i32.const 0) (i32.const 0) (select) (drop))) + ) + ) + "type mismatch" +) + +;; Third operand must be i32 + +(assert_invalid + (module (func (select (i32.const 1) (i32.const 1) (i64.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func (select (i32.const 1) (i32.const 1) (f32.const 1)) (drop))) + "type mismatch" +) +(assert_invalid + (module (func (select (i32.const 1) (i32.const 1) (f64.const 1)) (drop))) + "type mismatch" +) + +;; Result of select has type of first two operands + +(assert_invalid + (module (func (result i32) (select (i64.const 1) (i64.const 1) (i32.const 1)))) + "type mismatch" +) + + +;; Flat syntax + +(module + (table 1 funcref) + (func (result i32) unreachable select) + (func (result i32) unreachable select nop) + (func (result i32) unreachable select (select)) + (func (result i32) unreachable select select) + (func (result i32) unreachable select select select) + (func (result i32) unreachable select (result i32)) + (func (result i32) unreachable select (result i32) (result)) + (func (result i32) unreachable select (result i32) (result) select) + (func (result i32) unreachable select (result) (result i32) select (result i32)) + (func (result i32) unreachable select call_indirect) + (func (result i32) unreachable select call_indirect select) +) diff --git a/proposals/memory64/simd_address.wast b/proposals/wasm-3.0/simd_address.wast similarity index 100% rename from proposals/memory64/simd_address.wast rename to proposals/wasm-3.0/simd_address.wast diff --git a/proposals/wasm-3.0/simd_lane.wast b/proposals/wasm-3.0/simd_lane.wast new file mode 100644 index 0000000..3dbd0c9 --- /dev/null +++ b/proposals/wasm-3.0/simd_lane.wast @@ -0,0 +1,1265 @@ +;; Tests for the extract_lane, replace_lane, swizzle and shuffle group instructions + + +(module + (func (export "i8x16_extract_lane_s-first") (param v128) (result i32) + (i8x16.extract_lane_s 0 (local.get 0))) + (func (export "i8x16_extract_lane_s-last") (param v128) (result i32) + (i8x16.extract_lane_s 15 (local.get 0))) + (func (export "i8x16_extract_lane_u-first") (param v128) (result i32) + (i8x16.extract_lane_u 0 (local.get 0))) + (func (export "i8x16_extract_lane_u-last") (param v128) (result i32) + (i8x16.extract_lane_u 15 (local.get 0))) + (func (export "i16x8_extract_lane_s-first") (param v128) (result i32) + (i16x8.extract_lane_s 0 (local.get 0))) + (func (export "i16x8_extract_lane_s-last") (param v128) (result i32) + (i16x8.extract_lane_s 7 (local.get 0))) + (func (export "i16x8_extract_lane_u-first") (param v128) (result i32) + (i16x8.extract_lane_u 0 (local.get 0))) + (func (export "i16x8_extract_lane_u-last") (param v128) (result i32) + (i16x8.extract_lane_u 7 (local.get 0))) + (func (export "i32x4_extract_lane-first") (param v128) (result i32) + (i32x4.extract_lane 0 (local.get 0))) + (func (export "i32x4_extract_lane-last") (param v128) (result i32) + (i32x4.extract_lane 3 (local.get 0))) + (func (export "f32x4_extract_lane-first") (param v128) (result f32) + (f32x4.extract_lane 0 (local.get 0))) + (func (export "f32x4_extract_lane-last") (param v128) (result f32) + (f32x4.extract_lane 3 (local.get 0))) + (func (export "i8x16_replace_lane-first") (param v128 i32) (result v128) + (i8x16.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "i8x16_replace_lane-last") (param v128 i32) (result v128) + (i8x16.replace_lane 15 (local.get 0) (local.get 1))) + (func (export "i16x8_replace_lane-first") (param v128 i32) (result v128) + (i16x8.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "i16x8_replace_lane-last") (param v128 i32) (result v128) + (i16x8.replace_lane 7 (local.get 0) (local.get 1))) + (func (export "i32x4_replace_lane-first") (param v128 i32) (result v128) + (i32x4.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "i32x4_replace_lane-last") (param v128 i32) (result v128) + (i32x4.replace_lane 3 (local.get 0) (local.get 1))) + (func (export "f32x4_replace_lane-first") (param v128 f32) (result v128) + (f32x4.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "f32x4_replace_lane-last") (param v128 f32) (result v128) + (f32x4.replace_lane 3 (local.get 0) (local.get 1))) + (func (export "i64x2_extract_lane-first") (param v128) (result i64) + (i64x2.extract_lane 0 (local.get 0))) + (func (export "i64x2_extract_lane-last") (param v128) (result i64) + (i64x2.extract_lane 1 (local.get 0))) + (func (export "f64x2_extract_lane-first") (param v128) (result f64) + (f64x2.extract_lane 0 (local.get 0))) + (func (export "f64x2_extract_lane-last") (param v128) (result f64) + (f64x2.extract_lane 1 (local.get 0))) + (func (export "i64x2_replace_lane-first") (param v128 i64) (result v128) + (i64x2.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "i64x2_replace_lane-last") (param v128 i64) (result v128) + (i64x2.replace_lane 1 (local.get 0) (local.get 1))) + (func (export "f64x2_replace_lane-first") (param v128 f64) (result v128) + (f64x2.replace_lane 0 (local.get 0) (local.get 1))) + (func (export "f64x2_replace_lane-last") (param v128 f64) (result v128) + (f64x2.replace_lane 1 (local.get 0) (local.get 1))) + + ;; Swizzle and shuffle + (func (export "v8x16_swizzle") (param v128 v128) (result v128) + (i8x16.swizzle (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-1") (param v128 v128) (result v128) + (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-2") (param v128 v128) (result v128) + (i8x16.shuffle 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-3") (param v128 v128) (result v128) + (i8x16.shuffle 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-4") (param v128 v128) (result v128) + (i8x16.shuffle 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-5") (param v128 v128) (result v128) + (i8x16.shuffle 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-6") (param v128 v128) (result v128) + (i8x16.shuffle 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 (local.get 0) (local.get 1))) + (func (export "v8x16_shuffle-7") (param v128 v128) (result v128) + (i8x16.shuffle 0 0 0 0 0 0 0 0 16 16 16 16 16 16 16 16 (local.get 0) (local.get 1))) +) + +(assert_return (invoke "i8x16_extract_lane_s-first" (v128.const i8x16 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 127)) +(assert_return (invoke "i8x16_extract_lane_s-first" (v128.const i8x16 0x7f 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 127)) +(assert_return (invoke "i8x16_extract_lane_s-first" (v128.const i8x16 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const -1)) +(assert_return (invoke "i8x16_extract_lane_s-first" (v128.const i8x16 0xff 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const -1)) +(assert_return (invoke "i8x16_extract_lane_u-first" (v128.const i8x16 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 255)) +(assert_return (invoke "i8x16_extract_lane_u-first" (v128.const i8x16 0xff 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 255)) +(assert_return (invoke "i8x16_extract_lane_s-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -128)) (i32.const -128)) +(assert_return (invoke "i8x16_extract_lane_s-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x80)) (i32.const -128)) +(assert_return (invoke "i8x16_extract_lane_u-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1)) (i32.const 255)) +(assert_return (invoke "i8x16_extract_lane_u-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0xff)) (i32.const 255)) +(assert_return (invoke "i8x16_extract_lane_u-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -128)) (i32.const 128)) +(assert_return (invoke "i8x16_extract_lane_u-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x80)) (i32.const 128)) + +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 32767 0 0 0 0 0 0 0)) (i32.const 32767)) +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 0x7fff 0 0 0 0 0 0 0)) (i32.const 32767)) +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 65535 0 0 0 0 0 0 0)) (i32.const -1)) +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 0xffff 0 0 0 0 0 0 0)) (i32.const -1)) +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 012_345 0 0 0 0 0 0 0)) (i32.const 12345)) +(assert_return (invoke "i16x8_extract_lane_s-first" (v128.const i16x8 -0x0_1234 0 0 0 0 0 0 0)) (i32.const -0x1234)) +(assert_return (invoke "i16x8_extract_lane_u-first" (v128.const i16x8 65535 0 0 0 0 0 0 0)) (i32.const 65535)) +(assert_return (invoke "i16x8_extract_lane_u-first" (v128.const i16x8 0xffff 0 0 0 0 0 0 0)) (i32.const 65535)) +(assert_return (invoke "i16x8_extract_lane_u-first" (v128.const i16x8 012_345 0 0 0 0 0 0 0)) (i32.const 12345)) +(assert_return (invoke "i16x8_extract_lane_u-first" (v128.const i16x8 -0x0_1234 0 0 0 0 0 0 0)) (i32.const 60876)) +(assert_return (invoke "i16x8_extract_lane_s-last" (v128.const i16x8 0 0 0 0 0 0 0 -32768)) (i32.const -32768)) +(assert_return (invoke "i16x8_extract_lane_s-last" (v128.const i16x8 0 0 0 0 0 0 0 0x8000)) (i32.const -32768)) +(assert_return (invoke "i16x8_extract_lane_s-last" (v128.const i16x8 0 0 0 0 0 0 0 06_789)) (i32.const 6789)) +(assert_return (invoke "i16x8_extract_lane_s-last" (v128.const i16x8 0 0 0 0 0 0 0 -0x0_6789)) (i32.const -0x6789)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 -1)) (i32.const 65535)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 0xffff)) (i32.const 65535)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 -32768)) (i32.const 32768)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 0x8000)) (i32.const 32768)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 06_789)) (i32.const 6789)) +(assert_return (invoke "i16x8_extract_lane_u-last" (v128.const i16x8 0 0 0 0 0 0 0 -0x0_6789)) (i32.const 39031)) + +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 2147483647 0 0 0)) (i32.const 2147483647)) +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 0x7fffffff 0 0 0)) (i32.const 2147483647)) +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 4294967295 0 0 0)) (i32.const -1)) +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 0xffffffff 0 0 0)) (i32.const -1)) +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 01_234_567_890 0 0 0)) (i32.const 1234567890)) +(assert_return (invoke "i32x4_extract_lane-first" (v128.const i32x4 -0x0_1234_5678 0 0 0)) (i32.const -0x12345678)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 -2147483648)) (i32.const -2147483648)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 0x80000000)) (i32.const -2147483648)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 -1)) (i32.const -1)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 0xffffffff)) (i32.const -1)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 0_987_654_321)) (i32.const 987654321)) +(assert_return (invoke "i32x4_extract_lane-last" (v128.const i32x4 0 0 0 -0x0_1234_5678)) (i32.const -0x12345678)) + +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 9223372036854775807 0)) (i64.const 9223372036854775807)) +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 0x7ffffffffffffffe 0)) (i64.const 0x7ffffffffffffffe)) +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 18446744073709551615 0)) (i64.const -1)) +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 0xffffffffffffffff 0)) (i64.const -1)) +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 01_234_567_890_123_456_789 0)) (i64.const 1234567890123456789)) +(assert_return (invoke "i64x2_extract_lane-first" (v128.const i64x2 0x0_1234_5678_90AB_cdef 0)) (i64.const 0x1234567890abcdef)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i64x2 0 9223372036854775808)) (i64.const -9223372036854775808)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i64x2 0 0x8000000000000000)) (i64.const -0x8000000000000000)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i64x2 0 0x8000000000000000)) (i64.const 0x8000000000000000)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0x7f)) (i64.const 9223372036854775807)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0x8000)) (i64.const -9223372036854775808)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i32x4 0 0 0xffffffff 0x7fffffff)) (i64.const 9223372036854775807)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const f64x2 -inf +inf)) (i64.const 0x7ff0000000000000)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i64x2 0 01_234_567_890_123_456_789)) (i64.const 1234567890123456789)) +(assert_return (invoke "i64x2_extract_lane-last" (v128.const i64x2 0 0x0_1234_5678_90AB_cdef)) (i64.const 0x1234567890abcdef)) + +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 -5.0 0.0 0.0 0.0)) (f32.const -5.0)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 1e38 0.0 0.0 0.0)) (f32.const 1e38)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 0x1.fffffep127 0.0 0.0 0.0)) (f32.const 0x1.fffffep127)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 0x1p127 0.0 0.0 0.0)) (f32.const 0x1p127)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 inf 0.0 0.0 0.0)) (f32.const inf)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 nan inf 0.0 0.0)) (f32.const nan)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 0123456789.0123456789e+019 0.0 0.0 0.0)) (f32.const 123456789.0123456789e+019)) +(assert_return (invoke "f32x4_extract_lane-first" (v128.const f32x4 0x0123456789ABCDEF.019aFp-019 0.0 0.0 0.0)) (f32.const 0x123456789ABCDEF.019aFp-019)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 -1e38)) (f32.const -1e38)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 -0x1.fffffep127)) (f32.const -0x1.fffffep127)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 -0x1p127)) (f32.const -0x1p127)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 -inf)) (f32.const -inf)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 -inf nan)) (f32.const nan)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 0123456789.)) (f32.const 123456789.0)) +(assert_return (invoke "f32x4_extract_lane-last" (v128.const f32x4 0.0 0.0 0.0 0x0123456789ABCDEF.)) (f32.const 0x123456789ABCDEF.0p0)) + +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 -1.5 0.0)) (f64.const -1.5)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 1.5 0.0)) (f64.const 1.5)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 -1.7976931348623157e-308 0x0p+0)) (f64.const -1.7976931348623157e-308)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 1.7976931348623157e-308 0x0p-0)) (f64.const 1.7976931348623157e-308)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 -0x1.fffffffffffffp-1023 0x0p+0)) (f64.const -0x1.fffffffffffffp-1023)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 0x1.fffffffffffffp-1023 0x0p-0)) (f64.const 0x1.fffffffffffffp-1023)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 -inf 0.0)) (f64.const -inf)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 inf 0.0)) (f64.const inf)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 -nan -0.0)) (f64.const -nan)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 nan 0.0)) (f64.const nan)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 0123456789.0123456789e+019 0.0)) (f64.const 123456789.0123456789e+019)) +(assert_return (invoke "f64x2_extract_lane-first" (v128.const f64x2 0x0123456789ABCDEFabcdef.0123456789ABCDEFabcdefp-019 0.0)) (f64.const 0x123456789ABCDEFabcdef.0123456789ABCDEFabcdefp-019)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 2.25)) (f64.const 2.25)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 -2.25)) (f64.const -2.25)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0x0p-0 -1.7976931348623157e+308)) (f64.const -1.7976931348623157e+308)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0x0p+0 1.7976931348623157e+308)) (f64.const 1.7976931348623157e+308)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0x0p-0 -0x1.fffffffffffffp+1023)) (f64.const -0x1.fffffffffffffp+1023)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0x0p+0 0x1.fffffffffffffp+1023)) (f64.const 0x1.fffffffffffffp+1023)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 -0.0 -inf)) (f64.const -inf)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 inf)) (f64.const inf)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 -0.0 -nan)) (f64.const -nan)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 nan)) (f64.const nan)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 0123456789.)) (f64.const 123456789.0)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const f64x2 0.0 0x0123456789ABCDEFabcdef.)) (f64.const 0x123456789ABCDEFabcdef.0)) + +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (f64.const 0.0)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0x80)) (f64.const -0.0)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0x4000)) (f64.const 2.0)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0xc000)) (f64.const -2.0)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i32x4 0 0 0xffffffff 0x7fefffff)) (f64.const 0x1.fffffffffffffp+1023)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i32x4 0 0 0 0x00100000)) (f64.const 0x1.0000000000000p-1022)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i32x4 0 0 0xffffffff 0x000fffff)) (f64.const 0x1.ffffffffffffep-1023)) +(assert_return (invoke "f64x2_extract_lane-last" (v128.const i32x4 0 0 1 0)) (f64.const 0x0.0000000000002p-1023)) + +(assert_return (invoke "i8x16_replace_lane-first" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 127)) (v128.const i8x16 127 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i8x16_replace_lane-first" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 128)) (v128.const i8x16 -128 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i8x16_replace_lane-first" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 255)) (v128.const i8x16 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i8x16_replace_lane-first" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 256)) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i8x16_replace_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const -128)) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -128)) +(assert_return (invoke "i8x16_replace_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const -129)) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127)) +(assert_return (invoke "i8x16_replace_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 32767)) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0xff)) +(assert_return (invoke "i8x16_replace_lane-last" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const -32768)) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 32767)) (v128.const i16x8 32767 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 32768)) (v128.const i16x8 -32768 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 65535)) (v128.const i16x8 -1 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 65536)) (v128.const i16x8 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 012345)) (v128.const i16x8 012_345 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-first" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const -0x01234)) (v128.const i16x8 -0x0_1234 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const -32768)) (v128.const i16x8 0 0 0 0 0 0 0 -32768)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const -32769)) (v128.const i16x8 0 0 0 0 0 0 0 32767)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 0x7fffffff)) (v128.const i16x8 0 0 0 0 0 0 0 0xffff)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 0x80000000)) (v128.const i16x8 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 054321)) (v128.const i16x8 0 0 0 0 0 0 0 054_321)) +(assert_return (invoke "i16x8_replace_lane-last" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const -0x04321)) (v128.const i16x8 0 0 0 0 0 0 0 -0x0_4321)) + +(assert_return (invoke "i32x4_replace_lane-first" (v128.const i32x4 0 0 0 0) (i32.const 2147483647)) (v128.const i32x4 2147483647 0 0 0)) +(assert_return (invoke "i32x4_replace_lane-first" (v128.const i32x4 0 0 0 0) (i32.const 4294967295)) (v128.const i32x4 -1 0 0 0)) +(assert_return (invoke "i32x4_replace_lane-first" (v128.const i32x4 0 0 0 0) (i32.const 01234567890)) (v128.const i32x4 01_234_567_890 0 0 0)) +(assert_return (invoke "i32x4_replace_lane-first" (v128.const i32x4 0 0 0 0) (i32.const -0x012345678)) (v128.const i32x4 -0x0_1234_5678 0 0 0)) +(assert_return (invoke "i32x4_replace_lane-last" (v128.const i32x4 0 0 0 0) (i32.const 2147483648)) (v128.const i32x4 0 0 0 2147483648)) +(assert_return (invoke "i32x4_replace_lane-last" (v128.const i32x4 0 0 0 0) (i32.const -2147483648)) (v128.const i32x4 0 0 0 -2147483648)) +(assert_return (invoke "i32x4_replace_lane-last" (v128.const i32x4 0 0 0 0) (i32.const 01234567890)) (v128.const i32x4 0 0 0 01_234_567_890)) +(assert_return (invoke "i32x4_replace_lane-last" (v128.const i32x4 0 0 0 0) (i32.const -0x012345678)) (v128.const i32x4 0 0 0 -0x0_1234_5678)) + +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 53.0)) (v128.const f32x4 53.0 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const i32x4 0 0 0 0 ) (f32.const 53.0)) (v128.const f32x4 53.0 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const nan)) (v128.const f32x4 nan 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const inf)) (v128.const f32x4 inf 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 nan 0.0 0.0 0.0) (f32.const 3.14)) (v128.const f32x4 3.14 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 inf 0.0 0.0 0.0) (f32.const 1e38)) (v128.const f32x4 1e38 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 inf 0.0 0.0 0.0) (f32.const 0x1.fffffep127)) (v128.const f32x4 0x1.fffffep127 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 inf 0.0 0.0 0.0) (f32.const 0x1p127)) (v128.const f32x4 0x1p127 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0123456789)) (v128.const f32x4 0123456789 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0123456789.)) (v128.const f32x4 0123456789. 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0x0123456789ABCDEF)) (v128.const f32x4 0x0123456789ABCDEF 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-first" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0x0123456789ABCDEF.)) (v128.const f32x4 0x0123456789ABCDEF. 0.0 0.0 0.0)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const -53.0)) (v128.const f32x4 0.0 0.0 0.0 -53.0)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const i32x4 0 0 0 0) (f32.const -53.0)) (v128.const f32x4 0.0 0.0 0.0 -53.0)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const nan)) (v128.const f32x4 0.0 0.0 0.0 nan)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const -inf)) (v128.const f32x4 0.0 0.0 0.0 -inf)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 nan) (f32.const 3.14)) (v128.const f32x4 0.0 0.0 0.0 3.14)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 -inf) (f32.const -1e38)) (v128.const f32x4 0.0 0.0 0.0 -1e38)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 -inf) (f32.const -0x1.fffffep127)) (v128.const f32x4 0.0 0.0 0.0 -0x1.fffffep127)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 -inf) (f32.const -0x1p127)) (v128.const f32x4 0.0 0.0 0.0 -0x1p127)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0123456789e019)) (v128.const f32x4 0.0 0.0 0.0 0123456789e019)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0123456789.e+019)) (v128.const f32x4 0.0 0.0 0.0 0123456789.e+019)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0x0123456789ABCDEFp019)) (v128.const f32x4 0.0 0.0 0.0 0x0123456789ABCDEFp019)) +(assert_return (invoke "f32x4_replace_lane-last" (v128.const f32x4 0.0 0.0 0.0 0.0) (f32.const 0x0123456789ABCDEF.p-019)) (v128.const f32x4 0.0 0.0 0.0 0x0123456789ABCDEF.p-019)) + +(assert_return (invoke "i64x2_replace_lane-first" (v128.const i64x2 0 0) (i64.const 9223372036854775807)) (v128.const i64x2 9223372036854775807 0)) +(assert_return (invoke "i64x2_replace_lane-first" (v128.const i64x2 0 0) (i64.const 18446744073709551615)) (v128.const i64x2 -1 0)) +(assert_return (invoke "i64x2_replace_lane-first" (v128.const i64x2 0 0) (i64.const 01234567890123456789)) (v128.const i64x2 01_234_567_890_123_456_789 0)) +(assert_return (invoke "i64x2_replace_lane-first" (v128.const i64x2 0 0) (i64.const 0x01234567890abcdef)) (v128.const i64x2 0x0_1234_5678_90AB_cdef 0)) +(assert_return (invoke "i64x2_replace_lane-last" (v128.const i64x2 0 0) (i64.const 9223372036854775808)) (v128.const i64x2 0 9223372036854775808)) +(assert_return (invoke "i64x2_replace_lane-last" (v128.const i64x2 0 0) (i64.const 9223372036854775808)) (v128.const i64x2 0 -9223372036854775808)) +(assert_return (invoke "i64x2_replace_lane-last" (v128.const i64x2 0 0) (i64.const 01234567890123456789)) (v128.const i64x2 0 01_234_567_890_123_456_789)) +(assert_return (invoke "i64x2_replace_lane-last" (v128.const i64x2 0 0) (i64.const 0x01234567890abcdef)) (v128.const i64x2 0 0x0_1234_5678_90AB_cdef)) + +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 1.0 1.0) (f64.const 0x0p+0)) (v128.const f64x2 0.0 1.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 -1.0 -1.0) (f64.const -0x0p-0)) (v128.const f64x2 -0.0 -1.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const 1.25)) (v128.const f64x2 1.25 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const -1.25)) (v128.const f64x2 -1.25 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 -nan 0.0) (f64.const -1.7976931348623157e+308)) (v128.const f64x2 -1.7976931348623157e+308 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 nan 0.0) (f64.const 1.7976931348623157e+308)) (v128.const f64x2 1.7976931348623157e+308 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 -inf 0.0) (f64.const -0x1.fffffffffffffp-1023)) (v128.const f64x2 -0x1.fffffffffffffp-1023 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 inf 0.0) (f64.const 0x1.fffffffffffffp-1023)) (v128.const f64x2 0x1.fffffffffffffp-1023 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const -nan)) (v128.const f64x2 -nan 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const nan)) (v128.const f64x2 nan 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const -inf)) (v128.const f64x2 -inf 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const inf)) (v128.const f64x2 inf 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const 0123456789)) (v128.const f64x2 0123456789 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const 0123456789.)) (v128.const f64x2 0123456789. 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const 0x0123456789ABCDEFabcdef)) (v128.const f64x2 0x0123456789ABCDEFabcdef 0.0)) +(assert_return (invoke "f64x2_replace_lane-first" (v128.const f64x2 0.0 0.0) (f64.const 0x0123456789ABCDEFabcdef.)) (v128.const f64x2 0x0123456789ABCDEFabcdef. 0.0)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 2.0 2.0) (f64.const 0.0)) (v128.const f64x2 2.0 0.0)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 -2.0 -2.0) (f64.const -0.0)) (v128.const f64x2 -2.0 -0.0)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const 2.25)) (v128.const f64x2 0.0 2.25)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const -2.25)) (v128.const f64x2 0.0 -2.25)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 -nan) (f64.const -1.7976931348623157e+308)) (v128.const f64x2 0.0 -1.7976931348623157e+308)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 nan) (f64.const 1.7976931348623157e+308)) (v128.const f64x2 0.0 1.7976931348623157e+308)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 -inf) (f64.const -0x1.fffffffffffffp-1023)) (v128.const f64x2 0.0 -0x1.fffffffffffffp-1023)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 inf) (f64.const 0x1.fffffffffffffp-1023)) (v128.const f64x2 0.0 0x1.fffffffffffffp-1023)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const -nan)) (v128.const f64x2 0.0 -nan)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const nan)) (v128.const f64x2 0.0 nan)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const -inf)) (v128.const f64x2 0.0 -inf)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const inf)) (v128.const f64x2 0.0 inf)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const 0123456789e019)) (v128.const f64x2 0.0 0123456789e019)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const 0123456789e+019)) (v128.const f64x2 0.0 0123456789e+019)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const 0123456789.e019)) (v128.const f64x2 0.0 0123456789.e019)) +(assert_return (invoke "f64x2_replace_lane-last" (v128.const f64x2 0.0 0.0) (f64.const 0123456789.e-019)) (v128.const f64x2 0.0 0123456789.e-019)) + +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 -8 -7 -6 -5 -4 -3 -2 -1 16 17 18 19 20 21 22 23)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) + (v128.const i8x16 115 114 113 112 111 110 109 108 107 106 105 104 103 102 101 100)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115) + (v128.const i8x16 -1 1 -2 2 -3 3 -4 4 -5 5 -6 6 -7 7 -8 8)) + (v128.const i8x16 0 101 0 102 0 103 0 104 0 105 0 106 0 107 0 108)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115) + (v128.const i8x16 9 16 10 17 11 18 12 19 13 20 14 21 15 22 16 23)) + (v128.const i8x16 109 0 110 0 111 0 112 0 113 0 114 0 115 0 0 0)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i8x16 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73) + (v128.const i8x16 9 16 10 17 11 18 12 19 13 20 14 21 15 22 16 23)) + (v128.const i8x16 0x6d 0 0x6e 0 0x6f 0 0x70 0 0x71 0 0x72 0 0x73 0 0 0)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i16x8 0x6465 0x6667 0x6869 0x6a6b 0x6c6d 0x6e6f 0x7071 0x7273) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i16x8 0x6465 0x6667 0x6869 0x6a6b 0x6c6d 0x6e6f 0x7071 0x7273)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i32x4 0x64656667 0x68696a6b 0x6c6d6e6f 0x70717273) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) + (v128.const i32x4 0x73727170 0x6f6e6d6c 0x6b6a6968 0x67666564)) +(assert_return (invoke "v8x16_swizzle" + (v128.const f32x4 nan -nan inf -inf) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i32x4 0x7fc00000 0xffc00000 0x7f800000 0xff800000)) +(assert_return (invoke "v8x16_swizzle" + (v128.const i32x4 0x67666564 0x6b6a6968 0x6f6e6d5c 0x73727170) + (v128.const f32x4 0.0 -0.0 inf -inf)) + (v128.const i32x4 0x64646464 0x00646464 0x00006464 0x00006464)) + +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) +(assert_return (invoke "v8x16_shuffle-2" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) +(assert_return (invoke "v8x16_shuffle-3" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16)) +(assert_return (invoke "v8x16_shuffle-4" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) +(assert_return (invoke "v8x16_shuffle-5" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "v8x16_shuffle-6" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16 -16)) +(assert_return (invoke "v8x16_shuffle-7" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i8x16 0 0 0 0 0 0 0 0 -16 -16 -16 -16 -16 -16 -16 -16)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i8x16 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73) + (v128.const i8x16 0xf0 0xf1 0xf2 0xf3 0xf4 0xf5 0xf6 0xf7 0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff)) + (v128.const i8x16 0x64 0x65 0x66 0x67 0x68 0x69 0x6a 0x6b 0x6c 0x6d 0x6e 0x6f 0x70 0x71 0x72 0x73)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i16x8 0x0100 0x0302 0x0504 0x0706 0x0908 0x0b0a 0x0d0c 0x0f0e) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1)) + (v128.const i16x8 0x0100 0x0302 0x0504 0x0706 0x0908 0x0b0a 0x0d0c 0x0f0e)) +(assert_return (invoke "v8x16_shuffle-2" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i32x4 0xf3f2f1f0 0xf7f6f5f4 0xfbfaf9f8 0xfffefdfc)) + (v128.const i32x4 0xf3f2f1f0 0xf7f6f5f4 0xfbfaf9f8 0xfffefdfc)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i32x4 0x10203 0x4050607 0x8090a0b 0xc0d0e0f) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i32x4 0x10203 0x4050607 0x8090a0b 0xc0d0e0f)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const f32x4 1.0 nan inf -inf) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i32x4 0x3f800000 0x7fc00000 0x7f800000 0xff800000)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i32x4 0x10203 0x4050607 0x8090a0b 0xc0d0e0f) + (v128.const f32x4 -0.0 nan inf -inf)) + (v128.const i32x4 0x10203 0x4050607 0x8090a0b 0xc0d0e0f)) + +;; More literals +(assert_return (invoke "v8x16_swizzle" + (v128.const i32x4 1_234_567_890 0x1234_5678 01_234_567_890 0x0_1234_5678) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) + (v128.const i32x4 0x4996_02d2 0x1234_5678 0x4996_02d2 0x1234_5678)) +(assert_return (invoke "v8x16_shuffle-1" + (v128.const i64x2 1_234_567_890_123_456_789_0 0x1234_5678_90AB_cdef) + (v128.const i64x2 01_234_567_890_123_456_789_0 0x0_1234_5678_90AB_cdef)) + (v128.const i32x4 0xeb1f_0ad2 0xab54_a98c 0x90ab_cdef 0x1234_5678)) + +;; Syntax errors for negative values + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_s -1 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_u -1 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_s -1 (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_u -1 (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i32x4.extract_lane -1 (v128.const i32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result f32) (f32x4.extract_lane -1 (v128.const f32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i8x16.replace_lane -1 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i16x8.replace_lane -1 (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i32x4.replace_lane -1 (v128.const i32x4 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (f32x4.replace_lane -1 (v128.const f32x4 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result i64) (i64x2.extract_lane -1 (v128.const i64x2 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result f64) (f64x2.extract_lane -1 (v128.const f64x2 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i64x2.replace_lane -1 (v128.const i64x2 0 0) (i64.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (f64x2.replace_lane -1 (v128.const f64x2 0 0) (f64.const 1)))") "unexpected token") + +;; Malformed lane index value + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_s 256 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_u 256 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_s 256 (v128.const i16x8 0 0 0 0 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_u 256 (v128.const i16x8 0 0 0 0 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result i32) (i32x4.extract_lane 256 (v128.const i32x4 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result f32) (f32x4.extract_lane 256 (v128.const f32x4 0 0 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (i8x16.replace_lane 256 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (i16x8.replace_lane 256 (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (i32x4.replace_lane 256 (v128.const i32x4 0 0 0 0) (i32.const 1)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (f32x4.replace_lane 256 (v128.const f32x4 0 0 0 0) (i32.const 1)))") "malformed lane index") +(assert_malformed (module quote "(func (result i64) (i64x2.extract_lane 256 (v128.const i64x2 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result f64) (f64x2.extract_lane 256 (v128.const f64x2 0 0)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (i64x2.replace_lane 256 (v128.const i64x2 0 0) (i64.const 1)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) (f64x2.replace_lane 256 (v128.const f64x2 0 0) (f64.const 1)))") "malformed lane index") + +;; Invalid lane index value + +(assert_invalid (module (func (result i32) (i8x16.extract_lane_s 16 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_s 255 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_u 16 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_u 255 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i16x8.extract_lane_s 8 (v128.const i16x8 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i16x8.extract_lane_s 255 (v128.const i16x8 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i16x8.extract_lane_u 8 (v128.const i16x8 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i16x8.extract_lane_u 255 (v128.const i16x8 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i32x4.extract_lane 4 (v128.const i32x4 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i32x4.extract_lane 255 (v128.const i32x4 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result f32) (f32x4.extract_lane 4 (v128.const f32x4 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result f32) (f32x4.extract_lane 255 (v128.const f32x4 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i8x16.replace_lane 16 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i8x16.replace_lane 255 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i16x8.replace_lane 16 (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i16x8.replace_lane 255 (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 4 (v128.const i32x4 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 255 (v128.const i32x4 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 4 (v128.const f32x4 0 0 0 0) (f32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 255 (v128.const f32x4 0 0 0 0) (f32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result i64) (i64x2.extract_lane 2 (v128.const i64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i64) (i64x2.extract_lane 255 (v128.const i64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result f64) (f64x2.extract_lane 2 (v128.const f64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result f64) (f64x2.extract_lane 255 (v128.const f64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i64x2.replace_lane 2 (v128.const i64x2 0 0) (i64.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i64x2.replace_lane 255 (v128.const i64x2 0 0) (i64.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f64x2.replace_lane 2 (v128.const f64x2 0 0) (f64.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f64x2.replace_lane 255 (v128.const f64x2 0 0) (f64.const 1.0)))) "invalid lane index") + +;; Lane index is determined by the instruction's interpretation only. + +(assert_invalid (module (func (result i32) (i16x8.extract_lane_s 8 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i16x8.extract_lane_u 8 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (i32x4.extract_lane 4 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result i32) (f32x4.extract_lane 4 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i16x8.replace_lane 8 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 4 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 4 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (f32.const 1)))) "invalid lane index") +(assert_invalid (module (func (result i64) (i64x2.extract_lane 2 (v128.const i64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result f64) (f64x2.extract_lane 2 (v128.const f64x2 0 0)))) "invalid lane index") +(assert_invalid (module (func (result v128) (i64x2.replace_lane 2 (v128.const i64x2 0 0) (i64.const 1)))) "invalid lane index") +(assert_invalid (module (func (result v128) (f64x2.replace_lane 2 (v128.const f64x2 0 0) (f64.const 1.0)))) "invalid lane index") + +;; Invalid parameters: required v128 but pass other types + +(assert_invalid (module (func (result i32) (i8x16.extract_lane_s 0 (i32.const 0)))) "type mismatch") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_u 0 (i64.const 0)))) "type mismatch") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_s 0 (f32.const 0.0)))) "type mismatch") +(assert_invalid (module (func (result i32) (i8x16.extract_lane_u 0 (f64.const 0.0)))) "type mismatch") +(assert_invalid (module (func (result i32) (i32x4.extract_lane 0 (i32.const 0)))) "type mismatch") +(assert_invalid (module (func (result f32) (f32x4.extract_lane 0 (f32.const 0.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (i8x16.replace_lane 0 (i32.const 0) (i32.const 1)))) "type mismatch") +(assert_invalid (module (func (result v128) (i16x8.replace_lane 0 (i64.const 0) (i32.const 1)))) "type mismatch") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 0 (i32.const 0) (i32.const 1)))) "type mismatch") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 0 (f32.const 0.0) (i32.const 1)))) "type mismatch") +(assert_invalid (module (func (result i64) (i64x2.extract_lane 0 (i64.const 0)))) "type mismatch") +(assert_invalid (module (func (result f64) (f64x2.extract_lane 0 (f64.const 0.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 0 (i32.const 0) (i32.const 1)))) "type mismatch") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 0 (f32.const 0.0) (i32.const 1)))) "type mismatch") + +;; Invalid types for the replaced value + +(assert_invalid (module (func (result v128) (i8x16.replace_lane 0 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (f32.const 1.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (i16x8.replace_lane 0 (v128.const i16x8 0 0 0 0 0 0 0 0) (f64.const 1.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (i32x4.replace_lane 0 (v128.const i32x4 0 0 0 0) (f32.const 1.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (f32x4.replace_lane 0 (v128.const f32x4 0 0 0 0) (i32.const 1)))) "type mismatch") + +(assert_invalid (module (func (result v128) (i64x2.replace_lane 0 (v128.const i64x2 0 0) (f64.const 1.0)))) "type mismatch") +(assert_invalid (module (func (result v128) (f64x2.replace_lane 0 (v128.const f64x2 0 0) (i64.const 1)))) "type mismatch") + +;; Invalid types for swizzle and shuffle values +(assert_invalid (module (func (result v128) + (i8x16.swizzle (i32.const 1) (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))) "type mismatch") +(assert_invalid (module (func (result v128) + (i8x16.swizzle (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) (i32.const 2)))) "type mismatch") +(assert_invalid (module (func (result v128) + (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (f32.const 3.0) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))) "type mismatch") +(assert_invalid (module (func (result v128) + (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) (f32.const 4.0)))) "type mismatch") + +;; i8x16.shuffle: the 1st argument must be 16-byte literals in 0..32 +(assert_malformed (module quote "(func (param v128) (result v128)" + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 (local.get 0) (local.get 0)))") + "invalid lane length") +(assert_malformed (module quote "(func (param v128) (result v128)" + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 (local.get 0) (local.get 0)))") + "invalid lane length") +(assert_malformed (module quote "(func (result v128)" + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 -1" + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)" + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128)" + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 256" + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)" + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_invalid (module (func (result v128) + (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 255 + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))) "invalid lane index") + +;; Possible wrong instruction names that'd be used + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane 0 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unknown operator") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane 0 (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unknown operator") +(assert_malformed (module quote "(func (result i32) (i32x4.extract_lane_s 0 (v128.const i32x4 0 0 0 0)))") "unknown operator") +(assert_malformed (module quote "(func (result i32) (i32x4.extract_lane_u 0 (v128.const i32x4 0 0 0 0)))") "unknown operator") +(assert_malformed (module quote "(func (result i32) (i64x2.extract_lane_s 0 (v128.const i64x2 0 0)))") "unknown operator") +(assert_malformed (module quote "(func (result i32) (i64x2.extract_lane_u 0 (v128.const i64x2 0 0)))") "unknown operator") + + +;; Old shuffle instruction names will not work +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle1 (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))") + "unknown operator") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle2_imm 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " + "(v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)))") + "unknown operator") +;; i8x16 not v8x16 +(assert_malformed (module quote "(func (result v128) " + "(v8x16.swizzle (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))") + "unknown operator") +(assert_malformed (module quote "(func (result v128) " + "(v8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) " + "(v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31)))") + "unknown operator") + + +;; Malformed lane index + +;; Pass params as the lane index + +(assert_malformed (module quote "(func (param i32) (result i32) (i8x16.extract_lane_s (local.get 0) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result i32) (i8x16.extract_lane_u (local.get 0) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result i32) (i16x8.extract_lane_s (local.get 0) (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result i32) (i16x8.extract_lane_u (local.get 0) (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result i32) (i32x4.extract_lane (local.get 0) (v128.const i32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result f32) (f32x4.extract_lane (local.get 0) (v128.const f32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (i8x16.replace_lane (local.get 0) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (i16x8.replace_lane (local.get 0) (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (i32x4.replace_lane (local.get 0) (v128.const i32x4 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (f32x4.replace_lane (local.get 0) (v128.const f32x4 0 0 0 0) (f32.const 1.0)))") "unexpected token") + +(assert_malformed (module quote "(func (param i32) (result i64) (i64x2.extract_lane (local.get 0) (v128.const i64x2 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result f64) (f64x2.extract_lane (local.get 0) (v128.const f64x2 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (i64x2.replace_lane (local.get 0) (v128.const i64x2 0 0) (i64.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (param i32) (result v128) (f64x2.replace_lane (local.get 0) (v128.const f64x2 0 0) (f64.const 1.0)))") "unexpected token") + +;; Pass non-literal as the lane index + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_s 1.5 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_u nan (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_s inf (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i16x8.extract_lane_u -inf (v128.const i16x8 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i32) (i32x4.extract_lane nan (v128.const i32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result f32) (f32x4.extract_lane nan (v128.const f32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i8x16.replace_lane -2.5 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i16x8.replace_lane nan (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i32x4.replace_lane inf (v128.const i32x4 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (f32x4.replace_lane -inf (v128.const f32x4 0 0 0 0) (f32.const 1.1)))") "unexpected token") + +;; i8x16.shuffle expects a 16-byte literals as first argument +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle (v128.const i8x16 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31) " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "invalid lane length") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15.0 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle 0.5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle -inf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 inf " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") +(assert_malformed (module quote "(func (result v128) " + "(i8x16.shuffle nan 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 " + "(v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) " + "(v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))") "malformed lane index") + + +;; Combination with each other + +(module + ;; as *.replace_lane's operand + (func (export "i8x16_extract_lane_s") (param v128 v128) (result v128) + (i8x16.replace_lane 0 (local.get 0) (i8x16.extract_lane_s 0 (local.get 1)))) + (func (export "i8x16_extract_lane_u") (param v128 v128) (result v128) + (i8x16.replace_lane 0 (local.get 0) (i8x16.extract_lane_u 0 (local.get 1)))) + (func (export "i16x8_extract_lane_s") (param v128 v128) (result v128) + (i16x8.replace_lane 0 (local.get 0) (i16x8.extract_lane_s 0 (local.get 1)))) + (func (export "i16x8_extract_lane_u") (param v128 v128) (result v128) + (i16x8.replace_lane 0 (local.get 0) (i16x8.extract_lane_u 0 (local.get 1)))) + (func (export "i32x4_extract_lane") (param v128 v128) (result v128) + (i32x4.replace_lane 0 (local.get 0) (i32x4.extract_lane 0 (local.get 1)))) + (func (export "f32x4_extract_lane") (param v128 v128) (result v128) + (i32x4.replace_lane 0 (local.get 0) (i32x4.extract_lane 0 (local.get 1)))) + (func (export "i64x2_extract_lane") (param v128 v128) (result v128) + (i64x2.replace_lane 0 (local.get 0) (i64x2.extract_lane 0 (local.get 1)))) + (func (export "f64x2_extract_lane") (param v128 v128) (result v128) + (f64x2.replace_lane 0 (local.get 0) (f64x2.extract_lane 0 (local.get 1)))) + + ;; as *.extract_lane's operand + (func (export "i8x16_replace_lane-s") (param v128 i32) (result i32) + (i8x16.extract_lane_s 15 (i8x16.replace_lane 15 (local.get 0) (local.get 1)))) + (func (export "i8x16_replace_lane-u") (param v128 i32) (result i32) + (i8x16.extract_lane_u 15 (i8x16.replace_lane 15 (local.get 0) (local.get 1)))) + (func (export "i16x8_replace_lane-s") (param v128 i32) (result i32) + (i16x8.extract_lane_s 7 (i16x8.replace_lane 7 (local.get 0) (local.get 1)))) + (func (export "i16x8_replace_lane-u") (param v128 i32) (result i32) + (i16x8.extract_lane_u 7 (i16x8.replace_lane 7 (local.get 0) (local.get 1)))) + (func (export "i32x4_replace_lane") (param v128 i32) (result i32) + (i32x4.extract_lane 3 (i32x4.replace_lane 3 (local.get 0) (local.get 1)))) + (func (export "f32x4_replace_lane") (param v128 f32) (result f32) + (f32x4.extract_lane 3 (f32x4.replace_lane 3 (local.get 0) (local.get 1)))) + (func (export "i64x2_replace_lane") (param v128 i64) (result i64) + (i64x2.extract_lane 1 (i64x2.replace_lane 1 (local.get 0) (local.get 1)))) + (func (export "f64x2_replace_lane") (param v128 f64) (result f64) + (f64x2.extract_lane 1 (f64x2.replace_lane 1 (local.get 0) (local.get 1)))) + + ;; i8x16.replace outputs as shuffle operand + (func (export "as-v8x16_swizzle-operand") (param v128 i32 v128) (result v128) + (i8x16.swizzle (i8x16.replace_lane 0 (local.get 0) (local.get 1)) (local.get 2))) + (func (export "as-v8x16_shuffle-operands") (param v128 i32 v128 i32) (result v128) + (i8x16.shuffle 16 1 18 3 20 5 22 7 24 9 26 11 28 13 30 15 + (i8x16.replace_lane 0 (local.get 0) (local.get 1)) + (i8x16.replace_lane 15 (local.get 2) (local.get 3)))) +) + +(assert_return (invoke "i8x16_extract_lane_s" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) (v128.const i8x16 -1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i8x16_extract_lane_u" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) (v128.const i8x16 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_extract_lane_s" (v128.const i16x8 0 0 0 0 0 0 0 0) (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) (v128.const i16x8 -1 0 0 0 0 0 0 0)) +(assert_return (invoke "i16x8_extract_lane_u" (v128.const i16x8 0 0 0 0 0 0 0 0) (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) (v128.const i16x8 65535 0 0 0 0 0 0 0)) +(assert_return (invoke "i32x4_extract_lane" (v128.const i32x4 0 0 0 0) (v128.const i32x4 0x10000 -1 -1 -1)) (v128.const i32x4 65536 0 0 0)) +(assert_return (invoke "f32x4_extract_lane" (v128.const f32x4 0 0 0 0) (v128.const f32x4 1e38 nan nan nan)) (v128.const f32x4 1e38 0 0 0)) +(assert_return (invoke "i8x16_replace_lane-s" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 255)) (i32.const -1)) +(assert_return (invoke "i8x16_replace_lane-u" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 255)) (i32.const 255)) +(assert_return (invoke "i16x8_replace_lane-s" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 65535)) (i32.const -1)) +(assert_return (invoke "i16x8_replace_lane-u" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 65535)) (i32.const 65535)) +(assert_return (invoke "i32x4_replace_lane" (v128.const i32x4 0 0 0 0) (i32.const -1)) (i32.const -1)) +(assert_return (invoke "f32x4_replace_lane" (v128.const f32x4 0 0 0 0) (f32.const 1.25)) (f32.const 1.25)) + +(assert_return (invoke "i64x2_extract_lane" (v128.const i64x2 0 0) (v128.const i64x2 0xffffffffffffffff -1)) (v128.const i64x2 0xffffffffffffffff 0)) +(assert_return (invoke "f64x2_extract_lane" (v128.const f64x2 0 0) (v128.const f64x2 1e308 nan)) (v128.const f64x2 1e308 0)) +(assert_return (invoke "i64x2_replace_lane" (v128.const i64x2 0 0) (i64.const -1)) (i64.const -1)) +(assert_return (invoke "f64x2_replace_lane" (v128.const f64x2 0 0) (f64.const 2.5)) (f64.const 2.5)) + +(assert_return (invoke "as-v8x16_swizzle-operand" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) (i32.const 255) + (v128.const i8x16 -1 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1)) + (v128.const i8x16 0 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1)) +(assert_return (invoke "as-v8x16_shuffle-operands" + (v128.const i8x16 0 255 0 255 15 255 0 255 255 255 0 255 127 255 0 255) (i32.const 1) + (v128.const i8x16 0x55 0 0x55 0 0x55 0 0x55 0 0x55 0 0x55 0 0x55 1 0x55 -1) (i32.const 0)) + (v128.const i8x16 0x55 0xff 0x55 0xff 0x55 0xff 0x55 0xff 0x55 0xff 0x55 0xff 0x55 0xff 0x55 0xff)) + +;; Combination with other SIMD instructions + +(module + ;; Constructing SIMD values + (func (export "as-i8x16_splat-operand") (param v128) (result v128) + (i8x16.splat (i8x16.extract_lane_s 0 (local.get 0)))) + (func (export "as-i16x8_splat-operand") (param v128) (result v128) + (i16x8.splat (i16x8.extract_lane_u 0 (local.get 0)))) + (func (export "as-i32x4_splat-operand") (param v128) (result v128) + (i32x4.splat (i32x4.extract_lane 0 (local.get 0)))) + (func (export "as-f32x4_splat-operand") (param v128) (result v128) + (f32x4.splat (f32x4.extract_lane 0 (local.get 0)))) + (func (export "as-i64x2_splat-operand") (param v128) (result v128) + (i64x2.splat (i64x2.extract_lane 0 (local.get 0)))) + (func (export "as-f64x2_splat-operand") (param v128) (result v128) + (f64x2.splat (f64x2.extract_lane 0 (local.get 0)))) + + ;; Integer arithmetic + (func (export "as-i8x16_add-operands") (param v128 i32 v128 i32) (result v128) + (i8x16.add (i8x16.replace_lane 0 (local.get 0) (local.get 1)) (i8x16.replace_lane 15 (local.get 2) (local.get 3)))) + (func (export "as-i16x8_add-operands") (param v128 i32 v128 i32) (result v128) + (i16x8.add (i16x8.replace_lane 0 (local.get 0) (local.get 1)) (i16x8.replace_lane 7 (local.get 2) (local.get 3)))) + (func (export "as-i32x4_add-operands") (param v128 i32 v128 i32) (result v128) + (i32x4.add (i32x4.replace_lane 0 (local.get 0) (local.get 1)) (i32x4.replace_lane 3 (local.get 2) (local.get 3)))) + (func (export "as-i64x2_add-operands") (param v128 i64 v128 i64) (result v128) + (i64x2.add (i64x2.replace_lane 0 (local.get 0) (local.get 1)) (i64x2.replace_lane 1 (local.get 2) (local.get 3)))) + + (func (export "swizzle-as-i8x16_add-operands") (param v128 v128 v128 v128) (result v128) + (i8x16.add (i8x16.swizzle (local.get 0) (local.get 1)) (i8x16.swizzle (local.get 2) (local.get 3)))) + (func (export "shuffle-as-i8x16_sub-operands") (param v128 v128 v128 v128) (result v128) + (i8x16.sub (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (local.get 0) (local.get 1)) + (i8x16.shuffle 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 (local.get 2) (local.get 3)))) + + ;; Boolean horizontal reductions + (func (export "as-i8x16_any_true-operand") (param v128 i32) (result i32) + (v128.any_true (i8x16.replace_lane 0 (local.get 0) (local.get 1)))) + (func (export "as-i16x8_any_true-operand") (param v128 i32) (result i32) + (v128.any_true (i16x8.replace_lane 0 (local.get 0) (local.get 1)))) + (func (export "as-i32x4_any_true-operand1") (param v128 i32) (result i32) + (v128.any_true (i32x4.replace_lane 0 (local.get 0) (local.get 1)))) + (func (export "as-i32x4_any_true-operand2") (param v128 i64) (result i32) + (v128.any_true (i64x2.replace_lane 0 (local.get 0) (local.get 1)))) + + (func (export "swizzle-as-i8x16_all_true-operands") (param v128 v128) (result i32) + (i8x16.all_true (i8x16.swizzle (local.get 0) (local.get 1)))) + (func (export "shuffle-as-i8x16_any_true-operands") (param v128 v128) (result i32) + (v128.any_true (i8x16.shuffle 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (local.get 0) (local.get 1)))) +) + +(assert_return (invoke "as-i8x16_splat-operand" (v128.const i8x16 0xff 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) +(assert_return (invoke "as-i16x8_splat-operand" (v128.const i16x8 -1 -1 -1 -1 0 0 0 0)) (v128.const i16x8 -1 -1 -1 -1 -1 -1 -1 -1)) +(assert_return (invoke "as-i32x4_splat-operand" (v128.const i32x4 0x10000 0 0 0)) (v128.const i32x4 65536 65536 65536 65536)) +(assert_return (invoke "as-f32x4_splat-operand" (v128.const f32x4 3.14 nan nan nan)) (v128.const f32x4 3.14 3.14 3.14 3.14)) +(assert_return (invoke "as-i64x2_splat-operand" (v128.const i64x2 -1 0)) (v128.const i64x2 -1 -1)) +(assert_return (invoke "as-f64x2_splat-operand" (v128.const f64x2 inf nan)) (v128.const f64x2 inf inf)) +(assert_return (invoke "as-i8x16_add-operands" + (v128.const i8x16 0xff 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) (i32.const 1) + (v128.const i8x16 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 0xff) (i32.const 1)) + (v128.const i8x16 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17 17)) +(assert_return (invoke "as-i16x8_add-operands" + (v128.const i16x8 -1 4 9 16 25 36 49 64) (i32.const 1) + (v128.const i16x8 64 49 36 25 16 9 4 -1) (i32.const 1)) + (v128.const i16x8 65 53 45 41 41 45 53 65)) +(assert_return (invoke "as-i32x4_add-operands" + (v128.const i32x4 -1 8 27 64) (i32.const 1) (v128.const i32x4 64 27 8 -1) (i32.const 1)) (v128.const i32x4 65 35 35 65)) +(assert_return (invoke "as-i64x2_add-operands" + (v128.const i64x2 -1 8) (i64.const 1) (v128.const i64x2 64 27) (i64.const 1)) (v128.const i64x2 65 9)) + +(assert_return (invoke "swizzle-as-i8x16_add-operands" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) + (v128.const i8x16 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1)) +(assert_return (invoke "shuffle-as-i8x16_sub-operands" + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) + (v128.const i8x16 -15 -13 -11 -9 -7 -5 -3 -1 1 3 5 7 9 11 13 15)) + +(assert_return (invoke "as-i8x16_any_true-operand" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-i16x8_any_true-operand" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)) (i32.const 1)) +(assert_return (invoke "as-i32x4_any_true-operand1" (v128.const i32x4 1 0 0 0) (i32.const 0)) (i32.const 0)) +(assert_return (invoke "as-i32x4_any_true-operand2" (v128.const i64x2 1 0) (i64.const 0)) (i32.const 0)) + +(assert_return (invoke "swizzle-as-i8x16_all_true-operands" + (v128.const i8x16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) (i32.const 1)) +(assert_return (invoke "swizzle-as-i8x16_all_true-operands" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 16)) (i32.const 0)) +(assert_return (invoke "shuffle-as-i8x16_any_true-operands" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)) (i32.const 1)) + +;; Load and store + +(module + (memory 1) + (func (export "as-v128_store-operand-1") (param v128 i32) (result v128) + (v128.store (i32.const 0) (i8x16.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) + (func (export "as-v128_store-operand-2") (param v128 i32) (result v128) + (v128.store (i32.const 0) (i16x8.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) + (func (export "as-v128_store-operand-3") (param v128 i32) (result v128) + (v128.store (i32.const 0) (i32x4.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) + (func (export "as-v128_store-operand-4") (param v128 f32) (result v128) + (v128.store (i32.const 0) (f32x4.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) + (func (export "as-v128_store-operand-5") (param v128 i64) (result v128) + (v128.store (i32.const 0) (i64x2.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) + (func (export "as-v128_store-operand-6") (param v128 f64) (result v128) + (v128.store (i32.const 0) (f64x2.replace_lane 0 (local.get 0) (local.get 1))) + (v128.load (i32.const 0))) +) + +(assert_return (invoke "as-v128_store-operand-1" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)) (v128.const i8x16 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) +(assert_return (invoke "as-v128_store-operand-2" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 256)) (v128.const i16x8 0x100 0 0 0 0 0 0 0)) +(assert_return (invoke "as-v128_store-operand-3" (v128.const i32x4 0 0 0 0) (i32.const 0xffffffff)) (v128.const i32x4 -1 0 0 0)) +(assert_return (invoke "as-v128_store-operand-4" (v128.const f32x4 0 0 0 0) (f32.const 3.14)) (v128.const f32x4 3.14 0 0 0)) +(assert_return (invoke "as-v128_store-operand-5" (v128.const i64x2 0 0) (i64.const 0xffffffffffffffff)) (v128.const i64x2 -1 0)) +(assert_return (invoke "as-v128_store-operand-6" (v128.const f64x2 0 0) (f64.const 3.14)) (v128.const f64x2 3.14 0)) + +;; As the argument of wasm core ops + +(module + (global $g (mut v128) (v128.const f32x4 0.0 0.0 0.0 0.0)) + (global $h (mut v128) (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + (func (export "as-if-condition-value") (param v128) (result i32) + (if (result i32) (i8x16.extract_lane_s 0 (local.get 0)) (then (i32.const 0xff)) (else (i32.const 0)))) + (func (export "as-return-value-1") (param v128 i32) (result v128) + (return (i16x8.replace_lane 0 (local.get 0) (local.get 1)))) + (func (export "as-local_set-value") (param v128) (result i32) (local i32) + (local.set 1 (i32x4.extract_lane 0 (local.get 0))) + (return (local.get 1))) + (func (export "as-global_set-value-1") (param v128 f32) (result v128) + (global.set $g (f32x4.replace_lane 0 (local.get 0) (local.get 1))) + (return (global.get $g))) + + (func (export "as-return-value-2") (param v128 v128) (result v128) + (return (i8x16.swizzle (local.get 0) (local.get 1)))) + (func (export "as-global_set-value-2") (param v128 v128) (result v128) + (global.set $h (i8x16.shuffle 0 1 2 3 4 5 6 7 24 25 26 27 28 29 30 31 (local.get 0) (local.get 1))) + (return (global.get $h))) + + (func (export "as-local_set-value-1") (param v128) (result i64) (local i64) + (local.set 1 (i64x2.extract_lane 0 (local.get 0))) + (return (local.get 1))) + (func (export "as-global_set-value-3") (param v128 f64) (result v128) + (global.set $g (f64x2.replace_lane 0 (local.get 0) (local.get 1))) + (return (global.get $g))) +) + +(assert_return (invoke "as-if-condition-value" (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) (i32.const 0)) +(assert_return (invoke "as-return-value-1" (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)) (v128.const i16x8 1 0 0 0 0 0 0 0)) +(assert_return (invoke "as-local_set-value" (v128.const i32x4 -1 -1 -1 -1)) (i32.const -1)) +(assert_return (invoke "as-global_set-value-1" (v128.const f32x4 0 0 0 0)(f32.const 3.14)) (v128.const f32x4 3.14 0 0 0)) + +(assert_return (invoke "as-return-value-2" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)) + (v128.const i8x16 -1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16)) +(assert_return (invoke "as-global_set-value-2" + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 -8 -7 -6 -5 -4 -3 -2 -1) + (v128.const i8x16 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1)) + (v128.const i8x16 -16 -15 -14 -13 -12 -11 -10 -9 8 7 6 5 4 3 2 1)) + +(assert_return (invoke "as-local_set-value-1" (v128.const i64x2 -1 -1)) (i64.const -1)) +(assert_return (invoke "as-global_set-value-3" (v128.const f64x2 0 0)(f64.const 3.14)) (v128.const f64x2 3.14 0)) + +;; Non-nat lane index + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_u +0x0f (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result f32) (f32x4.extract_lane +03 (v128.const f32x4 0 0 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result i64) (i64x2.extract_lane +1 (v128.const i64x2 0 0)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i8x16.replace_lane +015 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i16x8.replace_lane +0x7 (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (i32x4.replace_lane +3 (v128.const i32x4 0 0 0 0) (i32.const 1)))") "unexpected token") +(assert_malformed (module quote "(func (result v128) (f64x2.replace_lane +0x01 (v128.const f64x2 0 0) (f64.const 1.0)))") "unexpected token") + +;; Lane index literal + +(module (func (result i32) (i8x16.extract_lane_s 0x0f (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))) +(module (func (result i32) (i16x8.extract_lane_s 0x07 (v128.const i16x8 0 0 0 0 0 0 0 0)))) +(module (func (result i32) (i16x8.extract_lane_u 0x0_7 (v128.const i16x8 0 0 0 0 0 0 0 0)))) +(module (func (result i32) (i32x4.extract_lane 03 (v128.const i32x4 0 0 0 0)))) +(module (func (result f64) (f64x2.extract_lane 0x1 (v128.const f64x2 0 0)))) +(module (func (result v128) (f32x4.replace_lane 0x3 (v128.const f32x4 0 0 0 0) (f32.const 1.0)))) +(module (func (result v128) (i64x2.replace_lane 01 (v128.const i64x2 0 0) (i64.const 1)))) + +;; 1.0 is malformed lane index + +(assert_malformed (module quote "(func (result i32) (i8x16.extract_lane_s 1.0 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)))") "unexpected token") + +;; Test operation with empty argument + +(assert_malformed + (module quote + "(func $i8x16.extract_lane_s-1st-arg-empty (result i32)" + " (i8x16.extract_lane_s (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i8x16.extract_lane_s-2nd-arg-empty (result i32) + (i8x16.extract_lane_s 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i8x16.extract_lane_s-arg-empty (result i32)" + " (i8x16.extract_lane_s)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i16x8.extract_lane_u-1st-arg-empty (result i32)" + " (i16x8.extract_lane_u (v128.const i16x8 0 0 0 0 0 0 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i16x8.extract_lane_u-2nd-arg-empty (result i32) + (i16x8.extract_lane_u 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i16x8.extract_lane_u-arg-empty (result i32)" + " (i16x8.extract_lane_u)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i32x4.extract_lane-1st-arg-empty (result i32)" + " (i32x4.extract_lane (v128.const i32x4 0 0 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i32x4.extract_lane-2nd-arg-empty (result i32) + (i32x4.extract_lane 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i32x4.extract_lane-arg-empty (result i32)" + " (i32x4.extract_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i64x2.extract_lane-1st-arg-empty (result i64)" + " (i64x2.extract_lane (v128.const i64x2 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i64x2.extract_lane-2nd-arg-empty (result i64) + (i64x2.extract_lane 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i64x2.extract_lane-arg-empty (result i64)" + " (i64x2.extract_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $f32x4.extract_lane-1st-arg-empty (result f32)" + " (f32x4.extract_lane (v128.const f32x4 0 0 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $f32x4.extract_lane-2nd-arg-empty (result f32) + (f32x4.extract_lane 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $f32x4.extract_lane-arg-empty (result f32)" + " (f32x4.extract_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $f64x2.extract_lane-1st-arg-empty (result f64)" + " (f64x2.extract_lane (v128.const f64x2 0 0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $f64x2.extract_lane-2nd-arg-empty (result f64) + (f64x2.extract_lane 0) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $f64x2.extract_lane-arg-empty (result f64)" + " (f64x2.extract_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i8x16.replace_lane-1st-arg-empty (result v128)" + " (i8x16.replace_lane (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0) (i32.const 1))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i8x16.replace_lane-2nd-arg-empty (result v128) + (i8x16.replace_lane 0 (i32.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $i8x16.replace_lane-3rd-arg-empty (result v128) + (i8x16.replace_lane 0 (v128.const i8x16 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i8x16.replace_lane-arg-empty (result v128)" + " (i8x16.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i16x8.replace_lane-1st-arg-empty (result v128)" + " (i16x8.replace_lane (v128.const i16x8 0 0 0 0 0 0 0 0) (i32.const 1))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i16x8.replace_lane-2nd-arg-empty (result v128) + (i16x8.replace_lane 0 (i32.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $i16x8.replace_lane-3rd-arg-empty (result v128) + (i16x8.replace_lane 0 (v128.const i16x8 0 0 0 0 0 0 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i16x8.replace_lane-arg-empty (result v128)" + " (i16x8.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i32x4.replace_lane-1st-arg-empty (result v128)" + " (i32x4.replace_lane (v128.const i32x4 0 0 0 0) (i32.const 1))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i32x4.replace_lane-2nd-arg-empty (result v128) + (i32x4.replace_lane 0 (i32.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $i32x4.replace_lane-3rd-arg-empty (result v128) + (i32x4.replace_lane 0 (v128.const i32x4 0 0 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i32x4.replace_lane-arg-empty (result v128)" + " (i32x4.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $f32x4.replace_lane-1st-arg-empty (result v128)" + " (f32x4.replace_lane (v128.const f32x4 0 0 0 0) (f32.const 1.0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $f32x4.replace_lane-2nd-arg-empty (result v128) + (f32x4.replace_lane 0 (f32.const 1.0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $f32x4.replace_lane-3rd-arg-empty (result v128) + (f32x4.replace_lane 0 (v128.const f32x4 0 0 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $f32x4.replace_lane-arg-empty (result v128)" + " (f32x4.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i64x2.replace_lane-1st-arg-empty (result v128)" + " (i64x2.replace_lane (v128.const i64x2 0 0) (i64.const 1))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $i64x2.replace_lane-2nd-arg-empty (result v128) + (i64x2.replace_lane 0 (i64.const 1)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $i64x2.replace_lane-3rd-arg-empty (result v128) + (i64x2.replace_lane 0 (v128.const i64x2 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i64x2.replace_lane-arg-empty (result v128)" + " (i64x2.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $f64x2.replace_lane-1st-arg-empty (result v128)" + " (f64x2.replace_lane (v128.const f64x2 0 0) (f64.const 1.0))" + ")" + ) + "unexpected token" +) +(assert_invalid + (module + (func $f64x2.replace_lane-2nd-arg-empty (result v128) + (f64x2.replace_lane 0 (f64.const 1.0)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (func $f64x2.replace_lane-3rd-arg-empty (result v128) + (f64x2.replace_lane 0 (v128.const f64x2 0 0)) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $f64x2.replace_lane-arg-empty (result v128)" + " (f64x2.replace_lane)" + ")" + ) + "unexpected token" +) +(assert_malformed + (module quote + "(func $i8x16.shuffle-1st-arg-empty (result v128)" + " (i8x16.shuffle" + " (v128.const i8x16 0 1 2 3 5 6 6 7 8 9 10 11 12 13 14 15)" + " (v128.const i8x16 1 2 3 5 6 6 7 8 9 10 11 12 13 14 15 16)" + " )" + ")" + ) + "invalid lane length" +) +(assert_invalid + (module + (func $i8x16.shuffle-2nd-arg-empty (result v128) + (i8x16.shuffle 0 1 2 3 5 6 6 7 8 9 10 11 12 13 14 15 + (v128.const i8x16 1 2 3 5 6 6 7 8 9 10 11 12 13 14 15 16) + ) + ) + ) + "type mismatch" +) +(assert_malformed + (module quote + "(func $i8x16.shuffle-arg-empty (result v128)" + " (i8x16.shuffle)" + ")" + ) + "invalid lane length" +) diff --git a/proposals/wasm-3.0/simd_memory-multi.wast b/proposals/wasm-3.0/simd_memory-multi.wast new file mode 100644 index 0000000..202f2cd --- /dev/null +++ b/proposals/wasm-3.0/simd_memory-multi.wast @@ -0,0 +1,42 @@ +;; From wasmtime misc_testsuite/multi-memory/simple.wast + +;; Test syntax for load/store_lane immediates + +(module + (memory 1) + (memory $m 1) + + (func + (local $v v128) + + (drop (v128.load8_lane 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) + + (drop (v128.load8_lane $m 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane $m align=1 1 (i32.const 0) (local.get $v))) + + (drop (v128.load8_lane 1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v))) + (drop (v128.load8_lane 1 align=1 1 (i32.const 0) (local.get $v))) + + (v128.store8_lane 1 (i32.const 0) (local.get $v)) + (v128.store8_lane offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane align=1 1 (i32.const 0) (local.get $v)) + + (v128.store8_lane $m 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane $m align=1 1 (i32.const 0) (local.get $v)) + + (v128.store8_lane 1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 offset=0 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 offset=0 align=1 1 (i32.const 0) (local.get $v)) + (v128.store8_lane 1 align=1 1 (i32.const 0) (local.get $v)) + ) +) diff --git a/proposals/wasm-3.0/start0.wast b/proposals/wasm-3.0/start0.wast new file mode 100644 index 0000000..677279e --- /dev/null +++ b/proposals/wasm-3.0/start0.wast @@ -0,0 +1,42 @@ +(module + (memory 0) + (memory $m (data "A")) + (memory $n 1) + + (func $inc + (i32.store8 $m + (i32.const 0) + (i32.add + (i32.load8_u $m (i32.const 0)) + (i32.const 1) + ) + ) + ) + (func $get (result i32) + (return (i32.load8_u $m (i32.const 0))) + ) + (func $getn (result i32) + (return (i32.load8_u $n (i32.const 0))) + ) + (func $main + (call $inc) + (call $inc) + (call $inc) + ) + + (start $main) + (export "inc" (func $inc)) + (export "get" (func $get)) + (export "getn" (func $getn)) +) +(assert_return (invoke "get") (i32.const 68)) +(assert_return (invoke "getn") (i32.const 0)) + +(invoke "inc") +(assert_return (invoke "get") (i32.const 69)) +(assert_return (invoke "getn") (i32.const 0)) + +(invoke "inc") +(assert_return (invoke "get") (i32.const 70)) +(assert_return (invoke "getn") (i32.const 0)) + diff --git a/proposals/wasm-3.0/store.wast b/proposals/wasm-3.0/store.wast new file mode 100644 index 0000000..86f6263 --- /dev/null +++ b/proposals/wasm-3.0/store.wast @@ -0,0 +1,565 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + +(module $M1 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M1") + +(module $M2 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M2") + +(invoke $M1 "store" (i32.const 0) (i64.const 1)) +(invoke $M2 "store" (i32.const 0) (i64.const 2)) +(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) + +(module + (memory $mem1 (import "M1" "mem") 1) + (memory $mem2 (import "M2" "mem") 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) + + +(module + (memory (export "mem") 2) +) +(register "M") + +(module + (memory $mem1 (import "M" "mem") 2) + (memory $mem2 3) + + (data (memory $mem1) (i32.const 20) "\01\02\03\04\05") + (data (memory $mem2) (i32.const 50) "\0A\0B\0C\0D\0E") + + (func (export "read1") (param i32) (result i32) + (i32.load8_u $mem1 (local.get 0)) + ) + (func (export "read2") (param i32) (result i32) + (i32.load8_u $mem2 (local.get 0)) + ) + + (func (export "copy-1-to-2") + (local $i i32) + (local.set $i (i32.const 20)) + (loop $cont + (br_if 1 (i32.eq (local.get $i) (i32.const 23))) + (i32.store8 $mem2 (local.get $i) (i32.load8_u $mem1 (local.get $i))) + (local.set $i (i32.add (local.get $i) (i32.const 1))) + (br $cont) + ) + ) + + (func (export "copy-2-to-1") + (local $i i32) + (local.set $i (i32.const 50)) + (loop $cont + (br_if 1 (i32.eq (local.get $i) (i32.const 54))) + (i32.store8 $mem1 (local.get $i) (i32.load8_u $mem2 (local.get $i))) + (local.set $i (i32.add (local.get $i) (i32.const 1))) + (br $cont) + ) + ) +) + +(assert_return (invoke "read2" (i32.const 20)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 21)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 22)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 23)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 24)) (i32.const 0)) +(invoke "copy-1-to-2") +(assert_return (invoke "read2" (i32.const 20)) (i32.const 1)) +(assert_return (invoke "read2" (i32.const 21)) (i32.const 2)) +(assert_return (invoke "read2" (i32.const 22)) (i32.const 3)) +(assert_return (invoke "read2" (i32.const 23)) (i32.const 0)) +(assert_return (invoke "read2" (i32.const 24)) (i32.const 0)) + +(assert_return (invoke "read1" (i32.const 50)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 51)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 52)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 53)) (i32.const 0)) +(assert_return (invoke "read1" (i32.const 54)) (i32.const 0)) +(invoke "copy-2-to-1") +(assert_return (invoke "read1" (i32.const 50)) (i32.const 10)) +(assert_return (invoke "read1" (i32.const 51)) (i32.const 11)) +(assert_return (invoke "read1" (i32.const 52)) (i32.const 12)) +(assert_return (invoke "read1" (i32.const 53)) (i32.const 13)) +(assert_return (invoke "read1" (i32.const 54)) (i32.const 0)) + + +;; Store operator as the argument of control constructs and instructions + +(module + (memory 1) + + (func (export "as-block-value") + (block (i32.store (i32.const 0) (i32.const 1))) + ) + (func (export "as-loop-value") + (loop (i32.store (i32.const 0) (i32.const 1))) + ) + + (func (export "as-br-value") + (block (br 0 (i32.store (i32.const 0) (i32.const 1)))) + ) + (func (export "as-br_if-value") + (block + (br_if 0 (i32.store (i32.const 0) (i32.const 1)) (i32.const 1)) + ) + ) + (func (export "as-br_if-value-cond") + (block + (br_if 0 (i32.const 6) (i32.store (i32.const 0) (i32.const 1))) + ) + ) + (func (export "as-br_table-value") + (block + (br_table 0 (i32.store (i32.const 0) (i32.const 1)) (i32.const 1)) + ) + ) + + (func (export "as-return-value") + (return (i32.store (i32.const 0) (i32.const 1))) + ) + + (func (export "as-if-then") + (if (i32.const 1) (then (i32.store (i32.const 0) (i32.const 1)))) + ) + (func (export "as-if-else") + (if (i32.const 0) (then) (else (i32.store (i32.const 0) (i32.const 1)))) + ) +) + +(assert_return (invoke "as-block-value")) +(assert_return (invoke "as-loop-value")) + +(assert_return (invoke "as-br-value")) +(assert_return (invoke "as-br_if-value")) +(assert_return (invoke "as-br_if-value-cond")) +(assert_return (invoke "as-br_table-value")) + +(assert_return (invoke "as-return-value")) + +(assert_return (invoke "as-if-then")) +(assert_return (invoke "as-if-else")) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (i32.store32 (local.get 0) (i32.const 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (i32.store64 (local.get 0) (i64.const 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (i64.store64 (local.get 0) (i64.const 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (f32.store32 (local.get 0) (f32.const 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (f32.store64 (local.get 0) (f64.const 0)))" + ) + "unknown operator" +) + +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (f64.store32 (local.get 0) (f32.const 0)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(memory 1)" + "(func (param i32) (f64.store64 (local.get 0) (f64.const 0)))" + ) + "unknown operator" +) +;; store should have no retval + +(assert_invalid + (module (memory 1) (func (param i32) (result i32) (i32.store (i32.const 0) (i32.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store (i32.const 0) (i64.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param f32) (result f32) (f32.store (i32.const 0) (f32.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param f64) (result f64) (f64.store (i32.const 0) (f64.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i32) (result i32) (i32.store8 (i32.const 0) (i32.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i32) (result i32) (i32.store16 (i32.const 0) (i32.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store8 (i32.const 0) (i64.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store16 (i32.const 0) (i64.const 1)))) + "type mismatch" +) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store32 (i32.const 0) (i64.const 1)))) + "type mismatch" +) + + +(assert_invalid + (module + (memory 1) + (func $type-address-empty + (i32.store) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty + (i32.const 0) (i32.store) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-block + (i32.const 0) (i32.const 0) + (block (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-block + (i32.const 0) + (block (i32.const 0) (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-loop + (i32.const 0) (i32.const 0) + (loop (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-loop + (i32.const 0) + (loop (i32.const 0) (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-then + (i32.const 0) (i32.const 0) + (if (then (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-then + (i32.const 0) + (if (then (i32.const 0) (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-else + (i32.const 0) (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-else + (i32.const 0) + (if (result i32) (then (i32.const 0)) (else (i32.const 0) (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-br + (i32.const 0) (i32.const 0) + (block (br 0 (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-br + (i32.const 0) + (block (br 0 (i32.const 0) (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-br_if + (i32.const 0) (i32.const 0) + (block (br_if 0 (i32.store) (i32.const 1)) ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-br_if + (i32.const 0) + (block (br_if 0 (i32.const 0) (i32.store) (i32.const 1)) ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-br_table + (i32.const 0) (i32.const 0) + (block (br_table 0 (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-br_table + (i32.const 0) + (block (br_table 0 (i32.const 0) (i32.store))) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-return + (return (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-return + (return (i32.const 0) (i32.store)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-select + (select (i32.store) (i32.const 1) (i32.const 2)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-select + (select (i32.const 0) (i32.store) (i32.const 1) (i32.const 2)) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-address-empty-in-call + (call 1 (i32.store)) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $type-value-empty-in-call + (call 1 (i32.const 0) (i32.store)) + ) + (func (param i32) (result i32) (local.get 0)) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-address-empty-in-call_indirect + (block (result i32) + (call_indirect (type $sig) + (i32.store) (i32.const 0) + ) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (memory 1) + (func $f (param i32) (result i32) (local.get 0)) + (type $sig (func (param i32) (result i32))) + (table funcref (elem $f)) + (func $type-value-empty-in-call_indirect + (block (result i32) + (call_indirect (type $sig) + (i32.const 0) (i32.store) (i32.const 0) + ) + ) + ) + ) + "type mismatch" +) + + +;; Type check + +(assert_invalid (module (memory 1) (func (i32.store (f32.const 0) (i32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i32.store8 (f32.const 0) (i32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i32.store16 (f32.const 0) (i32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store (f32.const 0) (i32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store8 (f32.const 0) (i64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store16 (f32.const 0) (i64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store32 (f32.const 0) (i64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (f32.store (f32.const 0) (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (f64.store (f32.const 0) (f64.const 0)))) "type mismatch") + +(assert_invalid (module (memory 1) (func (i32.store (i32.const 0) (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i32.store8 (i32.const 0) (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i32.store16 (i32.const 0) (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store (i32.const 0) (f32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store8 (i32.const 0) (f64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store16 (i32.const 0) (f64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (i64.store32 (i32.const 0) (f64.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (f32.store (i32.const 0) (i32.const 0)))) "type mismatch") +(assert_invalid (module (memory 1) (func (f64.store (i32.const 0) (i64.const 0)))) "type mismatch") diff --git a/proposals/wasm-3.0/store0.wast b/proposals/wasm-3.0/store0.wast new file mode 100644 index 0000000..2f217b1 --- /dev/null +++ b/proposals/wasm-3.0/store0.wast @@ -0,0 +1,25 @@ +;; Multiple memories + +(module + (memory $mem1 1) + (memory $mem2 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/proposals/wasm-3.0/store1.wast b/proposals/wasm-3.0/store1.wast new file mode 100644 index 0000000..10cf2c4 --- /dev/null +++ b/proposals/wasm-3.0/store1.wast @@ -0,0 +1,52 @@ +(module $M1 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M1") + +(module $M2 + (memory (export "mem") 1) + + (func (export "load") (param i32) (result i64) + (i64.load (local.get 0)) + ) + (func (export "store") (param i32 i64) + (i64.store (local.get 0) (local.get 1)) + ) +) +(register "M2") + +(invoke $M1 "store" (i32.const 0) (i64.const 1)) +(invoke $M2 "store" (i32.const 0) (i64.const 2)) +(assert_return (invoke $M1 "load" (i32.const 0)) (i64.const 1)) +(assert_return (invoke $M2 "load" (i32.const 0)) (i64.const 2)) + +(module + (memory $mem1 (import "M1" "mem") 1) + (memory $mem2 (import "M2" "mem") 1) + + (func (export "load1") (param i32) (result i64) + (i64.load $mem1 (local.get 0)) + ) + (func (export "load2") (param i32) (result i64) + (i64.load $mem2 (local.get 0)) + ) + + (func (export "store1") (param i32 i64) + (i64.store $mem1 (local.get 0) (local.get 1)) + ) + (func (export "store2") (param i32 i64) + (i64.store $mem2 (local.get 0) (local.get 1)) + ) +) + +(invoke "store1" (i32.const 0) (i64.const 1)) +(invoke "store2" (i32.const 0) (i64.const 2)) +(assert_return (invoke "load1" (i32.const 0)) (i64.const 1)) +(assert_return (invoke "load2" (i32.const 0)) (i64.const 2)) diff --git a/proposals/wasm-3.0/struct.wast b/proposals/wasm-3.0/struct.wast new file mode 100644 index 0000000..6151fe1 --- /dev/null +++ b/proposals/wasm-3.0/struct.wast @@ -0,0 +1,229 @@ +;; Type syntax + +(module + (type (struct)) + (type (struct (field))) + (type (struct (field i8))) + (type (struct (field i8 i8 i8 i8))) + (type (struct (field $x1 i32) (field $y1 i32))) + (type (struct (field i8 i16 i32 i64 f32 f64 anyref funcref (ref 0) (ref null 1)))) + (type (struct (field i32 i64 i8) (field) (field) (field (ref null i31) anyref))) + (type (struct (field $x2 i32) (field f32 f64) (field $y2 i32))) +) + + +(assert_malformed + (module quote + "(type (struct (field $x i32) (field $x i32)))" + ) + "duplicate field" +) + + +;; Binding structure + +(module + (rec + (type $s0 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1)))) + (type $s1 (struct (field (ref 0) (ref 1) (ref $s0) (ref $s1)))) + ) + + (func (param (ref $forward))) + + (type $forward (struct)) +) + +(assert_invalid + (module (type (struct (field (ref 1))))) + "unknown type" +) +(assert_invalid + (module (type (struct (field (mut (ref 1)))))) + "unknown type" +) + + +;; Field names + +(module + (type (struct (field $x i32))) + (type $t1 (struct (field i32) (field $x f32))) + (type $t2 (struct (field i32 i32) (field $x i64))) + + (func (param (ref 0)) (result i32) (struct.get 0 $x (local.get 0))) + (func (param (ref $t1)) (result f32) (struct.get 1 $x (local.get 0))) + (func (param (ref $t2)) (result i64) (struct.get $t2 $x (local.get 0))) +) + +(assert_invalid + (module + (type (struct (field $x i64))) + (type $t (struct (field $x i32))) + (func (param (ref 0)) (result i32) (struct.get 0 $x (local.get 0))) + ) + "type mismatch" +) + + +;; Basic instructions + +(module + (type $vec (struct (field f32) (field $y (mut f32)) (field $z f32))) + + (global (ref $vec) (struct.new $vec (f32.const 1) (f32.const 2) (f32.const 3))) + (global (ref $vec) (struct.new_default $vec)) + + (func (export "new") (result anyref) + (struct.new_default $vec) + ) + + (func $get_0_0 (param $v (ref $vec)) (result f32) + (struct.get 0 0 (local.get $v)) + ) + (func (export "get_0_0") (result f32) + (call $get_0_0 (struct.new_default $vec)) + ) + (func $get_vec_0 (param $v (ref $vec)) (result f32) + (struct.get $vec 0 (local.get $v)) + ) + (func (export "get_vec_0") (result f32) + (call $get_vec_0 (struct.new_default $vec)) + ) + (func $get_0_y (param $v (ref $vec)) (result f32) + (struct.get 0 $y (local.get $v)) + ) + (func (export "get_0_y") (result f32) + (call $get_0_y (struct.new_default $vec)) + ) + (func $get_vec_y (param $v (ref $vec)) (result f32) + (struct.get $vec $y (local.get $v)) + ) + (func (export "get_vec_y") (result f32) + (call $get_vec_y (struct.new_default $vec)) + ) + + (func $set_get_y (param $v (ref $vec)) (param $y f32) (result f32) + (struct.set $vec $y (local.get $v) (local.get $y)) + (struct.get $vec $y (local.get $v)) + ) + (func (export "set_get_y") (param $y f32) (result f32) + (call $set_get_y (struct.new_default $vec) (local.get $y)) + ) + + (func $set_get_1 (param $v (ref $vec)) (param $y f32) (result f32) + (struct.set $vec 1 (local.get $v) (local.get $y)) + (struct.get $vec $y (local.get $v)) + ) + (func (export "set_get_1") (param $y f32) (result f32) + (call $set_get_1 (struct.new_default $vec) (local.get $y)) + ) +) + +(assert_return (invoke "new") (ref.struct)) + +(assert_return (invoke "get_0_0") (f32.const 0)) +(assert_return (invoke "get_vec_0") (f32.const 0)) +(assert_return (invoke "get_0_y") (f32.const 0)) +(assert_return (invoke "get_vec_y") (f32.const 0)) + +(assert_return (invoke "set_get_y" (f32.const 7)) (f32.const 7)) +(assert_return (invoke "set_get_1" (f32.const 7)) (f32.const 7)) + +(assert_invalid + (module + (type $s (struct (field i64))) + (func (export "struct.set-immutable") (param $s (ref $s)) + (struct.set $s 0 (local.get $s) (i64.const 1)) + ) + ) + "field is immutable" +) + + +;; Null dereference + +(module + (type $t (struct (field i32 (mut i32)))) + (func (export "struct.get-null") + (local (ref null $t)) (drop (struct.get $t 1 (local.get 0))) + ) + (func (export "struct.set-null") + (local (ref null $t)) (struct.set $t 1 (local.get 0) (i32.const 0)) + ) +) + +(assert_trap (invoke "struct.get-null") "null structure reference") +(assert_trap (invoke "struct.set-null") "null structure reference") + +;; Packed field instructions + +(module + (type $s (struct (field i8) (field (mut i8)) (field i16) (field (mut i16)))) + + (global (export "g0") (ref $s) (struct.new $s (i32.const 0) (i32.const 1) (i32.const 2) (i32.const 3))) + (global (export "g1") (ref $s) (struct.new $s (i32.const 254) (i32.const 255) (i32.const 65534) (i32.const 65535))) + + (func (export "get_packed_g0_0") (result i32 i32) + (struct.get_s 0 0 (global.get 0)) + (struct.get_u 0 0 (global.get 0)) + ) + + (func (export "get_packed_g1_0") (result i32 i32) + (struct.get_s 0 0 (global.get 1)) + (struct.get_u 0 0 (global.get 1)) + ) + + (func (export "get_packed_g0_1") (result i32 i32) + (struct.get_s 0 1 (global.get 0)) + (struct.get_u 0 1 (global.get 0)) + ) + + (func (export "get_packed_g1_1") (result i32 i32) + (struct.get_s 0 1 (global.get 1)) + (struct.get_u 0 1 (global.get 1)) + ) + + (func (export "get_packed_g0_2") (result i32 i32) + (struct.get_s 0 2 (global.get 0)) + (struct.get_u 0 2 (global.get 0)) + ) + + (func (export "get_packed_g1_2") (result i32 i32) + (struct.get_s 0 2 (global.get 1)) + (struct.get_u 0 2 (global.get 1)) + ) + + (func (export "get_packed_g0_3") (result i32 i32) + (struct.get_s 0 3 (global.get 0)) + (struct.get_u 0 3 (global.get 0)) + ) + + (func (export "get_packed_g1_3") (result i32 i32) + (struct.get_s 0 3 (global.get 1)) + (struct.get_u 0 3 (global.get 1)) + ) + + (func (export "set_get_packed_g0_1") (param i32) (result i32 i32) + (struct.set 0 1 (global.get 0) (local.get 0)) + (struct.get_s 0 1 (global.get 0)) + (struct.get_u 0 1 (global.get 0)) + ) + + (func (export "set_get_packed_g0_3") (param i32) (result i32 i32) + (struct.set 0 3 (global.get 0) (local.get 0)) + (struct.get_s 0 3 (global.get 0)) + (struct.get_u 0 3 (global.get 0)) + ) +) + +(assert_return (invoke "get_packed_g0_0") (i32.const 0) (i32.const 0)) +(assert_return (invoke "get_packed_g1_0") (i32.const -2) (i32.const 254)) +(assert_return (invoke "get_packed_g0_1") (i32.const 1) (i32.const 1)) +(assert_return (invoke "get_packed_g1_1") (i32.const -1) (i32.const 255)) +(assert_return (invoke "get_packed_g0_2") (i32.const 2) (i32.const 2)) +(assert_return (invoke "get_packed_g1_2") (i32.const -2) (i32.const 65534)) +(assert_return (invoke "get_packed_g0_3") (i32.const 3) (i32.const 3)) +(assert_return (invoke "get_packed_g1_3") (i32.const -1) (i32.const 65535)) + +(assert_return (invoke "set_get_packed_g0_1" (i32.const 257)) (i32.const 1) (i32.const 1)) +(assert_return (invoke "set_get_packed_g0_3" (i32.const 257)) (i32.const 257) (i32.const 257)) diff --git a/proposals/wasm-3.0/table-sub.wast b/proposals/wasm-3.0/table-sub.wast new file mode 100644 index 0000000..c3a7440 --- /dev/null +++ b/proposals/wasm-3.0/table-sub.wast @@ -0,0 +1,32 @@ +(module + (type $t (func)) + (table $t1 10 (ref null func)) + (table $t2 10 (ref null $t)) + (elem $el funcref) + (func $f + (table.init $t1 $el (i32.const 0) (i32.const 1) (i32.const 2)) + (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2)) + ) +) + +(assert_invalid + (module + (table $t1 10 funcref) + (table $t2 10 externref) + (func $f + (table.copy $t1 $t2 (i32.const 0) (i32.const 1) (i32.const 2)) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (table $t 10 funcref) + (elem $el externref) + (func $f + (table.init $t $el (i32.const 0) (i32.const 1) (i32.const 2)) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/table.wast b/proposals/wasm-3.0/table.wast new file mode 100644 index 0000000..a0feeff --- /dev/null +++ b/proposals/wasm-3.0/table.wast @@ -0,0 +1,186 @@ +;; Test table section structure + +(module (table 0 funcref)) +(module (table 1 funcref)) +(module (table 0 0 funcref)) +(module (table 0 1 funcref)) +(module (table 1 256 funcref)) +(module (table 0 65536 funcref)) +(module (table 0 0xffff_ffff funcref)) + +(module (table 1 (ref null func))) +(module (table 1 (ref null extern))) +(module (table 1 (ref null $t)) (type $t (func))) + +(module (table 0 funcref) (table 0 funcref)) +(module (table (import "spectest" "table") 0 funcref) (table 0 funcref)) + +(module (table 0 funcref (ref.null func))) +(module (table 1 funcref (ref.null func))) +(module (table 1 (ref null func) (ref.null func))) + +(assert_invalid (module (elem (i32.const 0))) "unknown table") +(assert_invalid (module (elem (i32.const 0) $f) (func $f)) "unknown table") + +(assert_invalid + (module (table 1 0 funcref)) + "size minimum must not be greater than maximum" +) +(assert_invalid + (module (table 0xffff_ffff 0 funcref)) + "size minimum must not be greater than maximum" +) + +(assert_invalid + (module quote "(table 0x1_0000_0000 funcref)") + "table size" +) +(assert_invalid + (module quote "(table 0x1_0000_0000 0x1_0000_0000 funcref)") + "table size" +) +(assert_invalid + (module quote "(table 0 0x1_0000_0000 funcref)") + "table size" +) + +;; Same as above but with i64 address types + +(module (table i64 0 funcref)) +(module (table i64 1 funcref)) +(module (table i64 0 0 funcref)) +(module (table i64 0 1 funcref)) +(module (table i64 1 256 funcref)) +(module (table i64 0 65536 funcref)) +(module (table i64 0 0xffff_ffff funcref)) + +(module (table i64 0 funcref) (table i64 0 funcref)) +(module (table (import "spectest" "table64") i64 0 funcref) (table i64 0 funcref)) + +(assert_invalid + (module (table i64 1 0 funcref)) + "size minimum must not be greater than maximum" +) +(assert_invalid + (module (table i64 0xffff_ffff 0 funcref)) + "size minimum must not be greater than maximum" +) + +;; Elem segments with no table + +(assert_invalid (module (elem (i32.const 0))) "unknown table") +(assert_invalid (module (elem (i32.const 0) $f) (func $f)) "unknown table") + +(assert_invalid + (module (table 1 (ref null func) (i32.const 0))) + "type mismatch" +) +(assert_invalid + (module (table 1 (ref func) (ref.null extern))) + "type mismatch" +) +(assert_invalid + (module (type $t (func)) (table 1 (ref $t) (ref.null func))) + "type mismatch" +) +(assert_invalid + (module (table 1 (ref func) (ref.null func))) + "type mismatch" +) +(assert_invalid + (module (table 0 (ref func))) + "type mismatch" +) +(assert_invalid + (module (table 0 (ref extern))) + "type mismatch" +) +(assert_invalid + (module (type $t (func)) (table 0 (ref $t))) + "type mismatch" +) + + +;; Table initializer + +(module + (global (export "g") (ref $f) (ref.func $f)) + (type $f (func)) + (func $f) +) +(register "M") + +(module + (global $g (import "M" "g") (ref $dummy)) + + (type $dummy (func)) + (func $dummy) + + (table $t1 10 funcref) + (table $t2 10 funcref (ref.func $dummy)) + (table $t3 10 (ref $dummy) (ref.func $dummy)) + (table $t4 10 funcref (global.get $g)) + (table $t5 10 (ref $dummy) (global.get $g)) + + (func (export "get1") (result funcref) (table.get $t1 (i32.const 1))) + (func (export "get2") (result funcref) (table.get $t2 (i32.const 4))) + (func (export "get3") (result funcref) (table.get $t3 (i32.const 7))) + (func (export "get4") (result funcref) (table.get $t4 (i32.const 8))) + (func (export "get5") (result funcref) (table.get $t5 (i32.const 9))) +) + +(assert_return (invoke "get1") (ref.null)) +(assert_return (invoke "get2") (ref.func)) +(assert_return (invoke "get3") (ref.func)) +(assert_return (invoke "get4") (ref.func)) +(assert_return (invoke "get5") (ref.func)) + + +(assert_invalid + (module + (type $f (func)) + (table 10 (ref $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $f (func)) + (table 0 (ref $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (type $f (func)) + (table 0 0 (ref $f)) + ) + "type mismatch" +) + + +;; Duplicate table identifiers + +(assert_malformed + (module quote + "(table $foo 1 funcref)" + "(table $foo 1 funcref)" + ) + "duplicate table" +) +(assert_malformed + (module quote + "(import \"\" \"\" (table $foo 1 funcref))" + "(table $foo 1 funcref)" + ) + "duplicate table" +) +(assert_malformed + (module quote + "(import \"\" \"\" (table $foo 1 funcref))" + "(import \"\" \"\" (table $foo 1 funcref))" + ) + "duplicate table" +) diff --git a/proposals/memory64/table_copy.wast b/proposals/wasm-3.0/table_copy.wast similarity index 100% rename from proposals/memory64/table_copy.wast rename to proposals/wasm-3.0/table_copy.wast diff --git a/proposals/memory64/table_copy_mixed.wast b/proposals/wasm-3.0/table_copy_mixed.wast similarity index 100% rename from proposals/memory64/table_copy_mixed.wast rename to proposals/wasm-3.0/table_copy_mixed.wast diff --git a/proposals/memory64/table_fill.wast b/proposals/wasm-3.0/table_fill.wast similarity index 100% rename from proposals/memory64/table_fill.wast rename to proposals/wasm-3.0/table_fill.wast diff --git a/proposals/memory64/table_get.wast b/proposals/wasm-3.0/table_get.wast similarity index 100% rename from proposals/memory64/table_get.wast rename to proposals/wasm-3.0/table_get.wast diff --git a/proposals/memory64/table_grow.wast b/proposals/wasm-3.0/table_grow.wast similarity index 100% rename from proposals/memory64/table_grow.wast rename to proposals/wasm-3.0/table_grow.wast diff --git a/proposals/memory64/table_init.wast b/proposals/wasm-3.0/table_init.wast similarity index 100% rename from proposals/memory64/table_init.wast rename to proposals/wasm-3.0/table_init.wast diff --git a/proposals/memory64/table_set.wast b/proposals/wasm-3.0/table_set.wast similarity index 100% rename from proposals/memory64/table_set.wast rename to proposals/wasm-3.0/table_set.wast diff --git a/proposals/memory64/table_size.wast b/proposals/wasm-3.0/table_size.wast similarity index 100% rename from proposals/memory64/table_size.wast rename to proposals/wasm-3.0/table_size.wast diff --git a/proposals/wasm-3.0/tag.wast b/proposals/wasm-3.0/tag.wast new file mode 100644 index 0000000..3ea8b55 --- /dev/null +++ b/proposals/wasm-3.0/tag.wast @@ -0,0 +1,61 @@ +;; Test tag section + +(module + (tag) + (tag (param i32)) + (tag (export "t2") (param i32)) + (tag $t3 (param i32 f32)) + (export "t3" (tag 3)) +) + +(register "test") + +(module + (tag $t0 (import "test" "t2") (param i32)) + (import "test" "t3" (tag $t1 (param i32 f32))) +) + +(assert_invalid + (module (tag (result i32))) + "non-empty tag result type" +) + + +;; Link-time typing + +(module + (rec + (type $t1 (func)) + (type $t2 (func)) + ) + (tag (export "tag") (type $t1)) +) + +(register "M") + +(module + (rec + (type $t1 (func)) + (type $t2 (func)) + ) + (tag (import "M" "tag") (type $t1)) +) + +(assert_unlinkable + (module + (rec + (type $t1 (func)) + (type $t2 (func)) + ) + (tag (import "M" "tag") (type $t2)) + ) + "incompatible import" +) + +(assert_unlinkable + (module + (type $t (func)) + (tag (import "M" "tag") (type $t)) + ) + "incompatible import" +) diff --git a/proposals/wasm-3.0/throw.wast b/proposals/wasm-3.0/throw.wast new file mode 100644 index 0000000..dc1aa4a --- /dev/null +++ b/proposals/wasm-3.0/throw.wast @@ -0,0 +1,55 @@ +;; Test throw instruction. + +(module + (tag $e0) + (tag $e-i32 (param i32)) + (tag $e-f32 (param f32)) + (tag $e-i64 (param i64)) + (tag $e-f64 (param f64)) + (tag $e-i32-i32 (param i32 i32)) + + (func $throw-if (export "throw-if") (param i32) (result i32) + (local.get 0) + (i32.const 0) (if (i32.ne) (then (throw $e0))) + (i32.const 0) + ) + + (func (export "throw-param-f32") (param f32) (local.get 0) (throw $e-f32)) + + (func (export "throw-param-i64") (param i64) (local.get 0) (throw $e-i64)) + + (func (export "throw-param-f64") (param f64) (local.get 0) (throw $e-f64)) + + (func (export "throw-polymorphic") (throw $e0) (throw $e-i32)) + + (func (export "throw-polymorphic-block") (block (result i32) (throw $e0)) (throw $e-i32)) + + (func $throw-1-2 (i32.const 1) (i32.const 2) (throw $e-i32-i32)) + (func (export "test-throw-1-2") + (block $h (result i32 i32) + (try_table (catch $e-i32-i32 $h) (call $throw-1-2)) + (return) + ) + (if (i32.ne (i32.const 2)) (then (unreachable))) + (if (i32.ne (i32.const 1)) (then (unreachable))) + ) +) + +(assert_return (invoke "throw-if" (i32.const 0)) (i32.const 0)) +(assert_exception (invoke "throw-if" (i32.const 10))) +(assert_exception (invoke "throw-if" (i32.const -1))) + +(assert_exception (invoke "throw-param-f32" (f32.const 5.0))) +(assert_exception (invoke "throw-param-i64" (i64.const 5))) +(assert_exception (invoke "throw-param-f64" (f64.const 5.0))) + +(assert_exception (invoke "throw-polymorphic")) +(assert_exception (invoke "throw-polymorphic-block")) + +(assert_return (invoke "test-throw-1-2")) + +(assert_invalid (module (func (throw 0))) "unknown tag 0") +(assert_invalid (module (tag (param i32)) (func (throw 0))) + "type mismatch: instruction requires [i32] but stack has []") +(assert_invalid (module (tag (param i32)) (func (i64.const 5) (throw 0))) + "type mismatch: instruction requires [i32] but stack has [i64]") diff --git a/proposals/wasm-3.0/throw_ref.wast b/proposals/wasm-3.0/throw_ref.wast new file mode 100644 index 0000000..f59710a --- /dev/null +++ b/proposals/wasm-3.0/throw_ref.wast @@ -0,0 +1,118 @@ +;; Test throw_ref instruction. + +(module + (tag $e0) + (tag $e1) + + (func (export "catch-throw_ref-0") + (block $h (result exnref) + (try_table (catch_ref $e0 $h) (throw $e0)) + (unreachable) + ) + (throw_ref) + ) + + (func (export "catch-throw_ref-1") (param i32) (result i32) + (block $h (result exnref) + (try_table (result i32) (catch_ref $e0 $h) (throw $e0)) + (return) + ) + (if (param exnref) (i32.eqz (local.get 0)) + (then (throw_ref)) + (else (drop)) + ) + (i32.const 23) + ) + + (func (export "catchall-throw_ref-0") + (block $h (result exnref) + (try_table (result exnref) (catch_all_ref $h) (throw $e0)) + ) + (throw_ref) + ) + + (func (export "catchall-throw_ref-1") (param i32) (result i32) + (block $h (result exnref) + (try_table (result i32) (catch_all_ref $h) (throw $e0)) + (return) + ) + (if (param exnref) (i32.eqz (local.get 0)) + (then (throw_ref)) + (else (drop)) + ) + (i32.const 23) + ) + + (func (export "throw_ref-nested") (param i32) (result i32) + (local $exn1 exnref) + (local $exn2 exnref) + (block $h1 (result exnref) + (try_table (result i32) (catch_ref $e1 $h1) (throw $e1)) + (return) + ) + (local.set $exn1) + (block $h2 (result exnref) + (try_table (result i32) (catch_ref $e0 $h2) (throw $e0)) + (return) + ) + (local.set $exn2) + (if (i32.eq (local.get 0) (i32.const 0)) + (then (throw_ref (local.get $exn1))) + ) + (if (i32.eq (local.get 0) (i32.const 1)) + (then (throw_ref (local.get $exn2))) + ) + (i32.const 23) + ) + + (func (export "throw_ref-recatch") (param i32) (result i32) + (local $e exnref) + (block $h1 (result exnref) + (try_table (result i32) (catch_ref $e0 $h1) (throw $e0)) + (return) + ) + (local.set $e) + (block $h2 (result exnref) + (try_table (result i32) (catch_ref $e0 $h2) + (if (i32.eqz (local.get 0)) + (then (throw_ref (local.get $e))) + ) + (i32.const 42) + ) + (return) + ) + (drop) (i32.const 23) + ) + + (func (export "throw_ref-stack-polymorphism") + (local $e exnref) + (block $h (result exnref) + (try_table (result f64) (catch_ref $e0 $h) (throw $e0)) + (unreachable) + ) + (local.set $e) + (i32.const 1) + (throw_ref (local.get $e)) + ) +) + +(assert_exception (invoke "catch-throw_ref-0")) + +(assert_exception (invoke "catch-throw_ref-1" (i32.const 0))) +(assert_return (invoke "catch-throw_ref-1" (i32.const 1)) (i32.const 23)) + +(assert_exception (invoke "catchall-throw_ref-0")) + +(assert_exception (invoke "catchall-throw_ref-1" (i32.const 0))) +(assert_return (invoke "catchall-throw_ref-1" (i32.const 1)) (i32.const 23)) +(assert_exception (invoke "throw_ref-nested" (i32.const 0))) +(assert_exception (invoke "throw_ref-nested" (i32.const 1))) +(assert_return (invoke "throw_ref-nested" (i32.const 2)) (i32.const 23)) + +(assert_return (invoke "throw_ref-recatch" (i32.const 0)) (i32.const 23)) +(assert_return (invoke "throw_ref-recatch" (i32.const 1)) (i32.const 42)) + +(assert_exception (invoke "throw_ref-stack-polymorphism")) + +(assert_invalid (module (func (throw_ref))) "type mismatch") +(assert_invalid (module (func (block (throw_ref)))) "type mismatch") diff --git a/proposals/wasm-3.0/token.wast b/proposals/wasm-3.0/token.wast new file mode 100644 index 0000000..44e41f2 --- /dev/null +++ b/proposals/wasm-3.0/token.wast @@ -0,0 +1,304 @@ +;; Test tokenization + +(assert_malformed + (module quote "(func (drop (i32.const0)))") + "unknown operator" +) +(assert_malformed + (module quote "(func br 0drop)") + "unknown operator" +) + + +;; Tokens can be delimited by parentheses + +(module + (func(nop)) +) +(module + (func (nop)nop) +) +(module + (func nop(nop)) +) +(module + (func(nop)(nop)) +) +(module + (func $f(nop)) +) +(module + (func br 0(nop)) +) +(module + (table 1 funcref) + (func) + (elem (i32.const 0)0) +) +(module + (table 1 funcref) + (func $f) + (elem (i32.const 0)$f) +) +(module + (memory 1) + (data (i32.const 0)"a") +) +(module + (import "spectest" "print"(func)) +) + + +;; Tokens can be delimited by comments + +(module + (func;;bla + ) +) +(module + (func (nop);;bla + ) +) +(module + (func nop;;bla + ) +) +(module + (func $f;;bla + ) +) +(module + (func br 0;;bla + ) +) +(module + (data "a";;bla + ) +) + + +;; Space required between symbols and non-parenthesis tokens + +(module + (func (block $l (i32.const 0) (br_table 0 $l))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table 0$l)))" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table 0$\"l\")))" + ) + "unknown operator" +) + +(module + (func (block $l (i32.const 0) (br_table $l 0))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $l0)))" + ) + "unknown label" +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $\"l\"0)))" + ) + "unknown operator" +) + +(module + (func (block $l (i32.const 0) (br_table $l $l))) +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $l$l)))" + ) + "unknown label" +) +(assert_malformed + (module quote + "(func (block $l (i32.const 0) (br_table $\"l\"$l)))" + ) + "unknown operator" +) + +(module + (func (block $l0 (i32.const 0) (br_table $l0))) +) +(module + (func (block $l$l (i32.const 0) (br_table $l$l))) +) + + +;; Space required between strings and non-parenthesis tokens + +(module + (data "a") +) +(assert_malformed + (module quote + "(data\"a\")" + ) + "unknown operator" +) + +(module + (data $l "a") +) +(assert_malformed + (module quote + "(data $l\"a\")" + ) + "unknown operator" +) + +(module + (data $l " a") +) +(assert_malformed + (module quote + "(data $l\" a\")" + ) + "unknown operator" +) + +(module + (data $l "a ") +) +(assert_malformed + (module quote + "(data $l\"a \")" + ) + "unknown operator" +) + +(module + (data $l "a " "b") +) +(assert_malformed + (module quote + "(data $l\"a \"\"b\")" + ) + "unknown operator" +) + +(module + (data $l "") +) +(assert_malformed + (module quote + "(data $l\"\")" + ) + "unknown operator" +) + +(module + (data $l " ") +) +(assert_malformed + (module quote + "(data $l\" \")" + ) + "unknown operator" +) + +(module + (data $l " ") +) +(assert_malformed + (module quote + "(data $l\" \")" + ) + "unknown operator" +) + +(module + (data "a" "b") +) +(assert_malformed + (module quote + "(data \"a\"\"b\")" + ) + "unknown operator" +) + +(module + (data "a" " b") +) +(assert_malformed + (module quote + "(data \"a\"\" b\")" + ) + "unknown operator" +) + +(module + (data "a " "b") +) +(assert_malformed + (module quote + "(data \"a \"\"b\")" + ) + "unknown operator" +) + +(module + (data "" "") +) +(assert_malformed + (module quote + "(data \"\"\"\")" + ) + "unknown operator" +) + +(module + (data "" " ") +) +(assert_malformed + (module quote + "(data \"\"\" \")" + ) + "unknown operator" +) + +(module + (data " " "") +) +(assert_malformed + (module quote + "(data \" \"\"\")" + ) + "unknown operator" +) + + +(assert_malformed + (module quote + "(func \"a\"x)" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func \"a\"0)" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func 0\"a\")" + ) + "unknown operator" +) +(assert_malformed + (module quote + "(func \"a\"$x)" + ) + "unknown operator" +) diff --git a/proposals/wasm-3.0/traps0.wast b/proposals/wasm-3.0/traps0.wast new file mode 100644 index 0000000..fd942e4 --- /dev/null +++ b/proposals/wasm-3.0/traps0.wast @@ -0,0 +1,35 @@ +(module + (memory $mem0 1) + (memory $mem1 1) + (memory $mem2 1) + + (func (export "no_dce.i32.load") (param $i i32) (drop (i32.load $mem1 (local.get $i)))) + (func (export "no_dce.i32.load16_s") (param $i i32) (drop (i32.load16_s $mem1 (local.get $i)))) + (func (export "no_dce.i32.load16_u") (param $i i32) (drop (i32.load16_u $mem1 (local.get $i)))) + (func (export "no_dce.i32.load8_s") (param $i i32) (drop (i32.load8_s $mem1 (local.get $i)))) + (func (export "no_dce.i32.load8_u") (param $i i32) (drop (i32.load8_u $mem1 (local.get $i)))) + (func (export "no_dce.i64.load") (param $i i32) (drop (i64.load $mem1 (local.get $i)))) + (func (export "no_dce.i64.load32_s") (param $i i32) (drop (i64.load32_s $mem1 (local.get $i)))) + (func (export "no_dce.i64.load32_u") (param $i i32) (drop (i64.load32_u $mem2 (local.get $i)))) + (func (export "no_dce.i64.load16_s") (param $i i32) (drop (i64.load16_s $mem2 (local.get $i)))) + (func (export "no_dce.i64.load16_u") (param $i i32) (drop (i64.load16_u $mem2 (local.get $i)))) + (func (export "no_dce.i64.load8_s") (param $i i32) (drop (i64.load8_s $mem2 (local.get $i)))) + (func (export "no_dce.i64.load8_u") (param $i i32) (drop (i64.load8_u $mem2 (local.get $i)))) + (func (export "no_dce.f32.load") (param $i i32) (drop (f32.load $mem2 (local.get $i)))) + (func (export "no_dce.f64.load") (param $i i32) (drop (f64.load $mem2 (local.get $i)))) +) + +(assert_trap (invoke "no_dce.i32.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load16_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load16_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load8_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i32.load8_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load32_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load32_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load16_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load16_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load8_s" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.i64.load8_u" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.f32.load" (i32.const 65536)) "out of bounds memory access") +(assert_trap (invoke "no_dce.f64.load" (i32.const 65536)) "out of bounds memory access") diff --git a/proposals/wasm-3.0/try_table.wast b/proposals/wasm-3.0/try_table.wast new file mode 100644 index 0000000..cda490b --- /dev/null +++ b/proposals/wasm-3.0/try_table.wast @@ -0,0 +1,468 @@ +;; Test try-catch blocks. + +(module + (tag $e0 (export "e0")) + (func (export "throw") (throw $e0)) +) + +(register "test") + +(module + (tag $imported-e0 (import "test" "e0")) + (tag $imported-e0-alias (import "test" "e0")) + (func $imported-throw (import "test" "throw")) + (tag $e0) + (tag $e1) + (tag $e2) + (tag $e-i32 (param i32)) + (tag $e-f32 (param f32)) + (tag $e-i64 (param i64)) + (tag $e-f64 (param f64)) + + (func $throw-if (param i32) (result i32) + (local.get 0) + (i32.const 0) (if (i32.ne) (then (throw $e0))) + (i32.const 0) + ) + + (func (export "simple-throw-catch") (param i32) (result i32) + (block $h + (try_table (result i32) (catch $e0 $h) + (if (i32.eqz (local.get 0)) (then (throw $e0)) (else)) + (i32.const 42) + ) + (return) + ) + (i32.const 23) + ) + + (func (export "unreachable-not-caught") + (block $h + (try_table (catch_all $h) (unreachable)) + (return) + ) + ) + + (func $div (param i32 i32) (result i32) + (local.get 0) (local.get 1) (i32.div_u) + ) + (func (export "trap-in-callee") (param i32 i32) (result i32) + (block $h + (try_table (result i32) (catch_all $h) + (call $div (local.get 0) (local.get 1)) + ) + (return) + ) + (i32.const 11) + ) + + (func (export "catch-complex-1") (param i32) (result i32) + (block $h1 + (try_table (result i32) (catch $e1 $h1) + (block $h0 + (try_table (result i32) (catch $e0 $h0) + (if (i32.eqz (local.get 0)) + (then (throw $e0)) + (else + (if (i32.eq (local.get 0) (i32.const 1)) + (then (throw $e1)) + (else (throw $e2)) + ) + ) + ) + (i32.const 2) + ) + (br 1) + ) + (i32.const 3) + ) + (return) + ) + (i32.const 4) + ) + + (func (export "catch-complex-2") (param i32) (result i32) + (block $h0 + (block $h1 + (try_table (result i32) (catch $e0 $h0) (catch $e1 $h1) + (if (i32.eqz (local.get 0)) + (then (throw $e0)) + (else + (if (i32.eq (local.get 0) (i32.const 1)) + (then (throw $e1)) + (else (throw $e2)) + ) + ) + ) + (i32.const 2) + ) + (return) + ) + (return (i32.const 4)) + ) + (i32.const 3) + ) + + (func (export "throw-catch-param-i32") (param i32) (result i32) + (block $h (result i32) + (try_table (result i32) (catch $e-i32 $h) + (throw $e-i32 (local.get 0)) + (i32.const 2) + ) + (return) + ) + (return) + ) + + (func (export "throw-catch-param-f32") (param f32) (result f32) + (block $h (result f32) + (try_table (result f32) (catch $e-f32 $h) + (throw $e-f32 (local.get 0)) + (f32.const 0) + ) + (return) + ) + (return) + ) + + (func (export "throw-catch-param-i64") (param i64) (result i64) + (block $h (result i64) + (try_table (result i64) (catch $e-i64 $h) + (throw $e-i64 (local.get 0)) + (i64.const 2) + ) + (return) + ) + (return) + ) + + (func (export "throw-catch-param-f64") (param f64) (result f64) + (block $h (result f64) + (try_table (result f64) (catch $e-f64 $h) + (throw $e-f64 (local.get 0)) + (f64.const 0) + ) + (return) + ) + (return) + ) + + (func (export "throw-catch_ref-param-i32") (param i32) (result i32) + (block $h (result i32 exnref) + (try_table (result i32) (catch_ref $e-i32 $h) + (throw $e-i32 (local.get 0)) + (i32.const 2) + ) + (return) + ) + (drop) (return) + ) + + (func (export "throw-catch_ref-param-f32") (param f32) (result f32) + (block $h (result f32 exnref) + (try_table (result f32) (catch_ref $e-f32 $h) + (throw $e-f32 (local.get 0)) + (f32.const 0) + ) + (return) + ) + (drop) (return) + ) + + (func (export "throw-catch_ref-param-i64") (param i64) (result i64) + (block $h (result i64 exnref) + (try_table (result i64) (catch_ref $e-i64 $h) + (throw $e-i64 (local.get 0)) + (i64.const 2) + ) + (return) + ) + (drop) (return) + ) + + (func (export "throw-catch_ref-param-f64") (param f64) (result f64) + (block $h (result f64 exnref) + (try_table (result f64) (catch_ref $e-f64 $h) + (throw $e-f64 (local.get 0)) + (f64.const 0) + ) + (return) + ) + (drop) (return) + ) + + (func $throw-param-i32 (param i32) (throw $e-i32 (local.get 0))) + (func (export "catch-param-i32") (param i32) (result i32) + (block $h (result i32) + (try_table (result i32) (catch $e-i32 $h) + (i32.const 0) + (call $throw-param-i32 (local.get 0)) + ) + (return) + ) + ) + + (func (export "catch-imported") (result i32) + (block $h + (try_table (result i32) (catch $imported-e0 $h) + (call $imported-throw (i32.const 1)) + ) + (return) + ) + (i32.const 2) + ) + + (func (export "catch-imported-alias") (result i32) + (block $h + (try_table (result i32) (catch $imported-e0 $h) + (throw $imported-e0-alias (i32.const 1)) + ) + (return) + ) + (i32.const 2) + ) + + (func (export "catchless-try") (param i32) (result i32) + (block $h + (try_table (result i32) (catch $e0 $h) + (try_table (result i32) (call $throw-if (local.get 0))) + ) + (return) + ) + (i32.const 1) + ) + + (func $throw-void (throw $e0)) + (func (export "return-call-in-try-catch") + (block $h + (try_table (catch $e0 $h) + (return_call $throw-void) + ) + ) + ) + + (table funcref (elem $throw-void)) + (func (export "return-call-indirect-in-try-catch") + (block $h + (try_table (catch $e0 $h) + (return_call_indirect (i32.const 0)) + ) + ) + ) + + (func (export "try-with-param") + (i32.const 0) (try_table (param i32) (drop)) + ) +) + +(assert_return (invoke "simple-throw-catch" (i32.const 0)) (i32.const 23)) +(assert_return (invoke "simple-throw-catch" (i32.const 1)) (i32.const 42)) + +(assert_trap (invoke "unreachable-not-caught") "unreachable") + +(assert_return (invoke "trap-in-callee" (i32.const 7) (i32.const 2)) (i32.const 3)) +(assert_trap (invoke "trap-in-callee" (i32.const 1) (i32.const 0)) "integer divide by zero") + +(assert_return (invoke "catch-complex-1" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "catch-complex-1" (i32.const 1)) (i32.const 4)) +(assert_exception (invoke "catch-complex-1" (i32.const 2))) + +(assert_return (invoke "catch-complex-2" (i32.const 0)) (i32.const 3)) +(assert_return (invoke "catch-complex-2" (i32.const 1)) (i32.const 4)) +(assert_exception (invoke "catch-complex-2" (i32.const 2))) + +(assert_return (invoke "throw-catch-param-i32" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "throw-catch-param-i32" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "throw-catch-param-i32" (i32.const 10)) (i32.const 10)) + +(assert_return (invoke "throw-catch-param-f32" (f32.const 5.0)) (f32.const 5.0)) +(assert_return (invoke "throw-catch-param-f32" (f32.const 10.5)) (f32.const 10.5)) + +(assert_return (invoke "throw-catch-param-i64" (i64.const 5)) (i64.const 5)) +(assert_return (invoke "throw-catch-param-i64" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "throw-catch-param-i64" (i64.const -1)) (i64.const -1)) + +(assert_return (invoke "throw-catch-param-f64" (f64.const 5.0)) (f64.const 5.0)) +(assert_return (invoke "throw-catch-param-f64" (f64.const 10.5)) (f64.const 10.5)) + +(assert_return (invoke "throw-catch_ref-param-i32" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "throw-catch_ref-param-i32" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "throw-catch_ref-param-i32" (i32.const 10)) (i32.const 10)) + +(assert_return (invoke "throw-catch_ref-param-f32" (f32.const 5.0)) (f32.const 5.0)) +(assert_return (invoke "throw-catch_ref-param-f32" (f32.const 10.5)) (f32.const 10.5)) + +(assert_return (invoke "throw-catch_ref-param-i64" (i64.const 5)) (i64.const 5)) +(assert_return (invoke "throw-catch_ref-param-i64" (i64.const 0)) (i64.const 0)) +(assert_return (invoke "throw-catch_ref-param-i64" (i64.const -1)) (i64.const -1)) + +(assert_return (invoke "throw-catch_ref-param-f64" (f64.const 5.0)) (f64.const 5.0)) +(assert_return (invoke "throw-catch_ref-param-f64" (f64.const 10.5)) (f64.const 10.5)) + +(assert_return (invoke "catch-param-i32" (i32.const 5)) (i32.const 5)) + +(assert_return (invoke "catch-imported") (i32.const 2)) +(assert_return (invoke "catch-imported-alias") (i32.const 2)) + +(assert_return (invoke "catchless-try" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "catchless-try" (i32.const 1)) (i32.const 1)) + +(assert_exception (invoke "return-call-in-try-catch")) +(assert_exception (invoke "return-call-indirect-in-try-catch")) + +(assert_return (invoke "try-with-param")) + +(module + (func $imported-throw (import "test" "throw")) + (tag $e0) + + (func (export "imported-mismatch") (result i32) + (block $h + (try_table (result i32) (catch_all $h) + (block $h0 + (try_table (result i32) (catch $e0 $h0) + (i32.const 1) + (call $imported-throw) + ) + (return) + ) + (i32.const 2) + ) + (return) + ) + (i32.const 3) + ) +) + +(assert_return (invoke "imported-mismatch") (i32.const 3)) + +(assert_malformed + (module quote "(module (func (catch_all)))") + "unexpected token" +) + +(assert_malformed + (module quote "(module (tag $e) (func (catch $e)))") + "unexpected token" +) + +(module + (tag $e) + (func (try_table (catch $e 0) (catch $e 0))) + (func (try_table (catch_all 0) (catch $e 0))) + (func (try_table (catch_all 0) (catch_all 0))) + (func (result exnref) (try_table (catch_ref $e 0) (catch_ref $e 0)) (unreachable)) + (func (result exnref) (try_table (catch_all_ref 0) (catch_ref $e 0)) (unreachable)) + (func (result exnref) (try_table (catch_all_ref 0) (catch_all_ref 0)) (unreachable)) +) + +(assert_invalid + (module (func (result i32) (try_table (result i32)))) + "type mismatch" +) +(assert_invalid + (module (func (result i32) (try_table (result i32) (i64.const 42)))) + "type mismatch" +) + +(assert_invalid + (module (tag) (func (try_table (catch_ref 0 0)))) + "type mismatch" +) +(assert_invalid + (module (tag) (func (result exnref) (try_table (catch 0 0)) (unreachable))) + "type mismatch" +) +(assert_invalid + (module (func (try_table (catch_all_ref 0)))) + "type mismatch" +) +(assert_invalid + (module (func (result exnref) (try_table (catch_all 0)) (unreachable))) + "type mismatch" +) +(assert_invalid + (module + (tag (param i64)) + (func (result i32 exnref) (try_table (result i32) (catch_ref 0 0) (i32.const 42))) + ) + "type mismatch" +) + + +(module + (type $t (func)) + (func $dummy) + (elem declare func $dummy) + + (tag $e (param (ref $t))) + (func $throw (throw $e (ref.func $dummy))) + + (func (export "catch") (result (ref null $t)) + (block $l (result (ref null $t)) + (try_table (catch $e $l) (call $throw)) + (unreachable) + ) + ) + (func (export "catch_ref1") (result (ref null $t)) + (block $l (result (ref null $t) (ref exn)) + (try_table (catch_ref $e $l) (call $throw)) + (unreachable) + ) + (drop) + ) + (func (export "catch_ref2") (result (ref null $t)) + (block $l (result (ref null $t) (ref null exn)) + (try_table (catch_ref $e $l) (call $throw)) + (unreachable) + ) + (drop) + ) + (func (export "catch_all_ref1") + (block $l (result (ref exn)) + (try_table (catch_all_ref $l) (call $throw)) + (unreachable) + ) + (drop) + ) + (func (export "catch_all_ref2") + (block $l (result (ref null exn)) + (try_table (catch_all_ref $l) (call $throw)) + (unreachable) + ) + (drop) + ) +) + +(assert_return (invoke "catch") (ref.func)) +(assert_return (invoke "catch_ref1") (ref.func)) +(assert_return (invoke "catch_ref2") (ref.func)) +(assert_return (invoke "catch_all_ref1")) +(assert_return (invoke "catch_all_ref2")) + +(assert_invalid + (module + (type $t (func)) + (tag $e (param (ref null $t))) + (func (export "catch") (result (ref $t)) + (block $l (result (ref $t)) + (try_table (catch $e $l)) + (unreachable) + ) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (func)) + (tag $e (param (ref null $t))) + (func (export "catch_ref") (result (ref $t)) + (block $l (result (ref $t) (ref exn)) + (try_table (catch $e $l)) + (unreachable) + ) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/type-canon.wast b/proposals/wasm-3.0/type-canon.wast new file mode 100644 index 0000000..2c723aa --- /dev/null +++ b/proposals/wasm-3.0/type-canon.wast @@ -0,0 +1,17 @@ +(module + (rec + (type $t1 (func (param i32 (ref $t3)))) + (type $t2 (func (param i32 (ref $t1)))) + (type $t3 (func (param i32 (ref $t2)))) + ) +) + +(module + (rec + (type $t0 (func (param i32 (ref $t2) (ref $t3)))) + (type $t1 (func (param i32 (ref $t0) i32 (ref $t4)))) + (type $t2 (func (param i32 (ref $t2) (ref $t1)))) + (type $t3 (func (param i32 (ref $t2) i32 (ref $t4)))) + (type $t4 (func (param (ref $t0) (ref $t2)))) + ) +) diff --git a/proposals/wasm-3.0/type-equivalence.wast b/proposals/wasm-3.0/type-equivalence.wast new file mode 100644 index 0000000..b3d1151 --- /dev/null +++ b/proposals/wasm-3.0/type-equivalence.wast @@ -0,0 +1,324 @@ +;; Syntactic types (validation time) + +;; Simple types. + +(module + (type $t1 (func (param f32 f32) (result f32))) + (type $t2 (func (param $x f32) (param $y f32) (result f32))) + + (func $f1 (param $r (ref $t1)) (call $f2 (local.get $r))) + (func $f2 (param $r (ref $t2)) (call $f1 (local.get $r))) +) + + +;; Indirect types. + +(module + (type $s0 (func (param i32) (result f32))) + (type $s1 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $s2 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $t1 (func (param (ref $s1)) (result (ref $s2)))) + (type $t2 (func (param (ref $s2)) (result (ref $s1)))) + + (func $f1 (param $r (ref $t1)) (call $f2 (local.get $r))) + (func $f2 (param $r (ref $t2)) (call $f1 (local.get $r))) +) + + +;; Recursive types. + +(module + (rec (type $t1 (func (param i32 (ref $t1))))) + (rec (type $t2 (func (param i32 (ref $t2))))) + + (func $f1 (param $r (ref $t1)) (call $f2 (local.get $r))) + (func $f2 (param $r (ref $t2)) (call $f1 (local.get $r))) +) + +(module + (type $t1 (func (param i32 (ref $t1)))) + (type $t2 (func (param i32 (ref $t2)))) + + (func $f1 (param $r (ref $t1)) (call $f2 (local.get $r))) + (func $f2 (param $r (ref $t2)) (call $f1 (local.get $r))) +) + + +;; Isomorphic recursive types. + +(module + (rec + (type $t0 (func (param i32 (ref $t1)))) + (type $t1 (func (param i32 (ref $t0)))) + ) + (rec + (type $t2 (func (param i32 (ref $t3)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + + (func $f0 (param $r (ref $t0)) + (call $f2 (local.get $r)) + ) + (func $f1 (param $r (ref $t1)) + (call $f3 (local.get $r)) + ) + (func $f2 (param $r (ref $t2)) + (call $f0 (local.get $r)) + ) + (func $f3 (param $r (ref $t3)) + (call $f1 (local.get $r)) + ) +) + + +;; Invalid recursion. + +(assert_invalid + (module + (type $t1 (func (param (ref $t2)))) + (type $t2 (func (param (ref $t1)))) + ) + "unknown type" +) + + +;; Semantic types (run time) + +;; Simple types. + +(module + (type $t1 (func (param f32 f32))) + (type $t2 (func (param $x f32) (param $y f32))) + + (func $f1 (type $t1)) + (func $f2 (type $t2)) + (table funcref (elem $f1 $f2)) + + (func (export "run") + (call_indirect (type $t1) (f32.const 1) (f32.const 2) (i32.const 1)) + (call_indirect (type $t2) (f32.const 1) (f32.const 2) (i32.const 0)) + ) +) +(assert_return (invoke "run")) + + +;; Indirect types. + +(module + (type $s0 (func (param i32))) + (type $s1 (func (param i32 (ref $s0)))) + (type $s2 (func (param i32 (ref $s0)))) + (type $t1 (func (param (ref $s1)))) + (type $t2 (func (param (ref $s2)))) + + (func $s1 (type $s1)) + (func $s2 (type $s2)) + (func $f1 (type $t1)) + (func $f2 (type $t2)) + (table funcref (elem $f1 $f2 $s1 $s2)) + + (func (export "run") + (call_indirect (type $t1) (ref.func $s1) (i32.const 0)) + (call_indirect (type $t1) (ref.func $s1) (i32.const 1)) + (call_indirect (type $t1) (ref.func $s2) (i32.const 0)) + (call_indirect (type $t1) (ref.func $s2) (i32.const 1)) + (call_indirect (type $t2) (ref.func $s1) (i32.const 0)) + (call_indirect (type $t2) (ref.func $s1) (i32.const 1)) + (call_indirect (type $t2) (ref.func $s2) (i32.const 0)) + (call_indirect (type $t2) (ref.func $s2) (i32.const 1)) + ) +) +(assert_return (invoke "run")) + + +;; Recursive types. + +(module + (rec (type $t1 (func (result (ref null $t1))))) + (rec (type $t2 (func (result (ref null $t2))))) + + (func $f1 (type $t1) (ref.null $t1)) + (func $f2 (type $t2) (ref.null $t2)) + (table funcref (elem $f1 $f2)) + + (func (export "run") + (block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 0))) + (block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 0))) + (block (result (ref null $t2)) (call_indirect (type $t1) (i32.const 0))) + (block (result (ref null $t2)) (call_indirect (type $t2) (i32.const 0))) + (block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 1))) + (block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 1))) + (block (result (ref null $t2)) (call_indirect (type $t1) (i32.const 1))) + (block (result (ref null $t2)) (call_indirect (type $t2) (i32.const 1))) + (br 0) + ) +) +(assert_return (invoke "run")) + + +;; Isomorphic recursive types. + +(module + (rec + (type $t1 (func (param i32 (ref $t1)))) + (type $t2 (func (param i32 (ref $t3)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + + (rec + (type $u1 (func (param i32 (ref $u1)))) + (type $u2 (func (param i32 (ref $u3)))) + (type $u3 (func (param i32 (ref $u2)))) + ) + + (func $f1 (type $t1)) + (func $f2 (type $t2)) + (func $f3 (type $t3)) + (table funcref (elem $f1 $f2 $f3)) + + (func (export "run") + (call_indirect (type $t1) (i32.const 1) (ref.func $f1) (i32.const 0)) + (call_indirect (type $t2) (i32.const 1) (ref.func $f3) (i32.const 1)) + (call_indirect (type $t3) (i32.const 1) (ref.func $f2) (i32.const 2)) + (call_indirect (type $u1) (i32.const 1) (ref.func $f1) (i32.const 0)) + (call_indirect (type $u2) (i32.const 1) (ref.func $f3) (i32.const 1)) + (call_indirect (type $u3) (i32.const 1) (ref.func $f2) (i32.const 2)) + ) +) +(assert_return (invoke "run")) + + +;; Semantic types (link time) + +;; Simple types. + +(module + (type $t1 (func (param f32 f32) (result f32))) + (func (export "f") (param (ref $t1))) +) +(register "M") +(module + (type $t2 (func (param $x f32) (param $y f32) (result f32))) + (func (import "M" "f") (param (ref $t2))) +) + + +;; Indirect types. + +(module + (type $s0 (func (param i32) (result f32))) + (type $s1 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $s2 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $t1 (func (param (ref $s1)) (result (ref $s2)))) + (type $t2 (func (param (ref $s2)) (result (ref $s1)))) + (func (export "f1") (param (ref $t1))) + (func (export "f2") (param (ref $t1))) +) +(register "N") +(module + (type $s0 (func (param i32) (result f32))) + (type $s1 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $s2 (func (param i32 (ref $s0)) (result (ref $s0)))) + (type $t1 (func (param (ref $s1)) (result (ref $s2)))) + (type $t2 (func (param (ref $s2)) (result (ref $s1)))) + (func (import "N" "f1") (param (ref $t1))) + (func (import "N" "f1") (param (ref $t2))) + (func (import "N" "f2") (param (ref $t1))) + (func (import "N" "f2") (param (ref $t1))) +) + + +;; Recursive types. + +(module + (rec (type $t1 (func (param i32 (ref $t1))))) + (func (export "f") (param (ref $t1))) +) +(register "Mr1") +(module + (rec (type $t2 (func (param i32 (ref $t2))))) + (func (import "Mr1" "f") (param (ref $t2))) +) + + +;; Isomorphic recursive types. + +(module + (rec + (type $t1 (func (param i32 (ref $t1)))) + (type $t2 (func (param i32 (ref $t3)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + (func (export "f1") (param (ref $t1))) + (func (export "f2") (param (ref $t2))) + (func (export "f3") (param (ref $t3))) +) +(register "Mr2") +(module + (rec + (type $t1 (func (param i32 (ref $t1)))) + (type $t2 (func (param i32 (ref $t3)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + (func (import "Mr2" "f1") (param (ref $t1))) + (func (import "Mr2" "f2") (param (ref $t2))) + (func (import "Mr2" "f3") (param (ref $t3))) +) + +(module + (rec + (type $t1 (func (param i32 (ref $t3)))) + (type $t2 (func (param i32 (ref $t1)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + (func (export "f1") (param (ref $t1))) + (func (export "f2") (param (ref $t2))) + (func (export "f3") (param (ref $t3))) +) +(register "Mr3") +(module + (rec + (type $t1 (func (param i32 (ref $t3)))) + (type $t2 (func (param i32 (ref $t1)))) + (type $t3 (func (param i32 (ref $t2)))) + ) + (func (import "Mr3" "f1") (param (ref $t1))) + (func (import "Mr3" "f2") (param (ref $t2))) + (func (import "Mr3" "f3") (param (ref $t3))) +) + +(module + (rec + (type $t1 (func (param i32 (ref $u1)))) + (type $u1 (func (param f32 (ref $t1)))) + ) + + (rec + (type $t2 (func (param i32 (ref $u3)))) + (type $u2 (func (param f32 (ref $t3)))) + (type $t3 (func (param i32 (ref $u2)))) + (type $u3 (func (param f32 (ref $t2)))) + ) + + (func (export "f1") (param (ref $t1))) + (func (export "f2") (param (ref $t2))) + (func (export "f3") (param (ref $t3))) +) +(register "Mr4") +(module + (rec + (type $t1 (func (param i32 (ref $u1)))) + (type $u1 (func (param f32 (ref $t1)))) + ) + + (rec + (type $t2 (func (param i32 (ref $u3)))) + (type $u2 (func (param f32 (ref $t3)))) + (type $t3 (func (param i32 (ref $u2)))) + (type $u3 (func (param f32 (ref $t2)))) + ) + + (func (import "Mr4" "f1") (param (ref $t1))) + (func (import "Mr4" "f2") (param (ref $t2))) + (func (import "Mr4" "f3") (param (ref $t3))) +) diff --git a/proposals/wasm-3.0/type-rec.wast b/proposals/wasm-3.0/type-rec.wast new file mode 100644 index 0000000..5c4ba58 --- /dev/null +++ b/proposals/wasm-3.0/type-rec.wast @@ -0,0 +1,158 @@ +;; Static matching of recursive types + +(module + (rec (type $f1 (func)) (type (struct (field (ref $f1))))) + (rec (type $f2 (func)) (type (struct (field (ref $f2))))) + (func $f (type $f2)) + (global (ref $f1) (ref.func $f)) +) + +(module + (rec (type $f1 (func)) (type (struct (field (ref $f1))))) + (rec (type $f2 (func)) (type (struct (field (ref $f2))))) + (rec + (type $g1 (func)) + (type (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1)))) + ) + (rec + (type $g2 (func)) + (type (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2)))) + ) + (func $g (type $g2)) + (global (ref $g1) (ref.func $g)) +) + +(assert_invalid + (module + (rec (type $f1 (func)) (type (struct (field (ref $f1))))) + (rec (type $f2 (func)) (type (struct (field (ref $f1))))) + (func $f (type $f2)) + (global (ref $f1) (ref.func $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (rec (type $f0 (func)) (type (struct (field (ref $f0))))) + (rec (type $f1 (func)) (type (struct (field (ref $f0))))) + (rec (type $f2 (func)) (type (struct (field (ref $f1))))) + (func $f (type $f2)) + (global (ref $f1) (ref.func $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (rec (type $f1 (func)) (type (struct))) + (rec (type (struct)) (type $f2 (func))) + (global (ref $f1) (ref.func $f)) + (func $f (type $f2)) + ) + "type mismatch" +) + +(assert_invalid + (module + (rec (type $f1 (func)) (type (struct))) + (rec (type $f2 (func)) (type (struct)) (type (func))) + (global (ref $f1) (ref.func $f)) + (func $f (type $f2)) + ) + "type mismatch" +) + + +;; Link-time matching of recursive function types + +(module $M + (rec (type $f1 (func)) (type (struct))) + (func (export "f") (type $f1)) +) +(register "M" $M) + +(module + (rec (type $f2 (func)) (type (struct))) + (func (import "M" "f") (type $f2)) +) + +(assert_unlinkable + (module + (rec (type (struct)) (type $f2 (func))) + (func (import "M" "f") (type $f2)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (rec (type $f2 (func))) + (func (import "M" "f") (type $f2)) + ) + "incompatible import type" +) + + +;; Dynamic matching of recursive function types + +(module + (rec (type $f1 (func)) (type (struct))) + (rec (type $f2 (func)) (type (struct))) + (table funcref (elem $f1)) + (func $f1 (type $f1)) + (func (export "run") (call_indirect (type $f2) (i32.const 0))) +) +(assert_return (invoke "run")) + +(module + (rec (type $f1 (func)) (type (struct))) + (rec (type (struct)) (type $f2 (func))) + (table funcref (elem $f1)) + (func $f1 (type $f1)) + (func (export "run") (call_indirect (type $f2) (i32.const 0))) +) +(assert_trap (invoke "run") "indirect call type mismatch") + +(module + (rec (type $f1 (func)) (type (struct))) + (rec (type $f2 (func))) + (table funcref (elem $f1)) + (func $f1 (type $f1)) + (func (export "run") (call_indirect (type $f2) (i32.const 0))) +) +(assert_trap (invoke "run") "indirect call type mismatch") + + +;; Implicit function types never pick up non-singleton recursive types + +(module + (rec (type $s (struct))) + (rec (type $t (func (param (ref $s))))) + (func $f (param (ref $s))) ;; okay, type is equivalent to $t + (global (ref $t) (ref.func $f)) +) + +(assert_invalid + (module + (rec + (type $s (struct)) + (type $t (func (param (ref $s)))) + ) + (func $f (param (ref $s))) ;; type is not equivalent to $t + (global (ref $t) (ref.func $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (rec + (type (struct)) + (type $t (func)) + ) + (func $f) ;; type is not equivalent to $t + (global (ref $t) (ref.func $f)) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/type-subtyping.wast b/proposals/wasm-3.0/type-subtyping.wast new file mode 100644 index 0000000..f2b33d7 --- /dev/null +++ b/proposals/wasm-3.0/type-subtyping.wast @@ -0,0 +1,833 @@ +;; Definitions + +(module + (type $e0 (sub (array i32))) + (type $e1 (sub $e0 (array i32))) + + (type $e2 (sub (array anyref))) + (type $e3 (sub (array (ref null $e0)))) + (type $e4 (sub (array (ref $e1)))) + + (type $m1 (sub (array (mut i32)))) + (type $m2 (sub $m1 (array (mut i32)))) +) + +(module + (type $e0 (sub (struct))) + (type $e1 (sub $e0 (struct))) + (type $e2 (sub $e1 (struct (field i32)))) + (type $e3 (sub $e2 (struct (field i32 (ref null $e0))))) + (type $e4 (sub $e3 (struct (field i32 (ref $e0) (mut i64))))) + (type $e5 (sub $e4 (struct (field i32 (ref $e1) (mut i64))))) +) + +(module + (type $s (sub (struct))) + (type $s' (sub $s (struct))) + + (type $f1 (sub (func (param (ref $s')) (result anyref)))) + (type $f2 (sub $f1 (func (param (ref $s)) (result (ref any))))) + (type $f3 (sub $f2 (func (param (ref null $s)) (result (ref $s))))) + (type $f4 (sub $f3 (func (param (ref null struct)) (result (ref $s'))))) +) + + +;; Recursive definitions + +(module + (type $t (sub (struct (field anyref)))) + (rec (type $r (sub $t (struct (field (ref $r)))))) + (type $t' (sub $r (struct (field (ref $r) i32)))) +) + +(module + (rec + (type $r1 (sub (struct (field i32 (ref $r1))))) + ) + (rec + (type $r2 (sub $r1 (struct (field i32 (ref $r3))))) + (type $r3 (sub $r1 (struct (field i32 (ref $r2))))) + ) +) + +(module + (rec + (type $a1 (sub (struct (field i32 (ref $a2))))) + (type $a2 (sub (struct (field i64 (ref $a1))))) + ) + (rec + (type $b1 (sub $a2 (struct (field i64 (ref $a1) i32)))) + (type $b2 (sub $a1 (struct (field i32 (ref $a2) i32)))) + (type $b3 (sub $a2 (struct (field i64 (ref $b2) i32)))) + ) +) + + +;; Subsumption + +(module + (rec + (type $t1 (sub (func (param i32 (ref $t3))))) + (type $t2 (sub $t1 (func (param i32 (ref $t2))))) + (type $t3 (sub $t2 (func (param i32 (ref $t1))))) + ) + + (func $f1 (param $r (ref $t1)) + (call $f1 (local.get $r)) + ) + (func $f2 (param $r (ref $t2)) + (call $f1 (local.get $r)) + (call $f2 (local.get $r)) + ) + (func $f3 (param $r (ref $t3)) + (call $f1 (local.get $r)) + (call $f2 (local.get $r)) + (call $f3 (local.get $r)) + ) +) + +(module + (rec + (type $t1 (sub (func (result i32 (ref $u1))))) + (type $u1 (sub (func (result f32 (ref $t1))))) + ) + + (rec + (type $t2 (sub $t1 (func (result i32 (ref $u3))))) + (type $u2 (sub $u1 (func (result f32 (ref $t3))))) + (type $t3 (sub $t1 (func (result i32 (ref $u2))))) + (type $u3 (sub $u1 (func (result f32 (ref $t2))))) + ) + + (func $f1 (param $r (ref $t1)) + (call $f1 (local.get $r)) + ) + (func $f2 (param $r (ref $t2)) + (call $f1 (local.get $r)) + (call $f2 (local.get $r)) + ) + (func $f3 (param $r (ref $t3)) + (call $f1 (local.get $r)) + (call $f3 (local.get $r)) + ) +) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func $g (type $g2)) + (global (ref $g1) (ref.func $g)) +) + +(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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (rec + (type $g2 (sub $f2 (func))) + (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2))))) + ) + (func $g (type $g2)) + (global (ref $g1) (ref.func $g)) +) + +(assert_invalid + (module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func $g (type $g2)) + (global (ref $g1) (ref.func $g)) + ) + "type mismatch" +) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g (sub $f1 (func))) (type (struct))) + (func $g (type $g)) + (global (ref $f1) (ref.func $g)) +) + +(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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (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 $h (type $h)) + (global (ref $f1) (ref.func $h)) + (global (ref $g1) (ref.func $h)) +) + + +(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)))))) + (func $f11 (type $f11) (unreachable)) + (func $f12 (type $f12) (unreachable)) + (global (ref $f11) (ref.func $f11)) + (global (ref $f21) (ref.func $f11)) + (global (ref $f12) (ref.func $f12)) + (global (ref $f22) (ref.func $f12)) +) + +(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)))))) + (rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11)))))) + (rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21)))))) + (func $g11 (type $g11) (unreachable)) + (func $g12 (type $g12) (unreachable)) + (global (ref $f11) (ref.func $g11)) + (global (ref $f21) (ref.func $g11)) + (global (ref $f11) (ref.func $g12)) + (global (ref $f21) (ref.func $g12)) + (global (ref $g11) (ref.func $g11)) + (global (ref $g21) (ref.func $g11)) + (global (ref $g12) (ref.func $g12)) + (global (ref $g22) (ref.func $g12)) +) + +(assert_invalid + (module + (rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func $f (type $f21)) + (global (ref $f11) (ref.func $f)) + ) + "type mismatch" +) + +(assert_invalid + (module + (rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func)))) + (rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func $f (type $f21)) + (global (ref $f11) (ref.func $f)) + ) + "type mismatch" +) + + +;; Runtime types + +(module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + + (func $f0 (type $t0) (ref.null func)) + (func $f1 (type $t1) (ref.null $t1)) + (func $f2 (type $t2) (ref.null $t2)) + (table funcref (elem $f0 $f1 $f2)) + + (func (export "run") + (block (result (ref null func)) (call_indirect (type $t0) (i32.const 0))) + (block (result (ref null func)) (call_indirect (type $t0) (i32.const 1))) + (block (result (ref null func)) (call_indirect (type $t0) (i32.const 2))) + (block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 1))) + (block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 2))) + (block (result (ref null $t2)) (call_indirect (type $t2) (i32.const 2))) + + (block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 0)))) + (block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 1)))) + (block (result (ref null $t0)) (ref.cast (ref $t0) (table.get (i32.const 2)))) + (block (result (ref null $t1)) (ref.cast (ref $t1) (table.get (i32.const 1)))) + (block (result (ref null $t1)) (ref.cast (ref $t1) (table.get (i32.const 2)))) + (block (result (ref null $t2)) (ref.cast (ref $t2) (table.get (i32.const 2)))) + (br 0) + ) + + (func (export "fail1") + (block (result (ref null $t1)) (call_indirect (type $t1) (i32.const 0))) + (br 0) + ) + (func (export "fail2") + (block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 0))) + (br 0) + ) + (func (export "fail3") + (block (result (ref null $t1)) (call_indirect (type $t2) (i32.const 1))) + (br 0) + ) + + (func (export "fail4") + (ref.cast (ref $t1) (table.get (i32.const 0))) + (br 0) + ) + (func (export "fail5") + (ref.cast (ref $t2) (table.get (i32.const 0))) + (br 0) + ) + (func (export "fail6") + (ref.cast (ref $t2) (table.get (i32.const 1))) + (br 0) + ) +) +(assert_return (invoke "run")) +(assert_trap (invoke "fail1") "indirect call") +(assert_trap (invoke "fail2") "indirect call") +(assert_trap (invoke "fail3") "indirect call") +(assert_trap (invoke "fail4") "cast") +(assert_trap (invoke "fail5") "cast") +(assert_trap (invoke "fail6") "cast") + +(module + (type $t1 (sub (func))) + (type $t2 (sub final (func))) + + (func $f1 (type $t1)) + (func $f2 (type $t2)) + (table funcref (elem $f1 $f2)) + + (func (export "fail1") + (block (call_indirect (type $t1) (i32.const 1))) + ) + (func (export "fail2") + (block (call_indirect (type $t2) (i32.const 0))) + ) + + (func (export "fail3") + (ref.cast (ref $t1) (table.get (i32.const 1))) + (drop) + ) + (func (export "fail4") + (ref.cast (ref $t2) (table.get (i32.const 0))) + (drop) + ) +) +(assert_trap (invoke "fail1") "indirect call") +(assert_trap (invoke "fail2") "indirect call") +(assert_trap (invoke "fail3") "cast") +(assert_trap (invoke "fail4") "cast") + +(module + (type $t1 (sub (func))) + (type $t2 (sub $t1 (func))) + (type $t3 (sub $t2 (func))) + (type $t4 (sub final (func))) + + (func $f2 (type $t2)) + (func $f3 (type $t3)) + (table (ref null $t2) (elem $f2 $f3)) + + (func (export "run") + (call_indirect (type $t1) (i32.const 0)) + (call_indirect (type $t1) (i32.const 1)) + (call_indirect (type $t2) (i32.const 0)) + (call_indirect (type $t2) (i32.const 1)) + (call_indirect (type $t3) (i32.const 1)) + ) + + (func (export "fail1") + (call_indirect (type $t3) (i32.const 0)) + ) + (func (export "fail2") + (call_indirect (type $t4) (i32.const 0)) + ) +) +(assert_return (invoke "run")) +(assert_trap (invoke "fail1") "indirect call") +(assert_trap (invoke "fail2") "indirect call") + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func $g (type $g2)) (elem declare func $g) + (func (export "run") (result i32) + (ref.test (ref $g1) (ref.func $g)) + ) +) +(assert_return (invoke "run") (i32.const 1)) + +(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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (rec + (type $g2 (sub $f2 (func))) + (type (sub $s2 (struct (field (ref $f1) (ref $f2) (ref $f1) (ref $f2) (ref $g2))))) + ) + (func $g (type $g2)) (elem declare func $g) + (func (export "run") (result i32) + (ref.test (ref $g1) (ref.func $g)) + ) +) +(assert_return (invoke "run") (i32.const 1)) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func $g (type $g2)) (elem declare func $g) + (func (export "run") (result i32) + (ref.test (ref $g1) (ref.func $g)) + ) +) +(assert_return (invoke "run") (i32.const 0)) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g (sub $f1 (func))) (type (struct))) + (func $g (type $g)) (elem declare func $g) + (func (export "run") (result i32) + (ref.test (ref $f1) (ref.func $g)) + ) +) +(assert_return (invoke "run") (i32.const 1)) + +(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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (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 $h (type $h)) (elem declare func $h) + (func (export "run") (result i32 i32) + (ref.test (ref $f1) (ref.func $h)) + (ref.test (ref $g1) (ref.func $h)) + ) +) +(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)))))) + (func $f11 (type $f11) (unreachable)) (elem declare func $f11) + (func $f12 (type $f12) (unreachable)) (elem declare func $f12) + (func (export "run") (result i32 i32 i32 i32) + (ref.test (ref $f11) (ref.func $f11)) + (ref.test (ref $f21) (ref.func $f11)) + (ref.test (ref $f12) (ref.func $f12)) + (ref.test (ref $f22) (ref.func $f12)) + ) +) +(assert_return (invoke "run") + (i32.const 1) (i32.const 1) (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)))))) + (rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11)))))) + (rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21)))))) + (func $g11 (type $g11) (unreachable)) (elem declare func $g11) + (func $g12 (type $g12) (unreachable)) (elem declare func $g12) + (func (export "run") (result i32 i32 i32 i32 i32 i32 i32 i32) + (ref.test (ref $f11) (ref.func $g11)) + (ref.test (ref $f21) (ref.func $g11)) + (ref.test (ref $f11) (ref.func $g12)) + (ref.test (ref $f21) (ref.func $g12)) + (ref.test (ref $g11) (ref.func $g11)) + (ref.test (ref $g21) (ref.func $g11)) + (ref.test (ref $g12) (ref.func $g12)) + (ref.test (ref $g22) (ref.func $g12)) + ) +) +(assert_return (invoke "run") + (i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1) + (i32.const 1) (i32.const 1) (i32.const 1) (i32.const 1) +) + +(module + (rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func $f (type $f21)) (elem declare func $f) + (func (export "run") (result i32) + (ref.test (ref $f11) (ref.func $f)) + ) +) +(assert_return (invoke "run") (i32.const 0)) + +(module + (rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func)))) + (rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func $f (type $f21)) (elem declare func $f) + (func (export "run") (result i32) + (ref.test (ref $f11) (ref.func $f)) + ) +) +(assert_return (invoke "run") (i32.const 0)) + + + +;; Linking + +(module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + + (func (export "f0") (type $t0) (ref.null func)) + (func (export "f1") (type $t1) (ref.null $t1)) + (func (export "f2") (type $t2) (ref.null $t2)) +) +(register "M") + +(module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + + (func (import "M" "f0") (type $t0)) + (func (import "M" "f1") (type $t0)) + (func (import "M" "f1") (type $t1)) + (func (import "M" "f2") (type $t0)) + (func (import "M" "f2") (type $t1)) + (func (import "M" "f2") (type $t2)) +) + +(assert_unlinkable + (module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + (func (import "M" "f0") (type $t1)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + (func (import "M" "f0") (type $t2)) + ) + "incompatible import type" +) + +(assert_unlinkable + (module + (type $t0 (sub (func (result (ref null func))))) + (rec (type $t1 (sub $t0 (func (result (ref null $t1)))))) + (rec (type $t2 (sub $t1 (func (result (ref null $t2)))))) + (func (import "M" "f1") (type $t2)) + ) + "incompatible import type" +) + +(module + (type $t1 (sub (func))) + (type $t2 (sub final (func))) + (func (export "f1") (type $t1)) + (func (export "f2") (type $t2)) +) +(register "M2") + +(assert_unlinkable + (module + (type $t1 (sub (func))) + (type $t2 (sub final (func))) + (func (import "M2" "f1") (type $t2)) + ) + "incompatible import type" +) +(assert_unlinkable + (module + (type $t1 (sub (func))) + (type $t2 (sub final (func))) + (func (import "M2" "f2") (type $t1)) + ) + "incompatible import type" +) + + +(module + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func (export "g") (type $g2)) +) +(register "M3") +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (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)) +) +(register "M4") +(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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (func (import "M4" "g") (type $g1)) +) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $g2 (sub $f2 (func))) (type (struct))) + (func (export "g") (type $g2)) +) +(register "M5") +(assert_unlinkable + (module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $g1 (sub $f1 (func))) (type (struct))) + (func (import "M5" "g") (type $g1)) + ) + "incompatible import" +) + +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g (sub $f1 (func))) (type (struct))) + (func (export "g") (type $g)) +) +(register "M6") +(module + (rec (type $f1 (sub (func))) (type (struct (field (ref $f1))))) + (rec (type $f2 (sub (func))) (type (struct (field (ref $f2))))) + (rec (type $g (sub $f1 (func))) (type (struct))) + (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 $g1 (sub $f1 (func))) + (type (sub $s1 (struct (field (ref $f1) (ref $f1) (ref $f2) (ref $f2) (ref $g1))))) + ) + (rec (type $h (sub $g1 (func))) (type (struct))) + (func (import "M7" "h") (type $f1)) + (func (import "M7" "h") (type $g1)) +) + + +(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)))))) + (func (export "f11") (type $f11) (unreachable)) + (func (export "f12") (type $f12) (unreachable)) +) +(register "M8") +(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)))))) + (func (import "M8" "f11") (type $f11)) + (func (import "M8" "f11") (type $f21)) + (func (import "M8" "f12") (type $f12)) + (func (import "M8" "f12") (type $f22)) +) + +(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)))))) + (rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11)))))) + (rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21)))))) + (func (export "g11") (type $g11) (unreachable)) + (func (export "g12") (type $g12) (unreachable)) +) +(register "M9") +(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)))))) + (rec (type $g11 (sub $f11 (func (result (ref func))))) (type $g12 (sub $g11 (func (result (ref $g11)))))) + (rec (type $g21 (sub $f21 (func (result (ref func))))) (type $g22 (sub $g21 (func (result (ref $g21)))))) + (func (import "M9" "g11") (type $f11)) + (func (import "M9" "g11") (type $f21)) + (func (import "M9" "g12") (type $f11)) + (func (import "M9" "g12") (type $f21)) + (func (import "M9" "g11") (type $g11)) + (func (import "M9" "g11") (type $g21)) + (func (import "M9" "g12") (type $g12)) + (func (import "M9" "g12") (type $g22)) +) + +(module + (rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func (export "f") (type $f21)) +) +(register "M10") +(assert_unlinkable + (module + (rec (type $f11 (sub (func))) (type $f12 (sub $f11 (func)))) + (func (import "M10" "f") (type $f11)) + ) + "incompatible import" +) + +(module + (rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func)))) + (rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func)))) + (rec (type $f21 (sub (func))) (type $f22 (sub $f11 (func)))) + (func (export "f") (type $f21)) +) +(register "M11") +(assert_unlinkable + (module + (rec (type $f01 (sub (func))) (type $f02 (sub $f01 (func)))) + (rec (type $f11 (sub (func))) (type $f12 (sub $f01 (func)))) + (func (import "M11" "f") (type $f11)) + ) + "incompatible import" +) + + + +;; Finality violation + +(assert_invalid + (module + (type $t (func)) + (type $s (sub $t (func))) + ) + "sub type" +) + +(assert_invalid + (module + (type $t (struct)) + (type $s (sub $t (struct))) + ) + "sub type" +) + +(assert_invalid + (module + (type $t (sub final (func))) + (type $s (sub $t (func))) + ) + "sub type" +) + +(assert_invalid + (module + (type $t (sub (func))) + (type $s (sub final $t (func))) + (type $u (sub $s (func))) + ) + "sub type" +) + + + +;; Invalid subtyping definitions + +(assert_invalid + (module + (type $a0 (sub (array i32))) + (type $s0 (sub $a0 (struct))) + ) + "sub type" +) + +(assert_invalid + (module + (type $f0 (sub (func (param i32) (result i32)))) + (type $s0 (sub $f0 (struct))) + ) + "sub type" +) + +(assert_invalid + (module + (type $s0 (sub (struct))) + (type $a0 (sub $s0 (array i32))) + ) + "sub type" +) + +(assert_invalid + (module + (type $f0 (sub (func (param i32) (result i32)))) + (type $a0 (sub $f0 (array i32))) + ) + "sub type" +) + +(assert_invalid + (module + (type $s0 (sub (struct))) + (type $f0 (sub $s0 (func (param i32) (result i32)))) + ) + "sub type" +) + +(assert_invalid + (module + (type $a0 (sub (array i32))) + (type $f0 (sub $a0 (func (param i32) (result i32)))) + ) + "sub type" +) + +(assert_invalid + (module + (type $a0 (sub (array i32))) + (type $a1 (sub $a0 (array i64))) + ) + "sub type" +) + +(assert_invalid + (module + (type $s0 (sub (struct (field i32)))) + (type $s1 (sub $s0 (struct (field i64)))) + ) + "sub type" +) + +(assert_invalid + (module + (type $f0 (sub (func))) + (type $f1 (sub $f0 (func (param i32)))) + ) + "sub type" +) diff --git a/proposals/wasm-3.0/unreached-invalid.wast b/proposals/wasm-3.0/unreached-invalid.wast new file mode 100644 index 0000000..1dfcf91 --- /dev/null +++ b/proposals/wasm-3.0/unreached-invalid.wast @@ -0,0 +1,782 @@ +;; Failures in unreachable code. + +(assert_invalid + (module (func $local-index (unreachable) (drop (local.get 0)))) + "unknown local" +) +(assert_invalid + (module (func $global-index (unreachable) (drop (global.get 0)))) + "unknown global" +) +(assert_invalid + (module (func $func-index (unreachable) (call 1))) + "unknown function" +) +(assert_invalid + (module (func $label-index (unreachable) (br 1))) + "unknown label" +) + +(assert_invalid + (module (func $type-num-vs-num + (unreachable) (drop (i64.eqz (i32.const 0)))) + ) + "type mismatch" +) +(assert_invalid + (module (func $type-poly-num-vs-num (result i32) + (unreachable) (i64.const 0) (i32.const 0) (select) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-poly-transitive-num-vs-num (result i32) + (unreachable) + (i64.const 0) (i32.const 0) (select) + (i32.const 0) (i32.const 0) (select) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unconsumed-const (unreachable) (i32.const 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-unconsumed-result (unreachable) (i32.eqz))) + "type mismatch" +) +(assert_invalid + (module (func $type-unconsumed-result2 + (unreachable) (i32.const 0) (i32.add) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unconsumed-poly0 (unreachable) (select))) + "type mismatch" +) +(assert_invalid + (module (func $type-unconsumed-poly1 (unreachable) (i32.const 0) (select))) + "type mismatch" +) +(assert_invalid + (module (func $type-unconsumed-poly2 + (unreachable) (i32.const 0) (i32.const 0) (select) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-after-break + (block (br 0) (block (drop (i32.eqz (nop))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-after-break + (block (br 0) (drop (i32.eqz (f32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-after-break + (block (br 0) (block (drop (f32.eq (i32.const 1))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-after-break + (block (br 0) (drop (f32.eq (i32.const 1) (f32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-after-break + (block (br 0) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-after-break (result i32) + (block (result i32) (i32.const 1) (br 0) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-void-after-break + (block (loop (br 1) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-num-after-break (result i32) + (loop (result i32) (br 1 (i32.const 1)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-void-after-break + (br 0) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-num-after-break (result i32) + (br 0 (i32.const 1)) (f32.const 0) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-after-return + (return) (block (drop (i32.eqz (nop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-after-return + (return) (drop (i32.eqz (f32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-after-return + (return) (block (drop (f32.eq (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-after-return + (return) (drop (f32.eq (i32.const 1) (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-after-return + (block (return) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-after-return (result i32) + (block (result i32) (i32.const 1) (return (i32.const 0)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-void-after-return + (block (loop (return) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-num-after-return (result i32) + (loop (result i32) (return (i32.const 1)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-void-after-return + (return) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-num-after-return (result i32) + (return (i32.const 1)) (f32.const 0) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-after-unreachable + (unreachable) (block (drop (i32.eqz (nop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-void-in-loop-after-unreachable + (unreachable) (loop (drop (i32.eqz (nop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-void-in-i32-loop-after-unreachable + (unreachable) (loop (result i32) (i32.eqz (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-after-unreachable + (unreachable) (drop (i32.eqz (f32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-after-unreachable + (unreachable) (block (drop (f32.eq (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-after-unreachable + (unreachable) (drop (f32.eq (i32.const 1) (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-after-unreachable + (block (unreachable) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-after-unreachable (result i32) + (block (result i32) (i32.const 1) (unreachable) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-void-after-unreachable + (block (loop (unreachable) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-num-after-unreachable (result i32) + (loop (result i32) (unreachable) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-void-after-unreachable + (unreachable) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-num-after-unreachable (result i32) + (unreachable) (f32.const 0) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-void-in-if-after-unreachable + (unreachable) (if (i32.const 0) (then (drop (i32.eqz (nop))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-void-in-else-after-unreachable + (unreachable) (if (i32.const 0) (then (nop)) (else (drop (i32.eqz (nop))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-void-in-else-after-unreachable-if + (if (i32.const 0) (then (unreachable)) (else (drop (i32.eqz (nop))))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-after-nested-unreachable + (block (unreachable)) (block (drop (i32.eqz (nop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-after-nested-unreachable + (block (unreachable)) (drop (i32.eqz (f32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-after-nested-unreachable + (block (unreachable)) (block (drop (f32.eq (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-after-nested-unreachable + (block (unreachable)) (drop (f32.eq (i32.const 1) (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-after-nested-unreachable + (block (block (unreachable)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-after-nested-unreachable + (result i32) + (block (result i32) (i32.const 1) (block (unreachable)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-void-after-nested-unreachable + (block (loop (block (unreachable)) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-num-after-nested-unreachable + (result i32) + (loop (result i32) (block (unreachable)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-void-after-nested-unreachable + (block (unreachable)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-num-after-nested-unreachable + (result i32) + (block (unreachable)) (f32.const 0) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-after-infinite-loop + (loop (br 0)) (block (drop (i32.eqz (nop)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-after-infinite-loop + (loop (br 0)) (drop (i32.eqz (f32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-after-infinite-loop + (loop (br 0)) (block (drop (f32.eq (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-after-infinite-loop + (loop (br 0)) (drop (f32.eq (i32.const 1) (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-after-infinite-loop + (block (loop (br 0)) (i32.const 1)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-after-infinite-loop (result i32) + (block (result i32) (i32.const 1) (loop (br 0)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-void-after-infinite-loop + (block (loop (loop (br 0)) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-num-vs-num-after-infinite-loop (result i32) + (loop (result i32) (loop (br 0)) (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-void-after-infinite-loop + (loop (br 0)) (i32.const 1) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-func-value-num-vs-num-after-infinite-loop (result i32) + (loop (br 0)) (f32.const 0) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-unary-num-vs-void-in-dead-body + (if (i32.const 0) (then (drop (i32.eqz (nop))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-unary-num-vs-num-in-dead-body + (if (i32.const 0) (then (drop (i32.eqz (f32.const 1))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-void-in-dead-body + (if (i32.const 0) (then (drop (f32.eq (i32.const 1))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-binary-num-vs-num-in-dead-body + (if (i32.const 0) (then (drop (f32.eq (i32.const 1) (f32.const 0))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-if-value-num-vs-void-in-dead-body + (if (i32.const 0) (then (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-if-value-num-vs-num-in-dead-body (result i32) + (if (result i32) (i32.const 0) (then (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-in-dead-body + (if (i32.const 0) (then (block (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-in-dead-body (result i32) + (if (result i32) (i32.const 0) (then (block (result i32) (f32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-void-in-dead-body + (if (i32.const 0) (then (loop (i32.const 1)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-num-vs-num-in-dead-body (result i32) + (if (result i32) (i32.const 0) (then (loop (result i32) (f32.const 0)))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-return-second-num-vs-num (result i32) + (return (i32.const 1)) (return (f64.const 1)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-br-second-num-vs-num (result i32) + (block (result i32) (br 0 (i32.const 1)) (br 0 (f64.const 1))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-br_if-cond-num-vs-num-after-unreachable + (block (br_if 0 (unreachable) (f32.const 0))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_if-num-vs-void-after-unreachable (result i32) + (block (result i32) + (block (unreachable) (br_if 1 (i32.const 0) (i32.const 0))) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_if-num-vs-num-after-unreachable (result i32) + (block (result i32) + (block (result f32) (unreachable) (br_if 1 (i32.const 0) (i32.const 0))) + (drop) (i32.const 0) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_if-num2-vs-num-after-unreachable (result i32) + (block (result i32) + (unreachable) (br_if 0 (i32.const 0) (i32.const 0)) (i32.const 0) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_table-num-vs-num-after-unreachable + (block (br_table 0 (unreachable) (f32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_table-label-num-vs-num-after-unreachable (result i32) + (block (result i32) (unreachable) (br_table 0 (f32.const 0) (i32.const 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-br_table-label-num-vs-label-void-after-unreachable + (block + (block (result f32) + (unreachable) + (br_table 0 1 0 (i32.const 1)) + ) + (drop) + ) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-block-value-nested-unreachable-num-vs-void + (block (i32.const 3) (block (unreachable))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-unreachable-void-vs-num (result i32) + (block (block (unreachable))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-unreachable-num-vs-num (result i32) + (block (result i64) (i64.const 0) (block (unreachable))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-unreachable-num2-vs-void (result i32) + (block (i32.const 3) (block (i64.const 1) (unreachable))) (i32.const 9) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-block-value-nested-br-num-vs-void + (block (i32.const 3) (block (br 1))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-br-void-vs-num (result i32) + (block (result i32) (block (br 1 (i32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-br-num-vs-num (result i32) + (block (result i32) (i64.const 0) (block (br 1 (i32.const 0)))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-block-value-nested2-br-num-vs-void + (block (block (i32.const 3) (block (br 2)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested2-br-void-vs-num (result i32) + (block (result i32) (block (block (br 2 (i32.const 0))))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested2-br-num-vs-num (result i32) + (block (result i32) + (block (result i64) (i64.const 0) (block (br 2 (i32.const 0)))) + ) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested2-br-num2-vs-void (result i32) + (block (i32.const 3) (block (i64.const 1) (br 1))) (i32.const 9) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-block-value-nested-return-num-vs-void + (block (i32.const 3) (block (return))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-return-void-vs-num (result i32) + (block (block (return (i32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-return-num-vs-num (result i32) + (block (result i64) (i64.const 0) (block (return (i32.const 0)))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-block-value-nested-return-num2-vs-void (result i32) + (block (i32.const 3) (block (i64.const 1) (return (i32.const 0)))) + (i32.const 9) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-loop-value-nested-unreachable-num-vs-void + (loop (i32.const 3) (block (unreachable))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-nested-unreachable-void-vs-num (result i32) + (loop (block (unreachable))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-loop-value-nested-unreachable-num-vs-num (result i32) + (loop (result i64) (i64.const 0) (block (unreachable))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-cont-last-void-vs-empty (result i32) + (loop (br 0 (nop))) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-cont-last-num-vs-empty (result i32) + (loop (br 0 (i32.const 0))) + )) + "type mismatch" +) + +(assert_invalid + (module (func $tee-local-unreachable-value + (local i32) + (local.tee 0 (unreachable)) + )) + "type mismatch" +) +(assert_invalid + (module (func $br_if-unreachable (result i32) + (block (result i32) + (block + (br_if 1 (unreachable) (i32.const 0)) + ) + (i32.const 0) + ) + )) + "type mismatch" +) +(assert_invalid + (module + (func $type-br_if-after-unreachable (result i64) + (unreachable) + (br_if 0) + (i64.extend_i32_u) + ) + ) + "type mismatch" +) + +(assert_invalid + (module + (func $type-after-ref.as_non_null + (unreachable) + (ref.as_non_null) + (f32.abs) + ) + ) + "type mismatch" +) + +;; The first two operands should have the same type as each other +(assert_invalid + (module (func (unreachable) (select (i32.const 1) (i64.const 1) (i32.const 1)) (drop))) + "type mismatch" +) + +(assert_invalid + (module (func (unreachable) (select (i64.const 1) (i32.const 1) (i32.const 1)) (drop))) + "type mismatch" +) + +;; Third operand must be i32 +(assert_invalid + (module (func (unreachable) (select (i32.const 1) (i32.const 1) (i64.const 1)) (drop))) + "type mismatch" +) + +(assert_invalid + (module (func (unreachable) (select (i32.const 1) (i64.const 1)) (drop))) + "type mismatch" +) + +(assert_invalid + (module (func (unreachable) (select (i64.const 1)) (drop))) + "type mismatch" +) + +;; Result of select has type of first two operands (type of second operand when first one is omitted) +(assert_invalid + (module (func (result i32) (unreachable) (select (i64.const 1) (i32.const 1)))) + "type mismatch" +) + + +;; select always has non-empty result +(assert_invalid + (module (func (unreachable) (select))) + "type mismatch" +) + +(assert_invalid + (module (func $meet-bottom (param i32) (result externref) + (block $l1 (result externref) + (drop + (block $l2 (result i32) + (br_table $l2 $l1 $l2 (ref.null extern) (local.get 0)) + ) + ) + (ref.null extern) + ) + )) + "type mismatch" +) + + +(assert_invalid + (module + (type $t (func (param i32) (result i64))) + (func (result i32) + (unreachable) + (call_ref $t) + ) + ) + "type mismatch" +) +(assert_invalid + (module + (type $t (func (param i32) (result i32 i32))) + (func (result i32) + (unreachable) + (call_ref $t) + ) + ) + "type mismatch" +) diff --git a/proposals/wasm-3.0/unreached-valid.wast b/proposals/wasm-3.0/unreached-valid.wast new file mode 100644 index 0000000..f3feb0f --- /dev/null +++ b/proposals/wasm-3.0/unreached-valid.wast @@ -0,0 +1,108 @@ +(module + + ;; Check that both sides of the select are evaluated + (func (export "select-trap-left") (param $cond i32) (result i32) + (select (unreachable) (i32.const 0) (local.get $cond)) + ) + (func (export "select-trap-right") (param $cond i32) (result i32) + (select (i32.const 0) (unreachable) (local.get $cond)) + ) + + (func (export "select-unreached") + (unreachable) (select) + (unreachable) (i32.const 0) (select) + (unreachable) (i32.const 0) (i32.const 0) (select) + (unreachable) (i32.const 0) (i32.const 0) (i32.const 0) (select) + (unreachable) (f32.const 0) (i32.const 0) (select) + (unreachable) + ) + + (func (export "select-unreached-result1") (result i32) + (unreachable) (i32.add (select)) + ) + + (func (export "select-unreached-result2") (result i64) + (unreachable) (i64.add (select (i64.const 0) (i32.const 0))) + ) + + (func (export "select-unreached-num") + (unreachable) + (select) + (i32.eqz) + (drop) + ) + (func (export "select-unreached-ref") + (unreachable) + (select) + (ref.is_null) + (drop) + ) + + (type $t (func (param i32) (result i32))) + (func (export "call_ref-unreached") (result i32) + (unreachable) + (call_ref $t) + ) +) + +(assert_trap (invoke "select-trap-left" (i32.const 1)) "unreachable") +(assert_trap (invoke "select-trap-left" (i32.const 0)) "unreachable") +(assert_trap (invoke "select-trap-right" (i32.const 1)) "unreachable") +(assert_trap (invoke "select-trap-right" (i32.const 0)) "unreachable") + +(assert_trap (invoke "select-unreached-result1") "unreachable") +(assert_trap (invoke "select-unreached-result2") "unreachable") +(assert_trap (invoke "select-unreached-num") "unreachable") +(assert_trap (invoke "select-unreached-ref") "unreachable") + +(assert_trap (invoke "call_ref-unreached") "unreachable") + + +;; Validation after unreachable + +(module + (func (export "meet-bottom") + (block (result f64) + (block (result f32) + (unreachable) + (br_table 0 1 1 (i32.const 1)) + ) + (drop) + (f64.const 0) + ) + (drop) + ) +) + +(assert_trap (invoke "meet-bottom") "unreachable") + + +;; Bottom heap type + +(module + (func (result (ref func)) + (unreachable) + (ref.as_non_null) + ) + (func (result (ref extern)) + (unreachable) + (ref.as_non_null) + ) + + (func (result (ref func)) + (block (result funcref) + (unreachable) + (br_on_null 0) + (return) + ) + (unreachable) + ) + (func (result (ref extern)) + (block (result externref) + (unreachable) + (br_on_null 0) + (return) + ) + (unreachable) + ) +) From 765e40c52f85ea2ae98ea271792011c278596c63 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 18 Nov 2024 10:02:02 -0800 Subject: [PATCH 3/3] Review comments --- update-testsuite.sh | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/update-testsuite.sh b/update-testsuite.sh index a8227b2..1574535 100755 --- a/update-testsuite.sh +++ b/update-testsuite.sh @@ -48,8 +48,10 @@ update_repo() { local dir=$1 local branch=main local repo=$dir - [ "${repo}" == "wasm-3.0" ] && branch="wasm-3.0" - [ "${repo}" == "wasm-3.0" ] && repo="spec" + if [ "${repo}" == "wasm-3.0" ]; then + branch="wasm-3.0" + repo="spec" + fi pushdir repos if [ -d ${dir} ]; then log_and_run git -C ${dir} fetch origin @@ -85,17 +87,18 @@ merge_with_spec() { set_upstream ${repo} - [ "${repo}" == "wasm-3.0" ] && return + local head_ref=origin/HEAD + [ "${repo}" == "wasm-3.0" ] && head_ref=origin/wasm-3.0 pushdir repos/${repo} # Create and checkout "try-merge" branch. if ! git branch | grep try-merge >/dev/null; then - log_and_run git branch try-merge origin/HEAD + log_and_run git branch try-merge $head_ref fi log_and_run git checkout try-merge # Attempt to merge with upstream branch in spec repo. - log_and_run git reset origin/HEAD --hard + log_and_run git reset $head_ref --hard try_log_and_run git merge -q spec/$upstream -m "merged" if [ $? -ne 0 ]; then # Ignore merge conflicts in non-test directories. @@ -129,7 +132,6 @@ for repo in ${repos}; do continue fi - echo "++ updating222 ${repo}" if [ "${repo}" = "spec" ]; then wast_dir=. log_and_run cp $(find repos/${repo}/test/core -name \*.wast) ${wast_dir} @@ -177,8 +179,10 @@ for repo in ${repos}; do branch=main dir=${repo} - [ "${repo}" == "wasm-3.0" ] && branch="wasm-3.0" - [ "${repo}" == "wasm-3.0" ] && repo="spec" + if [ "${repo}" == "wasm-3.0" ]; then + branch="wasm-3.0" + repo="spec" + fi repo_sha=$(git -C repos/${dir} log --max-count=1 --oneline origin/$branch | sed -e 's/ .*//') echo " ${dir}:" >> commit_message echo " https://github.com/WebAssembly/${repo}/commit/${repo_sha}" >> commit_message