summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorThomas Lively <tlively@google.com>2024-12-13 13:23:42 -0800
committerGitHub <noreply@github.com>2024-12-13 13:23:42 -0800
commit8a88ba280b2847d4d25d0859a87529e2132ebab8 (patch)
treea4723dbd4f43b1b01b8bcc3bcdbf5f80f7d93d4a /test
parent52bc45fc34ec6868400216074744147e9d922685 (diff)
downloadbinaryen-8a88ba280b2847d4d25d0859a87529e2132ebab8.tar.gz
binaryen-8a88ba280b2847d4d25d0859a87529e2132ebab8.tar.bz2
binaryen-8a88ba280b2847d4d25d0859a87529e2132ebab8.zip
Support control flow inputs in IRBuilder (#7149)
Since multivalue was standardized, WebAssembly has supported not only multiple results but also an arbitrary number of inputs on control flow structures, but until now Binaryen did not support control flow input. Binaryen IR still has no way to represent control flow input, so lower it away using scratch locals in IRBuilder. Since both the text and binary parsers use IRBuilder, this gives us full support for parsing control flow inputs. The lowering scheme is mostly simple. A local.set writing the control flow inputs to a scratch local is inserted immediately before the control flow structure begins and a local.get retrieving those inputs is inserted inside the control flow structure before the rest of its body. The only complications come from ifs, in which the inputs must be retrieved at the beginning of both arms, and from loops, where branches to the beginning of the loop must be transformed so their values are written to the scratch local along the way. Resolves #6407.
Diffstat (limited to 'test')
-rw-r--r--test/lit/binary/bad-multivalue-block.test16
-rw-r--r--test/lit/binary/bad-multivalue-block.test.wasmbin34 -> 0 bytes
-rw-r--r--test/lit/binary/bad-multivalue-if.test22
-rw-r--r--test/lit/binary/bad-multivalue-if.test.wasmbin38 -> 0 bytes
-rw-r--r--test/lit/control-flow-input.wast623
-rw-r--r--test/lit/control-flow-input.wast.wasmbin0 -> 793 bytes
-rw-r--r--test/lit/parse-bad-block-params.wast12
7 files changed, 623 insertions, 50 deletions
diff --git a/test/lit/binary/bad-multivalue-block.test b/test/lit/binary/bad-multivalue-block.test
deleted file mode 100644
index 8b100fe89..000000000
--- a/test/lit/binary/bad-multivalue-block.test
+++ /dev/null
@@ -1,16 +0,0 @@
-;; Test that we error properly on a block with a bad multivalue (inputs).
-
-;; File contents:
-;;
-;; (module
-;; (func $test
-;; i32.const 0
-;; (block (param i32)
-;; drop
-;; )
-;; )
-;; )
-
-;; RUN: not wasm-opt -all %s.wasm 2>&1 | filecheck %s
-
-;; CHECK: control flow inputs are not supported yet
diff --git a/test/lit/binary/bad-multivalue-block.test.wasm b/test/lit/binary/bad-multivalue-block.test.wasm
deleted file mode 100644
index e44b9033f..000000000
--- a/test/lit/binary/bad-multivalue-block.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/binary/bad-multivalue-if.test b/test/lit/binary/bad-multivalue-if.test
deleted file mode 100644
index 8fe206012..000000000
--- a/test/lit/binary/bad-multivalue-if.test
+++ /dev/null
@@ -1,22 +0,0 @@
-;; Test that we error properly on an if with a bad multivalue (inputs).
-
-;; File contents:
-;;
-;; (module
-;; (func $test
-;; i32.const 0
-;; i32.const 1
-;; (if (param i32)
-;; (then
-;; drop
-;; )
-;; (else
-;; drop
-;; )
-;; )
-;; )
-;; )
-
-;; RUN: not wasm-opt -all %s.wasm 2>&1 | filecheck %s
-
-;; CHECK: control flow inputs are not supported yet
diff --git a/test/lit/binary/bad-multivalue-if.test.wasm b/test/lit/binary/bad-multivalue-if.test.wasm
deleted file mode 100644
index baddfec4e..000000000
--- a/test/lit/binary/bad-multivalue-if.test.wasm
+++ /dev/null
Binary files differ
diff --git a/test/lit/control-flow-input.wast b/test/lit/control-flow-input.wast
new file mode 100644
index 000000000..7baae35f0
--- /dev/null
+++ b/test/lit/control-flow-input.wast
@@ -0,0 +1,623 @@
+;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
+
+;; Check that control flow input is correctly parsed using scratch locals. The
+;; binary input file is generated from this file using WABT's wat2wasm
+;; --enable-all --debug-names and should be regenerated when new tests are added
+;; here.
+
+;; RUN: wasm-opt -all %s -S -o - | filecheck %s
+;; RUN: wasm-opt -all %s.wasm -S -o - | filecheck %s
+
+(module
+ (type $id (func (param i32) (result i32)))
+
+ ;; CHECK: (tag $e (param i32))
+ (tag $e (param i32))
+
+ ;; CHECK: (func $block (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block (result i32)
+ i32.const 0
+ block (param i32) (result i32)
+ end
+ )
+
+ ;; CHECK: (func $block-multivalue (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local $scratch (tuple i32 i64))
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block-multivalue (result i32 i64)
+ i32.const 0
+ i64.const 1
+ block (param i32 i64) (result i32 i64)
+ end
+ )
+
+ ;; CHECK: (func $block-drop (type $2)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block-drop
+ i32.const 0
+ block (param i32)
+ drop
+ end
+ )
+
+ ;; CHECK: (func $block-multivalue-drop (type $2)
+ ;; CHECK-NEXT: (local $scratch (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_1 (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_2 i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.set $scratch_2
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.tee $scratch_1
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $scratch_1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $scratch_2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block-multivalue-drop
+ i32.const 0
+ i64.const 1
+ block (param i32 i64)
+ drop
+ drop
+ end
+ )
+
+ ;; CHECK: (func $block-passthrough-nop (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local $scratch_1 i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.set $scratch_1
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (nop)
+ ;; CHECK-NEXT: (local.get $scratch_1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block-passthrough-nop (result i32)
+ i32.const 0
+ block (param i32) (result i32)
+ nop
+ end
+ )
+
+ ;; CHECK: (func $block-passthrough-type (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $block-passthrough-type (result i32)
+ i32.const 0
+ block (type $id)
+ end
+ )
+
+ ;; CHECK: (func $loop (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop (result i32)
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $loop (result i32)
+ i32.const 0
+ loop (param i32) (result i32)
+ end
+ )
+
+ ;; CHECK: (func $loop-branch (type $2)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label0
+ ;; CHECK-NEXT: (block $label1
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (block $label (result i32)
+ ;; CHECK-NEXT: (br $label
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $loop-branch
+ i32.const 0
+ loop (param i32)
+ br 0
+ end
+ )
+
+ ;; CHECK: (func $loop-branch-cond (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label0 (result i32)
+ ;; CHECK-NEXT: (block $label1 (result i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (block $label (result i32)
+ ;; CHECK-NEXT: (br $label1
+ ;; CHECK-NEXT: (br_if $label
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $loop-branch-cond (result i32)
+ i32.const 0
+ loop (param i32) (result i32)
+ i32.const 1
+ br_if 0
+ end
+ )
+
+ ;; CHECK: (func $loop-branch-cond-drop (type $2)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label0
+ ;; CHECK-NEXT: (block $label1
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (block $label (result i32)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (br_if $label
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $loop-branch-cond-drop
+ i32.const 0
+ loop (param i32)
+ i32.const 1
+ br_if 0
+ drop
+ end
+ )
+
+ ;; CHECK: (func $loop-branch-cond-new-val (type $4) (result i64)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label0 (result i64)
+ ;; CHECK-NEXT: (block $label1 (result i64)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (block $label (result i32)
+ ;; CHECK-NEXT: (br $label1
+ ;; CHECK-NEXT: (block (result i64)
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (br_if $label
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i64.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $loop-branch-cond-new-val (result i64)
+ i32.const 0
+ loop (param i32) (result i64)
+ i32.const 1
+ br_if 0
+ drop
+ i64.const 2
+ end
+ )
+
+ ;; CHECK: (func $nested-loops-multivalue (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local $scratch (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_1 (tuple i32 i64))
+ ;; CHECK-NEXT: (block $label2 (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label10
+ ;; CHECK-NEXT: (block $label11
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (block $label1 (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local.set $scratch_1
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (loop $label0
+ ;; CHECK-NEXT: (block $label3
+ ;; CHECK-NEXT: (local.set $scratch_1
+ ;; CHECK-NEXT: (block $label (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (br_table $label $label1 $label2
+ ;; CHECK-NEXT: (local.get $scratch_1)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label11)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (br $label10)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (unreachable)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $nested-loops-multivalue (result i32 i64)
+ i32.const 0
+ i64.const 1
+ loop (param i32 i64)
+ loop (param i32 i64)
+ i32.const 2
+ br_table 0 1 2
+ end
+ end
+ unreachable
+ )
+
+ ;; CHECK: (func $if (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if (result i32)
+ i32.const 0
+ i32.const 1
+ if (param i32) (result i32)
+ end
+ )
+
+ ;; CHECK: (func $if-new-val (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-new-val (result i32)
+ i32.const 0
+ i32.const 1
+ if (param i32) (result i32)
+ drop
+ i32.const 2
+ end
+ )
+
+ ;; CHECK: (func $if-multivalue (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (local $scratch (tuple i32 i64))
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (type $1) (result i32 i64)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-multivalue (result i32 i64)
+ i32.const 0
+ i64.const 1
+ i32.const 2
+ if (param i32 i64) (result i32 i64)
+ end
+ )
+
+ ;; CHECK: (func $if-else (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (result i32)
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-else (result i32)
+ i32.const 0
+ i32.const 1
+ if (param i32) (result i32)
+ else
+ end
+ )
+
+ ;; CHECK: (func $if-else-drop (type $2)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-else-drop
+ i32.const 0
+ i32.const 1
+ if (param i32)
+ drop
+ else
+ drop
+ end
+ )
+
+ ;; CHECK: (func $if-else-multivalue (type $5) (result f32)
+ ;; CHECK-NEXT: (local $scratch (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_1 (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_2 i32)
+ ;; CHECK-NEXT: (local $scratch_3 (tuple i32 i64))
+ ;; CHECK-NEXT: (local $scratch_4 i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (tuple.make 2
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: (i64.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (if (result f32)
+ ;; CHECK-NEXT: (i32.const 2)
+ ;; CHECK-NEXT: (then
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.set $scratch_2
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.tee $scratch_1
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $scratch_1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $scratch_2)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (f32.const 3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (else
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (block (result i32)
+ ;; CHECK-NEXT: (local.set $scratch_4
+ ;; CHECK-NEXT: (tuple.extract 2 0
+ ;; CHECK-NEXT: (local.tee $scratch_3
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (drop
+ ;; CHECK-NEXT: (tuple.extract 2 1
+ ;; CHECK-NEXT: (local.get $scratch_3)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (local.get $scratch_4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (f32.const 4)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $if-else-multivalue (result f32)
+ i32.const 0
+ i64.const 1
+ i32.const 2
+ if (param i32 i64) (result f32)
+ drop
+ drop
+ f32.const 3
+ else
+ drop
+ drop
+ f32.const 4
+ end
+ )
+
+ ;; CHECK: (func $try (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try (result i32)
+ i32.const 0
+ try (param i32) (result i32)
+ end
+ )
+
+ ;; CHECK: (func $try-catch (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch $e
+ ;; CHECK-NEXT: (pop i32)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-catch (result i32)
+ i32.const 0
+ try (param i32) (result i32)
+ catch $e
+ end
+ )
+
+ ;; CHECK: (func $try-catch-all (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (catch_all
+ ;; CHECK-NEXT: (i32.const 1)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-catch-all (result i32)
+ i32.const 0
+ try (param i32) (result i32)
+ catch_all
+ i32.const 1
+ end
+ )
+
+ ;; CHECK: (func $try-catch-delegate (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try (result i32)
+ ;; CHECK-NEXT: (do
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (delegate 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-catch-delegate (result i32)
+ i32.const 0
+ try (param i32) (result i32)
+ delegate 0
+ )
+
+ ;; CHECK: (func $try-table (type $0) (result i32)
+ ;; CHECK-NEXT: (local $scratch i32)
+ ;; CHECK-NEXT: (local.set $scratch
+ ;; CHECK-NEXT: (i32.const 0)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: (try_table (result i32)
+ ;; CHECK-NEXT: (local.get $scratch)
+ ;; CHECK-NEXT: )
+ ;; CHECK-NEXT: )
+ (func $try-table (result i32)
+ i32.const 0
+ try_table (param i32) (result i32)
+ end
+ )
+)
diff --git a/test/lit/control-flow-input.wast.wasm b/test/lit/control-flow-input.wast.wasm
new file mode 100644
index 000000000..664d1be84
--- /dev/null
+++ b/test/lit/control-flow-input.wast.wasm
Binary files differ
diff --git a/test/lit/parse-bad-block-params.wast b/test/lit/parse-bad-block-params.wast
deleted file mode 100644
index 67e05989c..000000000
--- a/test/lit/parse-bad-block-params.wast
+++ /dev/null
@@ -1,12 +0,0 @@
-;; RUN: not wasm-opt %s -S -o - 2>&1 | filecheck %s
-
-;; CHECK: 8:11: error: block parameters not yet supported
-
-(module
- (func
- (i32.const 0)
- (block (param i32)
- (drop)
- )
- )
-)