From 36d22d82aa202bb199967e9512281e9a53db42c9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 21:33:14 +0200 Subject: Adding upstream version 115.7.0esr. Signed-off-by: Daniel Baumann --- .../spec/exception-handling/call_indirect.wast.js | 1240 ++++++++++++++++++++ .../wasm/spec/exception-handling/custom.wast.js | 157 +++ .../wasm/spec/exception-handling/directives.txt | 1 + .../spec/exception-handling/harness/directives.txt | 1 + .../spec/exception-handling/harness/harness.js | 360 ++++++ .../wasm/spec/exception-handling/rethrow.wast.js | 140 +++ .../spec/exception-handling/table_fill.wast.js | 234 ++++ .../wasm/spec/exception-handling/table_get.wast.js | 126 ++ .../spec/exception-handling/table_grow.wast.js | 268 +++++ .../wasm/spec/exception-handling/table_set.wast.js | 177 +++ .../spec/exception-handling/table_size.wast.js | 172 +++ .../tests/wasm/spec/exception-handling/tag.wast.js | 40 + .../wasm/spec/exception-handling/throw.wast.js | 87 ++ .../wasm/spec/exception-handling/try_catch.wast.js | 318 +++++ .../spec/exception-handling/try_delegate.wast.js | 177 +++ .../exception-handling/unreached-valid.wast.js | 85 ++ 16 files changed, 3583 insertions(+) create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/call_indirect.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/custom.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/directives.txt create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/harness/directives.txt create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/harness/harness.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/rethrow.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/table_fill.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/table_get.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/table_grow.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/table_set.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/table_size.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/tag.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/throw.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/try_catch.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/try_delegate.wast.js create mode 100644 js/src/jit-test/tests/wasm/spec/exception-handling/unreached-valid.wast.js (limited to 'js/src/jit-test/tests/wasm/spec/exception-handling') diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/call_indirect.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/call_indirect.wast.js new file mode 100644 index 0000000000..cde2d92cef --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/call_indirect.wast.js @@ -0,0 +1,1240 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/call_indirect.wast + +// ./test/core/call_indirect.wast:3 +let $0 = instantiate(`(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 $$out-f64-i32 (func (result f64 i32))) + (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 $$over-i32-f64 (func (param i32 f64) (result i32 f64))) + (type $$swap-i32-i64 (func (param i32 i64) (result i64 i32))) + (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 $$const-f64-i32 (type $$out-f64-i32) (f64.const 0xf64) (i32.const 32)) + + (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 $$id-i32-f64 (type $$over-i32-f64) (local.get 0) (local.get 1)) + (func $$swap-i32-i64 (type $$swap-i32-i64) (local.get 1) (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 ;; 0..3 + $$id-i32 $$id-i64 $$id-f32 $$id-f64 ;; 4..7 + $$f32-i32 $$i32-i64 $$f64-f32 $$i64-f64 ;; 9..11 + $$fac-i64 $$fib-i64 $$even $$odd ;; 12..15 + $$runaway $$mutual-runaway1 $$mutual-runaway2 ;; 16..18 + $$over-i32-duplicate $$over-i64-duplicate ;; 19..20 + $$over-f32-duplicate $$over-f64-duplicate ;; 21..22 + $$fac-i32 $$fac-f32 $$fac-f64 ;; 23..25 + $$fib-i32 $$fib-f32 $$fib-f64 ;; 26..28 + $$const-f64-i32 $$id-i32-f64 $$swap-i32-i64 ;; 29..31 + ) + ) + + ;; Syntax + + (func + (call_indirect (i32.const 0)) + (call_indirect (param i64) (i64.const 0) (i32.const 0)) + (call_indirect (param i64) (param) (param f64 i32 i64) + (i64.const 0) (f64.const 0) (i32.const 0) (i64.const 0) (i32.const 0) + ) + (call_indirect (result) (i32.const 0)) + (drop (i32.eqz (call_indirect (result i32) (i32.const 0)))) + (drop (i32.eqz (call_indirect (result i32) (result) (i32.const 0)))) + (drop (i32.eqz + (call_indirect (param i64) (result i32) (i64.const 0) (i32.const 0)) + )) + (drop (i32.eqz + (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) + ) + )) + (drop (i64.eqz + (call_indirect (type $$over-i64) (param i64) (result i64) + (i64.const 0) (i32.const 0) + ) + )) + ) + + ;; Typing + + (func (export "type-i32") (result i32) + (call_indirect (type $$out-i32) (i32.const 0)) + ) + (func (export "type-i64") (result i64) + (call_indirect (type $$out-i64) (i32.const 1)) + ) + (func (export "type-f32") (result f32) + (call_indirect (type $$out-f32) (i32.const 2)) + ) + (func (export "type-f64") (result f64) + (call_indirect (type $$out-f64) (i32.const 3)) + ) + (func (export "type-f64-i32") (result f64 i32) + (call_indirect (type $$out-f64-i32) (i32.const 29)) + ) + + (func (export "type-index") (result i64) + (call_indirect (type $$over-i64) (i64.const 100) (i32.const 5)) + ) + + (func (export "type-first-i32") (result i32) + (call_indirect (type $$over-i32) (i32.const 32) (i32.const 4)) + ) + (func (export "type-first-i64") (result i64) + (call_indirect (type $$over-i64) (i64.const 64) (i32.const 5)) + ) + (func (export "type-first-f32") (result f32) + (call_indirect (type $$over-f32) (f32.const 1.32) (i32.const 6)) + ) + (func (export "type-first-f64") (result f64) + (call_indirect (type $$over-f64) (f64.const 1.64) (i32.const 7)) + ) + + (func (export "type-second-i32") (result i32) + (call_indirect (type $$f32-i32) (f32.const 32.1) (i32.const 32) (i32.const 8)) + ) + (func (export "type-second-i64") (result i64) + (call_indirect (type $$i32-i64) (i32.const 32) (i64.const 64) (i32.const 9)) + ) + (func (export "type-second-f32") (result f32) + (call_indirect (type $$f64-f32) (f64.const 64) (f32.const 32) (i32.const 10)) + ) + (func (export "type-second-f64") (result f64) + (call_indirect (type $$i64-f64) (i64.const 64) (f64.const 64.1) (i32.const 11)) + ) + + (func (export "type-all-f64-i32") (result f64 i32) + (call_indirect (type $$out-f64-i32) (i32.const 29)) + ) + (func (export "type-all-i32-f64") (result i32 f64) + (call_indirect (type $$over-i32-f64) + (i32.const 1) (f64.const 2) (i32.const 30) + ) + ) + (func (export "type-all-i32-i64") (result i64 i32) + (call_indirect (type $$swap-i32-i64) + (i32.const 1) (i64.const 2) (i32.const 31) + ) + ) + + ;; Dispatch + + (func (export "dispatch") (param i32 i64) (result i64) + (call_indirect (type $$over-i64) (local.get 1) (local.get 0)) + ) + + (func (export "dispatch-structural-i64") (param i32) (result i64) + (call_indirect (type $$over-i64-duplicate) (i64.const 9) (local.get 0)) + ) + (func (export "dispatch-structural-i32") (param i32) (result i32) + (call_indirect (type $$over-i32-duplicate) (i32.const 9) (local.get 0)) + ) + (func (export "dispatch-structural-f32") (param i32) (result f32) + (call_indirect (type $$over-f32-duplicate) (f32.const 9.0) (local.get 0)) + ) + (func (export "dispatch-structural-f64") (param i32) (result f64) + (call_indirect (type $$over-f64-duplicate) (f64.const 9.0) (local.get 0)) + ) + + ;; Recursion + + (func $$fac-i64 (export "fac-i64") (type $$over-i64) + (if (result i64) (i64.eqz (local.get 0)) + (then (i64.const 1)) + (else + (i64.mul + (local.get 0) + (call_indirect (type $$over-i64) + (i64.sub (local.get 0) (i64.const 1)) + (i32.const 12) + ) + ) + ) + ) + ) + + (func $$fib-i64 (export "fib-i64") (type $$over-i64) + (if (result i64) (i64.le_u (local.get 0) (i64.const 1)) + (then (i64.const 1)) + (else + (i64.add + (call_indirect (type $$over-i64) + (i64.sub (local.get 0) (i64.const 2)) + (i32.const 13) + ) + (call_indirect (type $$over-i64) + (i64.sub (local.get 0) (i64.const 1)) + (i32.const 13) + ) + ) + ) + ) + ) + + (func $$fac-i32 (export "fac-i32") (type $$over-i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 1)) + (else + (i32.mul + (local.get 0) + (call_indirect (type $$over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 23) + ) + ) + ) + ) + ) + + (func $$fac-f32 (export "fac-f32") (type $$over-f32) + (if (result f32) (f32.eq (local.get 0) (f32.const 0.0)) + (then (f32.const 1.0)) + (else + (f32.mul + (local.get 0) + (call_indirect (type $$over-f32) + (f32.sub (local.get 0) (f32.const 1.0)) + (i32.const 24) + ) + ) + ) + ) + ) + + (func $$fac-f64 (export "fac-f64") (type $$over-f64) + (if (result f64) (f64.eq (local.get 0) (f64.const 0.0)) + (then (f64.const 1.0)) + (else + (f64.mul + (local.get 0) + (call_indirect (type $$over-f64) + (f64.sub (local.get 0) (f64.const 1.0)) + (i32.const 25) + ) + ) + ) + ) + ) + + (func $$fib-i32 (export "fib-i32") (type $$over-i32) + (if (result i32) (i32.le_u (local.get 0) (i32.const 1)) + (then (i32.const 1)) + (else + (i32.add + (call_indirect (type $$over-i32) + (i32.sub (local.get 0) (i32.const 2)) + (i32.const 26) + ) + (call_indirect (type $$over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 26) + ) + ) + ) + ) + ) + + (func $$fib-f32 (export "fib-f32") (type $$over-f32) + (if (result f32) (f32.le (local.get 0) (f32.const 1.0)) + (then (f32.const 1.0)) + (else + (f32.add + (call_indirect (type $$over-f32) + (f32.sub (local.get 0) (f32.const 2.0)) + (i32.const 27) + ) + (call_indirect (type $$over-f32) + (f32.sub (local.get 0) (f32.const 1.0)) + (i32.const 27) + ) + ) + ) + ) + ) + + (func $$fib-f64 (export "fib-f64") (type $$over-f64) + (if (result f64) (f64.le (local.get 0) (f64.const 1.0)) + (then (f64.const 1.0)) + (else + (f64.add + (call_indirect (type $$over-f64) + (f64.sub (local.get 0) (f64.const 2.0)) + (i32.const 28) + ) + (call_indirect (type $$over-f64) + (f64.sub (local.get 0) (f64.const 1.0)) + (i32.const 28) + ) + ) + ) + ) + ) + + (func $$even (export "even") (param i32) (result i32) + (if (result i32) (i32.eqz (local.get 0)) + (then (i32.const 44)) + (else + (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 + (call_indirect (type $$over-i32) + (i32.sub (local.get 0) (i32.const 1)) + (i32.const 14) + ) + ) + ) + ) + + ;; Stack exhaustion + + ;; Implementations are required to have every call consume some abstract + ;; resource towards exhausting some abstract finite limit, such that + ;; infinitely recursive test cases reliably trap in finite time. This is + ;; because otherwise applications could come to depend on it on those + ;; implementations and be incompatible with implementations that don't do + ;; it (or don't do it under the same circumstances). + + (func $$runaway (export "runaway") (call_indirect (type $$proc) (i32.const 16))) + + (func $$mutual-runaway1 (export "mutual-runaway") (call_indirect (type $$proc) (i32.const 18))) + (func $$mutual-runaway2 (call_indirect (type $$proc) (i32.const 17))) + + ;; As parameter of control constructs and instructions + + (memory 1) + + (func (export "as-select-first") (result i32) + (select (call_indirect (type $$out-i32) (i32.const 0)) (i32.const 2) (i32.const 3)) + ) + (func (export "as-select-mid") (result i32) + (select (i32.const 2) (call_indirect (type $$out-i32) (i32.const 0)) (i32.const 3)) + ) + (func (export "as-select-last") (result i32) + (select (i32.const 2) (i32.const 3) (call_indirect (type $$out-i32) (i32.const 0))) + ) + + (func (export "as-if-condition") (result i32) + (if (result i32) (call_indirect (type $$out-i32) (i32.const 0)) (then (i32.const 1)) (else (i32.const 2))) + ) + + (func (export "as-br_if-first") (result i64) + (block (result i64) (br_if 0 (call_indirect (type $$out-i64) (i32.const 1)) (i32.const 2))) + ) + (func (export "as-br_if-last") (result i32) + (block (result i32) (br_if 0 (i32.const 2) (call_indirect (type $$out-i32) (i32.const 0)))) + ) + + (func (export "as-br_table-first") (result f32) + (block (result f32) (call_indirect (type $$out-f32) (i32.const 2)) (i32.const 2) (br_table 0 0)) + ) + (func (export "as-br_table-last") (result i32) + (block (result i32) (i32.const 2) (call_indirect (type $$out-i32) (i32.const 0)) (br_table 0 0)) + ) + + (func (export "as-store-first") + (call_indirect (type $$out-i32) (i32.const 0)) (i32.const 1) (i32.store) + ) + (func (export "as-store-last") + (i32.const 10) (call_indirect (type $$out-f64) (i32.const 3)) (f64.store) + ) + + (func (export "as-memory.grow-value") (result i32) + (memory.grow (call_indirect (type $$out-i32) (i32.const 0))) + ) + (func (export "as-return-value") (result i32) + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) (return) + ) + (func (export "as-drop-operand") + (call_indirect (type $$over-i64) (i64.const 1) (i32.const 5)) (drop) + ) + (func (export "as-br-value") (result f32) + (block (result f32) (br 0 (call_indirect (type $$over-f32) (f32.const 1) (i32.const 6)))) + ) + (func (export "as-local.set-value") (result f64) + (local f64) (local.set 0 (call_indirect (type $$over-f64) (f64.const 1) (i32.const 7))) (local.get 0) + ) + (func (export "as-local.tee-value") (result f64) + (local f64) (local.tee 0 (call_indirect (type $$over-f64) (f64.const 1) (i32.const 7))) + ) + (global $$a (mut f64) (f64.const 10.0)) + (func (export "as-global.set-value") (result f64) + (global.set $$a (call_indirect (type $$over-f64) (f64.const 1.0) (i32.const 7))) + (global.get $$a) + ) + + (func (export "as-load-operand") (result i32) + (i32.load (call_indirect (type $$out-i32) (i32.const 0))) + ) + + (func (export "as-unary-operand") (result f32) + (block (result f32) + (f32.sqrt + (call_indirect (type $$over-f32) (f32.const 0x0p+0) (i32.const 6)) + ) + ) + ) + + (func (export "as-binary-left") (result i32) + (block (result i32) + (i32.add + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + (i32.const 10) + ) + ) + ) + (func (export "as-binary-right") (result i32) + (block (result i32) + (i32.sub + (i32.const 10) + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + ) + ) + ) + + (func (export "as-test-operand") (result i32) + (block (result i32) + (i32.eqz + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + ) + ) + ) + + (func (export "as-compare-left") (result i32) + (block (result i32) + (i32.le_u + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + (i32.const 10) + ) + ) + ) + (func (export "as-compare-right") (result i32) + (block (result i32) + (i32.ne + (i32.const 10) + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + ) + ) + ) + + (func (export "as-convert-operand") (result i64) + (block (result i64) + (i64.extend_i32_s + (call_indirect (type $$over-i32) (i32.const 1) (i32.const 4)) + ) + ) + ) + +)`); + +// ./test/core/call_indirect.wast:471 +assert_return(() => invoke($0, `type-i32`, []), [value("i32", 306)]); + +// ./test/core/call_indirect.wast:472 +assert_return(() => invoke($0, `type-i64`, []), [value("i64", 356n)]); + +// ./test/core/call_indirect.wast:473 +assert_return(() => invoke($0, `type-f32`, []), [value("f32", 3890)]); + +// ./test/core/call_indirect.wast:474 +assert_return(() => invoke($0, `type-f64`, []), [value("f64", 3940)]); + +// ./test/core/call_indirect.wast:475 +assert_return(() => invoke($0, `type-f64-i32`, []), [value("f64", 3940), value("i32", 32)]); + +// ./test/core/call_indirect.wast:477 +assert_return(() => invoke($0, `type-index`, []), [value("i64", 100n)]); + +// ./test/core/call_indirect.wast:479 +assert_return(() => invoke($0, `type-first-i32`, []), [value("i32", 32)]); + +// ./test/core/call_indirect.wast:480 +assert_return(() => invoke($0, `type-first-i64`, []), [value("i64", 64n)]); + +// ./test/core/call_indirect.wast:481 +assert_return(() => invoke($0, `type-first-f32`, []), [value("f32", 1.32)]); + +// ./test/core/call_indirect.wast:482 +assert_return(() => invoke($0, `type-first-f64`, []), [value("f64", 1.64)]); + +// ./test/core/call_indirect.wast:484 +assert_return(() => invoke($0, `type-second-i32`, []), [value("i32", 32)]); + +// ./test/core/call_indirect.wast:485 +assert_return(() => invoke($0, `type-second-i64`, []), [value("i64", 64n)]); + +// ./test/core/call_indirect.wast:486 +assert_return(() => invoke($0, `type-second-f32`, []), [value("f32", 32)]); + +// ./test/core/call_indirect.wast:487 +assert_return(() => invoke($0, `type-second-f64`, []), [value("f64", 64.1)]); + +// ./test/core/call_indirect.wast:489 +assert_return(() => invoke($0, `type-all-f64-i32`, []), [value("f64", 3940), value("i32", 32)]); + +// ./test/core/call_indirect.wast:490 +assert_return(() => invoke($0, `type-all-i32-f64`, []), [value("i32", 1), value("f64", 2)]); + +// ./test/core/call_indirect.wast:491 +assert_return(() => invoke($0, `type-all-i32-i64`, []), [value("i64", 2n), value("i32", 1)]); + +// ./test/core/call_indirect.wast:493 +assert_return(() => invoke($0, `dispatch`, [5, 2n]), [value("i64", 2n)]); + +// ./test/core/call_indirect.wast:494 +assert_return(() => invoke($0, `dispatch`, [5, 5n]), [value("i64", 5n)]); + +// ./test/core/call_indirect.wast:495 +assert_return(() => invoke($0, `dispatch`, [12, 5n]), [value("i64", 120n)]); + +// ./test/core/call_indirect.wast:496 +assert_return(() => invoke($0, `dispatch`, [13, 5n]), [value("i64", 8n)]); + +// ./test/core/call_indirect.wast:497 +assert_return(() => invoke($0, `dispatch`, [20, 2n]), [value("i64", 2n)]); + +// ./test/core/call_indirect.wast:498 +assert_trap(() => invoke($0, `dispatch`, [0, 2n]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:499 +assert_trap(() => invoke($0, `dispatch`, [15, 2n]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:500 +assert_trap(() => invoke($0, `dispatch`, [32, 2n]), `undefined element`); + +// ./test/core/call_indirect.wast:501 +assert_trap(() => invoke($0, `dispatch`, [-1, 2n]), `undefined element`); + +// ./test/core/call_indirect.wast:502 +assert_trap(() => invoke($0, `dispatch`, [1213432423, 2n]), `undefined element`); + +// ./test/core/call_indirect.wast:504 +assert_return(() => invoke($0, `dispatch-structural-i64`, [5]), [value("i64", 9n)]); + +// ./test/core/call_indirect.wast:505 +assert_return(() => invoke($0, `dispatch-structural-i64`, [12]), [value("i64", 362880n)]); + +// ./test/core/call_indirect.wast:506 +assert_return(() => invoke($0, `dispatch-structural-i64`, [13]), [value("i64", 55n)]); + +// ./test/core/call_indirect.wast:507 +assert_return(() => invoke($0, `dispatch-structural-i64`, [20]), [value("i64", 9n)]); + +// ./test/core/call_indirect.wast:508 +assert_trap(() => invoke($0, `dispatch-structural-i64`, [11]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:509 +assert_trap(() => invoke($0, `dispatch-structural-i64`, [22]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:511 +assert_return(() => invoke($0, `dispatch-structural-i32`, [4]), [value("i32", 9)]); + +// ./test/core/call_indirect.wast:512 +assert_return(() => invoke($0, `dispatch-structural-i32`, [23]), [value("i32", 362880)]); + +// ./test/core/call_indirect.wast:513 +assert_return(() => invoke($0, `dispatch-structural-i32`, [26]), [value("i32", 55)]); + +// ./test/core/call_indirect.wast:514 +assert_return(() => invoke($0, `dispatch-structural-i32`, [19]), [value("i32", 9)]); + +// ./test/core/call_indirect.wast:515 +assert_trap(() => invoke($0, `dispatch-structural-i32`, [9]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:516 +assert_trap(() => invoke($0, `dispatch-structural-i32`, [21]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:518 +assert_return(() => invoke($0, `dispatch-structural-f32`, [6]), [value("f32", 9)]); + +// ./test/core/call_indirect.wast:519 +assert_return(() => invoke($0, `dispatch-structural-f32`, [24]), [value("f32", 362880)]); + +// ./test/core/call_indirect.wast:520 +assert_return(() => invoke($0, `dispatch-structural-f32`, [27]), [value("f32", 55)]); + +// ./test/core/call_indirect.wast:521 +assert_return(() => invoke($0, `dispatch-structural-f32`, [21]), [value("f32", 9)]); + +// ./test/core/call_indirect.wast:522 +assert_trap(() => invoke($0, `dispatch-structural-f32`, [8]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:523 +assert_trap(() => invoke($0, `dispatch-structural-f32`, [19]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:525 +assert_return(() => invoke($0, `dispatch-structural-f64`, [7]), [value("f64", 9)]); + +// ./test/core/call_indirect.wast:526 +assert_return(() => invoke($0, `dispatch-structural-f64`, [25]), [value("f64", 362880)]); + +// ./test/core/call_indirect.wast:527 +assert_return(() => invoke($0, `dispatch-structural-f64`, [28]), [value("f64", 55)]); + +// ./test/core/call_indirect.wast:528 +assert_return(() => invoke($0, `dispatch-structural-f64`, [22]), [value("f64", 9)]); + +// ./test/core/call_indirect.wast:529 +assert_trap(() => invoke($0, `dispatch-structural-f64`, [10]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:530 +assert_trap(() => invoke($0, `dispatch-structural-f64`, [18]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:532 +assert_return(() => invoke($0, `fac-i64`, [0n]), [value("i64", 1n)]); + +// ./test/core/call_indirect.wast:533 +assert_return(() => invoke($0, `fac-i64`, [1n]), [value("i64", 1n)]); + +// ./test/core/call_indirect.wast:534 +assert_return(() => invoke($0, `fac-i64`, [5n]), [value("i64", 120n)]); + +// ./test/core/call_indirect.wast:535 +assert_return(() => invoke($0, `fac-i64`, [25n]), [value("i64", 7034535277573963776n)]); + +// ./test/core/call_indirect.wast:537 +assert_return(() => invoke($0, `fac-i32`, [0]), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:538 +assert_return(() => invoke($0, `fac-i32`, [1]), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:539 +assert_return(() => invoke($0, `fac-i32`, [5]), [value("i32", 120)]); + +// ./test/core/call_indirect.wast:540 +assert_return(() => invoke($0, `fac-i32`, [10]), [value("i32", 3628800)]); + +// ./test/core/call_indirect.wast:542 +assert_return(() => invoke($0, `fac-f32`, [value("f32", 0)]), [value("f32", 1)]); + +// ./test/core/call_indirect.wast:543 +assert_return(() => invoke($0, `fac-f32`, [value("f32", 1)]), [value("f32", 1)]); + +// ./test/core/call_indirect.wast:544 +assert_return(() => invoke($0, `fac-f32`, [value("f32", 5)]), [value("f32", 120)]); + +// ./test/core/call_indirect.wast:545 +assert_return(() => invoke($0, `fac-f32`, [value("f32", 10)]), [value("f32", 3628800)]); + +// ./test/core/call_indirect.wast:547 +assert_return(() => invoke($0, `fac-f64`, [value("f64", 0)]), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:548 +assert_return(() => invoke($0, `fac-f64`, [value("f64", 1)]), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:549 +assert_return(() => invoke($0, `fac-f64`, [value("f64", 5)]), [value("f64", 120)]); + +// ./test/core/call_indirect.wast:550 +assert_return(() => invoke($0, `fac-f64`, [value("f64", 10)]), [value("f64", 3628800)]); + +// ./test/core/call_indirect.wast:552 +assert_return(() => invoke($0, `fib-i64`, [0n]), [value("i64", 1n)]); + +// ./test/core/call_indirect.wast:553 +assert_return(() => invoke($0, `fib-i64`, [1n]), [value("i64", 1n)]); + +// ./test/core/call_indirect.wast:554 +assert_return(() => invoke($0, `fib-i64`, [2n]), [value("i64", 2n)]); + +// ./test/core/call_indirect.wast:555 +assert_return(() => invoke($0, `fib-i64`, [5n]), [value("i64", 8n)]); + +// ./test/core/call_indirect.wast:556 +assert_return(() => invoke($0, `fib-i64`, [20n]), [value("i64", 10946n)]); + +// ./test/core/call_indirect.wast:558 +assert_return(() => invoke($0, `fib-i32`, [0]), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:559 +assert_return(() => invoke($0, `fib-i32`, [1]), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:560 +assert_return(() => invoke($0, `fib-i32`, [2]), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:561 +assert_return(() => invoke($0, `fib-i32`, [5]), [value("i32", 8)]); + +// ./test/core/call_indirect.wast:562 +assert_return(() => invoke($0, `fib-i32`, [20]), [value("i32", 10946)]); + +// ./test/core/call_indirect.wast:564 +assert_return(() => invoke($0, `fib-f32`, [value("f32", 0)]), [value("f32", 1)]); + +// ./test/core/call_indirect.wast:565 +assert_return(() => invoke($0, `fib-f32`, [value("f32", 1)]), [value("f32", 1)]); + +// ./test/core/call_indirect.wast:566 +assert_return(() => invoke($0, `fib-f32`, [value("f32", 2)]), [value("f32", 2)]); + +// ./test/core/call_indirect.wast:567 +assert_return(() => invoke($0, `fib-f32`, [value("f32", 5)]), [value("f32", 8)]); + +// ./test/core/call_indirect.wast:568 +assert_return(() => invoke($0, `fib-f32`, [value("f32", 20)]), [value("f32", 10946)]); + +// ./test/core/call_indirect.wast:570 +assert_return(() => invoke($0, `fib-f64`, [value("f64", 0)]), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:571 +assert_return(() => invoke($0, `fib-f64`, [value("f64", 1)]), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:572 +assert_return(() => invoke($0, `fib-f64`, [value("f64", 2)]), [value("f64", 2)]); + +// ./test/core/call_indirect.wast:573 +assert_return(() => invoke($0, `fib-f64`, [value("f64", 5)]), [value("f64", 8)]); + +// ./test/core/call_indirect.wast:574 +assert_return(() => invoke($0, `fib-f64`, [value("f64", 20)]), [value("f64", 10946)]); + +// ./test/core/call_indirect.wast:576 +assert_return(() => invoke($0, `even`, [0]), [value("i32", 44)]); + +// ./test/core/call_indirect.wast:577 +assert_return(() => invoke($0, `even`, [1]), [value("i32", 99)]); + +// ./test/core/call_indirect.wast:578 +assert_return(() => invoke($0, `even`, [100]), [value("i32", 44)]); + +// ./test/core/call_indirect.wast:579 +assert_return(() => invoke($0, `even`, [77]), [value("i32", 99)]); + +// ./test/core/call_indirect.wast:580 +assert_return(() => invoke($0, `odd`, [0]), [value("i32", 99)]); + +// ./test/core/call_indirect.wast:581 +assert_return(() => invoke($0, `odd`, [1]), [value("i32", 44)]); + +// ./test/core/call_indirect.wast:582 +assert_return(() => invoke($0, `odd`, [200]), [value("i32", 99)]); + +// ./test/core/call_indirect.wast:583 +assert_return(() => invoke($0, `odd`, [77]), [value("i32", 44)]); + +// ./test/core/call_indirect.wast:585 +assert_exhaustion(() => invoke($0, `runaway`, []), `call stack exhausted`); + +// ./test/core/call_indirect.wast:586 +assert_exhaustion(() => invoke($0, `mutual-runaway`, []), `call stack exhausted`); + +// ./test/core/call_indirect.wast:588 +assert_return(() => invoke($0, `as-select-first`, []), [value("i32", 306)]); + +// ./test/core/call_indirect.wast:589 +assert_return(() => invoke($0, `as-select-mid`, []), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:590 +assert_return(() => invoke($0, `as-select-last`, []), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:592 +assert_return(() => invoke($0, `as-if-condition`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:594 +assert_return(() => invoke($0, `as-br_if-first`, []), [value("i64", 356n)]); + +// ./test/core/call_indirect.wast:595 +assert_return(() => invoke($0, `as-br_if-last`, []), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:597 +assert_return(() => invoke($0, `as-br_table-first`, []), [value("f32", 3890)]); + +// ./test/core/call_indirect.wast:598 +assert_return(() => invoke($0, `as-br_table-last`, []), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:600 +assert_return(() => invoke($0, `as-store-first`, []), []); + +// ./test/core/call_indirect.wast:601 +assert_return(() => invoke($0, `as-store-last`, []), []); + +// ./test/core/call_indirect.wast:603 +assert_return(() => invoke($0, `as-memory.grow-value`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:604 +assert_return(() => invoke($0, `as-return-value`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:605 +assert_return(() => invoke($0, `as-drop-operand`, []), []); + +// ./test/core/call_indirect.wast:606 +assert_return(() => invoke($0, `as-br-value`, []), [value("f32", 1)]); + +// ./test/core/call_indirect.wast:607 +assert_return(() => invoke($0, `as-local.set-value`, []), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:608 +assert_return(() => invoke($0, `as-local.tee-value`, []), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:609 +assert_return(() => invoke($0, `as-global.set-value`, []), [value("f64", 1)]); + +// ./test/core/call_indirect.wast:610 +assert_return(() => invoke($0, `as-load-operand`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:612 +assert_return(() => invoke($0, `as-unary-operand`, []), [value("f32", 0)]); + +// ./test/core/call_indirect.wast:613 +assert_return(() => invoke($0, `as-binary-left`, []), [value("i32", 11)]); + +// ./test/core/call_indirect.wast:614 +assert_return(() => invoke($0, `as-binary-right`, []), [value("i32", 9)]); + +// ./test/core/call_indirect.wast:615 +assert_return(() => invoke($0, `as-test-operand`, []), [value("i32", 0)]); + +// ./test/core/call_indirect.wast:616 +assert_return(() => invoke($0, `as-compare-left`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:617 +assert_return(() => invoke($0, `as-compare-right`, []), [value("i32", 1)]); + +// ./test/core/call_indirect.wast:618 +assert_return(() => invoke($0, `as-convert-operand`, []), [value("i64", 1n)]); + +// ./test/core/call_indirect.wast:623 +let $1 = instantiate(`(module + (type $$ii-i (func (param i32 i32) (result i32))) + + (table $$t1 funcref (elem $$f $$g)) + (table $$t2 funcref (elem $$h $$i $$j)) + (table $$t3 4 funcref) + (elem (table $$t3) (i32.const 0) func $$g $$h) + (elem (table $$t3) (i32.const 3) func $$z) + + (func $$f (type $$ii-i) (i32.add (local.get 0) (local.get 1))) + (func $$g (type $$ii-i) (i32.sub (local.get 0) (local.get 1))) + (func $$h (type $$ii-i) (i32.mul (local.get 0) (local.get 1))) + (func $$i (type $$ii-i) (i32.div_u (local.get 0) (local.get 1))) + (func $$j (type $$ii-i) (i32.rem_u (local.get 0) (local.get 1))) + (func $$z) + + (func (export "call-1") (param i32 i32 i32) (result i32) + (call_indirect $$t1 (type $$ii-i) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "call-2") (param i32 i32 i32) (result i32) + (call_indirect $$t2 (type $$ii-i) (local.get 0) (local.get 1) (local.get 2)) + ) + (func (export "call-3") (param i32 i32 i32) (result i32) + (call_indirect $$t3 (type $$ii-i) (local.get 0) (local.get 1) (local.get 2)) + ) +)`); + +// ./test/core/call_indirect.wast:650 +assert_return(() => invoke($1, `call-1`, [2, 3, 0]), [value("i32", 5)]); + +// ./test/core/call_indirect.wast:651 +assert_return(() => invoke($1, `call-1`, [2, 3, 1]), [value("i32", -1)]); + +// ./test/core/call_indirect.wast:652 +assert_trap(() => invoke($1, `call-1`, [2, 3, 2]), `undefined element`); + +// ./test/core/call_indirect.wast:654 +assert_return(() => invoke($1, `call-2`, [2, 3, 0]), [value("i32", 6)]); + +// ./test/core/call_indirect.wast:655 +assert_return(() => invoke($1, `call-2`, [2, 3, 1]), [value("i32", 0)]); + +// ./test/core/call_indirect.wast:656 +assert_return(() => invoke($1, `call-2`, [2, 3, 2]), [value("i32", 2)]); + +// ./test/core/call_indirect.wast:657 +assert_trap(() => invoke($1, `call-2`, [2, 3, 3]), `undefined element`); + +// ./test/core/call_indirect.wast:659 +assert_return(() => invoke($1, `call-3`, [2, 3, 0]), [value("i32", -1)]); + +// ./test/core/call_indirect.wast:660 +assert_return(() => invoke($1, `call-3`, [2, 3, 1]), [value("i32", 6)]); + +// ./test/core/call_indirect.wast:661 +assert_trap(() => invoke($1, `call-3`, [2, 3, 2]), `uninitialized element`); + +// ./test/core/call_indirect.wast:662 +assert_trap(() => invoke($1, `call-3`, [2, 3, 3]), `indirect call type mismatch`); + +// ./test/core/call_indirect.wast:663 +assert_trap(() => invoke($1, `call-3`, [2, 3, 4]), `undefined element`); + +// ./test/core/call_indirect.wast:668 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (type $$sig) (result i32) (param i32) (i32.const 0) (i32.const 0) ) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:680 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (param i32) (type $$sig) (result i32) (i32.const 0) (i32.const 0) ) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:692 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (param i32) (result i32) (type $$sig) (i32.const 0) (i32.const 0) ) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:704 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (result i32) (type $$sig) (param i32) (i32.const 0) (i32.const 0) ) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:716 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (result i32) (param i32) (type $$sig) (i32.const 0) (i32.const 0) ) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:728 +assert_malformed( + () => instantiate(`(table 0 funcref) (func (result i32) (call_indirect (result i32) (param i32) (i32.const 0) (i32.const 0)) ) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:738 +assert_malformed( + () => instantiate(`(table 0 funcref) (func (call_indirect (param $$x i32) (i32.const 0) (i32.const 0))) `), + `unexpected token`, +); + +// ./test/core/call_indirect.wast:745 +assert_malformed( + () => instantiate(`(type $$sig (func)) (table 0 funcref) (func (result i32) (call_indirect (type $$sig) (result i32) (i32.const 0)) ) `), + `inline function type`, +); + +// ./test/core/call_indirect.wast:755 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (type $$sig) (result i32) (i32.const 0)) ) `), + `inline function type`, +); + +// ./test/core/call_indirect.wast:765 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32) (result i32))) (table 0 funcref) (func (call_indirect (type $$sig) (param i32) (i32.const 0) (i32.const 0)) ) `), + `inline function type`, +); + +// ./test/core/call_indirect.wast:775 +assert_malformed( + () => instantiate(`(type $$sig (func (param i32 i32) (result i32))) (table 0 funcref) (func (result i32) (call_indirect (type $$sig) (param i32) (result i32) (i32.const 0) (i32.const 0) ) ) `), + `inline function type`, +); + +// ./test/core/call_indirect.wast:790 +assert_invalid( + () => instantiate(`(module + (type (func)) + (func $$no-table (call_indirect (type 0) (i32.const 0))) + )`), + `unknown table`, +); + +// ./test/core/call_indirect.wast:798 +assert_invalid( + () => instantiate(`(module + (type (func)) + (table 0 funcref) + (func $$type-void-vs-num (i32.eqz (call_indirect (type 0) (i32.const 0)))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:806 +assert_invalid( + () => instantiate(`(module + (type (func (result i64))) + (table 0 funcref) + (func $$type-num-vs-num (i32.eqz (call_indirect (type 0) (i32.const 0)))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:815 +assert_invalid( + () => instantiate(`(module + (type (func (param i32))) + (table 0 funcref) + (func $$arity-0-vs-1 (call_indirect (type 0) (i32.const 0))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:823 +assert_invalid( + () => instantiate(`(module + (type (func (param f64 i32))) + (table 0 funcref) + (func $$arity-0-vs-2 (call_indirect (type 0) (i32.const 0))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:831 +assert_invalid( + () => instantiate(`(module + (type (func)) + (table 0 funcref) + (func $$arity-1-vs-0 (call_indirect (type 0) (i32.const 1) (i32.const 0))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:839 +assert_invalid( + () => instantiate(`(module + (type (func)) + (table 0 funcref) + (func $$arity-2-vs-0 + (call_indirect (type 0) (f64.const 2) (i32.const 1) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:850 +assert_invalid( + () => instantiate(`(module + (type (func (param i32))) + (table 0 funcref) + (func $$type-func-void-vs-i32 (call_indirect (type 0) (i32.const 1) (nop))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:858 +assert_invalid( + () => instantiate(`(module + (type (func (param i32))) + (table 0 funcref) + (func $$type-func-num-vs-i32 (call_indirect (type 0) (i32.const 0) (i64.const 1))) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:867 +assert_invalid( + () => instantiate(`(module + (type (func (param i32 i32))) + (table 0 funcref) + (func $$type-first-void-vs-num + (call_indirect (type 0) (nop) (i32.const 1) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:877 +assert_invalid( + () => instantiate(`(module + (type (func (param i32 i32))) + (table 0 funcref) + (func $$type-second-void-vs-num + (call_indirect (type 0) (i32.const 1) (nop) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:887 +assert_invalid( + () => instantiate(`(module + (type (func (param i32 f64))) + (table 0 funcref) + (func $$type-first-num-vs-num + (call_indirect (type 0) (f64.const 1) (i32.const 1) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:897 +assert_invalid( + () => instantiate(`(module + (type (func (param f64 i32))) + (table 0 funcref) + (func $$type-second-num-vs-num + (call_indirect (type 0) (i32.const 1) (f64.const 1) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:908 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32)) + (type $$sig (func (param i32))) + (table funcref (elem $$f)) + (func $$type-first-empty-in-block + (block + (call_indirect (type $$sig) (i32.const 0)) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:921 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32 i32)) + (type $$sig (func (param i32 i32))) + (table funcref (elem $$f)) + (func $$type-second-empty-in-block + (block + (call_indirect (type $$sig) (i32.const 0) (i32.const 0)) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:934 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32)) + (type $$sig (func (param i32))) + (table funcref (elem $$f)) + (func $$type-first-empty-in-loop + (loop + (call_indirect (type $$sig) (i32.const 0)) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:947 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32 i32)) + (type $$sig (func (param i32 i32))) + (table funcref (elem $$f)) + (func $$type-second-empty-in-loop + (loop + (call_indirect (type $$sig) (i32.const 0) (i32.const 0)) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:960 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32)) + (type $$sig (func (param i32))) + (table funcref (elem $$f)) + (func $$type-first-empty-in-then + (i32.const 0) (i32.const 0) + (if + (then + (call_indirect (type $$sig) (i32.const 0)) + ) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:976 +assert_invalid( + () => instantiate(`(module + (func $$f (param i32 i32)) + (type $$sig (func (param i32 i32))) + (table funcref (elem $$f)) + (func $$type-second-empty-in-then + (i32.const 0) (i32.const 0) + (if + (then + (call_indirect (type $$sig) (i32.const 0) (i32.const 0)) + ) + ) + ) + )`), + `type mismatch`, +); + +// ./test/core/call_indirect.wast:996 +assert_invalid( + () => instantiate(`(module + (table 0 funcref) + (func $$unbound-type (call_indirect (type 1) (i32.const 0))) + )`), + `unknown type`, +); + +// ./test/core/call_indirect.wast:1003 +assert_invalid( + () => instantiate(`(module + (table 0 funcref) + (func $$large-type (call_indirect (type 1012321300) (i32.const 0))) + )`), + `unknown type`, +); + +// ./test/core/call_indirect.wast:1014 +assert_invalid( + () => instantiate(`(module (table funcref (elem 0 0)))`), + `unknown function`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/custom.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/custom.wast.js new file mode 100644 index 0000000000..747db66dec --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/custom.wast.js @@ -0,0 +1,157 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/custom.wast + +// ./test/core/custom.wast:1 +let $0 = instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\24\\10" "a custom section" "this is the payload" + "\\00\\20\\10" "a custom section" "this is payload" + "\\00\\11\\10" "a custom section" "" + "\\00\\10\\00" "" "this is payload" + "\\00\\01\\00" "" "" + "\\00\\24\\10" "\\00\\00custom sectio\\00" "this is the payload" + "\\00\\24\\10" "\\ef\\bb\\bfa custom sect" "this is the payload" + "\\00\\24\\10" "a custom sect\\e2\\8c\\a3" "this is the payload" + "\\00\\1f\\16" "module within a module" "\\00asm" "\\01\\00\\00\\00" +)`); + +// ./test/core/custom.wast:14 +let $1 = instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\01\\01\\00" ;; type section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\02\\01\\00" ;; import section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\03\\01\\00" ;; function section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\04\\01\\00" ;; table section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\05\\01\\00" ;; memory section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\06\\01\\00" ;; global section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\07\\01\\00" ;; export section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\09\\01\\00" ;; element section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\0a\\01\\00" ;; code section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" + "\\0b\\01\\00" ;; data section + "\\00\\0e\\06" "custom" "payload" + "\\00\\0e\\06" "custom" "payload" +)`); + +// ./test/core/custom.wast:50 +let $2 = instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\01\\07\\01\\60\\02\\7f\\7f\\01\\7f" ;; type section + "\\00\\1a\\06" "custom" "this is the payload" ;; custom section + "\\03\\02\\01\\00" ;; function section + "\\07\\0a\\01\\06\\61\\64\\64\\54\\77\\6f\\00\\00" ;; export section + "\\0a\\09\\01\\07\\00\\20\\00\\20\\01\\6a\\0b" ;; code section + "\\00\\1b\\07" "custom2" "this is the payload" ;; custom section +)`); + +// ./test/core/custom.wast:60 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00" + )`), + `unexpected end`, +); + +// ./test/core/custom.wast:68 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\00" + )`), + `unexpected end`, +); + +// ./test/core/custom.wast:76 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\00\\00\\05\\01\\00\\07\\00\\00" + )`), + `unexpected end`, +); + +// ./test/core/custom.wast:84 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\26\\10" "a custom section" "this is the payload" + )`), + `unexpected end`, +); + +// ./test/core/custom.wast:92 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\00\\25\\10" "a custom section" "this is the payload" + "\\00\\24\\10" "a custom section" "this is the payload" + )`), + `malformed section id`, +); + +// ./test/core/custom.wast:101 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\01\\07\\01\\60\\02\\7f\\7f\\01\\7f" ;; type section + "\\00\\25\\10" "a custom section" "this is the payload" ;; wrong length! + "\\03\\02\\01\\00" ;; function section + "\\0a\\09\\01\\07\\00\\20\\00\\20\\01\\6a\\0b" ;; code section + "\\00\\1b\\07" "custom2" "this is the payload" ;; custom section + )`), + `function and code section have inconsistent lengths`, +); + +// ./test/core/custom.wast:114 +assert_malformed( + () => instantiate(`(module binary + "\\00asm\\01\\00\\00\\00" + "\\00asm\\01\\00\\00\\00" + )`), + `length out of bounds`, +); + +// ./test/core/custom.wast:122 +assert_malformed( + () => instantiate(`(module binary + "\\00asm" "\\01\\00\\00\\00" + "\\05\\03\\01\\00\\01" ;; memory section + "\\0c\\01\\02" ;; data count section (2 segments) + "\\0b\\06\\01\\00\\41\\00\\0b\\00" ;; data section (1 segment) + )`), + `data count and data section have inconsistent lengths`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/directives.txt b/js/src/jit-test/tests/wasm/spec/exception-handling/directives.txt new file mode 100644 index 0000000000..82c2a20004 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/directives.txt @@ -0,0 +1 @@ +|jit-test| test-also=--wasm-compiler=optimizing; test-also=--wasm-compiler=baseline; test-also=--wasm-test-serialization; test-also=--test-wasm-await-tier2; test-also=--disable-wasm-huge-memory; skip-variant-if: --disable-wasm-huge-memory, !wasmHugeMemorySupported(); local-include:harness/harness.js; --wasm-exceptions; skip-if: !wasmExceptionsEnabled() \ No newline at end of file diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/harness/directives.txt b/js/src/jit-test/tests/wasm/spec/exception-handling/harness/directives.txt new file mode 100644 index 0000000000..d41243abbb --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/harness/directives.txt @@ -0,0 +1 @@ +|jit-test| skip-if: true \ No newline at end of file diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/harness/harness.js b/js/src/jit-test/tests/wasm/spec/exception-handling/harness/harness.js new file mode 100644 index 0000000000..ba615e05dd --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/harness/harness.js @@ -0,0 +1,360 @@ +"use strict"; + +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (!wasmIsSupported()) { + quit(); +} + +function bytes(type, bytes) { + var typedBuffer = new Uint8Array(bytes); + return wasmGlobalFromArrayBuffer(type, typedBuffer.buffer); +} +function value(type, value) { + return new WebAssembly.Global({ + value: type, + mutable: false, + }, value); +} + +function i8x16(elements) { + let typedBuffer = new Uint8Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} +function i16x8(elements) { + let typedBuffer = new Uint16Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} +function i32x4(elements) { + let typedBuffer = new Uint32Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} +function i64x2(elements) { + let typedBuffer = new BigUint64Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} +function f32x4(elements) { + let typedBuffer = new Float32Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} +function f64x2(elements) { + let typedBuffer = new Float64Array(elements); + return wasmGlobalFromArrayBuffer("v128", typedBuffer.buffer); +} + +function either(...arr) { + return new EitherVariants(arr); +} + +class F32x4Pattern { + constructor(x, y, z, w) { + this.x = x; + this.y = y; + this.z = z; + this.w = w; + } +} + +class F64x2Pattern { + constructor(x, y) { + this.x = x; + this.y = y; + } +} + +let externrefs = {}; +let externsym = Symbol("externref"); +function externref(s) { + if (!(s in externrefs)) externrefs[s] = { [externsym]: s }; + return externrefs[s]; +} +function is_externref(x) { + return (x !== null && externsym in x) ? 1 : 0; +} +function is_funcref(x) { + return typeof x === "function" ? 1 : 0; +} +function eq_externref(x, y) { + return x === y ? 1 : 0; +} +function eq_funcref(x, y) { + return x === y ? 1 : 0; +} + +let spectest = { + externref: externref, + is_externref: is_externref, + is_funcref: is_funcref, + eq_externref: eq_externref, + eq_funcref: eq_funcref, + print: console.log.bind(console), + print_i32: console.log.bind(console), + print_i32_f32: console.log.bind(console), + print_f64_f64: console.log.bind(console), + print_f32: console.log.bind(console), + print_f64: console.log.bind(console), + global_i32: 666, + global_i64: 666n, + global_f32: 666, + global_f64: 666, + table: new WebAssembly.Table({ + initial: 10, + maximum: 20, + element: "anyfunc", + }), + memory: new WebAssembly.Memory({ initial: 1, maximum: 2 }), +}; + +let linkage = { + spectest, +}; + +function getInstance(instanceish) { + if (typeof instanceish === "string") { + assertEq( + instanceish in linkage, + true, + `'${instanceish}'' must be registered`, + ); + return linkage[instanceish]; + } + return instanceish; +} + +function instantiate(source) { + let bytecode = wasmTextToBinary(source); + let module = new WebAssembly.Module(bytecode); + let instance = new WebAssembly.Instance(module, linkage); + return instance.exports; +} + +function register(instanceish, name) { + linkage[name] = getInstance(instanceish); +} + +function invoke(instanceish, field, params) { + let func = getInstance(instanceish)[field]; + assertEq(func instanceof Function, true, "expected a function"); + return wasmLosslessInvoke(func, ...params); +} + +function get(instanceish, field) { + let global = getInstance(instanceish)[field]; + assertEq( + global instanceof WebAssembly.Global, + true, + "expected a WebAssembly.Global", + ); + return global; +} + +function assert_trap(thunk, message) { + try { + thunk(); + assertEq("normal return", "trap"); + } catch (err) { + assertEq( + err instanceof WebAssembly.RuntimeError, + true, + "expected trap", + ); + } +} + +let StackOverflow; +try { + (function f() { + 1 + f(); + })(); +} catch (e) { + StackOverflow = e.constructor; +} +function assert_exhaustion(thunk, message) { + try { + thunk(); + assertEq("normal return", "exhaustion"); + } catch (err) { + assertEq( + err instanceof StackOverflow, + true, + "expected exhaustion", + ); + } +} + +function assert_invalid(thunk, message) { + try { + thunk(); + assertEq("valid module", "invalid module"); + } catch (err) { + assertEq( + err instanceof WebAssembly.LinkError || + err instanceof WebAssembly.CompileError, + true, + "expected an invalid module", + ); + } +} + +function assert_unlinkable(thunk, message) { + try { + thunk(); + assertEq(true, false, "expected an unlinkable module"); + } catch (err) { + assertEq( + err instanceof WebAssembly.LinkError || + err instanceof WebAssembly.CompileError, + true, + "expected an unlinkable module", + ); + } +} + +function assert_malformed(thunk, message) { + try { + thunk(); + assertEq("valid module", "malformed module"); + } catch (err) { + assertEq( + err instanceof TypeError || + err instanceof SyntaxError || + err instanceof WebAssembly.CompileError || + err instanceof WebAssembly.LinkError, + true, + `expected a malformed module`, + ); + } +} + +function assert_exception(thunk) { + let thrown = false; + try { + thunk(); + } catch (err) { + thrown = true; + } + assertEq(thrown, true, "expected an exception to be thrown"); +} + +function assert_return(thunk, expected) { + let results = thunk(); + + if (results === undefined) { + results = []; + } else if (!Array.isArray(results)) { + results = [results]; + } + if (!Array.isArray(expected)) { + expected = [expected]; + } + + if (!compareResults(results, expected)) { + let got = results.map((x) => formatResult(x)).join(", "); + let wanted = expected.map((x) => formatExpected(x)).join(", "); + assertEq( + `[${got}]`, + `[${wanted}]`, + ); + assertEq(true, false, `${got} !== ${wanted}`); + } +} + +function formatResult(result) { + if (typeof (result) === "object") { + return wasmGlobalToString(result); + } else { + return `${result}`; + } +} + +function formatExpected(expected) { + if ( + expected === `f32_canonical_nan` || + expected === `f32_arithmetic_nan` || + expected === `f64_canonical_nan` || + expected === `f64_arithmetic_nan` + ) { + return expected; + } else if (expected instanceof F32x4Pattern) { + return `f32x4(${formatExpected(expected.x)}, ${ + formatExpected(expected.y) + }, ${formatExpected(expected.z)}, ${formatExpected(expected.w)})`; + } else if (expected instanceof F64x2Pattern) { + return `f64x2(${formatExpected(expected.x)}, ${ + formatExpected(expected.y) + })`; + } else if (expected instanceof EitherVariants) { + return expected.formatExpected(); + } else if (typeof (expected) === "object") { + return wasmGlobalToString(expected); + } else { + throw new Error("unknown expected result"); + } +} + +class EitherVariants { + constructor(arr) { + this.arr = arr; + } + matches(v) { + return this.arr.some((e) => compareResult(v, e)); + } + formatExpected() { + return `either(${this.arr.map(formatExpected).join(", ")})`; + } +} + +function compareResults(results, expected) { + if (results.length !== expected.length) { + return false; + } + for (let i in results) { + if (expected[i] instanceof EitherVariants) { + return expected[i].matches(results[i]); + } + if (!compareResult(results[i], expected[i])) { + return false; + } + } + return true; +} + +function compareResult(result, expected) { + if ( + expected === `canonical_nan` || + expected === `arithmetic_nan` + ) { + return wasmGlobalIsNaN(result, expected); + } else if (expected instanceof F32x4Pattern) { + return compareResult( + wasmGlobalExtractLane(result, "f32x4", 0), + expected.x, + ) && + compareResult(wasmGlobalExtractLane(result, "f32x4", 1), expected.y) && + compareResult(wasmGlobalExtractLane(result, "f32x4", 2), expected.z) && + compareResult(wasmGlobalExtractLane(result, "f32x4", 3), expected.w); + } else if (expected instanceof F64x2Pattern) { + return compareResult( + wasmGlobalExtractLane(result, "f64x2", 0), + expected.x, + ) && + compareResult(wasmGlobalExtractLane(result, "f64x2", 1), expected.y); + } else if (typeof (expected) === "object") { + return wasmGlobalsEqual(result, expected); + } else { + throw new Error("unknown expected result"); + } +} diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/rethrow.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/rethrow.wast.js new file mode 100644 index 0000000000..a995b8dc37 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/rethrow.wast.js @@ -0,0 +1,140 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/rethrow.wast + +// ./test/core/rethrow.wast:3 +let $0 = instantiate(`(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)) + ) + ) +)`); + +// ./test/core/rethrow.wast:75 +assert_exception(() => invoke($0, `catch-rethrow-0`, [])); + +// ./test/core/rethrow.wast:77 +assert_exception(() => invoke($0, `catch-rethrow-1`, [0])); + +// ./test/core/rethrow.wast:78 +assert_return(() => invoke($0, `catch-rethrow-1`, [1]), [value("i32", 23)]); + +// ./test/core/rethrow.wast:80 +assert_exception(() => invoke($0, `catchall-rethrow-0`, [])); + +// ./test/core/rethrow.wast:82 +assert_exception(() => invoke($0, `catchall-rethrow-1`, [0])); + +// ./test/core/rethrow.wast:83 +assert_return(() => invoke($0, `catchall-rethrow-1`, [1]), [value("i32", 23)]); + +// ./test/core/rethrow.wast:84 +assert_exception(() => invoke($0, `rethrow-nested`, [0])); + +// ./test/core/rethrow.wast:85 +assert_exception(() => invoke($0, `rethrow-nested`, [1])); + +// ./test/core/rethrow.wast:86 +assert_return(() => invoke($0, `rethrow-nested`, [2]), [value("i32", 23)]); + +// ./test/core/rethrow.wast:88 +assert_return(() => invoke($0, `rethrow-recatch`, [0]), [value("i32", 23)]); + +// ./test/core/rethrow.wast:89 +assert_return(() => invoke($0, `rethrow-recatch`, [1]), [value("i32", 42)]); + +// ./test/core/rethrow.wast:91 +assert_exception(() => invoke($0, `rethrow-stack-polymorphism`, [])); + +// ./test/core/rethrow.wast:93 +assert_invalid(() => instantiate(`(module (func (rethrow 0)))`), `invalid rethrow label`); + +// ./test/core/rethrow.wast:94 +assert_invalid( + () => instantiate(`(module (func (block (rethrow 0))))`), + `invalid rethrow label`, +); + +// ./test/core/rethrow.wast:95 +assert_invalid( + () => instantiate(`(module (func (try (do (rethrow 0)) (delegate 0))))`), + `invalid rethrow label`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/table_fill.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/table_fill.wast.js new file mode 100644 index 0000000000..9381e67fc5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/table_fill.wast.js @@ -0,0 +1,234 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/table_fill.wast + +// ./test/core/table_fill.wast:1 +let $0 = instantiate(`(module + (table $$t 10 externref) + + (func (export "fill") (param $$i i32) (param $$r externref) (param $$n i32) + (table.fill $$t (local.get $$i) (local.get $$r) (local.get $$n)) + ) + + (func (export "get") (param $$i i32) (result externref) + (table.get $$t (local.get $$i)) + ) +)`); + +// ./test/core/table_fill.wast:13 +assert_return(() => invoke($0, `get`, [1]), [value('externref', null)]); + +// ./test/core/table_fill.wast:14 +assert_return(() => invoke($0, `get`, [2]), [value('externref', null)]); + +// ./test/core/table_fill.wast:15 +assert_return(() => invoke($0, `get`, [3]), [value('externref', null)]); + +// ./test/core/table_fill.wast:16 +assert_return(() => invoke($0, `get`, [4]), [value('externref', null)]); + +// ./test/core/table_fill.wast:17 +assert_return(() => invoke($0, `get`, [5]), [value('externref', null)]); + +// ./test/core/table_fill.wast:19 +assert_return(() => invoke($0, `fill`, [2, externref(1), 3]), []); + +// ./test/core/table_fill.wast:20 +assert_return(() => invoke($0, `get`, [1]), [value('externref', null)]); + +// ./test/core/table_fill.wast:21 +assert_return(() => invoke($0, `get`, [2]), [value('externref', externref(1))]); + +// ./test/core/table_fill.wast:22 +assert_return(() => invoke($0, `get`, [3]), [value('externref', externref(1))]); + +// ./test/core/table_fill.wast:23 +assert_return(() => invoke($0, `get`, [4]), [value('externref', externref(1))]); + +// ./test/core/table_fill.wast:24 +assert_return(() => invoke($0, `get`, [5]), [value('externref', null)]); + +// ./test/core/table_fill.wast:26 +assert_return(() => invoke($0, `fill`, [4, externref(2), 2]), []); + +// ./test/core/table_fill.wast:27 +assert_return(() => invoke($0, `get`, [3]), [value('externref', externref(1))]); + +// ./test/core/table_fill.wast:28 +assert_return(() => invoke($0, `get`, [4]), [value('externref', externref(2))]); + +// ./test/core/table_fill.wast:29 +assert_return(() => invoke($0, `get`, [5]), [value('externref', externref(2))]); + +// ./test/core/table_fill.wast:30 +assert_return(() => invoke($0, `get`, [6]), [value('externref', null)]); + +// ./test/core/table_fill.wast:32 +assert_return(() => invoke($0, `fill`, [4, externref(3), 0]), []); + +// ./test/core/table_fill.wast:33 +assert_return(() => invoke($0, `get`, [3]), [value('externref', externref(1))]); + +// ./test/core/table_fill.wast:34 +assert_return(() => invoke($0, `get`, [4]), [value('externref', externref(2))]); + +// ./test/core/table_fill.wast:35 +assert_return(() => invoke($0, `get`, [5]), [value('externref', externref(2))]); + +// ./test/core/table_fill.wast:37 +assert_return(() => invoke($0, `fill`, [8, externref(4), 2]), []); + +// ./test/core/table_fill.wast:38 +assert_return(() => invoke($0, `get`, [7]), [value('externref', null)]); + +// ./test/core/table_fill.wast:39 +assert_return(() => invoke($0, `get`, [8]), [value('externref', externref(4))]); + +// ./test/core/table_fill.wast:40 +assert_return(() => invoke($0, `get`, [9]), [value('externref', externref(4))]); + +// ./test/core/table_fill.wast:42 +assert_return(() => invoke($0, `fill`, [9, null, 1]), []); + +// ./test/core/table_fill.wast:43 +assert_return(() => invoke($0, `get`, [8]), [value('externref', externref(4))]); + +// ./test/core/table_fill.wast:44 +assert_return(() => invoke($0, `get`, [9]), [value('externref', null)]); + +// ./test/core/table_fill.wast:46 +assert_return(() => invoke($0, `fill`, [10, externref(5), 0]), []); + +// ./test/core/table_fill.wast:47 +assert_return(() => invoke($0, `get`, [9]), [value('externref', null)]); + +// ./test/core/table_fill.wast:49 +assert_trap(() => invoke($0, `fill`, [8, externref(6), 3]), `out of bounds table access`); + +// ./test/core/table_fill.wast:53 +assert_return(() => invoke($0, `get`, [7]), [value('externref', null)]); + +// ./test/core/table_fill.wast:54 +assert_return(() => invoke($0, `get`, [8]), [value('externref', externref(4))]); + +// ./test/core/table_fill.wast:55 +assert_return(() => invoke($0, `get`, [9]), [value('externref', null)]); + +// ./test/core/table_fill.wast:57 +assert_trap(() => invoke($0, `fill`, [11, null, 0]), `out of bounds table access`); + +// ./test/core/table_fill.wast:62 +assert_trap(() => invoke($0, `fill`, [11, null, 10]), `out of bounds table access`); + +// ./test/core/table_fill.wast:70 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-value-length-empty-vs-i32-i32 + (table.fill $$t) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:79 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-empty-vs-i32 + (table.fill $$t (ref.null extern) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:88 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-value-empty-vs + (table.fill $$t (i32.const 1) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:97 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-length-empty-vs-i32 + (table.fill $$t (i32.const 1) (ref.null extern)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:106 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-index-f32-vs-i32 + (table.fill $$t (f32.const 1) (ref.null extern) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:115 +assert_invalid( + () => instantiate(`(module + (table $$t 0 funcref) + (func $$type-value-vs-funcref (param $$r externref) + (table.fill $$t (i32.const 1) (local.get $$r) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:124 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-length-f32-vs-i32 + (table.fill $$t (i32.const 1) (ref.null extern) (f32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:134 +assert_invalid( + () => instantiate(`(module + (table $$t1 1 externref) + (table $$t2 1 funcref) + (func $$type-value-externref-vs-funcref-multi (param $$r externref) + (table.fill $$t2 (i32.const 0) (local.get $$r) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_fill.wast:145 +assert_invalid( + () => instantiate(`(module + (table $$t 1 externref) + (func $$type-result-empty-vs-num (result i32) + (table.fill $$t (i32.const 0) (ref.null extern) (i32.const 1)) + ) + )`), + `type mismatch`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/table_get.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/table_get.wast.js new file mode 100644 index 0000000000..f4982cde3a --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/table_get.wast.js @@ -0,0 +1,126 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/table_get.wast + +// ./test/core/table_get.wast:1 +let $0 = instantiate(`(module + (table $$t2 2 externref) + (table $$t3 3 funcref) + (elem (table $$t3) (i32.const 1) func $$dummy) + (func $$dummy) + + (func (export "init") (param $$r externref) + (table.set $$t2 (i32.const 1) (local.get $$r)) + (table.set $$t3 (i32.const 2) (table.get $$t3 (i32.const 1))) + ) + + (func (export "get-externref") (param $$i i32) (result externref) + (table.get $$t2 (local.get $$i)) + ) + (func $$f3 (export "get-funcref") (param $$i i32) (result funcref) + (table.get $$t3 (local.get $$i)) + ) + + (func (export "is_null-funcref") (param $$i i32) (result i32) + (ref.is_null (call $$f3 (local.get $$i))) + ) +)`); + +// ./test/core/table_get.wast:24 +invoke($0, `init`, [externref(1)]); + +// ./test/core/table_get.wast:26 +assert_return(() => invoke($0, `get-externref`, [0]), [value('externref', null)]); + +// ./test/core/table_get.wast:27 +assert_return(() => invoke($0, `get-externref`, [1]), [value('externref', externref(1))]); + +// ./test/core/table_get.wast:29 +assert_return(() => invoke($0, `get-funcref`, [0]), [value('anyfunc', null)]); + +// ./test/core/table_get.wast:30 +assert_return(() => invoke($0, `is_null-funcref`, [1]), [value("i32", 0)]); + +// ./test/core/table_get.wast:31 +assert_return(() => invoke($0, `is_null-funcref`, [2]), [value("i32", 0)]); + +// ./test/core/table_get.wast:33 +assert_trap(() => invoke($0, `get-externref`, [2]), `out of bounds table access`); + +// ./test/core/table_get.wast:34 +assert_trap(() => invoke($0, `get-funcref`, [3]), `out of bounds table access`); + +// ./test/core/table_get.wast:35 +assert_trap(() => invoke($0, `get-externref`, [-1]), `out of bounds table access`); + +// ./test/core/table_get.wast:36 +assert_trap(() => invoke($0, `get-funcref`, [-1]), `out of bounds table access`); + +// ./test/core/table_get.wast:41 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-empty-vs-i32 (result externref) + (table.get $$t) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_get.wast:50 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-f32-vs-i32 (result externref) + (table.get $$t (f32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_get.wast:60 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-result-externref-vs-empty + (table.get $$t (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_get.wast:69 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-result-externref-vs-funcref (result funcref) + (table.get $$t (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_get.wast:79 +assert_invalid( + () => instantiate(`(module + (table $$t1 1 funcref) + (table $$t2 1 externref) + (func $$type-result-externref-vs-funcref-multi (result funcref) + (table.get $$t2 (i32.const 0)) + ) + )`), + `type mismatch`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/table_grow.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/table_grow.wast.js new file mode 100644 index 0000000000..f299984d66 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/table_grow.wast.js @@ -0,0 +1,268 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/table_grow.wast + +// ./test/core/table_grow.wast:1 +let $0 = instantiate(`(module + (table $$t 0 externref) + + (func (export "get") (param $$i i32) (result externref) (table.get $$t (local.get $$i))) + (func (export "set") (param $$i i32) (param $$r externref) (table.set $$t (local.get $$i) (local.get $$r))) + + (func (export "grow") (param $$sz i32) (param $$init externref) (result i32) + (table.grow $$t (local.get $$init) (local.get $$sz)) + ) + (func (export "size") (result i32) (table.size $$t)) +)`); + +// ./test/core/table_grow.wast:13 +assert_return(() => invoke($0, `size`, []), [value("i32", 0)]); + +// ./test/core/table_grow.wast:14 +assert_trap(() => invoke($0, `set`, [0, externref(2)]), `out of bounds table access`); + +// ./test/core/table_grow.wast:15 +assert_trap(() => invoke($0, `get`, [0]), `out of bounds table access`); + +// ./test/core/table_grow.wast:17 +assert_return(() => invoke($0, `grow`, [1, null]), [value("i32", 0)]); + +// ./test/core/table_grow.wast:18 +assert_return(() => invoke($0, `size`, []), [value("i32", 1)]); + +// ./test/core/table_grow.wast:19 +assert_return(() => invoke($0, `get`, [0]), [value('externref', null)]); + +// ./test/core/table_grow.wast:20 +assert_return(() => invoke($0, `set`, [0, externref(2)]), []); + +// ./test/core/table_grow.wast:21 +assert_return(() => invoke($0, `get`, [0]), [value('externref', externref(2))]); + +// ./test/core/table_grow.wast:22 +assert_trap(() => invoke($0, `set`, [1, externref(2)]), `out of bounds table access`); + +// ./test/core/table_grow.wast:23 +assert_trap(() => invoke($0, `get`, [1]), `out of bounds table access`); + +// ./test/core/table_grow.wast:25 +assert_return(() => invoke($0, `grow`, [4, externref(3)]), [value("i32", 1)]); + +// ./test/core/table_grow.wast:26 +assert_return(() => invoke($0, `size`, []), [value("i32", 5)]); + +// ./test/core/table_grow.wast:27 +assert_return(() => invoke($0, `get`, [0]), [value('externref', externref(2))]); + +// ./test/core/table_grow.wast:28 +assert_return(() => invoke($0, `set`, [0, externref(2)]), []); + +// ./test/core/table_grow.wast:29 +assert_return(() => invoke($0, `get`, [0]), [value('externref', externref(2))]); + +// ./test/core/table_grow.wast:30 +assert_return(() => invoke($0, `get`, [1]), [value('externref', externref(3))]); + +// ./test/core/table_grow.wast:31 +assert_return(() => invoke($0, `get`, [4]), [value('externref', externref(3))]); + +// ./test/core/table_grow.wast:32 +assert_return(() => invoke($0, `set`, [4, externref(4)]), []); + +// ./test/core/table_grow.wast:33 +assert_return(() => invoke($0, `get`, [4]), [value('externref', externref(4))]); + +// ./test/core/table_grow.wast:34 +assert_trap(() => invoke($0, `set`, [5, externref(2)]), `out of bounds table access`); + +// ./test/core/table_grow.wast:35 +assert_trap(() => invoke($0, `get`, [5]), `out of bounds table access`); + +// ./test/core/table_grow.wast:39 +let $1 = instantiate(`(module + (table $$t 0x10 funcref) + (elem declare func $$f) + (func $$f (export "grow") (result i32) + (table.grow $$t (ref.func $$f) (i32.const 0xffff_fff0)) + ) +)`); + +// ./test/core/table_grow.wast:47 +assert_return(() => invoke($1, `grow`, []), [value("i32", -1)]); + +// ./test/core/table_grow.wast:50 +let $2 = instantiate(`(module + (table $$t 0 externref) + (func (export "grow") (param i32) (result i32) + (table.grow $$t (ref.null extern) (local.get 0)) + ) +)`); + +// ./test/core/table_grow.wast:57 +assert_return(() => invoke($2, `grow`, [0]), [value("i32", 0)]); + +// ./test/core/table_grow.wast:58 +assert_return(() => invoke($2, `grow`, [1]), [value("i32", 0)]); + +// ./test/core/table_grow.wast:59 +assert_return(() => invoke($2, `grow`, [0]), [value("i32", 1)]); + +// ./test/core/table_grow.wast:60 +assert_return(() => invoke($2, `grow`, [2]), [value("i32", 1)]); + +// ./test/core/table_grow.wast:61 +assert_return(() => invoke($2, `grow`, [800]), [value("i32", 3)]); + +// ./test/core/table_grow.wast:64 +let $3 = instantiate(`(module + (table $$t 0 10 externref) + (func (export "grow") (param i32) (result i32) + (table.grow $$t (ref.null extern) (local.get 0)) + ) +)`); + +// ./test/core/table_grow.wast:71 +assert_return(() => invoke($3, `grow`, [0]), [value("i32", 0)]); + +// ./test/core/table_grow.wast:72 +assert_return(() => invoke($3, `grow`, [1]), [value("i32", 0)]); + +// ./test/core/table_grow.wast:73 +assert_return(() => invoke($3, `grow`, [1]), [value("i32", 1)]); + +// ./test/core/table_grow.wast:74 +assert_return(() => invoke($3, `grow`, [2]), [value("i32", 2)]); + +// ./test/core/table_grow.wast:75 +assert_return(() => invoke($3, `grow`, [6]), [value("i32", 4)]); + +// ./test/core/table_grow.wast:76 +assert_return(() => invoke($3, `grow`, [0]), [value("i32", 10)]); + +// ./test/core/table_grow.wast:77 +assert_return(() => invoke($3, `grow`, [1]), [value("i32", -1)]); + +// ./test/core/table_grow.wast:78 +assert_return(() => invoke($3, `grow`, [65536]), [value("i32", -1)]); + +// ./test/core/table_grow.wast:81 +let $4 = instantiate(`(module + (table $$t 10 funcref) + (func (export "grow") (param i32) (result i32) + (table.grow $$t (ref.null func) (local.get 0)) + ) + (elem declare func 1) + (func (export "check-table-null") (param i32 i32) (result funcref) + (local funcref) + (local.set 2 (ref.func 1)) + (block + (loop + (local.set 2 (table.get $$t (local.get 0))) + (br_if 1 (i32.eqz (ref.is_null (local.get 2)))) + (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) + ) +)`); + +// ./test/core/table_grow.wast:103 +assert_return(() => invoke($4, `check-table-null`, [0, 9]), [value('anyfunc', null)]); + +// ./test/core/table_grow.wast:104 +assert_return(() => invoke($4, `grow`, [10]), [value("i32", 10)]); + +// ./test/core/table_grow.wast:105 +assert_return(() => invoke($4, `check-table-null`, [0, 19]), [value('anyfunc', null)]); + +// ./test/core/table_grow.wast:110 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-init-size-empty-vs-i32-externref (result i32) + (table.grow $$t) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:119 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-size-empty-vs-i32 (result i32) + (table.grow $$t (ref.null extern)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:128 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-init-empty-vs-externref (result i32) + (table.grow $$t (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:137 +assert_invalid( + () => instantiate(`(module + (table $$t 0 externref) + (func $$type-size-f32-vs-i32 (result i32) + (table.grow $$t (ref.null extern) (f32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:146 +assert_invalid( + () => instantiate(`(module + (table $$t 0 funcref) + (func $$type-init-externref-vs-funcref (param $$r externref) (result i32) + (table.grow $$t (local.get $$r) (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:156 +assert_invalid( + () => instantiate(`(module + (table $$t 1 externref) + (func $$type-result-i32-vs-empty + (table.grow $$t (ref.null extern) (i32.const 0)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_grow.wast:165 +assert_invalid( + () => instantiate(`(module + (table $$t 1 externref) + (func $$type-result-i32-vs-f32 (result f32) + (table.grow $$t (ref.null extern) (i32.const 0)) + ) + )`), + `type mismatch`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/table_set.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/table_set.wast.js new file mode 100644 index 0000000000..b44fcfc002 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/table_set.wast.js @@ -0,0 +1,177 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/table_set.wast + +// ./test/core/table_set.wast:1 +let $0 = instantiate(`(module + (table $$t2 1 externref) + (table $$t3 2 funcref) + (elem (table $$t3) (i32.const 1) func $$dummy) + (func $$dummy) + + (func (export "get-externref") (param $$i i32) (result externref) + (table.get $$t2 (local.get $$i)) + ) + (func $$f3 (export "get-funcref") (param $$i i32) (result funcref) + (table.get $$t3 (local.get $$i)) + ) + + (func (export "set-externref") (param $$i i32) (param $$r externref) + (table.set $$t2 (local.get $$i) (local.get $$r)) + ) + (func (export "set-funcref") (param $$i i32) (param $$r funcref) + (table.set $$t3 (local.get $$i) (local.get $$r)) + ) + (func (export "set-funcref-from") (param $$i i32) (param $$j i32) + (table.set $$t3 (local.get $$i) (table.get $$t3 (local.get $$j))) + ) + + (func (export "is_null-funcref") (param $$i i32) (result i32) + (ref.is_null (call $$f3 (local.get $$i))) + ) +)`); + +// ./test/core/table_set.wast:29 +assert_return(() => invoke($0, `get-externref`, [0]), [value('externref', null)]); + +// ./test/core/table_set.wast:30 +assert_return(() => invoke($0, `set-externref`, [0, externref(1)]), []); + +// ./test/core/table_set.wast:31 +assert_return(() => invoke($0, `get-externref`, [0]), [value('externref', externref(1))]); + +// ./test/core/table_set.wast:32 +assert_return(() => invoke($0, `set-externref`, [0, null]), []); + +// ./test/core/table_set.wast:33 +assert_return(() => invoke($0, `get-externref`, [0]), [value('externref', null)]); + +// ./test/core/table_set.wast:35 +assert_return(() => invoke($0, `get-funcref`, [0]), [value('anyfunc', null)]); + +// ./test/core/table_set.wast:36 +assert_return(() => invoke($0, `set-funcref-from`, [0, 1]), []); + +// ./test/core/table_set.wast:37 +assert_return(() => invoke($0, `is_null-funcref`, [0]), [value("i32", 0)]); + +// ./test/core/table_set.wast:38 +assert_return(() => invoke($0, `set-funcref`, [0, null]), []); + +// ./test/core/table_set.wast:39 +assert_return(() => invoke($0, `get-funcref`, [0]), [value('anyfunc', null)]); + +// ./test/core/table_set.wast:41 +assert_trap(() => invoke($0, `set-externref`, [2, null]), `out of bounds table access`); + +// ./test/core/table_set.wast:42 +assert_trap(() => invoke($0, `set-funcref`, [3, null]), `out of bounds table access`); + +// ./test/core/table_set.wast:43 +assert_trap(() => invoke($0, `set-externref`, [-1, null]), `out of bounds table access`); + +// ./test/core/table_set.wast:44 +assert_trap(() => invoke($0, `set-funcref`, [-1, null]), `out of bounds table access`); + +// ./test/core/table_set.wast:46 +assert_trap(() => invoke($0, `set-externref`, [2, externref(0)]), `out of bounds table access`); + +// ./test/core/table_set.wast:47 +assert_trap(() => invoke($0, `set-funcref-from`, [3, 1]), `out of bounds table access`); + +// ./test/core/table_set.wast:48 +assert_trap(() => invoke($0, `set-externref`, [-1, externref(0)]), `out of bounds table access`); + +// ./test/core/table_set.wast:49 +assert_trap(() => invoke($0, `set-funcref-from`, [-1, 1]), `out of bounds table access`); + +// ./test/core/table_set.wast:54 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-value-empty-vs-i32-externref + (table.set $$t) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:63 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-index-empty-vs-i32 + (table.set $$t (ref.null extern)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:72 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-value-empty-vs-externref + (table.set $$t (i32.const 1)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:81 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-size-f32-vs-i32 + (table.set $$t (f32.const 1) (ref.null extern)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:90 +assert_invalid( + () => instantiate(`(module + (table $$t 10 funcref) + (func $$type-value-externref-vs-funcref (param $$r externref) + (table.set $$t (i32.const 1) (local.get $$r)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:100 +assert_invalid( + () => instantiate(`(module + (table $$t1 1 externref) + (table $$t2 1 funcref) + (func $$type-value-externref-vs-funcref-multi (param $$r externref) + (table.set $$t2 (i32.const 0) (local.get $$r)) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_set.wast:111 +assert_invalid( + () => instantiate(`(module + (table $$t 10 externref) + (func $$type-result-empty-vs-num (result i32) + (table.set $$t (i32.const 0) (ref.null extern)) + ) + )`), + `type mismatch`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/table_size.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/table_size.wast.js new file mode 100644 index 0000000000..1a574c2ba9 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/table_size.wast.js @@ -0,0 +1,172 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/table_size.wast + +// ./test/core/table_size.wast:1 +let $0 = instantiate(`(module + (table $$t0 0 externref) + (table $$t1 1 externref) + (table $$t2 0 2 externref) + (table $$t3 3 8 externref) + + (func (export "size-t0") (result i32) (table.size $$t0)) + (func (export "size-t1") (result i32) (table.size $$t1)) + (func (export "size-t2") (result i32) (table.size $$t2)) + (func (export "size-t3") (result i32) (table.size $$t3)) + + (func (export "grow-t0") (param $$sz i32) + (drop (table.grow $$t0 (ref.null extern) (local.get $$sz))) + ) + (func (export "grow-t1") (param $$sz i32) + (drop (table.grow $$t1 (ref.null extern) (local.get $$sz))) + ) + (func (export "grow-t2") (param $$sz i32) + (drop (table.grow $$t2 (ref.null extern) (local.get $$sz))) + ) + (func (export "grow-t3") (param $$sz i32) + (drop (table.grow $$t3 (ref.null extern) (local.get $$sz))) + ) +)`); + +// ./test/core/table_size.wast:26 +assert_return(() => invoke($0, `size-t0`, []), [value("i32", 0)]); + +// ./test/core/table_size.wast:27 +assert_return(() => invoke($0, `grow-t0`, [1]), []); + +// ./test/core/table_size.wast:28 +assert_return(() => invoke($0, `size-t0`, []), [value("i32", 1)]); + +// ./test/core/table_size.wast:29 +assert_return(() => invoke($0, `grow-t0`, [4]), []); + +// ./test/core/table_size.wast:30 +assert_return(() => invoke($0, `size-t0`, []), [value("i32", 5)]); + +// ./test/core/table_size.wast:31 +assert_return(() => invoke($0, `grow-t0`, [0]), []); + +// ./test/core/table_size.wast:32 +assert_return(() => invoke($0, `size-t0`, []), [value("i32", 5)]); + +// ./test/core/table_size.wast:34 +assert_return(() => invoke($0, `size-t1`, []), [value("i32", 1)]); + +// ./test/core/table_size.wast:35 +assert_return(() => invoke($0, `grow-t1`, [1]), []); + +// ./test/core/table_size.wast:36 +assert_return(() => invoke($0, `size-t1`, []), [value("i32", 2)]); + +// ./test/core/table_size.wast:37 +assert_return(() => invoke($0, `grow-t1`, [4]), []); + +// ./test/core/table_size.wast:38 +assert_return(() => invoke($0, `size-t1`, []), [value("i32", 6)]); + +// ./test/core/table_size.wast:39 +assert_return(() => invoke($0, `grow-t1`, [0]), []); + +// ./test/core/table_size.wast:40 +assert_return(() => invoke($0, `size-t1`, []), [value("i32", 6)]); + +// ./test/core/table_size.wast:42 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 0)]); + +// ./test/core/table_size.wast:43 +assert_return(() => invoke($0, `grow-t2`, [3]), []); + +// ./test/core/table_size.wast:44 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 0)]); + +// ./test/core/table_size.wast:45 +assert_return(() => invoke($0, `grow-t2`, [1]), []); + +// ./test/core/table_size.wast:46 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 1)]); + +// ./test/core/table_size.wast:47 +assert_return(() => invoke($0, `grow-t2`, [0]), []); + +// ./test/core/table_size.wast:48 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 1)]); + +// ./test/core/table_size.wast:49 +assert_return(() => invoke($0, `grow-t2`, [4]), []); + +// ./test/core/table_size.wast:50 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 1)]); + +// ./test/core/table_size.wast:51 +assert_return(() => invoke($0, `grow-t2`, [1]), []); + +// ./test/core/table_size.wast:52 +assert_return(() => invoke($0, `size-t2`, []), [value("i32", 2)]); + +// ./test/core/table_size.wast:54 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 3)]); + +// ./test/core/table_size.wast:55 +assert_return(() => invoke($0, `grow-t3`, [1]), []); + +// ./test/core/table_size.wast:56 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 4)]); + +// ./test/core/table_size.wast:57 +assert_return(() => invoke($0, `grow-t3`, [3]), []); + +// ./test/core/table_size.wast:58 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 7)]); + +// ./test/core/table_size.wast:59 +assert_return(() => invoke($0, `grow-t3`, [0]), []); + +// ./test/core/table_size.wast:60 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 7)]); + +// ./test/core/table_size.wast:61 +assert_return(() => invoke($0, `grow-t3`, [2]), []); + +// ./test/core/table_size.wast:62 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 7)]); + +// ./test/core/table_size.wast:63 +assert_return(() => invoke($0, `grow-t3`, [1]), []); + +// ./test/core/table_size.wast:64 +assert_return(() => invoke($0, `size-t3`, []), [value("i32", 8)]); + +// ./test/core/table_size.wast:69 +assert_invalid( + () => instantiate(`(module + (table $$t 1 externref) + (func $$type-result-i32-vs-empty + (table.size $$t) + ) + )`), + `type mismatch`, +); + +// ./test/core/table_size.wast:78 +assert_invalid( + () => instantiate(`(module + (table $$t 1 externref) + (func $$type-result-i32-vs-f32 (result f32) + (table.size $$t) + ) + )`), + `type mismatch`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/tag.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/tag.wast.js new file mode 100644 index 0000000000..70e75a12d1 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/tag.wast.js @@ -0,0 +1,40 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/tag.wast + +// ./test/core/tag.wast:3 +let $0 = instantiate(`(module + (tag) + (tag (param i32)) + (tag (export "t2") (param i32)) + (tag $$t3 (param i32 f32)) + (export "t3" (tag 3)) +)`); + +// ./test/core/tag.wast:11 +register($0, `test`); + +// ./test/core/tag.wast:13 +let $1 = instantiate(`(module + (tag $$t0 (import "test" "t2") (param i32)) + (import "test" "t3" (tag $$t1 (param i32 f32))) +)`); + +// ./test/core/tag.wast:18 +assert_invalid( + () => instantiate(`(module (tag (result i32)))`), + `non-empty tag result type`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/throw.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/throw.wast.js new file mode 100644 index 0000000000..cb0baf0d4c --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/throw.wast.js @@ -0,0 +1,87 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/throw.wast + +// ./test/core/throw.wast:3 +let $0 = instantiate(`(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))) + ) + ) + ) +)`); + +// ./test/core/throw.wast:37 +assert_return(() => invoke($0, `throw-if`, [0]), [value("i32", 0)]); + +// ./test/core/throw.wast:38 +assert_exception(() => invoke($0, `throw-if`, [10])); + +// ./test/core/throw.wast:39 +assert_exception(() => invoke($0, `throw-if`, [-1])); + +// ./test/core/throw.wast:41 +assert_exception(() => invoke($0, `throw-param-f32`, [value("f32", 5)])); + +// ./test/core/throw.wast:42 +assert_exception(() => invoke($0, `throw-param-i64`, [5n])); + +// ./test/core/throw.wast:43 +assert_exception(() => invoke($0, `throw-param-f64`, [value("f64", 5)])); + +// ./test/core/throw.wast:45 +assert_return(() => invoke($0, `test-throw-1-2`, []), []); + +// ./test/core/throw.wast:47 +assert_invalid(() => instantiate(`(module (func (throw 0)))`), `unknown tag 0`); + +// ./test/core/throw.wast:48 +assert_invalid( + () => instantiate(`(module (tag (param i32)) (func (throw 0)))`), + `type mismatch: instruction requires [i32] but stack has []`, +); + +// ./test/core/throw.wast:50 +assert_invalid( + () => instantiate(`(module (tag (param i32)) (func (i64.const 5) (throw 0)))`), + `type mismatch: instruction requires [i32] but stack has [i64]`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/try_catch.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/try_catch.wast.js new file mode 100644 index 0000000000..ab67fc936c --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/try_catch.wast.js @@ -0,0 +1,318 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/try_catch.wast + +// ./test/core/try_catch.wast:3 +let $0 = instantiate(`(module + (tag $$e0 (export "e0")) + (func (export "throw") (throw $$e0)) +)`); + +// ./test/core/try_catch.wast:8 +register($0, `test`); + +// ./test/core/try_catch.wast:10 +let $1 = instantiate(`(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)) + ) + ) +)`); + +// ./test/core/try_catch.wast:152 +assert_return(() => invoke($1, `empty-catch`, []), []); + +// ./test/core/try_catch.wast:154 +assert_return(() => invoke($1, `simple-throw-catch`, [0]), [value("i32", 23)]); + +// ./test/core/try_catch.wast:155 +assert_return(() => invoke($1, `simple-throw-catch`, [1]), [value("i32", 42)]); + +// ./test/core/try_catch.wast:157 +assert_trap(() => invoke($1, `unreachable-not-caught`, []), `unreachable`); + +// ./test/core/try_catch.wast:159 +assert_return(() => invoke($1, `trap-in-callee`, [7, 2]), [value("i32", 3)]); + +// ./test/core/try_catch.wast:160 +assert_trap(() => invoke($1, `trap-in-callee`, [1, 0]), `integer divide by zero`); + +// ./test/core/try_catch.wast:162 +assert_return(() => invoke($1, `catch-complex-1`, [0]), [value("i32", 3)]); + +// ./test/core/try_catch.wast:163 +assert_return(() => invoke($1, `catch-complex-1`, [1]), [value("i32", 4)]); + +// ./test/core/try_catch.wast:164 +assert_exception(() => invoke($1, `catch-complex-1`, [2])); + +// ./test/core/try_catch.wast:166 +assert_return(() => invoke($1, `catch-complex-2`, [0]), [value("i32", 3)]); + +// ./test/core/try_catch.wast:167 +assert_return(() => invoke($1, `catch-complex-2`, [1]), [value("i32", 4)]); + +// ./test/core/try_catch.wast:168 +assert_exception(() => invoke($1, `catch-complex-2`, [2])); + +// ./test/core/try_catch.wast:170 +assert_return(() => invoke($1, `throw-catch-param-i32`, [0]), [value("i32", 0)]); + +// ./test/core/try_catch.wast:171 +assert_return(() => invoke($1, `throw-catch-param-i32`, [1]), [value("i32", 1)]); + +// ./test/core/try_catch.wast:172 +assert_return(() => invoke($1, `throw-catch-param-i32`, [10]), [value("i32", 10)]); + +// ./test/core/try_catch.wast:174 +assert_return(() => invoke($1, `throw-catch-param-f32`, [value("f32", 5)]), [value("f32", 5)]); + +// ./test/core/try_catch.wast:175 +assert_return(() => invoke($1, `throw-catch-param-f32`, [value("f32", 10.5)]), [value("f32", 10.5)]); + +// ./test/core/try_catch.wast:177 +assert_return(() => invoke($1, `throw-catch-param-i64`, [5n]), [value("i64", 5n)]); + +// ./test/core/try_catch.wast:178 +assert_return(() => invoke($1, `throw-catch-param-i64`, [0n]), [value("i64", 0n)]); + +// ./test/core/try_catch.wast:179 +assert_return(() => invoke($1, `throw-catch-param-i64`, [-1n]), [value("i64", -1n)]); + +// ./test/core/try_catch.wast:181 +assert_return(() => invoke($1, `throw-catch-param-f64`, [value("f64", 5)]), [value("f64", 5)]); + +// ./test/core/try_catch.wast:182 +assert_return(() => invoke($1, `throw-catch-param-f64`, [value("f64", 10.5)]), [value("f64", 10.5)]); + +// ./test/core/try_catch.wast:184 +assert_return(() => invoke($1, `catch-param-i32`, [5]), [value("i32", 5)]); + +// ./test/core/try_catch.wast:186 +assert_return(() => invoke($1, `catch-imported`, []), [value("i32", 2)]); + +// ./test/core/try_catch.wast:188 +assert_return(() => invoke($1, `catchless-try`, [0]), [value("i32", 0)]); + +// ./test/core/try_catch.wast:189 +assert_return(() => invoke($1, `catchless-try`, [1]), [value("i32", 1)]); + +// ./test/core/try_catch.wast:191 +let $2 = instantiate(`(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)) + ) + ) +)`); + +// ./test/core/try_catch.wast:211 +assert_return(() => invoke($2, `imported-mismatch`, []), [value("i32", 3)]); + +// ./test/core/try_catch.wast:213 +assert_malformed(() => instantiate(`(module (func (catch_all))) `), `unexpected token`); + +// ./test/core/try_catch.wast:218 +assert_malformed( + () => instantiate(`(module (tag $$e) (func (catch $$e))) `), + `unexpected token`, +); + +// ./test/core/try_catch.wast:223 +assert_malformed( + () => instantiate(`(module (func (try (do) (catch_all) (catch_all)))) `), + `unexpected token`, +); + +// ./test/core/try_catch.wast:230 +assert_invalid( + () => instantiate(`(module (func (result i32) (try (result i32) (do))))`), + `type mismatch: instruction requires [i32] but stack has []`, +); + +// ./test/core/try_catch.wast:232 +assert_invalid( + () => instantiate(`(module (func (result i32) (try (result i32) (do (i64.const 42)))))`), + `type mismatch: instruction requires [i32] but stack has [i64]`, +); + +// ./test/core/try_catch.wast:234 +assert_invalid( + () => instantiate(`(module (tag) (func (try (do) (catch 0 (i32.const 42)))))`), + `type mismatch: block requires [] but stack has [i32]`, +); + +// ./test/core/try_catch.wast:236 +assert_invalid( + () => instantiate(`(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]`, +); + +// ./test/core/try_catch.wast:241 +assert_invalid( + () => instantiate(`(module (func (try (do) (catch_all (i32.const 42)))))`), + `type mismatch: block requires [] but stack has [i32]`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/try_delegate.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/try_delegate.wast.js new file mode 100644 index 0000000000..83400f02f5 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/try_delegate.wast.js @@ -0,0 +1,177 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/try_delegate.wast + +// ./test/core/try_delegate.wast:3 +let $0 = instantiate(`(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") + (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)) + ) + ) +)`); + +// ./test/core/try_delegate.wast:97 +assert_return(() => invoke($0, `delegate-no-throw`, []), [value("i32", 1)]); + +// ./test/core/try_delegate.wast:99 +assert_return(() => invoke($0, `delegate-throw`, [0]), [value("i32", 1)]); + +// ./test/core/try_delegate.wast:100 +assert_return(() => invoke($0, `delegate-throw`, [1]), [value("i32", 2)]); + +// ./test/core/try_delegate.wast:102 +assert_exception(() => invoke($0, `delegate-throw-no-catch`, [])); + +// ./test/core/try_delegate.wast:104 +assert_return(() => invoke($0, `delegate-merge`, [1, 0]), [value("i32", 2)]); + +// ./test/core/try_delegate.wast:105 +assert_exception(() => invoke($0, `delegate-merge`, [2, 0])); + +// ./test/core/try_delegate.wast:106 +assert_return(() => invoke($0, `delegate-merge`, [0, 1]), [value("i32", 2)]); + +// ./test/core/try_delegate.wast:107 +assert_exception(() => invoke($0, `delegate-merge`, [0, 2])); + +// ./test/core/try_delegate.wast:108 +assert_return(() => invoke($0, `delegate-merge`, [0, 0]), [value("i32", 1)]); + +// ./test/core/try_delegate.wast:110 +assert_return(() => invoke($0, `delegate-skip`, []), [value("i32", 3)]); + +// ./test/core/try_delegate.wast:112 +assert_return(() => invoke($0, `delegate-to-block`, []), [value("i32", 1)]); + +// ./test/core/try_delegate.wast:113 +assert_return(() => invoke($0, `delegate-to-catch`, []), [value("i32", 1)]); + +// ./test/core/try_delegate.wast:115 +assert_exception(() => invoke($0, `delegate-to-caller`, [])); + +// ./test/core/try_delegate.wast:117 +assert_malformed(() => instantiate(`(module (func (delegate 0))) `), `unexpected token`); + +// ./test/core/try_delegate.wast:122 +assert_malformed( + () => instantiate(`(module (tag $$e) (func (try (do) (catch $$e) (delegate 0)))) `), + `unexpected token`, +); + +// ./test/core/try_delegate.wast:127 +assert_malformed( + () => instantiate(`(module (func (try (do) (catch_all) (delegate 0)))) `), + `unexpected token`, +); + +// ./test/core/try_delegate.wast:132 +assert_malformed( + () => instantiate(`(module (func (try (do) (delegate) (delegate 0)))) `), + `unexpected token`, +); + +// ./test/core/try_delegate.wast:137 +assert_invalid( + () => instantiate(`(module (func (try (do) (delegate 1))))`), + `unknown label`, +); diff --git a/js/src/jit-test/tests/wasm/spec/exception-handling/unreached-valid.wast.js b/js/src/jit-test/tests/wasm/spec/exception-handling/unreached-valid.wast.js new file mode 100644 index 0000000000..20ee3b42c7 --- /dev/null +++ b/js/src/jit-test/tests/wasm/spec/exception-handling/unreached-valid.wast.js @@ -0,0 +1,85 @@ +/* Copyright 2021 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ./test/core/unreached-valid.wast + +// ./test/core/unreached-valid.wast:1 +let $0 = instantiate(`(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_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))) + ) + + (func (export "unreachable-num") + (unreachable) + (select) + (i32.eqz) + (drop) + ) + (func (export "unreachable-ref") + (unreachable) + (select) + (ref.is_null) + (drop) + ) +)`); + +// ./test/core/unreached-valid.wast:42 +assert_trap(() => invoke($0, `select-trap-left`, [1]), `unreachable`); + +// ./test/core/unreached-valid.wast:43 +assert_trap(() => invoke($0, `select-trap-left`, [0]), `unreachable`); + +// ./test/core/unreached-valid.wast:44 +assert_trap(() => invoke($0, `select-trap-right`, [1]), `unreachable`); + +// ./test/core/unreached-valid.wast:45 +assert_trap(() => invoke($0, `select-trap-right`, [0]), `unreachable`); + +// ./test/core/unreached-valid.wast:49 +let $1 = instantiate(`(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) + ) +)`); -- cgit v1.2.3