From 10b32d661108fb4ec2cb32cf36a074e67455f89e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Sat, 30 Jan 2016 20:37:09 -0800 Subject: [PATCH 1/8] Put br_if conditions last. This implements the second half of https://github.com/WebAssembly/design/pull/489. Desugaring br_if to if+break was fairly awkward; adding br_if to the kernel language was straightforward and avoided the awkwardness. This change happened to expose an aspect of `br_if`'s type checking which differed from my expectations, so I've taken the liberty of fixing that too. See the deleted assert_invalid in test/labels.wast and the added $br_if1 testcase. `br_if` either sends its value to the destination label or to its own result. --- ml-proto/host/parser.mly | 3 ++- ml-proto/spec/ast.ml | 2 +- ml-proto/spec/check.ml | 5 +++++ ml-proto/spec/desugar.ml | 6 ++++-- ml-proto/spec/eval.ml | 5 +++++ ml-proto/spec/kernel.ml | 1 + ml-proto/test/labels.wast | 20 +++++++++++++------- 7 files changed, 31 insertions(+), 11 deletions(-) diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index 9d92550205..9da657ac37 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -233,7 +233,8 @@ expr1 : | LOOP labeling1 labeling1 expr_list { fun c -> let c' = $2 c in let c'' = $3 c' in Loop ($4 c'') } | BR var expr_opt { fun c -> Br ($2 c label, $3 c) } - | BR_IF expr var expr_opt { fun c -> Br_if ($2 c, $3 c label, $4 c) } + | BR_IF expr var { fun c -> Br_if (None, $2 c, $3 c label) } + | BR_IF expr expr var { fun c -> Br_if (Some ($2 c), $3 c, $4 c label) } | RETURN expr_opt { let at1 = ati 1 in fun c -> Return (label c ("return" @@ at1) @@ at1, $2 c) } diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index 086837736d..0b2239c043 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -19,7 +19,7 @@ and expr' = | Block of expr list | Loop of expr list | Br of var * expr option - | Br_if of expr * var * expr option + | Br_if of expr option * expr * var | Return of var * expr option | If of expr * expr | If_else of expr * expr * expr diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index fdd19b6830..f170b48b5e 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -133,6 +133,11 @@ let rec check_expr c et e = | Break (x, eo) -> check_expr_opt c (label c x) eo e.at + | Br_if (eo, e, x) -> + check_expr_opt c (label c x) eo e.at; + check_expr c (Some Int32Type) e; + check_type (label c x) et e.at + | If (e1, e2, e3) -> check_expr c (Some Int32Type) e1; check_expr c et e2; diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index bad75cc63b..4c3024d34e 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -17,6 +17,9 @@ and shift' n = function | Break (x, eo) -> let x' = if x.it < n then x else (x.it + 1) @@ x.at in Break (x', Lib.Option.map (shift n) eo) + | Br_if (eo, e, x) -> + let x' = if x.it < n then x else (x.it + 1) @@ x.at in + Br_if (Lib.Option.map (shift n) eo, shift n e, x') | If (e1, e2, e3) -> If (shift n e1, shift n e2, shift n e3) | Switch (e, xs, x, es) -> Switch (shift n e, xs, x, List.map (shift n) es) | Call (x, es) -> Call (x, List.map (shift n) es) @@ -53,8 +56,7 @@ and expr' at = function | Ast.Block es -> Block (List.map expr es) | Ast.Loop es -> Block [Loop (seq es) @@ at] | Ast.Br (x, eo) -> Break (x, Lib.Option.map expr eo) - | Ast.Br_if (e, x, eo) -> - If (expr e, Break (x, Lib.Option.map expr eo) @@ at, opt eo) + | Ast.Br_if (eo, e, x) -> Br_if (Lib.Option.map expr eo, expr e, x) | Ast.Return (x, eo) -> Break (x, Lib.Option.map expr eo) | Ast.If (e1, e2) -> If (expr e1, expr e2, Nop @@ Source.after e2.at) | Ast.If_else (e1, e2, e3) -> If (expr e1, expr e2, expr e3) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 601fbf0b00..0d53c575ee 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -154,6 +154,11 @@ let rec eval_expr (c : config) (e : expr) = | Break (x, eo) -> raise (label c x (eval_expr_opt c eo)) + | Br_if (eo, e, x) -> + let i = int32 (eval_expr c e) e.at in + let v = eval_expr_opt c eo in + if i <> 0l then raise (label c x (eval_expr_opt c eo)) else v + | If (e1, e2, e3) -> let i = int32 (eval_expr c e1) e1.at in eval_expr c (if i <> 0l then e2 else e3) diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index 36d70484d4..8ce0db28e0 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -82,6 +82,7 @@ and expr' = | Block of expr list (* execute in sequence *) | Loop of expr (* loop header *) | Break of var * expr option (* break to n-th surrounding label *) + | Br_if of expr option * expr * var (* conditional break *) | If of expr * expr * expr (* conditional *) | Switch of expr * var list * var * expr list (* table switch *) | Call of var * expr list (* call function *) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 539f4ef3a3..86c3713295 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -90,7 +90,7 @@ ) ) - (func $br_if (result i32) + (func $br_if0 (result i32) (local $i i32) (set_local $i (i32.const 0)) (block $outer @@ -100,13 +100,16 @@ (br_if (i32.const 1) $inner) (set_local $i (i32.or (get_local $i) (i32.const 0x2))) ) - (br_if (i32.const 0) $outer (set_local $i (i32.or (get_local $i) (i32.const 0x4)))) + (br_if (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (i32.const 0) $outer) (set_local $i (i32.or (get_local $i) (i32.const 0x8))) - (br_if (i32.const 1) $outer (set_local $i (i32.or (get_local $i) (i32.const 0x10)))) + (br_if (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (i32.const 1) $outer) (set_local $i (i32.or (get_local $i) (i32.const 0x20))) ) ) + (func $br_if1 (param i32) (result f32) + (block $l (f32.neg (block $i (br_if (f32.const 3) (get_local 0) $l))))) + (func $misc1 (result i32) (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) ) @@ -123,7 +126,8 @@ (export "loop5" $loop5) (export "switch" $switch) (export "return" $return) - (export "br_if" $br_if) + (export "br_if0" $br_if0) + (export "br_if1" $br_if1) (export "misc1" $misc1) (export "misc2" $misc2) ) @@ -143,11 +147,13 @@ (assert_return (invoke "return" (i32.const 0)) (i32.const 0)) (assert_return (invoke "return" (i32.const 1)) (i32.const 2)) (assert_return (invoke "return" (i32.const 2)) (i32.const 2)) -(assert_return (invoke "br_if") (i32.const 0x1d)) +(assert_return (invoke "br_if0") (i32.const 0x1d)) +(assert_return (invoke "br_if1" (i32.const 0)) (f32.const -3)) +(assert_return (invoke "br_if1" (i32.const 1)) (f32.const 3)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) (assert_invalid (module (func (loop $l (br $l (i32.const 0))))) "arity mismatch") (assert_invalid (module (func (block $l (f32.neg (br_if (i32.const 1) $l)) (nop)))) "type mismatch") -(assert_invalid (module (func (result f32) (block $l (br_if (i32.const 1) $l (f32.const 0))))) "type mismatch") - +(assert_invalid (module (func (result i32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") +(assert_invalid (module (func (param i32) (result i32) (block $l (f32.neg (br_if (f32.const 0) (get_local 0) $l))))) "type mismatch") From a5ab0ac93a9df2ddcf8480e1b4cdb082e11996d2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 15:47:31 -0800 Subject: [PATCH 2/8] Make br_if return (). --- ml-proto/spec/check.ml | 2 +- ml-proto/spec/eval.ml | 2 +- ml-proto/test/labels.wast | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index f170b48b5e..a5fb324bd8 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -136,7 +136,7 @@ let rec check_expr c et e = | Br_if (eo, e, x) -> check_expr_opt c (label c x) eo e.at; check_expr c (Some Int32Type) e; - check_type (label c x) et e.at + check_type None et e.at | If (e1, e2, e3) -> check_expr c (Some Int32Type) e1; diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 0d53c575ee..b9269657c4 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -157,7 +157,7 @@ let rec eval_expr (c : config) (e : expr) = | Br_if (eo, e, x) -> let i = int32 (eval_expr c e) e.at in let v = eval_expr_opt c eo in - if i <> 0l then raise (label c x (eval_expr_opt c eo)) else v + if i <> 0l then raise (label c x (eval_expr_opt c eo)) else None | If (e1, e2, e3) -> let i = int32 (eval_expr c e1) e1.at in diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 86c3713295..48cce1fc42 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -107,9 +107,6 @@ ) ) - (func $br_if1 (param i32) (result f32) - (block $l (f32.neg (block $i (br_if (f32.const 3) (get_local 0) $l))))) - (func $misc1 (result i32) (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) ) @@ -127,7 +124,6 @@ (export "switch" $switch) (export "return" $return) (export "br_if0" $br_if0) - (export "br_if1" $br_if1) (export "misc1" $misc1) (export "misc2" $misc2) ) @@ -148,12 +144,13 @@ (assert_return (invoke "return" (i32.const 1)) (i32.const 2)) (assert_return (invoke "return" (i32.const 2)) (i32.const 2)) (assert_return (invoke "br_if0") (i32.const 0x1d)) -(assert_return (invoke "br_if1" (i32.const 0)) (f32.const -3)) -(assert_return (invoke "br_if1" (i32.const 1)) (f32.const 3)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) (assert_invalid (module (func (loop $l (br $l (i32.const 0))))) "arity mismatch") (assert_invalid (module (func (block $l (f32.neg (br_if (i32.const 1) $l)) (nop)))) "type mismatch") + +(assert_invalid (module (func (result f32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") (assert_invalid (module (func (result i32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") +(assert_invalid (module (func (block $l (f32.neg (br_if (f32.const 0) (i32.const 1) $l))))) "arity mismatch") (assert_invalid (module (func (param i32) (result i32) (block $l (f32.neg (br_if (f32.const 0) (get_local 0) $l))))) "type mismatch") From 3e02d68ce6a8c31df515234a89cf331eeec1d89e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 16:26:39 -0800 Subject: [PATCH 3/8] Add another test. --- ml-proto/test/labels.wast | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 48cce1fc42..bd19ebbc6a 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -154,3 +154,6 @@ (assert_invalid (module (func (result i32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") (assert_invalid (module (func (block $l (f32.neg (br_if (f32.const 0) (i32.const 1) $l))))) "arity mismatch") (assert_invalid (module (func (param i32) (result i32) (block $l (f32.neg (br_if (f32.const 0) (get_local 0) $l))))) "type mismatch") +(assert_invalid (module (func (param i32) (result f32) + (block $l (f32.neg (block $i (br_if (f32.const 3) (get_local 0) $l)))))) + "type mismatch") From 81b1a30349b86e092918352c7f63baf6de6841b3 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 16:35:04 -0800 Subject: [PATCH 4/8] Fix an unused variable. --- ml-proto/spec/eval.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index b9269657c4..9fe92666f6 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -157,7 +157,7 @@ let rec eval_expr (c : config) (e : expr) = | Br_if (eo, e, x) -> let i = int32 (eval_expr c e) e.at in let v = eval_expr_opt c eo in - if i <> 0l then raise (label c x (eval_expr_opt c eo)) else None + if i <> 0l then raise (label c x v) else None | If (e1, e2, e3) -> let i = int32 (eval_expr c e1) e1.at in From e3d441e662e551e4f0d76eb74027758869e453b9 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 17:09:36 -0800 Subject: [PATCH 5/8] Add the testcase from #227. --- ml-proto/test/labels.wast | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index bd19ebbc6a..dca28925e1 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -107,6 +107,11 @@ ) ) + (func $br_if1 (result i32) + (block $l0 + (br_if (block $l1 (br $l1 (i32.const 1))) (i32.const 1) $l0) + (i32.const 1))) + (func $misc1 (result i32) (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) ) @@ -124,6 +129,7 @@ (export "switch" $switch) (export "return" $return) (export "br_if0" $br_if0) + (export "br_if1" $br_if1) (export "misc1" $misc1) (export "misc2" $misc2) ) @@ -144,6 +150,7 @@ (assert_return (invoke "return" (i32.const 1)) (i32.const 2)) (assert_return (invoke "return" (i32.const 2)) (i32.const 2)) (assert_return (invoke "br_if0") (i32.const 0x1d)) +(assert_return (invoke "br_if1") (i32.const 1)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) From 74cf378b9038af3316ddb9be519335ee97ed4c80 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 17:17:37 -0800 Subject: [PATCH 6/8] Add more tests from related discussions. --- ml-proto/test/labels.wast | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index dca28925e1..6b421d8640 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -112,6 +112,14 @@ (br_if (block $l1 (br $l1 (i32.const 1))) (i32.const 1) $l0) (i32.const 1))) + (func $br_if2 (result i32) + (block $l0 + (if (i32.const 1) + (br $l0 + (block $l1 + (br $l1 (i32.const 1))))) + (i32.const 1))) + (func $misc1 (result i32) (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) ) @@ -130,6 +138,7 @@ (export "return" $return) (export "br_if0" $br_if0) (export "br_if1" $br_if1) + (export "br_if2" $br_if2) (export "misc1" $misc1) (export "misc2" $misc2) ) @@ -151,6 +160,7 @@ (assert_return (invoke "return" (i32.const 2)) (i32.const 2)) (assert_return (invoke "br_if0") (i32.const 0x1d)) (assert_return (invoke "br_if1") (i32.const 1)) +(assert_return (invoke "br_if2") (i32.const 1)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) @@ -164,3 +174,12 @@ (assert_invalid (module (func (param i32) (result f32) (block $l (f32.neg (block $i (br_if (f32.const 3) (get_local 0) $l)))))) "type mismatch") +(assert_invalid (module (func (block $l0 (br_if (nop) (i32.const 1) $l0)))) + "arity mismatch") +(assert_invalid (module (func (result i32) + (block $l0 + (if_else (i32.const 1) + (br $l0 (block $l1 (br $l1 (i32.const 1)))) + (block (block $l1 (br $l1 (i32.const 1))) (nop)) + ) + (i32.const 1)))) "arity mismatch") From 6077e09ed6cd2f024fabd4fa2eeae7d111646a2e Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Thu, 4 Feb 2016 18:04:05 -0800 Subject: [PATCH 7/8] Use the desired evaluation order. --- ml-proto/spec/eval.ml | 2 +- ml-proto/test/labels.wast | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 9fe92666f6..02d72108d8 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -155,8 +155,8 @@ let rec eval_expr (c : config) (e : expr) = raise (label c x (eval_expr_opt c eo)) | Br_if (eo, e, x) -> - let i = int32 (eval_expr c e) e.at in let v = eval_expr_opt c eo in + let i = int32 (eval_expr c e) e.at in if i <> 0l then raise (label c x v) else None | If (e1, e2, e3) -> diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 6b421d8640..15f27eb0aa 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -120,6 +120,16 @@ (br $l1 (i32.const 1))))) (i32.const 1))) + (func $br_if3 (result i32) + (local $i1 i32) + (i32.add (block $l0 + (br_if (set_local $i1 (i32.const 1)) + (set_local $i1 (i32.const 2)) + $l0) + (i32.const 0)) + (i32.const 0)) + (get_local $i1)) + (func $misc1 (result i32) (block $l1 (i32.xor (br $l1 (i32.const 1)) (i32.const 2))) ) @@ -139,6 +149,7 @@ (export "br_if0" $br_if0) (export "br_if1" $br_if1) (export "br_if2" $br_if2) + (export "br_if3" $br_if3) (export "misc1" $misc1) (export "misc2" $misc2) ) @@ -161,6 +172,7 @@ (assert_return (invoke "br_if0") (i32.const 0x1d)) (assert_return (invoke "br_if1") (i32.const 1)) (assert_return (invoke "br_if2") (i32.const 1)) +(assert_return (invoke "br_if3") (i32.const 2)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) From 1f85c51fc26165465b2e415ac4646cb28cbdf8c0 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 5 Feb 2016 08:10:51 -0800 Subject: [PATCH 8/8] Change the position of the label operand, to be consistent with plain br (and calls). --- ml-proto/host/parser.mly | 4 ++-- ml-proto/spec/ast.ml | 2 +- ml-proto/spec/check.ml | 2 +- ml-proto/spec/desugar.ml | 6 +++--- ml-proto/spec/eval.ml | 2 +- ml-proto/spec/kernel.ml | 2 +- ml-proto/test/fac.wast | 4 ++-- ml-proto/test/labels.wast | 30 +++++++++++++++--------------- 8 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index 9da657ac37..24875067b8 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -233,8 +233,8 @@ expr1 : | LOOP labeling1 labeling1 expr_list { fun c -> let c' = $2 c in let c'' = $3 c' in Loop ($4 c'') } | BR var expr_opt { fun c -> Br ($2 c label, $3 c) } - | BR_IF expr var { fun c -> Br_if (None, $2 c, $3 c label) } - | BR_IF expr expr var { fun c -> Br_if (Some ($2 c), $3 c, $4 c label) } + | BR_IF var expr { fun c -> Br_if ($2 c label, None, $3 c) } + | BR_IF var expr expr { fun c -> Br_if ($2 c label, Some ($3 c), $4 c) } | RETURN expr_opt { let at1 = ati 1 in fun c -> Return (label c ("return" @@ at1) @@ at1, $2 c) } diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index 0b2239c043..4154b859e3 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -19,7 +19,7 @@ and expr' = | Block of expr list | Loop of expr list | Br of var * expr option - | Br_if of expr option * expr * var + | Br_if of var * expr option * expr | Return of var * expr option | If of expr * expr | If_else of expr * expr * expr diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index a5fb324bd8..42d9c4f7f1 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -133,7 +133,7 @@ let rec check_expr c et e = | Break (x, eo) -> check_expr_opt c (label c x) eo e.at - | Br_if (eo, e, x) -> + | Br_if (x, eo, e) -> check_expr_opt c (label c x) eo e.at; check_expr c (Some Int32Type) e; check_type None et e.at diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index 4c3024d34e..ebd467528e 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -17,9 +17,9 @@ and shift' n = function | Break (x, eo) -> let x' = if x.it < n then x else (x.it + 1) @@ x.at in Break (x', Lib.Option.map (shift n) eo) - | Br_if (eo, e, x) -> + | Br_if (x, eo, e) -> let x' = if x.it < n then x else (x.it + 1) @@ x.at in - Br_if (Lib.Option.map (shift n) eo, shift n e, x') + Br_if (x', Lib.Option.map (shift n) eo, shift n e) | If (e1, e2, e3) -> If (shift n e1, shift n e2, shift n e3) | Switch (e, xs, x, es) -> Switch (shift n e, xs, x, List.map (shift n) es) | Call (x, es) -> Call (x, List.map (shift n) es) @@ -56,7 +56,7 @@ and expr' at = function | Ast.Block es -> Block (List.map expr es) | Ast.Loop es -> Block [Loop (seq es) @@ at] | Ast.Br (x, eo) -> Break (x, Lib.Option.map expr eo) - | Ast.Br_if (eo, e, x) -> Br_if (Lib.Option.map expr eo, expr e, x) + | Ast.Br_if (x, eo, e) -> Br_if (x, Lib.Option.map expr eo, expr e) | Ast.Return (x, eo) -> Break (x, Lib.Option.map expr eo) | Ast.If (e1, e2) -> If (expr e1, expr e2, Nop @@ Source.after e2.at) | Ast.If_else (e1, e2, e3) -> If (expr e1, expr e2, expr e3) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 02d72108d8..403b0859e7 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -154,7 +154,7 @@ let rec eval_expr (c : config) (e : expr) = | Break (x, eo) -> raise (label c x (eval_expr_opt c eo)) - | Br_if (eo, e, x) -> + | Br_if (x, eo, e) -> let v = eval_expr_opt c eo in let i = int32 (eval_expr c e) e.at in if i <> 0l then raise (label c x v) else None diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index 8ce0db28e0..054ed7666e 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -82,7 +82,7 @@ and expr' = | Block of expr list (* execute in sequence *) | Loop of expr (* loop header *) | Break of var * expr option (* break to n-th surrounding label *) - | Br_if of expr option * expr * var (* conditional break *) + | Br_if of var * expr option * expr (* conditional break *) | If of expr * expr * expr (* conditional *) | Switch of expr * var list * var * expr list (* table switch *) | Call of var * expr list (* call function *) diff --git a/ml-proto/test/fac.wast b/ml-proto/test/fac.wast index 4d19074d12..40459ca95e 100644 --- a/ml-proto/test/fac.wast +++ b/ml-proto/test/fac.wast @@ -62,11 +62,11 @@ (local i64) (set_local 1 (i64.const 1)) (block - (br_if (i64.lt_s (get_local 0) (i64.const 2)) 0) + (br_if 0 (i64.lt_s (get_local 0) (i64.const 2))) (loop (set_local 1 (i64.mul (get_local 1) (get_local 0))) (set_local 0 (i64.add (get_local 0) (i64.const -1))) - (br_if (i64.gt_s (get_local 0) (i64.const 1)) 0) + (br_if 0 (i64.gt_s (get_local 0) (i64.const 1))) ) ) (get_local 1) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 15f27eb0aa..8c51f054c6 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -95,21 +95,21 @@ (set_local $i (i32.const 0)) (block $outer (block $inner - (br_if (i32.const 0) $inner) + (br_if $inner (i32.const 0)) (set_local $i (i32.or (get_local $i) (i32.const 0x1))) - (br_if (i32.const 1) $inner) + (br_if $inner (i32.const 1)) (set_local $i (i32.or (get_local $i) (i32.const 0x2))) ) - (br_if (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (i32.const 0) $outer) + (br_if $outer (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (i32.const 0)) (set_local $i (i32.or (get_local $i) (i32.const 0x8))) - (br_if (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (i32.const 1) $outer) + (br_if $outer (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (i32.const 1)) (set_local $i (i32.or (get_local $i) (i32.const 0x20))) ) ) (func $br_if1 (result i32) (block $l0 - (br_if (block $l1 (br $l1 (i32.const 1))) (i32.const 1) $l0) + (br_if $l0 (block $l1 (br $l1 (i32.const 1))) (i32.const 1)) (i32.const 1))) (func $br_if2 (result i32) @@ -123,9 +123,9 @@ (func $br_if3 (result i32) (local $i1 i32) (i32.add (block $l0 - (br_if (set_local $i1 (i32.const 1)) - (set_local $i1 (i32.const 2)) - $l0) + (br_if $l0 + (set_local $i1 (i32.const 1)) + (set_local $i1 (i32.const 2))) (i32.const 0)) (i32.const 0)) (get_local $i1)) @@ -177,16 +177,16 @@ (assert_return (invoke "misc2") (i32.const 1)) (assert_invalid (module (func (loop $l (br $l (i32.const 0))))) "arity mismatch") -(assert_invalid (module (func (block $l (f32.neg (br_if (i32.const 1) $l)) (nop)))) "type mismatch") +(assert_invalid (module (func (block $l (f32.neg (br_if $l (i32.const 1))) (nop)))) "type mismatch") -(assert_invalid (module (func (result f32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") -(assert_invalid (module (func (result i32) (block $l (br_if (f32.const 0) (i32.const 1) $l)))) "type mismatch") -(assert_invalid (module (func (block $l (f32.neg (br_if (f32.const 0) (i32.const 1) $l))))) "arity mismatch") -(assert_invalid (module (func (param i32) (result i32) (block $l (f32.neg (br_if (f32.const 0) (get_local 0) $l))))) "type mismatch") +(assert_invalid (module (func (result f32) (block $l (br_if $l (f32.const 0) (i32.const 1))))) "type mismatch") +(assert_invalid (module (func (result i32) (block $l (br_if $l (f32.const 0) (i32.const 1))))) "type mismatch") +(assert_invalid (module (func (block $l (f32.neg (br_if $l (f32.const 0) (i32.const 1)))))) "arity mismatch") +(assert_invalid (module (func (param i32) (result i32) (block $l (f32.neg (br_if $l (f32.const 0) (get_local 0)))))) "type mismatch") (assert_invalid (module (func (param i32) (result f32) - (block $l (f32.neg (block $i (br_if (f32.const 3) (get_local 0) $l)))))) + (block $l (f32.neg (block $i (br_if $l (f32.const 3) (get_local 0))))))) "type mismatch") -(assert_invalid (module (func (block $l0 (br_if (nop) (i32.const 1) $l0)))) +(assert_invalid (module (func (block $l0 (br_if $l0 (nop) (i32.const 1))))) "arity mismatch") (assert_invalid (module (func (result i32) (block $l0