From a6b107408176730a408e3728bcff985643e270e7 Mon Sep 17 00:00:00 2001 From: rossberg-chromium Date: Mon, 9 May 2016 19:01:08 +0200 Subject: [PATCH 1/9] Make drops explicit --- ml-proto/host/encode.ml | 2 + ml-proto/host/format.ml | 4 +- ml-proto/host/lexer.mll | 1 + ml-proto/host/parser.mly | 3 +- ml-proto/spec/ast.ml | 1 + ml-proto/spec/check.ml | 70 +++++--- ml-proto/spec/decode.ml | 2 +- ml-proto/spec/desugar.ml | 2 + ml-proto/spec/eval.ml | 15 +- ml-proto/spec/kernel.ml | 1 + ml-proto/test/address.wast | 4 +- ml-proto/test/block.wast | 2 +- ml-proto/test/break-drop.wast | 18 +- .../expected-output/store_retval.wast.log | 13 -- ml-proto/test/exports.wast | 22 ++- ml-proto/test/functions.wast | 12 +- ml-proto/test/labels.wast | 33 ++-- ml-proto/test/left-to-right.wast | 166 +++++++++--------- ml-proto/test/memory.wast | 18 +- ml-proto/test/memory_redundancy.wast | 2 +- ml-proto/test/memory_trap.wast | 6 +- ml-proto/test/resizing.wast | 11 +- ml-proto/test/start.wast | 2 +- ml-proto/test/store_retval.wast | 84 +++++---- ml-proto/test/traps.wast | 40 ++--- ml-proto/test/unreachable.wast | 24 +-- 26 files changed, 293 insertions(+), 265 deletions(-) delete mode 100644 ml-proto/test/expected-output/store_retval.wast.log diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index c92d907aae..a365107818 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -116,6 +116,8 @@ let encode m = | Br_table (xs, x, eo, e) -> opt expr eo; expr e; op 0x08; arity1 eo; vec var32 xs; var32 x + | Ast.Drop e -> unary e 0x09 + | Ast.I32_const c -> op 0x0a; vs32 c.it | Ast.I64_const c -> op 0x0b; vs64 c.it | Ast.F32_const c -> op 0x0c; f32 c.it diff --git a/ml-proto/host/format.ml b/ml-proto/host/format.ml index 1c0072594f..923d63cfc2 100644 --- a/ml-proto/host/format.ml +++ b/ml-proto/host/format.ml @@ -180,8 +180,10 @@ let rec expr e = match e.it with | Nop -> "nop", [] | Unreachable -> "unreachable", [] + | Drop e -> "drop", [expr e] + | Block ([], {it = Loop e}) -> "loop", [expr e] | Block (es, e) -> "block", list expr (es @ [e]) - | Loop e -> "loop", [expr e] + | Loop e -> assert false | Break (x, eo) -> "br " ^ var x, opt expr eo | BreakIf (x, eo, e) -> "br_if " ^ var x, opt expr eo @ [expr e] | BreakTable (xs, x, eo, e) -> diff --git a/ml-proto/host/lexer.mll b/ml-proto/host/lexer.mll index 4774d41d93..88f23f09f8 100644 --- a/ml-proto/host/lexer.mll +++ b/ml-proto/host/lexer.mll @@ -140,6 +140,7 @@ rule token = parse | "nop" { NOP } | "unreachable" { UNREACHABLE } + | "drop" { DROP } | "block" { BLOCK } | "loop" { LOOP } | "br" { BR } diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index e72a360693..fb8de59a66 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -125,7 +125,7 @@ let implicit_decl c t at = %} %token INT FLOAT TEXT VAR VALUE_TYPE LPAR RPAR -%token NOP BLOCK IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE +%token NOP DROP BLOCK IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE %token CALL CALL_IMPORT CALL_INDIRECT RETURN %token GET_LOCAL SET_LOCAL LOAD STORE OFFSET ALIGN %token CONST UNARY BINARY COMPARE CONVERT @@ -222,6 +222,7 @@ expr : expr1 : | NOP { fun c -> Nop } | UNREACHABLE { fun c -> Unreachable } + | DROP expr { fun c -> Drop ($2 c) } | BLOCK labeling expr_list { fun c -> let c' = $2 c in Block ($3 c') } | LOOP labeling expr_list { fun c -> let c' = anon_label c in let c'' = $2 c' in Loop ($3 c'') } diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index efff76c307..f21671daa9 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -13,6 +13,7 @@ and expr' = (* Control *) | Nop | Unreachable + | Drop of expr | Block of expr list | Loop of expr list | Br of var * expr option diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index a74ed444f4..c8f34f9f06 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -14,6 +14,8 @@ let require b at s = if not b then error at s (* Context *) +type expr_type_guess = [`Known of expr_type | `Unknown] ref + type context = { types : func_type list; @@ -21,7 +23,7 @@ type context = imports : func_type list; locals : value_type list; return : expr_type; - labels : expr_type list; + labels : expr_type_guess list; has_memory : bool } @@ -36,12 +38,20 @@ let local c x = lookup "local" c.locals x let label c x = lookup "label" c.labels x -(* Type comparison *) +(* Type Unification *) + +let known_of = function `Known et -> et | `Unknown -> assert false let check_type actual expected at = - require (expected = None || actual = expected) at + if !expected = `Unknown then expected := `Known actual; + require (!expected = `Known actual) at ("type mismatch: expression has type " ^ string_of_expr_type actual ^ - " but the context requires " ^ string_of_expr_type expected) + " but the context requires " ^ string_of_expr_type (known_of !expected)) + +let unknown () = ref `Unknown +let known et = ref (`Known et) +let none = known None +let some t = known (Some t) (* Type Synthesis *) @@ -99,7 +109,7 @@ let type_hostop = function (* Type Analysis *) (* - * check_expr : context -> expr_type -> expr -> unit + * check_expr : context -> expr_type_guess -> expr -> unit * * Conventions: * c : context @@ -107,7 +117,7 @@ let type_hostop = function * eo : expr option * v : value * t : value_type - * et : expr_type + * et : expr_type_guess *) let rec check_expr c et e = @@ -118,13 +128,16 @@ let rec check_expr c et e = | Unreachable -> () + | Drop e -> + check_expr c (unknown ()) e + | Block (es, e) -> let c' = {c with labels = et :: c.labels} in - List.iter (check_expr c' None) es; + List.iter (check_expr c' none) es; check_expr c' et e | Loop e1 -> - let c' = {c with labels = None :: c.labels} in + let c' = {c with labels = none :: c.labels} in check_expr c' et e1 | Break (x, eo) -> @@ -132,23 +145,23 @@ let rec check_expr c et e = | BreakIf (x, eo, e1) -> check_expr_opt c (label c x) eo e.at; - check_expr c (Some Int32Type) e1; + check_expr c (some Int32Type) e1; check_type None et e.at | BreakTable (xs, x, eo, e1) -> List.iter (fun x -> check_expr_opt c (label c x) eo e.at) xs; check_expr_opt c (label c x) eo e.at; - check_expr c (Some Int32Type) e1 + check_expr c (some Int32Type) e1 | If (e1, e2, e3) -> - check_expr c (Some Int32Type) e1; + check_expr c (some Int32Type) e1; check_expr c et e2; check_expr c et e3 | Select (e1, e2, e3) -> check_expr c et e1; check_expr c et e2; - check_expr c (Some Int32Type) e3 + check_expr c (some Int32Type) e3 | Call (x, es) -> let {ins; out} = func c x in @@ -162,7 +175,7 @@ let rec check_expr c et e = | CallIndirect (x, e1, es) -> let {ins; out} = type_ c.types x in - check_expr c (Some Int32Type) e1; + check_expr c (some Int32Type) e1; check_exprs c ins es e.at; check_type out et e.at @@ -170,9 +183,8 @@ let rec check_expr c et e = check_type (Some (local c x)) et e.at | SetLocal (x, e1) -> - let t = local c x in - check_expr c (Some t) e1; - check_type (Some t) et e.at + check_expr c (some (local c x)) e1; + check_type None et e.at | Load (memop, e1) -> check_load c et memop e1 e.at @@ -193,29 +205,29 @@ let rec check_expr c et e = | Unary (unop, e1) -> let t = type_unop unop in - check_expr c (Some t) e1; + check_expr c (some t) e1; check_type (Some t) et e.at | Binary (binop, e1, e2) -> let t = type_binop binop in - check_expr c (Some t) e1; - check_expr c (Some t) e2; + check_expr c (some t) e1; + check_expr c (some t) e2; check_type (Some t) et e.at | Test (testop, e1) -> let t = type_testop testop in - check_expr c (Some t) e1; + check_expr c (some t) e1; check_type (Some Int32Type) et e.at | Compare (relop, e1, e2) -> let t = type_relop relop in - check_expr c (Some t) e1; - check_expr c (Some t) e2; + check_expr c (some t) e1; + check_expr c (some t) e2; check_type (Some Int32Type) et e.at | Convert (cvtop, e1) -> let t1, t = type_cvtop e.at cvtop in - check_expr c (Some t1) e1; + check_expr c (some t1) e1; check_type (Some t) et e.at | Host (hostop, es) -> @@ -225,7 +237,7 @@ let rec check_expr c et e = check_type out et e.at and check_exprs c ts es at = - let ets = List.map (fun x -> Some x) ts in + let ets = List.map some ts in try List.iter2 (check_expr c) ets es with Invalid_argument _ -> error at "arity mismatch" @@ -240,15 +252,15 @@ and check_literal c et l = and check_load c et memop e1 at = check_has_memory c at; check_memop memop at; - check_expr c (Some Int32Type) e1; + check_expr c (some Int32Type) e1; check_type (Some memop.ty) et at and check_store c et memop e1 e2 at = check_has_memory c at; check_memop memop at; - check_expr c (Some Int32Type) e1; - check_expr c (Some memop.ty) e2; - check_type (Some memop.ty) et at + check_expr c (some Int32Type) e1; + check_expr c (some memop.ty) e2; + check_type None et at and check_has_memory c at = require c.has_memory at "memory operators require a memory section" @@ -280,7 +292,7 @@ let check_func c f = let {ftype; locals; body} = f.it in let s = type_ c.types ftype in let c' = {c with locals = s.ins @ locals; return = s.out} in - check_expr c' s.out body + check_expr c' (known s.out) body let check_elem c x = ignore (func c x) diff --git a/ml-proto/spec/decode.ml b/ml-proto/spec/decode.ml index b3b4790949..58c1a0df4c 100644 --- a/ml-proto/spec/decode.ml +++ b/ml-proto/spec/decode.ml @@ -206,7 +206,7 @@ let rec expr stack s = let eo, es' = args1 b es s pos in Br_table (xs, x, eo, e), es' - | 0x09 as b, es -> illegal s pos b + | 0x09, e :: es -> Drop e, es | 0x0a, es -> I32_const (at vs32 s), es | 0x0b, es -> I64_const (at vs64 s), es diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index 91ed5f0912..9349eb5a50 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -11,6 +11,7 @@ let rec relabel f n e = relabel' f n e.it @@ e.at and relabel' f n = function | Nop -> Nop | Unreachable -> Unreachable + | Drop e -> Drop (relabel f n e) | Block (es, e) -> Block (List.map (relabel f (n + 1)) es, relabel f (n + 1) e) | Loop e -> Loop (relabel f (n + 1) e) @@ -61,6 +62,7 @@ and expr' at = function | Ast.Nop -> Nop | Ast.Unreachable -> Unreachable + | Ast.Drop e -> Drop (expr e) | Ast.Block [] -> Nop | Ast.Block es -> let es', e = Lib.List.split_last es in Block (List.map expr es', expr e) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index d892d74f52..b0053370c9 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -133,6 +133,10 @@ let rec eval_expr (c : config) (e : expr) = | Unreachable -> Trap.error e.at "unreachable executed" + | Drop e -> + eval_expr c e; + None + | Block (es, e) -> let module L = MakeLabel () in let c' = {c with labels = L.label :: c.labels} in @@ -193,7 +197,7 @@ let rec eval_expr (c : config) (e : expr) = | SetLocal (x, e1) -> let v1 = some (eval_expr c e1) e1.at in local c x := v1; - Some v1 + None | Load ({ty; offset; align = _}, e1) -> let mem = memory c e.at in @@ -207,7 +211,7 @@ let rec eval_expr (c : config) (e : expr) = let v2 = some (eval_expr c e2) e2.at in (try Memory.store mem v1 offset v2 with exn -> memory_error e.at exn); - Some v2 + None | LoadExtend ({memop = {ty; offset; align = _}; sz; ext}, e1) -> let mem = memory c e.at in @@ -221,7 +225,7 @@ let rec eval_expr (c : config) (e : expr) = let v2 = some (eval_expr c e2) e2.at in (try Memory.store_wrap mem v1 offset sz v2 with exn -> memory_error e.at exn); - Some v2 + None | Const v -> Some v.it @@ -269,10 +273,7 @@ and eval_func instance f vs = let ft = type_ c f.it.ftype in if List.length vs <> List.length ft.ins then Crash.error f.at "function called with wrong number of arguments"; - coerce ft.out (eval_expr c f.it.body) - -and coerce et vo = - if et = None then None else vo + eval_expr c f.it.body (* Host operators *) diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index 156b24a0f4..dc5d7f0ec5 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -78,6 +78,7 @@ type expr = expr' Source.phrase and expr' = | Nop (* do nothing *) | Unreachable (* trap *) + | Drop of expr (* forget a value *) | Block of expr list * expr (* execute in sequence *) | Loop of expr (* loop header *) | Break of var * expr option (* break to n-th surrounding label *) diff --git a/ml-proto/test/address.wast b/ml-proto/test/address.wast index e04b929f3f..4eba39a70e 100644 --- a/ml-proto/test/address.wast +++ b/ml-proto/test/address.wast @@ -21,7 +21,7 @@ ) (export "good" $good) - (func $bad2 (param $i i32) (i32.load offset=4294967295 (get_local $i))) + (func $bad2 (param $i i32) (drop (i32.load offset=4294967295 (get_local $i)))) (export "bad2" $bad2) ) @@ -31,4 +31,4 @@ (assert_trap (invoke "bad2" (i32.const 0)) "out of bounds memory access") (assert_trap (invoke "bad2" (i32.const 1)) "out of bounds memory access") -(assert_invalid (module (memory 1) (func $bad1 (param $i i32) (i32.load offset=4294967296 (get_local $i))) ) "offset too large") +(assert_invalid (module (memory 1) (func $bad1 (param $i i32) (drop (i32.load offset=4294967296 (get_local $i))))) "offset too large") diff --git a/ml-proto/test/block.wast b/ml-proto/test/block.wast index c8033b9621..ef8af41741 100644 --- a/ml-proto/test/block.wast +++ b/ml-proto/test/block.wast @@ -9,7 +9,7 @@ ) (func $multi (result i32) - (block (i32.const 5) (i32.const 6) (i32.const 7) (i32.const 8)) + (block (drop (i32.const 5)) (nop) (drop (i32.const 7)) (i32.const 8)) ) (func $effects (result i32) diff --git a/ml-proto/test/break-drop.wast b/ml-proto/test/break-drop.wast index 30b05b7df6..a14279574e 100644 --- a/ml-proto/test/break-drop.wast +++ b/ml-proto/test/break-drop.wast @@ -5,13 +5,13 @@ (func $br-nop (block (br 0 (nop)))) (export "br-nop" $br-nop) - (func $br-drop (block (br 0 (i32.const 1)))) + (func $br-drop (block (br 0 (drop (i32.const 1))))) (export "br-drop" $br-drop) - (func $br-block-nop (block (br 0 (block (i32.const 1) (nop))))) + (func $br-block-nop (block (br 0 (block (drop (i32.const 1)) (nop))))) (export "br-block-nop" $br-block-nop) - (func $br-block-drop (block (br 0 (block (nop) (i32.const 1))))) + (func $br-block-drop (block (br 0 (block (nop) (drop (i32.const 1)))))) (export "br-block-drop" $br-block-drop) (func $br_if (block (br_if 0 (i32.const 1)))) @@ -20,13 +20,13 @@ (func $br_if-nop (block (br_if 0 (nop) (i32.const 1)))) (export "br_if-nop" $br_if-nop) - (func $br_if-drop (block (br_if 0 (i32.const 1) (i32.const 1)))) + (func $br_if-drop (block (br_if 0 (drop (i32.const 1)) (i32.const 1)))) (export "br_if-drop" $br_if-drop) - (func $br_if-block-nop (block (br_if 0 (block (i32.const 1) (nop)) (i32.const 1)))) + (func $br_if-block-nop (block (br_if 0 (block (drop (i32.const 1)) (nop)) (i32.const 1)))) (export "br_if-block-nop" $br_if-block-nop) - (func $br_if-block-drop (block (br_if 0 (block (nop) (i32.const 1)) (i32.const 1)))) + (func $br_if-block-drop (block (br_if 0 (block (nop) (drop (i32.const 1))) (i32.const 1)))) (export "br_if-block-drop" $br_if-block-drop) (func $br_table (block (br_table 0 (i32.const 0)))) @@ -35,13 +35,13 @@ (func $br_table-nop (block (br_table 0 (nop) (i32.const 0)))) (export "br_table-nop" $br_table-nop) - (func $br_table-drop (block (br_table 0 (i32.const 1) (i32.const 0)))) + (func $br_table-drop (block (br_table 0 (drop (i32.const 1)) (i32.const 0)))) (export "br_table-drop" $br_table-drop) - (func $br_table-block-nop (block (br_table 0 (block (i32.const 1) (nop)) (i32.const 0)))) + (func $br_table-block-nop (block (br_table 0 (block (drop (i32.const 1)) (nop)) (i32.const 0)))) (export "br_table-block-nop" $br_table-block-nop) - (func $br_table-block-drop (block (br_table 0 (block (nop) (i32.const 1)) (i32.const 0)))) + (func $br_table-block-drop (block (br_table 0 (block (nop) (drop (i32.const 1))) (i32.const 0)))) (export "br_table-block-drop" $br_table-block-drop) ) diff --git a/ml-proto/test/expected-output/store_retval.wast.log b/ml-proto/test/expected-output/store_retval.wast.log deleted file mode 100644 index d54036acc6..0000000000 --- a/ml-proto/test/expected-output/store_retval.wast.log +++ /dev/null @@ -1,13 +0,0 @@ -1 : i32 -2 : i64 -3. : f32 -4. : f64 -11 : i32 -12 : i64 -13. : f32 -14. : f64 -512 : i32 -65536 : i32 -512 : i64 -65536 : i64 -4294967296 : i64 diff --git a/ml-proto/test/exports.wast b/ml-proto/test/exports.wast index 3a75499ae3..08266c4fe9 100644 --- a/ml-proto/test/exports.wast +++ b/ml-proto/test/exports.wast @@ -1,15 +1,19 @@ -(module (func (i32.const 1)) (export "a" 0)) -(module (func (i32.const 1)) (export "a" 0) (export "b" 0)) -(module (func (i32.const 1)) (func (i32.const 2)) (export "a" 0) (export "b" 1)) +(module (func) (export "a" 0)) +(module (func) (export "a" 0) (export "b" 0)) +(module (func) (func) (export "a" 0) (export "b" 1)) + (assert_invalid - (module (func (i32.const 1)) (export "a" 1)) - "unknown function 1") + (module (func) (export "a" 1)) + "unknown function 1" +) (assert_invalid - (module (func (i32.const 1)) (func (i32.const 2)) (export "a" 0) (export "a" 1)) - "duplicate export name") + (module (func) (func) (export "a" 0) (export "a" 1)) + "duplicate export name" +) (assert_invalid - (module (func (i32.const 1)) (export "a" 0) (export "a" 0)) - "duplicate export name") + (module (func) (export "a" 0) (export "a" 0)) + "duplicate export name" +) (module (func $f (param $n i32) (result i32) diff --git a/ml-proto/test/functions.wast b/ml-proto/test/functions.wast index 0510582d1f..a41582ef7e 100644 --- a/ml-proto/test/functions.wast +++ b/ml-proto/test/functions.wast @@ -5,13 +5,13 @@ (func $result-nop (nop)) (export "result-nop" $result-nop) - (func $result-drop (i32.const 1)) + (func $result-drop (drop (i32.const 1))) (export "result-drop" $result-drop) - (func $result-block-nop (block (i32.const 1) (nop))) + (func $result-block-nop (block (drop (i32.const 1)) (nop))) (export "result-block-nop" $result-block-nop) - (func $result-block-drop (block (nop) (i32.const 1))) + (func $result-block-drop (block (nop) (drop (i32.const 1)))) (export "result-block-drop" $result-block-drop) (func $return (return)) @@ -20,13 +20,13 @@ (func $return-nop (return (nop))) (export "return-nop" $return-nop) - (func $return-drop (return (i32.const 1))) + (func $return-drop (return (drop (i32.const 1)))) (export "return-drop" $return-drop) - (func $return-block-nop (return (block (i32.const 1) (nop)))) + (func $return-block-nop (return (block (drop (i32.const 1)) (nop)))) (export "return-block-nop" $return-block-nop) - (func $return-block-drop (return (block (nop) (i32.const 1)))) + (func $return-block-drop (return (block (nop) (drop (i32.const 1))))) (export "return-block-drop" $return-block-drop) ) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 6fdc594ddb..4c947b472e 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -114,13 +114,11 @@ (block $1 (br_table $0 $1 $2 $3 $default (get_local 0)) ) ;; 1 - (i32.const 1) ) ;; 2 (br $exit (i32.const 2)) ) ;; 3 (br $ret (i32.const 3)) ) ;; default - (i32.const 4) ) ;; 0 (i32.const 5) ) @@ -137,7 +135,6 @@ ) ;; 0 (return (i32.const 0)) ) ;; 1 - (i32.const 1) ) ;; default (i32.const 2) ) @@ -153,13 +150,13 @@ (set_local $i (i32.or (get_local $i) (i32.const 0x2))) ) (br_if $outer - (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (i32.const 0) + (block (set_local $i (i32.or (get_local $i) (i32.const 0x4))) (get_local $i)) (i32.const 0) ) (set_local $i (i32.or (get_local $i) (i32.const 0x8))) (br_if $outer - (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (i32.const 1) + (block (set_local $i (i32.or (get_local $i) (i32.const 0x10))) (get_local $i)) (i32.const 1) ) - (set_local $i (i32.or (get_local $i) (i32.const 0x20))) + (set_local $i (i32.or (get_local $i) (i32.const 0x20))) (get_local $i) ) ) @@ -178,12 +175,17 @@ (func $br_if3 (result i32) (local $i1 i32) - (i32.add - (block $l0 - (br_if $l0 (set_local $i1 (i32.const 1)) (set_local $i1 (i32.const 2))) + (drop + (i32.add + (block $l0 + (br_if $l0 + (block (set_local $i1 (i32.const 1)) (get_local $i1)) + (block (set_local $i1 (i32.const 2)) (get_local $i1)) + ) + (i32.const 0) + ) (i32.const 0) ) - (i32.const 0) ) (get_local $i1) ) @@ -196,7 +198,7 @@ (block $l0 (if (i32.const 1) (br $l0 (block $l1 (br $l1 (i32.const 1)))) - (block (block $l1 (br $l1 (i32.const 1))) (nop)) + (block (drop (block $l1 (br $l1 (i32.const 1))))) ) (i32.const 1) ) @@ -212,10 +214,11 @@ (func $redefinition (result i32) (block $l1 - (i32.add (block $l1 - (i32.const 2)) - (block $l1 - (br $l1 (i32.const 3))))) + (i32.add + (block $l1 (i32.const 2)) + (block $l1 (br $l1 (i32.const 3))) + ) + ) ) (export "block" $block) diff --git a/ml-proto/test/left-to-right.wast b/ml-proto/test/left-to-right.wast index 95a8b333e4..8c8ea104be 100644 --- a/ml-proto/test/left-to-right.wast +++ b/ml-proto/test/left-to-right.wast @@ -58,103 +58,103 @@ (func $f32_dummy (param f32 f32)) (func $f64_dummy (param f64 f64)) - (func $i32_add (result i32) (call $reset) (i32.add (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_sub (result i32) (call $reset) (i32.sub (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_mul (result i32) (call $reset) (i32.mul (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_div_s (result i32) (call $reset) (i32.div_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_div_u (result i32) (call $reset) (i32.div_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_rem_s (result i32) (call $reset) (i32.rem_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_rem_u (result i32) (call $reset) (i32.rem_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_and (result i32) (call $reset) (i32.and (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_or (result i32) (call $reset) (i32.or (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_xor (result i32) (call $reset) (i32.xor (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_shl (result i32) (call $reset) (i32.shl (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_shr_u (result i32) (call $reset) (i32.shr_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_shr_s (result i32) (call $reset) (i32.shr_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_eq (result i32) (call $reset) (i32.eq (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_ne (result i32) (call $reset) (i32.ne (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_lt_s (result i32) (call $reset) (i32.lt_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_le_s (result i32) (call $reset) (i32.le_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_lt_u (result i32) (call $reset) (i32.lt_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_le_u (result i32) (call $reset) (i32.le_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_gt_s (result i32) (call $reset) (i32.gt_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_ge_s (result i32) (call $reset) (i32.ge_s (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_gt_u (result i32) (call $reset) (i32.gt_u (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_ge_u (result i32) (call $reset) (i32.ge_u (call $i32_left) (call $i32_right)) (call $get)) + (func $i32_add (result i32) (call $reset) (drop (i32.add (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_sub (result i32) (call $reset) (drop (i32.sub (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_mul (result i32) (call $reset) (drop (i32.mul (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_div_s (result i32) (call $reset) (drop (i32.div_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_div_u (result i32) (call $reset) (drop (i32.div_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_rem_s (result i32) (call $reset) (drop (i32.rem_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_rem_u (result i32) (call $reset) (drop (i32.rem_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_and (result i32) (call $reset) (drop (i32.and (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_or (result i32) (call $reset) (drop (i32.or (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_xor (result i32) (call $reset) (drop (i32.xor (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_shl (result i32) (call $reset) (drop (i32.shl (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_shr_u (result i32) (call $reset) (drop (i32.shr_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_shr_s (result i32) (call $reset) (drop (i32.shr_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_eq (result i32) (call $reset) (drop (i32.eq (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_ne (result i32) (call $reset) (drop (i32.ne (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_lt_s (result i32) (call $reset) (drop (i32.lt_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_le_s (result i32) (call $reset) (drop (i32.le_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_lt_u (result i32) (call $reset) (drop (i32.lt_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_le_u (result i32) (call $reset) (drop (i32.le_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_gt_s (result i32) (call $reset) (drop (i32.gt_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_ge_s (result i32) (call $reset) (drop (i32.ge_s (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_gt_u (result i32) (call $reset) (drop (i32.gt_u (call $i32_left) (call $i32_right))) (call $get)) + (func $i32_ge_u (result i32) (call $reset) (drop (i32.ge_u (call $i32_left) (call $i32_right))) (call $get)) (func $i32_store (result i32) (call $reset) (i32.store (call $i32_left) (call $i32_right)) (call $get)) (func $i32_store8 (result i32) (call $reset) (i32.store8 (call $i32_left) (call $i32_right)) (call $get)) (func $i32_store16 (result i32) (call $reset) (i32.store16 (call $i32_left) (call $i32_right)) (call $get)) (func $i32_call (result i32) (call $reset) (call $i32_dummy (call $i32_left) (call $i32_right)) (call $get)) - (func $i32_call_indirect (result i32) (call $reset) (call_indirect $i32_T (call $i32_callee) (call $i32_right) (call $i32_another)) (call $get)) - (func $i32_select (result i32) (call $reset) (select (call $i32_left) (call $i32_right) (call $i32_bool)) (call $get)) + (func $i32_call_indirect (result i32) (call $reset) (drop (call_indirect $i32_T (call $i32_callee) (call $i32_right) (call $i32_another))) (call $get)) + (func $i32_select (result i32) (call $reset) (drop (select (call $i32_left) (call $i32_right) (call $i32_bool))) (call $get)) - (func $i64_add (result i32) (call $reset) (i64.add (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_sub (result i32) (call $reset) (i64.sub (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_mul (result i32) (call $reset) (i64.mul (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_div_s (result i32) (call $reset) (i64.div_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_div_u (result i32) (call $reset) (i64.div_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_rem_s (result i32) (call $reset) (i64.rem_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_rem_u (result i32) (call $reset) (i64.rem_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_and (result i32) (call $reset) (i64.and (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_or (result i32) (call $reset) (i64.or (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_xor (result i32) (call $reset) (i64.xor (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_shl (result i32) (call $reset) (i64.shl (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_shr_u (result i32) (call $reset) (i64.shr_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_shr_s (result i32) (call $reset) (i64.shr_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_eq (result i32) (call $reset) (i64.eq (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_ne (result i32) (call $reset) (i64.ne (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_lt_s (result i32) (call $reset) (i64.lt_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_le_s (result i32) (call $reset) (i64.le_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_lt_u (result i32) (call $reset) (i64.lt_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_le_u (result i32) (call $reset) (i64.le_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_gt_s (result i32) (call $reset) (i64.gt_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_ge_s (result i32) (call $reset) (i64.ge_s (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_gt_u (result i32) (call $reset) (i64.gt_u (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_ge_u (result i32) (call $reset) (i64.ge_u (call $i64_left) (call $i64_right)) (call $get)) + (func $i64_add (result i32) (call $reset) (drop (i64.add (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_sub (result i32) (call $reset) (drop (i64.sub (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_mul (result i32) (call $reset) (drop (i64.mul (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_div_s (result i32) (call $reset) (drop (i64.div_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_div_u (result i32) (call $reset) (drop (i64.div_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_rem_s (result i32) (call $reset) (drop (i64.rem_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_rem_u (result i32) (call $reset) (drop (i64.rem_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_and (result i32) (call $reset) (drop (i64.and (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_or (result i32) (call $reset) (drop (i64.or (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_xor (result i32) (call $reset) (drop (i64.xor (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_shl (result i32) (call $reset) (drop (i64.shl (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_shr_u (result i32) (call $reset) (drop (i64.shr_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_shr_s (result i32) (call $reset) (drop (i64.shr_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_eq (result i32) (call $reset) (drop (i64.eq (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_ne (result i32) (call $reset) (drop (i64.ne (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_lt_s (result i32) (call $reset) (drop (i64.lt_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_le_s (result i32) (call $reset) (drop (i64.le_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_lt_u (result i32) (call $reset) (drop (i64.lt_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_le_u (result i32) (call $reset) (drop (i64.le_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_gt_s (result i32) (call $reset) (drop (i64.gt_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_ge_s (result i32) (call $reset) (drop (i64.ge_s (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_gt_u (result i32) (call $reset) (drop (i64.gt_u (call $i64_left) (call $i64_right))) (call $get)) + (func $i64_ge_u (result i32) (call $reset) (drop (i64.ge_u (call $i64_left) (call $i64_right))) (call $get)) (func $i64_store (result i32) (call $reset) (i64.store (call $i32_left) (call $i64_right)) (call $get)) (func $i64_store8 (result i32) (call $reset) (i64.store8 (call $i32_left) (call $i64_right)) (call $get)) (func $i64_store16 (result i32) (call $reset) (i64.store16 (call $i32_left) (call $i64_right)) (call $get)) (func $i64_store32 (result i32) (call $reset) (i64.store32 (call $i32_left) (call $i64_right)) (call $get)) (func $i64_call (result i32) (call $reset) (call $i64_dummy (call $i64_left) (call $i64_right)) (call $get)) - (func $i64_call_indirect (result i32) (call $reset) (call_indirect $i64_T (call $i64_callee) (call $i64_right) (call $i64_another)) (call $get)) - (func $i64_select (result i32) (call $reset) (select (call $i64_left) (call $i64_right) (call $i64_bool)) (call $get)) + (func $i64_call_indirect (result i32) (call $reset) (drop (call_indirect $i64_T (call $i64_callee) (call $i64_right) (call $i64_another))) (call $get)) + (func $i64_select (result i32) (call $reset) (drop (select (call $i64_left) (call $i64_right) (call $i64_bool))) (call $get)) - (func $f32_add (result i32) (call $reset) (f32.add (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_sub (result i32) (call $reset) (f32.sub (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_mul (result i32) (call $reset) (f32.mul (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_div (result i32) (call $reset) (f32.div (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_copysign (result i32) (call $reset) (f32.copysign (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_eq (result i32) (call $reset) (f32.eq (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_ne (result i32) (call $reset) (f32.ne (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_lt (result i32) (call $reset) (f32.lt (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_le (result i32) (call $reset) (f32.le (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_gt (result i32) (call $reset) (f32.gt (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_ge (result i32) (call $reset) (f32.ge (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_min (result i32) (call $reset) (f32.min (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_max (result i32) (call $reset) (f32.max (call $f32_left) (call $f32_right)) (call $get)) + (func $f32_add (result i32) (call $reset) (drop (f32.add (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_sub (result i32) (call $reset) (drop (f32.sub (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_mul (result i32) (call $reset) (drop (f32.mul (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_div (result i32) (call $reset) (drop (f32.div (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_copysign (result i32) (call $reset) (drop (f32.copysign (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_eq (result i32) (call $reset) (drop (f32.eq (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_ne (result i32) (call $reset) (drop (f32.ne (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_lt (result i32) (call $reset) (drop (f32.lt (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_le (result i32) (call $reset) (drop (f32.le (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_gt (result i32) (call $reset) (drop (f32.gt (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_ge (result i32) (call $reset) (drop (f32.ge (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_min (result i32) (call $reset) (drop (f32.min (call $f32_left) (call $f32_right))) (call $get)) + (func $f32_max (result i32) (call $reset) (drop (f32.max (call $f32_left) (call $f32_right))) (call $get)) (func $f32_store (result i32) (call $reset) (f32.store (call $i32_left) (call $f32_right)) (call $get)) (func $f32_call (result i32) (call $reset) (call $f32_dummy (call $f32_left) (call $f32_right)) (call $get)) - (func $f32_call_indirect (result i32) (call $reset) (call_indirect $f32_T (call $f32_callee) (call $f32_right) (call $f32_another)) (call $get)) - (func $f32_select (result i32) (call $reset) (select (call $f32_left) (call $f32_right) (call $f32_bool)) (call $get)) + (func $f32_call_indirect (result i32) (call $reset) (drop (call_indirect $f32_T (call $f32_callee) (call $f32_right) (call $f32_another))) (call $get)) + (func $f32_select (result i32) (call $reset) (drop (select (call $f32_left) (call $f32_right) (call $f32_bool))) (call $get)) - (func $f64_add (result i32) (call $reset) (f64.add (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_sub (result i32) (call $reset) (f64.sub (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_mul (result i32) (call $reset) (f64.mul (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_div (result i32) (call $reset) (f64.div (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_copysign (result i32) (call $reset) (f64.copysign (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_eq (result i32) (call $reset) (f64.eq (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_ne (result i32) (call $reset) (f64.ne (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_lt (result i32) (call $reset) (f64.lt (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_le (result i32) (call $reset) (f64.le (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_gt (result i32) (call $reset) (f64.gt (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_ge (result i32) (call $reset) (f64.ge (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_min (result i32) (call $reset) (f64.min (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_max (result i32) (call $reset) (f64.max (call $f64_left) (call $f64_right)) (call $get)) + (func $f64_add (result i32) (call $reset) (drop (f64.add (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_sub (result i32) (call $reset) (drop (f64.sub (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_mul (result i32) (call $reset) (drop (f64.mul (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_div (result i32) (call $reset) (drop (f64.div (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_copysign (result i32) (call $reset) (drop (f64.copysign (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_eq (result i32) (call $reset) (drop (f64.eq (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_ne (result i32) (call $reset) (drop (f64.ne (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_lt (result i32) (call $reset) (drop (f64.lt (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_le (result i32) (call $reset) (drop (f64.le (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_gt (result i32) (call $reset) (drop (f64.gt (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_ge (result i32) (call $reset) (drop (f64.ge (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_min (result i32) (call $reset) (drop (f64.min (call $f64_left) (call $f64_right))) (call $get)) + (func $f64_max (result i32) (call $reset) (drop (f64.max (call $f64_left) (call $f64_right))) (call $get)) (func $f64_store (result i32) (call $reset) (f64.store (call $i32_left) (call $f64_right)) (call $get)) (func $f64_call (result i32) (call $reset) (call $f64_dummy (call $f64_left) (call $f64_right)) (call $get)) - (func $f64_call_indirect (result i32) (call $reset) (call_indirect $f64_T (call $f64_callee) (call $f64_right) (call $f64_another)) (call $get)) - (func $f64_select (result i32) (call $reset) (select (call $f64_left) (call $f64_right) (call $f64_bool)) (call $get)) + (func $f64_call_indirect (result i32) (call $reset) (drop (call_indirect $f64_T (call $f64_callee) (call $f64_right) (call $f64_another))) (call $get)) + (func $f64_select (result i32) (call $reset) (drop (select (call $f64_left) (call $f64_right) (call $f64_bool))) (call $get)) (func $br_if (result i32) (block @@ -166,8 +166,10 @@ (func $br_table (result i32) (block $a (call $reset) - (block $b - (br_table $a $b (call $i32_left) (call $i32_right)) + (drop + (block $b + (br_table $a $b (call $i32_left) (call $i32_right)) + ) ) (call $get) ) diff --git a/ml-proto/test/memory.wast b/ml-proto/test/memory.wast index 40d6f37588..5aca804df8 100644 --- a/ml-proto/test/memory.wast +++ b/ml-proto/test/memory.wast @@ -33,29 +33,29 @@ ) ;; Test alignment annotation rules -(module (memory 0) (func (i32.load8_u align=2 (i32.const 0)))) -(module (memory 0) (func (i32.load16_u align=4 (i32.const 0)))) -(module (memory 0) (func (i32.load align=8 (i32.const 0)))) -(module (memory 0) (func (f32.load align=8 (i32.const 0)))) +(module (memory 0) (func (drop (i32.load8_u align=2 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load16_u align=4 (i32.const 0))))) +(module (memory 0) (func (drop (i32.load align=8 (i32.const 0))))) +(module (memory 0) (func (drop (f32.load align=8 (i32.const 0))))) (assert_invalid - (module (memory 0) (func (i64.load align=0 (i32.const 0)))) + (module (memory 0) (func (drop (i64.load align=0 (i32.const 0))))) "non-power-of-two alignment" ) (assert_invalid - (module (memory 0) (func (i64.load align=3 (i32.const 0)))) + (module (memory 0) (func (drop (i64.load align=3 (i32.const 0))))) "non-power-of-two alignment" ) (assert_invalid - (module (memory 0) (func (i64.load align=5 (i32.const 0)))) + (module (memory 0) (func (drop (i64.load align=5 (i32.const 0))))) "non-power-of-two alignment" ) (assert_invalid - (module (memory 0) (func (i64.load align=6 (i32.const 0)))) + (module (memory 0) (func (drop (i64.load align=6 (i32.const 0))))) "non-power-of-two alignment" ) (assert_invalid - (module (memory 0) (func (i64.load align=7 (i32.const 0)))) + (module (memory 0) (func (drop (i64.load align=7 (i32.const 0))))) "non-power-of-two alignment" ) diff --git a/ml-proto/test/memory_redundancy.wast b/ml-proto/test/memory_redundancy.wast index 9053e04a48..e948b563f0 100644 --- a/ml-proto/test/memory_redundancy.wast +++ b/ml-proto/test/memory_redundancy.wast @@ -22,7 +22,7 @@ (export "test_redundant_load" $test_redundant_load) (func $test_redundant_load (result i32) - (i32.load (i32.const 8)) + (drop (i32.load (i32.const 8))) (f32.store (i32.const 5) (f32.const -0.0)) (i32.load (i32.const 8)) ) diff --git a/ml-proto/test/memory_trap.wast b/ml-proto/test/memory_trap.wast index 4894d7098b..a3f45abd6b 100644 --- a/ml-proto/test/memory_trap.wast +++ b/ml-proto/test/memory_trap.wast @@ -6,7 +6,7 @@ ) (export "store" $store) - (func $store (param $i i32) (param $v i32) (result i32) + (func $store (param $i i32) (param $v i32) (i32.store (i32.add (call $addr_limit) (get_local $i)) (get_local $v)) ) @@ -16,12 +16,12 @@ ) (export "grow_memory" $grow_memory) - (func $grow_memory (param i32) + (func $grow_memory (param i32) (result i32) (grow_memory (get_local 0)) ) ) -(assert_return (invoke "store" (i32.const -4) (i32.const 42)) (i32.const 42)) +(assert_return (invoke "store" (i32.const -4) (i32.const 42))) (assert_return (invoke "load" (i32.const -4)) (i32.const 42)) (assert_trap (invoke "store" (i32.const -3) (i32.const 13)) "out of bounds memory access") (assert_trap (invoke "load" (i32.const -3)) "out of bounds memory access") diff --git a/ml-proto/test/resizing.wast b/ml-proto/test/resizing.wast index 1a1073cdc9..b1792cd02b 100644 --- a/ml-proto/test/resizing.wast +++ b/ml-proto/test/resizing.wast @@ -5,13 +5,13 @@ (func $load_at_zero (result i32) (i32.load (i32.const 0))) (export "store_at_zero" $store_at_zero) - (func $store_at_zero (result i32) (i32.store (i32.const 0) (i32.const 2))) + (func $store_at_zero (i32.store (i32.const 0) (i32.const 2))) (export "load_at_page_size" $load_at_page_size) (func $load_at_page_size (result i32) (i32.load (i32.const 0x10000))) (export "store_at_page_size" $store_at_page_size) - (func $store_at_page_size (result i32) (i32.store (i32.const 0x10000) (i32.const 3))) + (func $store_at_page_size (i32.store (i32.const 0x10000) (i32.const 3))) (export "grow" $grow) (func $grow (param $sz i32) (result i32) (grow_memory (get_local $sz))) @@ -28,14 +28,15 @@ (assert_return (invoke "grow" (i32.const 1)) (i32.const 0)) (assert_return (invoke "size") (i32.const 1)) (assert_return (invoke "load_at_zero") (i32.const 0)) -(assert_return (invoke "store_at_zero") (i32.const 2)) +(assert_return (invoke "store_at_zero")) (assert_return (invoke "load_at_zero") (i32.const 2)) (assert_trap (invoke "store_at_page_size") "out of bounds memory access") (assert_trap (invoke "load_at_page_size") "out of bounds memory access") (assert_return (invoke "grow" (i32.const 4)) (i32.const 1)) (assert_return (invoke "size") (i32.const 5)) (assert_return (invoke "load_at_zero") (i32.const 2)) -(assert_return (invoke "store_at_zero") (i32.const 2)) +(assert_return (invoke "store_at_zero")) +(assert_return (invoke "load_at_zero") (i32.const 2)) (assert_return (invoke "load_at_page_size") (i32.const 0)) -(assert_return (invoke "store_at_page_size") (i32.const 3)) +(assert_return (invoke "store_at_page_size")) (assert_return (invoke "load_at_page_size") (i32.const 3)) diff --git a/ml-proto/test/start.wast b/ml-proto/test/start.wast index 042f98f0da..6b1e865d7c 100644 --- a/ml-proto/test/start.wast +++ b/ml-proto/test/start.wast @@ -1,5 +1,5 @@ (assert_invalid - (module (func (i32.const 1)) (start 1)) + (module (func) (start 1)) "unknown function 1" ) (assert_invalid diff --git a/ml-proto/test/store_retval.wast b/ml-proto/test/store_retval.wast index ba769ec855..3f4579cd9e 100644 --- a/ml-proto/test/store_retval.wast +++ b/ml-proto/test/store_retval.wast @@ -1,51 +1,57 @@ -(module - (memory 1) +(module) - (import $print_i32 "spectest" "print" (param i32)) - (import $print_i64 "spectest" "print" (param i64)) - (import $print_f32 "spectest" "print" (param f32)) - (import $print_f64 "spectest" "print" (param f64)) - - (func $run - (local $i32 i32) (local $i64 i64) (local $f32 f32) (local $f64 f64) - (call_import $print_i32 (set_local $i32 (i32.const 1))) - (call_import $print_i64 (set_local $i64 (i64.const 2))) - (call_import $print_f32 (set_local $f32 (f32.const 3))) - (call_import $print_f64 (set_local $f64 (f64.const 4))) - - (call_import $print_i32 (i32.store (i32.const 0) (i32.const 11))) - (call_import $print_i64 (i64.store (i32.const 0) (i64.const 12))) - (call_import $print_f32 (f32.store (i32.const 0) (f32.const 13))) - (call_import $print_f64 (f64.store (i32.const 0) (f64.const 14))) - - (call_import $print_i32 (i32.store8 (i32.const 0) (i32.const 512))) - (call_import $print_i32 (i32.store16 (i32.const 0) (i32.const 65536))) - (call_import $print_i64 (i64.store8 (i32.const 0) (i64.const 512))) - (call_import $print_i64 (i64.store16 (i32.const 0) (i64.const 65536))) - (call_import $print_i64 (i64.store32 (i32.const 0) (i64.const 4294967296))) - ) - (export "run" $run) +(assert_invalid + (module (func (param i32) (result i32) (set_local 0 (i32.const 1)))) + "type mismatch: expression has type () but the context requires i32" +) +(assert_invalid + (module (func (param i64) (result i64) (set_local 0 (i64.const 1)))) + "type mismatch: expression has type () but the context requires i64" +) +(assert_invalid + (module (func (param f32) (result f32) (set_local 0 (f32.const 1)))) + "type mismatch: expression has type () but the context requires f32" +) +(assert_invalid + (module (func (param f64) (result f64) (set_local 0 (f64.const 1)))) + "type mismatch: expression has type () but the context requires f64" ) -(invoke "run") +(assert_invalid + (module (memory 1) (func (param i32) (result i32) (i32.store (i32.const 0) (i32.const 1)))) + "type mismatch: expression has type () but the context requires i32" +) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store (i32.const 0) (i64.const 1)))) + "type mismatch: expression has type () but the context requires i64" +) +(assert_invalid + (module (memory 1) (func (param f32) (result f32) (f32.store (i32.const 0) (f32.const 1)))) + "type mismatch: expression has type () but the context requires f32" +) +(assert_invalid + (module (memory 1) (func (param f64) (result f64) (f64.store (i32.const 0) (f64.const 1)))) + "type mismatch: expression has type () but the context requires f64" +) (assert_invalid - (module (func (local $i32 i32) (local $i64 i64) - (set_local $i64 (set_local $i32 (i32.const 1))))) - "type mismatch: expression has type i32 but the context requires i64" + (module (memory 1) (func (param i32) (result i32) (i32.store8 (i32.const 0) (i32.const 1)))) + "type mismatch: expression has type () but the context requires i32" ) (assert_invalid - (module (func (local $i32 i32) (local $i64 i64) - (set_local $i32 (set_local $i64 (i64.const 1))))) - "type mismatch: expression has type i64 but the context requires i32" + (module (memory 1) (func (param i32) (result i32) (i32.store16 (i32.const 0) (i32.const 1)))) + "type mismatch: expression has type () but the context requires i32" ) (assert_invalid - (module (func (local $f32 f32) (local $f64 f64) - (set_local $f64 (set_local $f32 (f32.const 1))))) - "type mismatch: expression has type f32 but the context requires f64" + (module (memory 1) (func (param i64) (result i64) (i64.store8 (i32.const 0) (i64.const 1)))) + "type mismatch: expression has type () but the context requires i64" ) (assert_invalid - (module (func (local $f32 f32) (local $f64 f64) - (set_local $f32 (set_local $f64 (f64.const 1))))) - "type mismatch: expression has type f64 but the context requires f32" + (module (memory 1) (func (param i64) (result i64) (i64.store16 (i32.const 0) (i64.const 1)))) + "type mismatch: expression has type () but the context requires i64" ) +(assert_invalid + (module (memory 1) (func (param i64) (result i64) (i64.store32 (i32.const 0) (i64.const 1)))) + "type mismatch: expression has type () but the context requires i64" +) + diff --git a/ml-proto/test/traps.wast b/ml-proto/test/traps.wast index 05582e1e6a..b3a7508f24 100644 --- a/ml-proto/test/traps.wast +++ b/ml-proto/test/traps.wast @@ -3,13 +3,13 @@ ;; discard its return value. (module - (func $no_dce.i32.div_s (param $x i32) (param $y i32) + (func $no_dce.i32.div_s (param $x i32) (param $y i32) (result i32) (i32.div_s (get_local $x) (get_local $y))) - (func $no_dce.i32.div_u (param $x i32) (param $y i32) + (func $no_dce.i32.div_u (param $x i32) (param $y i32) (result i32) (i32.div_u (get_local $x) (get_local $y))) - (func $no_dce.i64.div_s (param $x i64) (param $y i64) + (func $no_dce.i64.div_s (param $x i64) (param $y i64) (result i64) (i64.div_s (get_local $x) (get_local $y))) - (func $no_dce.i64.div_u (param $x i64) (param $y i64) + (func $no_dce.i64.div_u (param $x i64) (param $y i64) (result i64) (i64.div_u (get_local $x) (get_local $y))) (export "no_dce.i32.div_s" $no_dce.i32.div_s) (export "no_dce.i32.div_u" $no_dce.i32.div_u) @@ -23,13 +23,13 @@ (assert_trap (invoke "no_dce.i64.div_u" (i64.const 1) (i64.const 0)) "integer divide by zero") (module - (func $no_dce.i32.rem_s (param $x i32) (param $y i32) + (func $no_dce.i32.rem_s (param $x i32) (param $y i32) (result i32) (i32.rem_s (get_local $x) (get_local $y))) - (func $no_dce.i32.rem_u (param $x i32) (param $y i32) + (func $no_dce.i32.rem_u (param $x i32) (param $y i32) (result i32) (i32.rem_u (get_local $x) (get_local $y))) - (func $no_dce.i64.rem_s (param $x i64) (param $y i64) + (func $no_dce.i64.rem_s (param $x i64) (param $y i64) (result i64) (i64.rem_s (get_local $x) (get_local $y))) - (func $no_dce.i64.rem_u (param $x i64) (param $y i64) + (func $no_dce.i64.rem_u (param $x i64) (param $y i64) (result i64) (i64.rem_u (get_local $x) (get_local $y))) (export "no_dce.i32.rem_s" $no_dce.i32.rem_s) (export "no_dce.i32.rem_u" $no_dce.i32.rem_u) @@ -43,14 +43,14 @@ (assert_trap (invoke "no_dce.i64.rem_u" (i64.const 1) (i64.const 0)) "integer divide by zero") (module - (func $no_dce.i32.trunc_s_f32 (param $x f32) (i32.trunc_s/f32 (get_local $x))) - (func $no_dce.i32.trunc_u_f32 (param $x f32) (i32.trunc_u/f32 (get_local $x))) - (func $no_dce.i32.trunc_s_f64 (param $x f64) (i32.trunc_s/f64 (get_local $x))) - (func $no_dce.i32.trunc_u_f64 (param $x f64) (i32.trunc_u/f64 (get_local $x))) - (func $no_dce.i64.trunc_s_f32 (param $x f32) (i64.trunc_s/f32 (get_local $x))) - (func $no_dce.i64.trunc_u_f32 (param $x f32) (i64.trunc_u/f32 (get_local $x))) - (func $no_dce.i64.trunc_s_f64 (param $x f64) (i64.trunc_s/f64 (get_local $x))) - (func $no_dce.i64.trunc_u_f64 (param $x f64) (i64.trunc_u/f64 (get_local $x))) + (func $no_dce.i32.trunc_s_f32 (param $x f32) (result i32) (i32.trunc_s/f32 (get_local $x))) + (func $no_dce.i32.trunc_u_f32 (param $x f32) (result i32) (i32.trunc_u/f32 (get_local $x))) + (func $no_dce.i32.trunc_s_f64 (param $x f64) (result i32) (i32.trunc_s/f64 (get_local $x))) + (func $no_dce.i32.trunc_u_f64 (param $x f64) (result i32) (i32.trunc_u/f64 (get_local $x))) + (func $no_dce.i64.trunc_s_f32 (param $x f32) (result i64) (i64.trunc_s/f32 (get_local $x))) + (func $no_dce.i64.trunc_u_f32 (param $x f32) (result i64) (i64.trunc_u/f32 (get_local $x))) + (func $no_dce.i64.trunc_s_f64 (param $x f64) (result i64) (i64.trunc_s/f64 (get_local $x))) + (func $no_dce.i64.trunc_u_f64 (param $x f64) (result i64) (i64.trunc_u/f64 (get_local $x))) (export "no_dce.i32.trunc_s_f32" $no_dce.i32.trunc_s_f32) (export "no_dce.i32.trunc_u_f32" $no_dce.i32.trunc_u_f32) @@ -75,13 +75,13 @@ (memory 1) (export "no_dce.i32.load" $no_dce.i32.load) - (func $no_dce.i32.load (param $i i32) (i32.load (get_local $i))) + (func $no_dce.i32.load (param $i i32) (result i32) (i32.load (get_local $i))) (export "no_dce.i64.load" $no_dce.i64.load) - (func $no_dce.i64.load (param $i i32) (i64.load (get_local $i))) + (func $no_dce.i64.load (param $i i32) (result i64) (i64.load (get_local $i))) (export "no_dce.f32.load" $no_dce.f32.load) - (func $no_dce.f32.load (param $i i32) (f32.load (get_local $i))) + (func $no_dce.f32.load (param $i i32) (result f32) (f32.load (get_local $i))) (export "no_dce.f64.load" $no_dce.f64.load) - (func $no_dce.f64.load (param $i i32) (f64.load (get_local $i))) + (func $no_dce.f64.load (param $i i32) (result f64) (f64.load (get_local $i))) ) (assert_trap (invoke "no_dce.i32.load" (i32.const 65536)) "out of bounds memory access") diff --git a/ml-proto/test/unreachable.wast b/ml-proto/test/unreachable.wast index 8423ee8a3c..4b9536714d 100644 --- a/ml-proto/test/unreachable.wast +++ b/ml-proto/test/unreachable.wast @@ -1,22 +1,24 @@ (module - (func $return_i32 (result i32) - (unreachable)) - (func $return_f64 (result f64) - (unreachable)) + (func $return_i32 (result i32) (unreachable)) + (func $return_f64 (result f64) (unreachable)) (func $if (param i32) (result f32) - (if (get_local 0) (unreachable) (f32.const 0))) + (if (get_local 0) (unreachable) (f32.const 0)) + ) - (func $block - (block (i32.const 1) (unreachable) (i32.const 2))) + (func $block (result i32) + (block (unreachable) (i32.const 2)) + ) (func $return_i64 (result i64) - (return (i64.const 1)) - (unreachable)) + (return (i64.const 1)) + (unreachable) + ) (func $call (result f64) - (call $return_i32) - (unreachable)) + (drop (call $return_i32)) + (unreachable) + ) (func $misc1 (result i32) (i32.xor (unreachable) (i32.const 10)) From 4361ff1caaf86f97846e6add1f4c4fd2cf04738d Mon Sep 17 00:00:00 2001 From: rossberg-chromium Date: Fri, 13 May 2016 13:17:19 +0200 Subject: [PATCH 2/9] Require arity 1 for drops and breaks --- ml-proto/spec/check.ml | 16 +++++---- ml-proto/test/break-drop.wast | 64 ++++++++--------------------------- ml-proto/test/functions.wast | 44 +++++++----------------- ml-proto/test/labels.wast | 8 +---- 4 files changed, 38 insertions(+), 94 deletions(-) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index c8f34f9f06..16a170a6ef 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -40,18 +40,21 @@ let label c x = lookup "label" c.labels x (* Type Unification *) -let known_of = function `Known et -> et | `Unknown -> assert false +let string_of_guess = function + | `Known et -> string_of_expr_type et + | `Unknown -> "" let check_type actual expected at = - if !expected = `Unknown then expected := `Known actual; + if !expected = `Unknown && actual <> None then expected := `Known actual; require (!expected = `Known actual) at ("type mismatch: expression has type " ^ string_of_expr_type actual ^ - " but the context requires " ^ string_of_expr_type (known_of !expected)) + " but the context requires " ^ string_of_guess !expected) let unknown () = ref `Unknown let known et = ref (`Known et) let none = known None let some t = known (Some t) +let is_some et = !et <> `Known None (* Type Synthesis *) @@ -242,9 +245,10 @@ and check_exprs c ts es at = with Invalid_argument _ -> error at "arity mismatch" and check_expr_opt c et eo at = - match eo with - | Some e -> check_expr c et e - | None -> check_type None et at + match is_some et, eo with + | false, None -> () + | true, Some e -> check_expr c et e + | _ -> error at "arity mismatch" and check_literal c et l = check_type (Some (type_value l.it)) et l.at diff --git a/ml-proto/test/break-drop.wast b/ml-proto/test/break-drop.wast index a14279574e..8477175e73 100644 --- a/ml-proto/test/break-drop.wast +++ b/ml-proto/test/break-drop.wast @@ -2,63 +2,29 @@ (func $br (block (br 0))) (export "br" $br) - (func $br-nop (block (br 0 (nop)))) - (export "br-nop" $br-nop) - - (func $br-drop (block (br 0 (drop (i32.const 1))))) - (export "br-drop" $br-drop) - - (func $br-block-nop (block (br 0 (block (drop (i32.const 1)) (nop))))) - (export "br-block-nop" $br-block-nop) - - (func $br-block-drop (block (br 0 (block (nop) (drop (i32.const 1)))))) - (export "br-block-drop" $br-block-drop) - (func $br_if (block (br_if 0 (i32.const 1)))) (export "br_if" $br_if) - (func $br_if-nop (block (br_if 0 (nop) (i32.const 1)))) - (export "br_if-nop" $br_if-nop) - - (func $br_if-drop (block (br_if 0 (drop (i32.const 1)) (i32.const 1)))) - (export "br_if-drop" $br_if-drop) - - (func $br_if-block-nop (block (br_if 0 (block (drop (i32.const 1)) (nop)) (i32.const 1)))) - (export "br_if-block-nop" $br_if-block-nop) - - (func $br_if-block-drop (block (br_if 0 (block (nop) (drop (i32.const 1))) (i32.const 1)))) - (export "br_if-block-drop" $br_if-block-drop) - (func $br_table (block (br_table 0 (i32.const 0)))) (export "br_table" $br_table) +) - (func $br_table-nop (block (br_table 0 (nop) (i32.const 0)))) - (export "br_table-nop" $br_table-nop) - - (func $br_table-drop (block (br_table 0 (drop (i32.const 1)) (i32.const 0)))) - (export "br_table-drop" $br_table-drop) - - (func $br_table-block-nop (block (br_table 0 (block (drop (i32.const 1)) (nop)) (i32.const 0)))) - (export "br_table-block-nop" $br_table-block-nop) +(assert_return (invoke "br")) +(assert_return (invoke "br_if")) +(assert_return (invoke "br_table")) - (func $br_table-block-drop (block (br_table 0 (block (nop) (drop (i32.const 1))) (i32.const 0)))) - (export "br_table-block-drop" $br_table-block-drop) +(assert_invalid + (module (func (block (br 0 (nop))))) + "arity mismatch" ) -(assert_return (invoke "br")) -(assert_return (invoke "br-nop")) -(assert_return (invoke "br-drop")) -(assert_return (invoke "br-block-nop")) -(assert_return (invoke "br-block-drop")) +(assert_invalid + (module (func (block (br_if 0 (nop) (i32.const 0))))) + "arity mismatch" +) -(assert_return (invoke "br_if")) -(assert_return (invoke "br_if-nop")) -(assert_return (invoke "br_if-drop")) -(assert_return (invoke "br_if-block-nop")) -(assert_return (invoke "br_if-block-drop")) +(assert_invalid + (module (func (block (br_table 0 (nop) (i32.const 0))))) + "arity mismatch" +) -(assert_return (invoke "br_table")) -(assert_return (invoke "br_table-nop")) -(assert_return (invoke "br_table-drop")) -(assert_return (invoke "br_table-block-nop")) -(assert_return (invoke "br_table-block-drop")) diff --git a/ml-proto/test/functions.wast b/ml-proto/test/functions.wast index a41582ef7e..7368f3ae28 100644 --- a/ml-proto/test/functions.wast +++ b/ml-proto/test/functions.wast @@ -2,43 +2,23 @@ (func $empty) (export "empty" $empty) - (func $result-nop (nop)) - (export "result-nop" $result-nop) + (func $nop (nop)) + (export "nop" $nop) - (func $result-drop (drop (i32.const 1))) - (export "result-drop" $result-drop) + (func $drop (drop (i32.const 1))) + (export "drop" $drop) - (func $result-block-nop (block (drop (i32.const 1)) (nop))) - (export "result-block-nop" $result-block-nop) - - (func $result-block-drop (block (nop) (drop (i32.const 1)))) - (export "result-block-drop" $result-block-drop) - - (func $return (return)) + (func $return (return) (unreachable)) (export "return" $return) - - (func $return-nop (return (nop))) - (export "return-nop" $return-nop) - - (func $return-drop (return (drop (i32.const 1)))) - (export "return-drop" $return-drop) - - (func $return-block-nop (return (block (drop (i32.const 1)) (nop)))) - (export "return-block-nop" $return-block-nop) - - (func $return-block-drop (return (block (nop) (drop (i32.const 1))))) - (export "return-block-drop" $return-block-drop) ) (assert_return (invoke "empty")) -(assert_return (invoke "result-nop")) -(assert_return (invoke "result-drop")) -(assert_return (invoke "result-block-nop")) -(assert_return (invoke "result-block-drop")) - +(assert_return (invoke "nop")) +(assert_return (invoke "drop")) (assert_return (invoke "return")) -(assert_return (invoke "return-nop")) -(assert_return (invoke "return-drop")) -(assert_return (invoke "return-block-nop")) -(assert_return (invoke "return-block-drop")) + +(assert_invalid + (module (func (return (nop)))) + "arity mismatch" +) diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 4c947b472e..1a182a331e 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -190,10 +190,6 @@ (get_local $i1) ) - (func $br_if4 - (block $l0 (br_if $l0 (nop) (i32.const 1))) - ) - (func $br (result i32) (block $l0 (if (i32.const 1) @@ -234,7 +230,6 @@ (export "br_if1" $br_if1) (export "br_if2" $br_if2) (export "br_if3" $br_if3) - (export "br_if4" $br_if4) (export "br" $br) (export "misc1" $misc1) (export "misc2" $misc2) @@ -261,7 +256,6 @@ (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 "br_if4")) (assert_return (invoke "br") (i32.const 1)) (assert_return (invoke "misc1") (i32.const 1)) (assert_return (invoke "misc2") (i32.const 1)) @@ -281,7 +275,7 @@ ) (assert_invalid (module (func (block $l (f32.neg (br_if $l (f32.const 0) (i32.const 1)))))) - "type mismatch" + "arity mismatch" ) (assert_invalid (module From f3a245410063ade319a820b57236531b9e53f72f Mon Sep 17 00:00:00 2001 From: rossberg-chromium Date: Fri, 20 May 2016 10:50:45 +0200 Subject: [PATCH 3/9] Minor naming cosmetics --- ml-proto/spec/check.ml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index 16a170a6ef..e256f90712 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -14,7 +14,7 @@ let require b at s = if not b then error at s (* Context *) -type expr_type_guess = [`Known of expr_type | `Unknown] ref +type expr_type_future = [`Known of expr_type | `SomeUnknown] ref type context = { @@ -23,7 +23,7 @@ type context = imports : func_type list; locals : value_type list; return : expr_type; - labels : expr_type_guess list; + labels : expr_type_future list; has_memory : bool } @@ -42,15 +42,15 @@ let label c x = lookup "label" c.labels x let string_of_guess = function | `Known et -> string_of_expr_type et - | `Unknown -> "" + | `SomeUnknown -> "" let check_type actual expected at = - if !expected = `Unknown && actual <> None then expected := `Known actual; + if !expected = `SomeUnknown && actual <> None then expected := `Known actual; require (!expected = `Known actual) at ("type mismatch: expression has type " ^ string_of_expr_type actual ^ " but the context requires " ^ string_of_guess !expected) -let unknown () = ref `Unknown +let some_unknown () = ref `SomeUnknown let known et = ref (`Known et) let none = known None let some t = known (Some t) @@ -132,7 +132,7 @@ let rec check_expr c et e = () | Drop e -> - check_expr c (unknown ()) e + check_expr c (some_unknown ()) e | Block (es, e) -> let c' = {c with labels = et :: c.labels} in From 1da6c92cc0e5a2bb8ee06efd47ba145ef831e879 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 23 May 2016 14:37:05 +0200 Subject: [PATCH 4/9] Fix overlooked name changes --- ml-proto/spec/check.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index e256f90712..7434b1e182 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -40,7 +40,7 @@ let label c x = lookup "label" c.labels x (* Type Unification *) -let string_of_guess = function +let string_of_future = function | `Known et -> string_of_expr_type et | `SomeUnknown -> "" @@ -48,7 +48,7 @@ let check_type actual expected at = if !expected = `SomeUnknown && actual <> None then expected := `Known actual; require (!expected = `Known actual) at ("type mismatch: expression has type " ^ string_of_expr_type actual ^ - " but the context requires " ^ string_of_guess !expected) + " but the context requires " ^ string_of_future !expected) let some_unknown () = ref `SomeUnknown let known et = ref (`Known et) @@ -112,7 +112,7 @@ let type_hostop = function (* Type Analysis *) (* - * check_expr : context -> expr_type_guess -> expr -> unit + * check_expr : context -> expr_type_future -> expr -> unit * * Conventions: * c : context @@ -120,7 +120,7 @@ let type_hostop = function * eo : expr option * v : value * t : value_type - * et : expr_type_guess + * et : expr_type_future *) let rec check_expr c et e = From 5311e97676c6e4175b9a1b132703649d141dabd2 Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 6 Jun 2016 18:29:19 +0200 Subject: [PATCH 5/9] Introduce tee_local --- ml-proto/host/encode.ml | 1 + ml-proto/host/format.ml | 2 +- ml-proto/host/lexer.mll | 1 + ml-proto/host/parser.mly | 3 ++- ml-proto/spec/ast.ml | 1 + ml-proto/spec/check.ml | 5 +++-- ml-proto/spec/decode.ml | 5 ++++- ml-proto/spec/desugar.ml | 3 ++- ml-proto/spec/eval.ml | 2 +- 9 files changed, 16 insertions(+), 7 deletions(-) diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index a365107818..918dc1cb0f 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -125,6 +125,7 @@ let encode m = | Ast.Get_local x -> op 0x0e; var x | Ast.Set_local (x, e) -> unary e 0x0f; var x + | Ast.Tee_local (x, e) -> unary e 0x10; var x | Ast.Call (x, es) -> nary es 0x12; var x | Ast.Call_import (x, es) -> nary es 0x1f; var x diff --git a/ml-proto/host/format.ml b/ml-proto/host/format.ml index 923d63cfc2..d98ae73e9b 100644 --- a/ml-proto/host/format.ml +++ b/ml-proto/host/format.ml @@ -200,7 +200,7 @@ let rec expr e = | CallImport (x, es) -> "call_import " ^ var x, list expr es | CallIndirect (x, e, es) -> "call_indirect " ^ var x, list expr (e::es) | GetLocal x -> "get_local " ^ var x, [] - | SetLocal (x, e) -> "set_local " ^ var x, [expr e] + | SetLocal (x, e) -> "tee_local " ^ var x, [expr e] | Load (op, e) -> memop "load" op, [expr e] | Store (op, e1, e2) -> memop "store" op, [expr e1; expr e2] | LoadExtend (op, e) -> extop op, [expr e] diff --git a/ml-proto/host/lexer.mll b/ml-proto/host/lexer.mll index 88f23f09f8..9b0d75732d 100644 --- a/ml-proto/host/lexer.mll +++ b/ml-proto/host/lexer.mll @@ -157,6 +157,7 @@ rule token = parse | "get_local" { GET_LOCAL } | "set_local" { SET_LOCAL } + | "tee_local" { TEE_LOCAL } | (nxx as t)".load" { LOAD (fun (o, a, e) -> diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index fb8de59a66..f0636eaacd 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -127,7 +127,7 @@ let implicit_decl c t at = %token INT FLOAT TEXT VAR VALUE_TYPE LPAR RPAR %token NOP DROP BLOCK IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE %token CALL CALL_IMPORT CALL_INDIRECT RETURN -%token GET_LOCAL SET_LOCAL LOAD STORE OFFSET ALIGN +%token GET_LOCAL SET_LOCAL TEE_LOCAL LOAD STORE OFFSET ALIGN %token CONST UNARY BINARY COMPARE CONVERT %token UNREACHABLE CURRENT_MEMORY GROW_MEMORY %token FUNC START TYPE PARAM RESULT LOCAL @@ -252,6 +252,7 @@ expr1 : { fun c -> Call_indirect ($2 c type_, $3 c, $4 c) } | GET_LOCAL var { fun c -> Get_local ($2 c local) } | SET_LOCAL var expr { fun c -> Set_local ($2 c local, $3 c) } + | TEE_LOCAL var expr { fun c -> Tee_local ($2 c local, $3 c) } | LOAD offset align expr { fun c -> $1 ($2, $3, $4 c) } | STORE offset align expr expr { fun c -> $1 ($2, $3, $4 c, $5 c) } | CONST literal { fun c -> fst (literal $1 $2) } diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index f21671daa9..6e9fddb957 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -29,6 +29,7 @@ and expr' = (* Locals *) | Get_local of var | Set_local of var * expr + | Tee_local of var * expr (* Memory access *) | I32_load of Memory.offset * int * expr diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index 7434b1e182..e4e056f402 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -132,7 +132,8 @@ let rec check_expr c et e = () | Drop e -> - check_expr c (some_unknown ()) e + check_expr c (some_unknown ()) e; + check_type None et e.at | Block (es, e) -> let c' = {c with labels = et :: c.labels} in @@ -187,7 +188,7 @@ let rec check_expr c et e = | SetLocal (x, e1) -> check_expr c (some (local c x)) e1; - check_type None et e.at + check_type (Some (local c x)) et e.at | Load (memop, e1) -> check_load c et memop e1 e.at diff --git a/ml-proto/spec/decode.ml b/ml-proto/spec/decode.ml index 58c1a0df4c..543b2660d8 100644 --- a/ml-proto/spec/decode.ml +++ b/ml-proto/spec/decode.ml @@ -219,8 +219,11 @@ let rec expr stack s = | 0x0f, e :: es -> let x = at var s in Set_local (x, e), es + | 0x10, e :: es -> + let x = at var s in + Tee_local (x, e), es - | 0x10 | 0x11 as b, _ -> illegal s pos b + | 0x11 as b, _ -> illegal s pos b | 0x12, es -> let n = arity s in diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index 9349eb5a50..e3df391cc7 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -80,7 +80,8 @@ and expr' at = function | Ast.Call_indirect (x, e, es) -> CallIndirect (x, expr e, List.map expr es) | Ast.Get_local x -> GetLocal x - | Ast.Set_local (x, e) -> SetLocal (x, expr e) + | Ast.Set_local (x, e) -> Drop (SetLocal (x, expr e) @@ at) + | Ast.Tee_local (x, e) -> SetLocal (x, expr e) | Ast.I32_load (offset, align, e) -> Load ({ty = Int32Type; offset; align}, expr e) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index b0053370c9..2b3840a744 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -197,7 +197,7 @@ let rec eval_expr (c : config) (e : expr) = | SetLocal (x, e1) -> let v1 = some (eval_expr c e1) e1.at in local c x := v1; - None + Some v1 | Load ({ty; offset; align = _}, e1) -> let mem = memory c e.at in From 75d7ae9f5850fac213df047bf57e59f654eda08a Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Fri, 17 Jun 2016 16:40:49 +0200 Subject: [PATCH 6/9] Adjust tests; add test for tee_local --- ml-proto/host/lexer.mll | 6 +- ml-proto/spec/eval.ml | 2 +- ml-proto/test/br.wast | 115 +++++++++++----- ml-proto/test/br_if.wast | 101 ++++++++------ ml-proto/test/br_table.wast | 125 ++++++++++++----- ml-proto/test/float_exprs.wast | 8 +- ml-proto/test/func.wast | 230 ++++++++++++++++++++------------ ml-proto/test/functions.wast | 24 ---- ml-proto/test/get_local.wast | 35 ++--- ml-proto/test/loop.wast | 171 ++++++++++++++---------- ml-proto/test/nop.wast | 25 ---- ml-proto/test/return.wast | 43 ++++-- ml-proto/test/set_local.wast | 101 +++++--------- ml-proto/test/tee_local.wast | 236 +++++++++++++++++++++++++++++++++ 14 files changed, 811 insertions(+), 411 deletions(-) delete mode 100644 ml-proto/test/functions.wast create mode 100644 ml-proto/test/tee_local.wast diff --git a/ml-proto/host/lexer.mll b/ml-proto/host/lexer.mll index 7a50745219..9824be3673 100644 --- a/ml-proto/host/lexer.mll +++ b/ml-proto/host/lexer.mll @@ -174,7 +174,7 @@ rule token = parse (F32_store (o, (Lib.Option.get a 4), e1, e2)) (F64_store (o, (Lib.Option.get a 8), e1, e2))) } | (ixx as t)".load"(mem_size as sz)"_"(sign as s) - { if t = "i32" && sz = "32" then error lexbuf "unknown opcode"; + { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; LOAD (fun (o, a, e) -> intop t (memsz sz @@ -191,7 +191,7 @@ rule token = parse (ext s (I64_load32_s (o, (Lib.Option.get a 4), e)) (I64_load32_u (o, (Lib.Option.get a 4), e))))) } | (ixx as t)".store"(mem_size as sz) - { if t = "i32" && sz = "32" then error lexbuf "unknown opcode"; + { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; STORE (fun (o, a, e1, e2) -> intop t (memsz sz @@ -383,7 +383,7 @@ rule token = parse | space { token lexbuf } | '\n' { Lexing.new_line lexbuf; token lexbuf } | eof { EOF } - | _ { error lexbuf "unknown opcode" } + | _ { error lexbuf "unknown operator" } and comment start = parse | ";)" { () } diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 2b3840a744..ce67762292 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -134,7 +134,7 @@ let rec eval_expr (c : config) (e : expr) = Trap.error e.at "unreachable executed" | Drop e -> - eval_expr c e; + ignore (eval_expr c e); None | Block (es, e) -> diff --git a/ml-proto/test/br.wast b/ml-proto/test/br.wast index a370f88af7..ce34922420 100644 --- a/ml-proto/test/br.wast +++ b/ml-proto/test/br.wast @@ -1,10 +1,13 @@ ;; Test `br` operator (module - (func "type-i32" (block (i32.ctz (br 0)))) - (func "type-i64" (block (i64.ctz (br 0)))) - (func "type-f32" (block (f32.neg (br 0)))) - (func "type-f64" (block (f64.neg (br 0)))) + ;; Auxiliary definition + (func $dummy) + + (func "type-i32" (block (drop (i32.ctz (br 0))))) + (func "type-i64" (block (drop (i64.ctz (br 0))))) + (func "type-f32" (block (drop (f32.neg (br 0))))) + (func "type-f64" (block (drop (f64.neg (br 0))))) (func "type-i32-value" (result i32) (block (i32.ctz (br 0 (i32.const 1))))) (func "type-i64-value" (result i64) (block (i64.ctz (br 0 (i64.const 2))))) @@ -12,26 +15,26 @@ (func "type-f64-value" (result f64) (block (f64.neg (br 0 (f64.const 4))))) (func "as-block-first" - (block (br 0) (i32.const 2)) + (block (br 0) (call $dummy)) ) (func "as-block-mid" - (block (i32.const 1) (br 0) (i32.const 2)) + (block (call $dummy) (br 0) (call $dummy)) ) (func "as-block-last" - (block (nop) (i32.const 1) (br 0)) + (block (nop) (call $dummy) (br 0)) ) (func "as-block-value" (result i32) - (block (nop) (i32.const 1) (br 0 (i32.const 2))) + (block (nop) (call $dummy) (br 0 (i32.const 2))) ) (func "as-loop-first" (result i32) (loop (br 1 (i32.const 3)) (i32.const 2)) ) (func "as-loop-mid" (result i32) - (loop (i32.const 1) (br 1 (i32.const 4)) (i32.const 2)) + (loop (call $dummy) (br 1 (i32.const 4)) (i32.const 2)) ) (func "as-loop-last" (result i32) - (loop (nop) (i32.const 1) (br 1 (i32.const 5))) + (loop (nop) (call $dummy) (br 1 (i32.const 5))) ) (func "as-br-value" (result i32) @@ -107,16 +110,36 @@ (type $sig (func (param i32 i32 i32) (result i32))) (table $f) (func "as-call_indirect-func" (result i32) - (block (call_indirect $sig (br 0 (i32.const 20)) (i32.const 1) (i32.const 2) (i32.const 3))) + (block + (call_indirect $sig + (br 0 (i32.const 20)) + (i32.const 1) (i32.const 2) (i32.const 3) + ) + ) ) (func "as-call_indirect-first" (result i32) - (block (call_indirect $sig (i32.const 0) (br 0 (i32.const 21)) (i32.const 2) (i32.const 3))) + (block + (call_indirect $sig + (i32.const 0) + (br 0 (i32.const 21)) (i32.const 2) (i32.const 3) + ) + ) ) (func "as-call_indirect-mid" (result i32) - (block (call_indirect $sig (i32.const 0) (i32.const 1) (br 0 (i32.const 22)) (i32.const 3))) + (block + (call_indirect $sig + (i32.const 0) + (i32.const 1) (br 0 (i32.const 22)) (i32.const 3) + ) + ) ) (func "as-call_indirect-last" (result i32) - (block (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (br 0 (i32.const 23)))) + (block + (call_indirect $sig + (i32.const 0) + (i32.const 1) (i32.const 2) (br 0 (i32.const 23)) + ) + ) ) (func "as-set_local-value" (result i32) (local f32) @@ -179,7 +202,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (call $dummy) (i32.add (i32.const 4) (br 0 (i32.const 8))) ) ) @@ -189,10 +212,12 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br 0 (br 1 (i32.const 8))) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br 0 (br 1 (i32.const 8))) + ) ) (i32.const 16) ) @@ -203,10 +228,13 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br_if 0 (br 1 (i32.const 8)) (i32.const 1)) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br_if 0 (br 1 (i32.const 8)) (i32.const 1)) + (i32.const 32) + ) ) (i32.const 16) ) @@ -217,7 +245,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_if 0 (i32.const 4) (br 0 (i32.const 8))) (i32.const 16) ) @@ -228,10 +256,12 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br_table 0 (br 1 (i32.const 8)) (i32.const 1)) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br_table 0 (br 1 (i32.const 8)) (i32.const 1)) + ) ) (i32.const 16) ) @@ -242,7 +272,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_table 0 (i32.const 4) (br 0 (i32.const 8))) (i32.const 16) ) @@ -338,9 +368,34 @@ (assert_return (invoke "nested-br_table-value-index") (i32.const 9)) (assert_invalid - (module (func $type-arg-void-vs-num (result i32) + (module (func $type-arg-empty-vs-num (result i32) (block (br 0) (i32.const 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-void-vs-empty + (block (br 0 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-num-vs-empty + (block (br 0 (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-poly-vs-empty + (block (br 0 (unreachable))) + )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-arg-void-vs-num (result i32) + (block (br 0 (nop)) (i32.const 1)) + )) "type mismatch" ) (assert_invalid diff --git a/ml-proto/test/br_if.wast b/ml-proto/test/br_if.wast index dfa989e2a3..d0a79b5d14 100644 --- a/ml-proto/test/br_if.wast +++ b/ml-proto/test/br_if.wast @@ -29,32 +29,18 @@ (loop (call $dummy) (br_if 1 (get_local 0))) ) - (func "as-br-value" (param i32) - (block (br 0 (br_if 0 (get_local 0)))) - ) - (func "as-br_if-value" (param i32 i32) - (block (br_if 0 (br_if 0 (get_local 0)) (get_local 1))) - ) - (func "as-br_table-value" (param i32 i32) - (block (br_table 0 0 0 (br_if 0 (get_local 0)) (get_local 1))) - ) - - (func "as-return-value" (param i32) - (block (return (br_if 0 (get_local 0)))) - ) - (func "as-if-then" (param i32 i32) - (block (if (get_local 0) (br_if 1 (i32.const 3) (get_local 1)) (call $dummy))) + (block (if (get_local 0) (br_if 1 (get_local 1)) (call $dummy))) ) (func "as-if-else" (param i32 i32) - (block (if (get_local 0) (call $dummy) (br_if 1 (i32.const 4) (get_local 1)))) + (block (if (get_local 0) (call $dummy) (br_if 1 (get_local 1)))) ) (func "nested-block-value" (param i32) (result i32) (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (i32.add (i32.const 4) (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 16)) @@ -67,7 +53,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br 0 (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) ) @@ -80,7 +66,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_if 0 (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) (i32.const 1) @@ -94,7 +80,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_if 0 (i32.const 4) (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 1)) @@ -108,7 +94,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_table 0 (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 4)) (i32.const 1) @@ -122,7 +108,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_table 0 (i32.const 4) (block (br_if 1 (i32.const 8) (get_local 0)) (i32.const 1)) @@ -152,24 +138,6 @@ (assert_return (invoke "as-loop-last" (i32.const 0))) (assert_return (invoke "as-loop-last" (i32.const 1))) -(assert_return (invoke "as-br-value" (i32.const 0))) -(assert_return (invoke "as-br-value" (i32.const 1))) - -(assert_return (invoke "as-br_if-value" (i32.const 0) (i32.const 0))) -(assert_return (invoke "as-br_if-value" (i32.const 1) (i32.const 0))) -(assert_return (invoke "as-br_if-value" (i32.const 0) (i32.const 1))) -(assert_return (invoke "as-br_if-value" (i32.const 1) (i32.const 1))) - -(assert_return (invoke "as-br_table-value" (i32.const 0) (i32.const 0))) -(assert_return (invoke "as-br_table-value" (i32.const 1) (i32.const 0))) -(assert_return (invoke "as-br_table-value" (i32.const 10) (i32.const 0))) -(assert_return (invoke "as-br_table-value" (i32.const 0) (i32.const 1))) -(assert_return (invoke "as-br_table-value" (i32.const 1) (i32.const 1))) -(assert_return (invoke "as-br_table-value" (i32.const 10) (i32.const 1))) - -(assert_return (invoke "as-return-value" (i32.const 0))) -(assert_return (invoke "as-return-value" (i32.const 1))) - (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 0))) (assert_return (invoke "as-if-then" (i32.const 4) (i32.const 0))) (assert_return (invoke "as-if-then" (i32.const 0) (i32.const 1))) @@ -227,14 +195,63 @@ ) (assert_invalid - (module (func $type-false-arg-void-vs-num (result i32) + (module (func $type-false-arg-empty-vs-num (result i32) (block (br_if 0 (i32.const 0)) (i32.const 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-true-arg-empty-vs-num (result i32) + (block (br_if 0 (i32.const 1)) (i32.const 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-false-arg-void-vs-empty + (block (br_if 0 (nop) (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-true-arg-void-vs-empty + (block (br_if 0 (nop) (i32.const 1))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-false-arg-num-vs-empty + (block (br_if 0 (i32.const 0) (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-true-arg-num-vs-empty + (block (br_if 0 (i32.const 0) (i32.const 1))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-false-arg-poly-vs-empty + (block (br_if 0 (unreachable) (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-true-arg-poly-vs-empty + (block (br_if 0 (unreachable) (i32.const 1))) + )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-false-arg-void-vs-num (result i32) + (block (br_if 0 (nop) (i32.const 0)) (i32.const 1)) + )) "type mismatch" ) (assert_invalid (module (func $type-true-arg-void-vs-num (result i32) - (block (br_if 0 (i32.const 1)) (i32.const 1)) + (block (br_if 0 (nop) (i32.const 1)) (i32.const 1)) )) "type mismatch" ) diff --git a/ml-proto/test/br_table.wast b/ml-proto/test/br_table.wast index 4378ea4e76..aab0a61c70 100644 --- a/ml-proto/test/br_table.wast +++ b/ml-proto/test/br_table.wast @@ -1,15 +1,26 @@ ;; Test `br_table` operator (module - (func "type-i32" (block (i32.ctz (br_table 0 0 (i32.const 0))))) - (func "type-i64" (block (i64.ctz (br_table 0 0 (i32.const 0))))) - (func "type-f32" (block (f32.neg (br_table 0 0 (i32.const 0))))) - (func "type-f64" (block (f64.neg (br_table 0 0 (i32.const 0))))) + ;; Auxiliary definition + (func $dummy) - (func "type-i32-value" (result i32) (block (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0))))) - (func "type-i64-value" (result i64) (block (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0))))) - (func "type-f32-value" (result f32) (block (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0))))) - (func "type-f64-value" (result f64) (block (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0))))) + (func "type-i32" (block (drop (i32.ctz (br_table 0 0 (i32.const 0)))))) + (func "type-i64" (block (drop (i64.ctz (br_table 0 0 (i32.const 0)))))) + (func "type-f32" (block (drop (f32.neg (br_table 0 0 (i32.const 0)))))) + (func "type-f64" (block (drop (f64.neg (br_table 0 0 (i32.const 0)))))) + + (func "type-i32-value" (result i32) + (block (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0)))) + ) + (func "type-i64-value" (result i64) + (block (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0)))) + ) + (func "type-f32-value" (result f32) + (block (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0)))) + ) + (func "type-f64-value" (result f64) + (block (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0)))) + ) (func "empty" (param i32) (result i32) (block (br_table 0 (get_local 0)) (return (i32.const 21))) @@ -32,9 +43,11 @@ (func "singleton-value" (param i32) (result i32) (block - (block - (br_table 0 1 (i32.const 33) (get_local 0)) - (return (i32.const 31)) + (drop + (block + (br_table 0 1 (i32.const 33) (get_local 0)) + (return (i32.const 31)) + ) ) (i32.const 32) ) @@ -819,26 +832,30 @@ ) (func "as-block-first" - (block (br_table 0 0 0 (i32.const 0)) (i32.const 2)) + (block (br_table 0 0 0 (i32.const 0)) (call $dummy)) ) (func "as-block-mid" - (block (i32.const 1) (br_table 0 0 0 (i32.const 0)) (i32.const 2)) + (block (call $dummy) (br_table 0 0 0 (i32.const 0)) (call $dummy)) ) (func "as-block-last" - (block (nop) (i32.const 1) (br_table 0 0 0 (i32.const 0))) + (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 0))) ) (func "as-block-value" (result i32) - (block (nop) (i32.const 1) (br_table 0 0 0 (i32.const 2) (i32.const 0))) + (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 2) (i32.const 0))) ) (func "as-loop-first" (result i32) - (loop (br_table 1 0 (i32.const 3) (i32.const 0)) (i32.const 1)) + (loop (br_table 1 1 (i32.const 3) (i32.const 0)) (i32.const 1)) ) (func "as-loop-mid" (result i32) - (loop (i32.const 1) (br_table 1 0 1 (i32.const 4) (i32.const -1)) (i32.const 2)) + (loop + (call $dummy) + (br_table 1 1 1 (i32.const 4) (i32.const -1)) + (i32.const 2) + ) ) (func "as-loop-last" (result i32) - (loop (nop) (i32.const 1) (br_table 0 1 0 (i32.const 5) (i32.const 1))) + (loop (nop) (call $dummy) (br_table 1 1 1 (i32.const 5) (i32.const 1))) ) (func "as-br-value" (result i32) @@ -984,15 +1001,18 @@ (func "nested-block-value" (param i32) (result i32) (block - (i32.const -1) + (drop (i32.const -1)) (i32.add (i32.const 1) (block (i32.add (i32.const 2) (block - (i32.const 4) - (i32.add (i32.const 8) (br_table 0 1 2 (i32.const 16) (get_local 0))) + (drop (i32.const 4)) + (i32.add + (i32.const 8) + (br_table 0 1 2 (i32.const 16) (get_local 0)) + ) ) ) ) @@ -1005,10 +1025,12 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br 0 (br_table 2 1 0 (i32.const 8) (get_local 0))) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br 0 (br_table 2 1 0 (i32.const 8) (get_local 0))) + ) ) (i32.const 16) ) @@ -1021,10 +1043,13 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br_if 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br_if 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) + (i32.const 32) + ) ) (i32.const 16) ) @@ -1037,7 +1062,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_if 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (get_local 0))) (i32.const 16) ) @@ -1050,10 +1075,13 @@ (i32.add (i32.const 1) (block - (i32.const 2) - (block - (i32.const 4) - (br_table 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) + (drop (i32.const 2)) + (drop + (block + (drop (i32.const 4)) + (br_table 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) + (i32.const 32) + ) ) (i32.const 16) ) @@ -1066,7 +1094,7 @@ (i32.add (i32.const 1) (block - (i32.const 2) + (drop (i32.const 2)) (br_table 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (get_local 0))) (i32.const 16) ) @@ -1257,9 +1285,34 @@ (assert_return (invoke "nested-br_table-value-index" (i32.const 9423975)) (i32.const 9)) (assert_invalid - (module (func $type-arg-void-vs-num (result i32) + (module (func $type-arg-empty-vs-num (result i32) (block (br_table 0 (i32.const 1)) (i32.const 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-void-vs-empty + (block (br_table 0 (nop) (i32.const 1))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-num-vs-empty + (block (br_table 0 (i32.const 0) (i32.const 1))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-arg-poly-vs-empty + (block (br_table 0 (unreachable) (i32.const 1))) + )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-arg-void-vs-num (result i32) + (block (br_table 0 (nop) (i32.const 1)) (i32.const 1)) + )) "type mismatch" ) (assert_invalid diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 2258d02ed1..b6c41e450c 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -1432,10 +1432,10 @@ (local $c f32) (local $t f32) (loop $exit $top - (set_local $t (f32.sub (f32.sub (set_local $sum (f32.add (get_local $c) (set_local $t (f32.sub (f32.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) + (set_local $t (f32.sub (f32.sub (tee_local $sum (f32.add (get_local $c) (tee_local $t (f32.sub (f32.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) (set_local $p (i32.add (get_local $p) (i32.const 4))) (set_local $c (get_local $sum)) - (br_if $top (set_local $n (i32.add (get_local $n) (i32.const -1)))) + (br_if $top (tee_local $n (i32.add (get_local $n) (i32.const -1)))) ) (get_local $sum) ) @@ -1467,10 +1467,10 @@ (local $c f64) (local $t f64) (loop $exit $top - (set_local $t (f64.sub (f64.sub (set_local $sum (f64.add (get_local $c) (set_local $t (f64.sub (f64.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) + (set_local $t (f64.sub (f64.sub (tee_local $sum (f64.add (get_local $c) (tee_local $t (f64.sub (f64.load (get_local $p)) (get_local $t))))) (get_local $c)) (get_local $t))) (set_local $p (i32.add (get_local $p) (i32.const 8))) (set_local $c (get_local $sum)) - (br_if $top (set_local $n (i32.add (get_local $n) (i32.const -1)))) + (br_if $top (tee_local $n (i32.add (get_local $n) (i32.const -1)))) ) (get_local $sum) ) diff --git a/ml-proto/test/func.wast b/ml-proto/test/func.wast index c79012bd97..70b9cc47f4 100644 --- a/ml-proto/test/func.wast +++ b/ml-proto/test/func.wast @@ -45,21 +45,22 @@ ;; Typing of locals - (func "local-first-i32" (local i32 i32) (result i32) (get_local 0)) - (func "local-first-i64" (local i64 i64) (result i64) (get_local 0)) - (func "local-first-f32" (local f32 f32) (result f32) (get_local 0)) - (func "local-first-f64" (local f64 f64) (result f64) (get_local 0)) - (func "local-second-i32" (local i32 i32) (result i32) (get_local 1)) - (func "local-second-i64" (local i64 i64) (result i64) (get_local 1)) - (func "local-second-f32" (local f32 f32) (result f32) (get_local 1)) - (func "local-second-f64" (local f64 f64) (result f64) (get_local 1)) - (func "local-mixed" (local f32) (local $x i32) (local i64 i32) (local) (local f64 i32) (result f64) - (f32.neg (get_local 0)) - (i32.eqz (get_local 1)) - (i64.eqz (get_local 2)) - (i32.eqz (get_local 3)) - (f64.neg (get_local 4)) - (i32.eqz (get_local 5)) + (func "local-first-i32" (result i32) (local i32 i32) (get_local 0)) + (func "local-first-i64" (result i64) (local i64 i64) (get_local 0)) + (func "local-first-f32" (result f32) (local f32 f32) (get_local 0)) + (func "local-first-f64" (result f64) (local f64 f64) (get_local 0)) + (func "local-second-i32" (result i32) (local i32 i32) (get_local 1)) + (func "local-second-i64" (result i64) (local i64 i64) (get_local 1)) + (func "local-second-f32" (result f32) (local f32 f32) (get_local 1)) + (func "local-second-f64" (result f64) (local f64 f64) (get_local 1)) + (func "local-mixed" (result f64) + (local f32) (local $x i32) (local i64 i32) (local) (local f64 i32) + (drop (f32.neg (get_local 0))) + (drop (i32.eqz (get_local 1))) + (drop (i64.eqz (get_local 2))) + (drop (i32.eqz (get_local 3))) + (drop (f64.neg (get_local 4))) + (drop (i32.eqz (get_local 5))) (get_local 4) ) @@ -73,13 +74,14 @@ (func "param-second-i64" (param i64 i64) (result i64) (get_local 1)) (func "param-second-f32" (param f32 f32) (result f32) (get_local 1)) (func "param-second-f64" (param f64 f64) (result f64) (get_local 1)) - (func "param-mixed" (param f32 i32) (param) (param $x i64) (param i32 f64 i32) (result f64) - (f32.neg (get_local 0)) - (i32.eqz (get_local 1)) - (i64.eqz (get_local 2)) - (i32.eqz (get_local 3)) - (f64.neg (get_local 4)) - (i32.eqz (get_local 5)) + (func "param-mixed" (param f32 i32) (param) (param $x i64) (param i32 f64 i32) + (result f64) + (drop (f32.neg (get_local 0))) + (drop (i32.eqz (get_local 1))) + (drop (i64.eqz (get_local 2))) + (drop (i32.eqz (get_local 3))) + (drop (f64.neg (get_local 4))) + (drop (i32.eqz (get_local 5))) (get_local 4) ) @@ -87,61 +89,45 @@ (func "empty") (func "value-void" (call $dummy)) - (func "value-drop" (i32.const 1)) (func "value-i32" (result i32) (i32.const 77)) (func "value-i64" (result i64) (i64.const 7777)) (func "value-f32" (result f32) (f32.const 77.7)) (func "value-f64" (result f64) (f64.const 77.77)) - (func "value-block-void" (block (i32.const 1) (call $dummy))) - (func "value-block-drop" (block (call $dummy) (i32.const 1))) + (func "value-block-void" (block (call $dummy) (call $dummy))) (func "value-block-i32" (result i32) (block (call $dummy) (i32.const 77))) - (func "return-nullary" (return)) - (func "return-void" (return (call $dummy))) - (func "return-drop" (return (i32.const 1))) + (func "return-empty" (return)) (func "return-i32" (result i32) (return (i32.const 78))) (func "return-i64" (result i64) (return (i64.const 7878))) (func "return-f32" (result f32) (return (f32.const 78.7))) (func "return-f64" (result f64) (return (f64.const 78.78))) - (func "return-block-void" (return (block (i32.const 1) (call $dummy)))) - (func "return-block-drop" (return (block (call $dummy) (i32.const 1)))) (func "return-block-i32" (result i32) (return (block (call $dummy) (i32.const 77))) ) - (func "break-nullary" (br 0)) - (func "break-void" (br 0 (call $dummy))) - (func "break-drop" (br 0 (i32.const 1))) + (func "break-empty" (br 0)) (func "break-i32" (result i32) (br 0 (i32.const 79))) (func "break-i64" (result i64) (br 0 (i64.const 7979))) (func "break-f32" (result f32) (br 0 (f32.const 79.9))) (func "break-f64" (result f64) (br 0 (f64.const 79.79))) - (func "break-block-void" (br 0 (block (i32.const 1) (call $dummy)))) - (func "break-block-drop" (br 0 (block (call $dummy) (i32.const 1)))) (func "break-block-i32" (result i32) (br 0 (block (call $dummy) (i32.const 77))) ) - (func "break-br_if-nullary" (param i32) + (func "break-br_if-empty" (param i32) (br_if 0 (get_local 0)) ) - (func "break-br_if-void" (param i32) - (br_if 0 (call $dummy) (get_local 0)) - ) (func "break-br_if-num" (param i32) (result i32) (br_if 0 (i32.const 50) (get_local 0)) (i32.const 51) ) - (func "break-br_table-nullary" (param i32) + (func "break-br_table-empty" (param i32) (br_table 0 0 0 (get_local 0)) ) - (func "break-br_table-void" (param i32) - (br_table 0 0 (call $dummy) (get_local 0)) - ) (func "break-br_table-num" (param i32) (result i32) (br_table 0 0 (i32.const 50) (get_local 0)) (i32.const 51) ) - (func "break-br_table-nested-nullary" (param i32) + (func "break-br_table-nested-empty" (param i32) (block (br_table 0 1 0 (get_local 0))) ) (func "break-br_table-nested-num" (param i32) (result i32) @@ -153,10 +139,10 @@ ;; Default initialization of locals - (func "init-local-i32" (local i32) (result i32) (get_local 0)) - (func "init-local-i64" (local i64) (result i64) (get_local 0)) - (func "init-local-f32" (local f32) (result f32) (get_local 0)) - (func "init-local-f64" (local f64) (result f64) (get_local 0)) + (func "init-local-i32" (result i32) (local i32) (get_local 0)) + (func "init-local-i64" (result i64) (local i64) (get_local 0)) + (func "init-local-f32" (result f32) (local f32) (get_local 0)) + (func "init-local-f64" (result f64) (local f64) (get_local 0)) ) (assert_return (invoke "local-first-i32") (i32.const 0)) @@ -204,60 +190,44 @@ (assert_return (invoke "empty")) (assert_return (invoke "value-void")) -(assert_return (invoke "value-drop")) (assert_return (invoke "value-i32") (i32.const 77)) (assert_return (invoke "value-i64") (i64.const 7777)) (assert_return (invoke "value-f32") (f32.const 77.7)) (assert_return (invoke "value-f64") (f64.const 77.77)) (assert_return (invoke "value-block-void")) -(assert_return (invoke "value-block-drop")) (assert_return (invoke "value-block-i32") (i32.const 77)) -(assert_return (invoke "return-nullary")) -(assert_return (invoke "return-void")) -(assert_return (invoke "return-drop")) +(assert_return (invoke "return-empty")) (assert_return (invoke "return-i32") (i32.const 78)) (assert_return (invoke "return-i64") (i64.const 7878)) (assert_return (invoke "return-f32") (f32.const 78.7)) (assert_return (invoke "return-f64") (f64.const 78.78)) -(assert_return (invoke "return-block-void")) -(assert_return (invoke "return-block-drop")) (assert_return (invoke "return-block-i32") (i32.const 77)) -(assert_return (invoke "break-nullary")) -(assert_return (invoke "break-void")) -(assert_return (invoke "break-drop")) +(assert_return (invoke "break-empty")) (assert_return (invoke "break-i32") (i32.const 79)) (assert_return (invoke "break-i64") (i64.const 7979)) (assert_return (invoke "break-f32") (f32.const 79.9)) (assert_return (invoke "break-f64") (f64.const 79.79)) -(assert_return (invoke "break-block-void")) -(assert_return (invoke "break-block-drop")) (assert_return (invoke "break-block-i32") (i32.const 77)) -(assert_return (invoke "break-br_if-nullary" (i32.const 0))) -(assert_return (invoke "break-br_if-nullary" (i32.const 2))) -(assert_return (invoke "break-br_if-void" (i32.const 0))) -(assert_return (invoke "break-br_if-void" (i32.const -1))) +(assert_return (invoke "break-br_if-empty" (i32.const 0))) +(assert_return (invoke "break-br_if-empty" (i32.const 2))) (assert_return (invoke "break-br_if-num" (i32.const 0)) (i32.const 51)) (assert_return (invoke "break-br_if-num" (i32.const 1)) (i32.const 50)) -(assert_return (invoke "break-br_table-nullary" (i32.const 0))) -(assert_return (invoke "break-br_table-nullary" (i32.const 1))) -(assert_return (invoke "break-br_table-nullary" (i32.const 5))) -(assert_return (invoke "break-br_table-nullary" (i32.const -1))) -(assert_return (invoke "break-br_table-void" (i32.const 0))) -(assert_return (invoke "break-br_table-void" (i32.const 1))) -(assert_return (invoke "break-br_table-void" (i32.const 2))) -(assert_return (invoke "break-br_table-void" (i32.const -100))) +(assert_return (invoke "break-br_table-empty" (i32.const 0))) +(assert_return (invoke "break-br_table-empty" (i32.const 1))) +(assert_return (invoke "break-br_table-empty" (i32.const 5))) +(assert_return (invoke "break-br_table-empty" (i32.const -1))) (assert_return (invoke "break-br_table-num" (i32.const 0)) (i32.const 50)) (assert_return (invoke "break-br_table-num" (i32.const 1)) (i32.const 50)) (assert_return (invoke "break-br_table-num" (i32.const 10)) (i32.const 50)) (assert_return (invoke "break-br_table-num" (i32.const -100)) (i32.const 50)) -(assert_return (invoke "break-br_table-nested-nullary" (i32.const 0))) -(assert_return (invoke "break-br_table-nested-nullary" (i32.const 1))) -(assert_return (invoke "break-br_table-nested-nullary" (i32.const 3))) -(assert_return (invoke "break-br_table-nested-nullary" (i32.const -2))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 0))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 1))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const 3))) +(assert_return (invoke "break-br_table-nested-empty" (i32.const -2))) (assert_return (invoke "break-br_table-nested-num" (i32.const 0)) (i32.const 52) ) @@ -280,7 +250,7 @@ ;; Invalid typing of locals (assert_invalid - (module (func $type-local-num-vs-num (local i32) (result i64) (get_local 0))) + (module (func $type-local-num-vs-num (result i64) (local i32) (get_local 0))) "type mismatch" ) (assert_invalid @@ -334,6 +304,12 @@ )) "type mismatch" ) +(assert_invalid + (module (func $type-value-num-vs-void + (i32.const 0) + )) + "type mismatch" +) (assert_invalid (module (func $type-value-num-vs-num (result i32) (f32.const 0) @@ -366,15 +342,57 @@ ) (assert_invalid - (module (func $type-return-last-void-vs-num (result i32) + (module (func $type-return-last-void-vs-enpty + (return (nop)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-last-num-vs-enpty + (return (i32.const 0)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-last-empty-vs-num (result i32) (return) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-last-void-vs-num (result i32) + (return (nop)) + )) "type mismatch" ) (assert_invalid - (module (func $type-return-void-vs-num (result i32) + (module (func $type-return-last-num-vs-num (result i32) + (return (i64.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-return-void-vs-empty + (return (nop)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-num-vs-empty + (return (i32.const 0)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-empty-vs-num (result i32) (return) (i32.const 1) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-return-void-vs-num (result i32) + (return (nop)) (i32.const 1) + )) "type mismatch" ) (assert_invalid @@ -397,15 +415,57 @@ ) (assert_invalid - (module (func $type-break-last-void-vs-num (result i32) + (module (func $type-break-last-void-vs-empty + (br 0 (nop)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-num-vs-empty + (br 0 (i32.const 0)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-empty-vs-num (result i32) (br 0) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-void-vs-num (result i32) + (br 0 (nop)) + )) "type mismatch" ) (assert_invalid - (module (func $type-break-void-vs-num (result i32) + (module (func $type-break-last-num-vs-num (result i32) + (br 0 (f32.const 0)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-break-void-vs-empty + (br 0 (i64.const 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-empty + (br 0 (i64.const 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-empty-vs-num (result i32) (br 0) (i32.const 1) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-void-vs-num (result i32) + (br 0 (nop)) (i32.const 1) + )) "type mismatch" ) (assert_invalid @@ -428,9 +488,15 @@ ) (assert_invalid - (module (func $type-break-nested-void-vs-num (result i32) + (module (func $type-break-nested-empty-vs-num (result i32) (block (br 1)) (br 0 (i32.const 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-void-vs-num (result i32) + (block (br 1 (nop))) (br 0 (i32.const 1)) + )) "type mismatch" ) (assert_invalid diff --git a/ml-proto/test/functions.wast b/ml-proto/test/functions.wast deleted file mode 100644 index 7368f3ae28..0000000000 --- a/ml-proto/test/functions.wast +++ /dev/null @@ -1,24 +0,0 @@ -(module - (func $empty) - (export "empty" $empty) - - (func $nop (nop)) - (export "nop" $nop) - - (func $drop (drop (i32.const 1))) - (export "drop" $drop) - - (func $return (return) (unreachable)) - (export "return" $return) -) - -(assert_return (invoke "empty")) -(assert_return (invoke "nop")) -(assert_return (invoke "drop")) -(assert_return (invoke "return")) - -(assert_invalid - (module (func (return (nop)))) - "arity mismatch" -) - diff --git a/ml-proto/test/get_local.wast b/ml-proto/test/get_local.wast index e2549dd149..a5d09833df 100644 --- a/ml-proto/test/get_local.wast +++ b/ml-proto/test/get_local.wast @@ -3,31 +3,33 @@ (module ;; Typing - (func "type-local-i32" (local i32) (result i32) (get_local 0)) - (func "type-local-i64" (local i64) (result i64) (get_local 0)) - (func "type-local-f32" (local f32) (result f32) (get_local 0)) - (func "type-local-f64" (local f64) (result f64) (get_local 0)) + (func "type-local-i32" (result i32) (local i32) (get_local 0)) + (func "type-local-i64" (result i64) (local i64) (get_local 0)) + (func "type-local-f32" (result f32) (local f32) (get_local 0)) + (func "type-local-f64" (result f64) (local f64) (get_local 0)) (func "type-param-i32" (param i32) (result i32) (get_local 0)) (func "type-param-i64" (param i64) (result i64) (get_local 0)) (func "type-param-f32" (param f32) (result f32) (get_local 0)) (func "type-param-f64" (param f64) (result f64) (get_local 0)) - (func "type-mixed" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) (result f64) - (i64.eqz (get_local 0)) - (f32.neg (get_local 1)) - (f64.neg (get_local 2)) - (i32.eqz (get_local 3)) - (i32.eqz (get_local 4)) - (f32.neg (get_local 5)) - (i64.eqz (get_local 6)) - (i64.eqz (get_local 7)) - (f64.neg (get_local 8)) + (func "type-mixed" (param i64 f32 f64 i32 i32) + (local f32 i64 i64 f64) + (drop (i64.eqz (get_local 0))) + (drop (f32.neg (get_local 1))) + (drop (f64.neg (get_local 2))) + (drop (i32.eqz (get_local 3))) + (drop (i32.eqz (get_local 4))) + (drop (f32.neg (get_local 5))) + (drop (i64.eqz (get_local 6))) + (drop (i64.eqz (get_local 7))) + (drop (f64.neg (get_local 8))) ) ;; Reading - (func "read" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) (result f64) + (func "read" (param i64 f32 f64 i32 i32) (result f64) + (local f32 i64 i64 f64) (set_local 5 (f32.const 5.5)) (set_local 6 (i64.const 6)) (set_local 8 (f64.const 8)) @@ -73,7 +75,6 @@ (invoke "type-mixed" (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) ) - (f64.const -0) ) (assert_return @@ -87,7 +88,7 @@ ;; Invalid typing of access to locals (assert_invalid - (module (func $type-local-num-vs-num (local i32) (result i64) (get_local 0))) + (module (func $type-local-num-vs-num (result i64) (local i32) (get_local 0))) "type mismatch" ) (assert_invalid diff --git a/ml-proto/test/loop.wast b/ml-proto/test/loop.wast index 13e9e1ccf3..bfe3e56829 100644 --- a/ml-proto/test/loop.wast +++ b/ml-proto/test/loop.wast @@ -88,63 +88,6 @@ (get_local 0) ) - (func "drop-mid" (result i32) - (loop (call $fx) (i32.const 7) (call $dummy) (i32.const 8)) - ) - (func "drop-last" - (loop (call $dummy) (call $fx) (nop) (i32.const 8)) - ) - (func "drop-break-void" - (loop (br 1 (nop))) - (loop (br 1 (call $dummy))) - (loop (br_if 1 (nop) (i32.const 0))) - (loop (br_if 1 (nop) (i32.const 1))) - (loop (br_if 1 (call $dummy) (i32.const 0))) - (loop (br_if 1 (call $dummy) (i32.const 1))) - (loop (br_table 1 (nop) (i32.const 3))) - (loop (br_table 1 1 1 (nop) (i32.const 1))) - ) - (func "drop-break-value" - (loop (br 1 (i32.const 8))) - (loop (br_if 1 (i32.const 11) (i32.const 0))) - (loop (br_if 1 (i32.const 10) (i32.const 1))) - (loop (br_table 1 (i32.const 9) (i32.const 5))) - (loop (br_table 1 1 1 (i32.const 8) (i32.const 1))) - ) - (func "drop-cont-void" - (loop (br 0 (nop))) - (loop (br 0 (call $dummy))) - (loop (br_if 0 (nop) (i32.const 0))) - (loop (br_if 0 (nop) (i32.const 1))) - (loop (br_if 0 (call $dummy) (i32.const 0))) - (loop (br_if 0 (call $dummy) (i32.const 1))) - (loop (br_table 0 (nop) (i32.const 3))) - (loop (br_table 0 1 1 (nop) (i32.const 1))) - ) - (func "drop-cont-value" - (loop (br 0 (i32.const 8))) - (loop (br_if 0 (i32.const 11) (i32.const 0))) - (loop (br_if 0 (i32.const 10) (i32.const 1))) - (loop (br_table 0 (i32.const 9) (i32.const 5))) - (loop (br_table 0 0 1 (i32.const 8) (i32.const 1))) - ) - (func "drop-break-value-heterogeneous" - (loop (br 1 (i32.const 8)) (br 1 (f64.const 8)) (br 1 (f32.const 8))) - (loop (br 1 (i32.const 8)) (br 1) (br 1 (f64.const 8))) - (loop (br 1 (i32.const 8)) (br 1) (br 1 (f32.const 8)) (i64.const 3)) - (loop (br 1) (br 1 (i32.const 8)) (br 1 (f64.const 8))) - (loop (br 1) (br 1 (i32.const 8)) (br 1 (f32.const 8)) (i64.const 3)) - (loop (loop (br 1) (br 3 (i32.const 8))) (br 1 (f32.const 8)) (block (br 2 (f64.const 7))) (i64.const 3)) - ) - (func "drop-cont-value-heterogeneous" - (loop (br 0 (i32.const 8)) (br 0 (f64.const 8)) (br 1 (f32.const 8))) - (loop (br 0 (i32.const 8)) (br 0) (br 0 (f64.const 8))) - (loop (br 0 (i32.const 8)) (br 0) (br 0 (f32.const 8)) (i64.const 3)) - (loop (br 0) (br 0 (i32.const 8)) (br 0 (f64.const 8))) - (loop (br 0) (br 0 (i32.const 8)) (br 0 (f32.const 8)) (i64.const 3)) - (loop (loop (br 1) (br 2 (i32.const 8))) (br 0 (f32.const 8)) (block (br 1 (f64.const 7))) (i64.const 3)) - ) - (func "effects" $fx (result i32) (local i32) (loop @@ -219,12 +162,6 @@ (assert_return (invoke "break-repeated") (i32.const 18)) (assert_return (invoke "break-inner") (i32.const 0x1f)) -(assert_return (invoke "drop-mid") (i32.const 8)) -(assert_return (invoke "drop-last")) -(assert_return (invoke "drop-break-void")) -(assert_return (invoke "drop-break-value")) -(assert_return (invoke "drop-break-value-heterogeneous")) - (assert_return (invoke "effects") (i32.const 1)) (assert_return (invoke "while" (i64.const 0)) (i64.const 1)) @@ -301,15 +238,52 @@ ) (assert_invalid - (module (func $type-break-last-void-vs-num (result i32) + (module (func $type-break-last-void-vs-empty + (loop (br 1 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-num-vs-empty + (loop (br 1 (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-empty-vs-num (result i32) (loop (br 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-void-vs-num (result i32) + (loop (br 1 (nop))) + )) "type mismatch" ) + (assert_invalid - (module (func $type-break-void-vs-num (result i32) + (module (func $type-break-void-vs-empty + (loop (br 1 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-empty + (loop (br 1 (i32.const 0))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-empty-vs-num (result i32) (loop (br 1) (i32.const 1)) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-void-vs-num (result i32) + (loop (br 1 (nop)) (i32.const 1)) + )) "type mismatch" ) (assert_invalid @@ -332,9 +306,27 @@ ) (assert_invalid - (module (func $type-break-nested-void-vs-num (result i32) + (module (func $type-break-nested-void-vs-empty + (loop (loop (br 3 (nop))) (br 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-num-vs-empty + (loop (loop (br 3 (i32.const 1))) (br 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-empty-vs-num (result i32) (loop (loop (br 3)) (br 1 (i32.const 1))) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-void-vs-num (result i32) + (loop (loop (br 3 (nop))) (br 1 (i32.const 1))) + )) "type mismatch" ) (assert_invalid @@ -343,10 +335,17 @@ )) "type mismatch" ) + (assert_invalid - (module (func $type-break-operand-void-vs-num (result i32) + (module (func $type-break-operand-empty-vs-num (result i32) (i32.ctz (loop (br 1))) )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-operand-void-vs-num (result i32) + (i32.ctz (loop (br 1 (nop)))) + )) "type mismatch" ) (assert_invalid @@ -356,3 +355,41 @@ "type mismatch" ) +(assert_invalid + (module (func $type-cont-last-void-vs-empty (result i32) + (loop (br 0 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-cont-last-num-vs-empty (result i32) + (loop (br 0 (i32.const 0))) + )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-cont-void-vs-empty (result i32) + (loop (br 0 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-empty (result i32) + (loop (br 0 (i32.const 0))) + )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-cont-nested-void-vs-empty + (loop (loop (br 2 (nop))) (br 1)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-cont-nested-num-vs-empty + (loop (loop (br 2 (i32.const 1))) (br 1)) + )) + "arity mismatch" +) diff --git a/ml-proto/test/nop.wast b/ml-proto/test/nop.wast index 8d4898f5f5..235d203adb 100644 --- a/ml-proto/test/nop.wast +++ b/ml-proto/test/nop.wast @@ -33,20 +33,6 @@ (loop (call $dummy) (nop)) ) - (func "as-br-value" - (block (br 0 (nop))) - ) - (func "as-br_if-value" (param i32) - (block (br_if 0 (nop) (get_local 0))) - ) - (func "as-br_table-value" (param i32) - (block (br_table 0 0 0 (nop) (get_local 0))) - ) - - (func "as-return-value" - (block (return (nop))) - ) - (func "as-if-then" (param i32) (block (if (get_local 0) (nop) (call $dummy))) ) @@ -67,17 +53,6 @@ (assert_return (invoke "as-loop-mid") (i32.const 2)) (assert_return (invoke "as-loop-last")) -(assert_return (invoke "as-br-value")) - -(assert_return (invoke "as-br_if-value" (i32.const 0))) -(assert_return (invoke "as-br_if-value" (i32.const 10))) - -(assert_return (invoke "as-br_table-value" (i32.const 0))) -(assert_return (invoke "as-br_table-value" (i32.const 1))) -(assert_return (invoke "as-br_table-value" (i32.const 10))) - -(assert_return (invoke "as-return-value")) - (assert_return (invoke "as-if-then" (i32.const 0))) (assert_return (invoke "as-if-then" (i32.const 4))) (assert_return (invoke "as-if-else" (i32.const 0))) diff --git a/ml-proto/test/return.wast b/ml-proto/test/return.wast index b5bdb1cb03..2124b831d9 100644 --- a/ml-proto/test/return.wast +++ b/ml-proto/test/return.wast @@ -1,10 +1,13 @@ ;; Test `return` operator (module - (func "type-i32" (i32.ctz (return))) - (func "type-i64" (i64.ctz (return))) - (func "type-f32" (f32.neg (return))) - (func "type-f64" (f64.neg (return))) + ;; Auxiliary definition + (func $dummy) + + (func "type-i32" (drop (i32.ctz (return)))) + (func "type-i64" (drop (i64.ctz (return)))) + (func "type-f32" (drop (f32.neg (return)))) + (func "type-f64" (drop (f64.neg (return)))) (func "nullary" (return)) (func "unary" (result f64) (return (f64.const 3.1))) @@ -13,36 +16,36 @@ (return (i32.const 1)) (i32.const 2) ) (func "as-func-mid" (result i32) - (i32.const 1) (return (i32.const 2)) (i32.const 3) + (call $dummy) (return (i32.const 2)) (i32.const 3) ) (func "as-func-last" - (nop) (i32.const 1) (return) + (nop) (call $dummy) (return) ) (func "as-func-value" (result i32) - (nop) (i32.const 1) (return (i32.const 3)) + (nop) (call $dummy) (return (i32.const 3)) ) (func "as-block-first" - (block (return) (i32.const 2)) + (block (return) (call $dummy)) ) (func "as-block-mid" - (block (i32.const 1) (return) (i32.const 2)) + (block (call $dummy) (return) (call $dummy)) ) (func "as-block-last" - (block (nop) (i32.const 1) (return)) + (block (nop) (call $dummy) (return)) ) (func "as-block-value" (result i32) - (block (nop) (i32.const 1) (return (i32.const 2))) + (block (nop) (call $dummy) (return (i32.const 2))) ) (func "as-loop-first" (result i32) (loop (return (i32.const 3)) (i32.const 2)) ) (func "as-loop-mid" (result i32) - (loop (i32.const 1) (return (i32.const 4)) (i32.const 2)) + (loop (call $dummy) (return (i32.const 4)) (i32.const 2)) ) (func "as-loop-last" (result i32) - (loop (nop) (i32.const 1) (return (i32.const 5))) + (loop (nop) (call $dummy) (return (i32.const 5))) ) (func "as-br-value" (result i32) @@ -271,7 +274,19 @@ (assert_return (invoke "as-grow_memory-size") (i32.const 40)) (assert_invalid - (module (func $type-value-void-vs-num (result f64) (return))) + (module (func $type-value-void-vs-empty (return (nop)))) + "arity mismatch" +) +(assert_invalid + (module (func $type-value-num-vs-empty (return (i32.const 0)))) + "arity mismatch" +) +(assert_invalid + (module (func $type-value-empty-vs-num (result f64) (return))) + "arity mismatch" +) +(assert_invalid + (module (func $type-value-void-vs-num (result f64) (return (nop)))) "type mismatch" ) (assert_invalid diff --git a/ml-proto/test/set_local.wast b/ml-proto/test/set_local.wast index e93960d9ea..e6b36fa166 100644 --- a/ml-proto/test/set_local.wast +++ b/ml-proto/test/set_local.wast @@ -3,31 +3,31 @@ (module ;; Typing - (func "type-local-i32" (local i32) (result i32) (set_local 0 (i32.const 0))) - (func "type-local-i64" (local i64) (result i64) (set_local 0 (i64.const 0))) - (func "type-local-f32" (local f32) (result f32) (set_local 0 (f32.const 0))) - (func "type-local-f64" (local f64) (result f64) (set_local 0 (f64.const 0))) + (func "type-local-i32" (local i32) (set_local 0 (i32.const 0))) + (func "type-local-i64" (local i64) (set_local 0 (i64.const 0))) + (func "type-local-f32" (local f32) (set_local 0 (f32.const 0))) + (func "type-local-f64" (local f64) (set_local 0 (f64.const 0))) - (func "type-param-i32" (param i32) (result i32) (set_local 0 (i32.const 10))) - (func "type-param-i64" (param i64) (result i64) (set_local 0 (i64.const 11))) - (func "type-param-f32" (param f32) (result f32) (set_local 0 (f32.const 11.1))) - (func "type-param-f64" (param f64) (result f64) (set_local 0 (f64.const 12.2))) + (func "type-param-i32" (param i32) (set_local 0 (i32.const 10))) + (func "type-param-i64" (param i64) (set_local 0 (i64.const 11))) + (func "type-param-f32" (param f32) (set_local 0 (f32.const 11.1))) + (func "type-param-f64" (param f64) (set_local 0 (f64.const 12.2))) (func "type-mixed" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) - (i64.eqz (set_local 0 (i64.const 0))) - (f32.neg (set_local 1 (f32.const 0))) - (f64.neg (set_local 2 (f64.const 0))) - (i32.eqz (set_local 3 (i32.const 0))) - (i32.eqz (set_local 4 (i32.const 0))) - (f32.neg (set_local 5 (f32.const 0))) - (i64.eqz (set_local 6 (i64.const 0))) - (i64.eqz (set_local 7 (i64.const 0))) - (f64.neg (set_local 8 (f64.const 0))) + (set_local 0 (i64.const 0)) + (set_local 1 (f32.const 0)) + (set_local 2 (f64.const 0)) + (set_local 3 (i32.const 0)) + (set_local 4 (i32.const 0)) + (set_local 5 (f32.const 0)) + (set_local 6 (i64.const 0)) + (set_local 7 (i64.const 0)) + (set_local 8 (f64.const 0)) ) ;; Writing - (func "write" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) (result i64) + (func "write" (param i64 f32 f64 i32 i32) (result i64) (local f32 i64 i64 f64) (set_local 1 (f32.const -0.3)) (set_local 3 (i32.const 40)) (set_local 4 (i32.const -7)) @@ -62,47 +62,17 @@ ) ) ) - - ;; Result - - (func "result" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) (result f64) - (f64.add - (f64.convert_u/i64 (set_local 0 (i64.const 1))) - (f64.add - (f64.promote/f32 (set_local 1 (f32.const 2))) - (f64.add - (set_local 2 (f64.const 3.3)) - (f64.add - (f64.convert_u/i32 (set_local 3 (i32.const 4))) - (f64.add - (f64.convert_s/i32 (set_local 4 (i32.const 5))) - (f64.add - (f64.promote/f32 (set_local 5 (f32.const 5.5))) - (f64.add - (f64.convert_u/i64 (set_local 6 (i64.const 6))) - (f64.add - (f64.convert_u/i64 (set_local 7 (i64.const 0))) - (set_local 8 (f64.const 8)) - ) - ) - ) - ) - ) - ) - ) - ) - ) ) -(assert_return (invoke "type-local-i32") (i32.const 0)) -(assert_return (invoke "type-local-i64") (i64.const 0)) -(assert_return (invoke "type-local-f32") (f32.const 0)) -(assert_return (invoke "type-local-f64") (f64.const 0)) +(assert_return (invoke "type-local-i32")) +(assert_return (invoke "type-local-i64")) +(assert_return (invoke "type-local-f32")) +(assert_return (invoke "type-local-f64")) -(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10)) -(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11)) -(assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1)) -(assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2)) +(assert_return (invoke "type-param-i32" (i32.const 2))) +(assert_return (invoke "type-param-i64" (i64.const 3))) +(assert_return (invoke "type-param-f32" (f32.const 4.4))) +(assert_return (invoke "type-param-f64" (f64.const 5.5))) (assert_return (invoke "type-mixed" @@ -117,26 +87,25 @@ (i64.const 56) ) -(assert_return - (invoke "result" - (i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5) - ) - (f64.const 34.8) -) - ;; Invalid typing of access to locals (assert_invalid - (module (func $type-local-num-vs-num (local i32) (result i64) (set_local 0 (i32.const 0)))) + (module (func $type-local-num-vs-num (result i64) (local i32) + (set_local 0 (i32.const 0)) + )) "type mismatch" ) (assert_invalid - (module (func $type-local-num-vs-num (local f32) (i32.eqz (set_local 0 (f32.const 0))))) + (module (func $type-local-num-vs-num (local f32) + (i32.eqz (set_local 0 (f32.const 0))) + )) "type mismatch" ) (assert_invalid - (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (set_local 1 (i64.const 0))))) + (module (func $type-local-num-vs-num (local f64 i64) + (f64.neg (set_local 1 (i64.const 0))) + )) "type mismatch" ) diff --git a/ml-proto/test/tee_local.wast b/ml-proto/test/tee_local.wast new file mode 100644 index 0000000000..a0fba46514 --- /dev/null +++ b/ml-proto/test/tee_local.wast @@ -0,0 +1,236 @@ +;; Test `tee_local` operator + +(module + ;; Typing + + (func "type-local-i32" (result i32) (local i32) (tee_local 0 (i32.const 0))) + (func "type-local-i64" (result i64) (local i64) (tee_local 0 (i64.const 0))) + (func "type-local-f32" (result f32) (local f32) (tee_local 0 (f32.const 0))) + (func "type-local-f64" (result f64) (local f64) (tee_local 0 (f64.const 0))) + + (func "type-param-i32" (param i32) (result i32) (tee_local 0 (i32.const 10))) + (func "type-param-i64" (param i64) (result i64) (tee_local 0 (i64.const 11))) + (func "type-param-f32" (param f32) (result f32) (tee_local 0 (f32.const 11.1))) + (func "type-param-f64" (param f64) (result f64) (tee_local 0 (f64.const 12.2))) + + (func "type-mixed" (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) + (drop (i64.eqz (tee_local 0 (i64.const 0)))) + (drop (f32.neg (tee_local 1 (f32.const 0)))) + (drop (f64.neg (tee_local 2 (f64.const 0)))) + (drop (i32.eqz (tee_local 3 (i32.const 0)))) + (drop (i32.eqz (tee_local 4 (i32.const 0)))) + (drop (f32.neg (tee_local 5 (f32.const 0)))) + (drop (i64.eqz (tee_local 6 (i64.const 0)))) + (drop (i64.eqz (tee_local 7 (i64.const 0)))) + (drop (f64.neg (tee_local 8 (f64.const 0)))) + ) + + ;; Writing + + (func "write" (param i64 f32 f64 i32 i32) (result i64) (local f32 i64 i64 f64) + (drop (tee_local 1 (f32.const -0.3))) + (drop (tee_local 3 (i32.const 40))) + (drop (tee_local 4 (i32.const -7))) + (drop (tee_local 5 (f32.const 5.5))) + (drop (tee_local 6 (i64.const 6))) + (drop (tee_local 8 (f64.const 8))) + (i64.trunc_s/f64 + (f64.add + (f64.convert_u/i64 (get_local 0)) + (f64.add + (f64.promote/f32 (get_local 1)) + (f64.add + (get_local 2) + (f64.add + (f64.convert_u/i32 (get_local 3)) + (f64.add + (f64.convert_s/i32 (get_local 4)) + (f64.add + (f64.promote/f32 (get_local 5)) + (f64.add + (f64.convert_u/i64 (get_local 6)) + (f64.add + (f64.convert_u/i64 (get_local 7)) + (get_local 8) + ) + ) + ) + ) + ) + ) + ) + ) + ) + ) + + ;; Result + + (func "result" (param i64 f32 f64 i32 i32) (result f64) + (local f32 i64 i64 f64) + (f64.add + (f64.convert_u/i64 (tee_local 0 (i64.const 1))) + (f64.add + (f64.promote/f32 (tee_local 1 (f32.const 2))) + (f64.add + (tee_local 2 (f64.const 3.3)) + (f64.add + (f64.convert_u/i32 (tee_local 3 (i32.const 4))) + (f64.add + (f64.convert_s/i32 (tee_local 4 (i32.const 5))) + (f64.add + (f64.promote/f32 (tee_local 5 (f32.const 5.5))) + (f64.add + (f64.convert_u/i64 (tee_local 6 (i64.const 6))) + (f64.add + (f64.convert_u/i64 (tee_local 7 (i64.const 0))) + (tee_local 8 (f64.const 8)) + ) + ) + ) + ) + ) + ) + ) + ) + ) +) + +(assert_return (invoke "type-local-i32") (i32.const 0)) +(assert_return (invoke "type-local-i64") (i64.const 0)) +(assert_return (invoke "type-local-f32") (f32.const 0)) +(assert_return (invoke "type-local-f64") (f64.const 0)) + +(assert_return (invoke "type-param-i32" (i32.const 2)) (i32.const 10)) +(assert_return (invoke "type-param-i64" (i64.const 3)) (i64.const 11)) +(assert_return (invoke "type-param-f32" (f32.const 4.4)) (f32.const 11.1)) +(assert_return (invoke "type-param-f64" (f64.const 5.5)) (f64.const 12.2)) + +(assert_return + (invoke "type-mixed" + (i64.const 1) (f32.const 2.2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) +) + +(assert_return + (invoke "write" + (i64.const 1) (f32.const 2) (f64.const 3.3) (i32.const 4) (i32.const 5) + ) + (i64.const 56) +) + +(assert_return + (invoke "result" + (i64.const -1) (f32.const -2) (f64.const -3.3) (i32.const -4) (i32.const -5) + ) + (f64.const 34.8) +) + + +;; Invalid typing of access to locals + +(assert_invalid + (module (func $type-local-num-vs-num (result i64) (local i32) (tee_local 0 (i32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f32) (i32.eqz (tee_local 0 (f32.const 0))))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-num-vs-num (local f64 i64) (f64.neg (tee_local 1 (i64.const 0))))) + "type mismatch" +) + +(assert_invalid + (module (func $type-local-arg-void-vs-num (local i32) (tee_local 0 (nop)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local i32) (tee_local 0 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local f32) (tee_local 0 (f64.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-local-arg-num-vs-num (local f64 i64) (tee_local 1 (f64.const 0)))) + "type mismatch" +) + + +;; Invalid typing of access to parameters + +(assert_invalid + (module (func $type-param-num-vs-num (param i32) (result i64) (get_local 0))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f32) (i32.eqz (get_local 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-num-vs-num (param f64 i64) (f64.neg (get_local 1)))) + "type mismatch" +) + +(assert_invalid + (module (func $type-param-arg-void-vs-num (param i32) (tee_local 0 (nop)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param i32) (tee_local 0 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param f32) (tee_local 0 (f64.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-param-arg-num-vs-num (param f64 i64) (tee_local 1 (f64.const 0)))) + "type mismatch" +) + + +;; Invalid local index + +(assert_invalid + (module (func $unbound-local (local i32 i64) (get_local 3))) + "unknown local" +) +(assert_invalid + (module (func $large-local (local i32 i64) (get_local 14324343))) + "unknown local" +) + +(assert_invalid + (module (func $unbound-param (param i32 i64) (get_local 2))) + "unknown local" +) +(assert_invalid + (module (func $large-param (local i32 i64) (get_local 714324343))) + "unknown local" +) + +(assert_invalid + (module (func $unbound-mixed (param i32) (local i32 i64) (get_local 3))) + "unknown local" +) +(assert_invalid + (module (func $large-mixed (param i64) (local i32 i64) (get_local 214324343))) + "unknown local" +) + +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param f32) (local i32) (tee_local 1 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param i64 i32) (local f32) (tee_local 1 (f32.const 0)))) + "type mismatch" +) +(assert_invalid + (module (func $type-mixed-arg-num-vs-num (param i64) (local f64 i64) (tee_local 1 (i64.const 0)))) + "type mismatch" +) + From 37f71e5c731bfa344d962921a5bcaea91157b99b Mon Sep 17 00:00:00 2001 From: Andreas Rossberg Date: Mon, 20 Jun 2016 17:38:40 +0200 Subject: [PATCH 7/9] Update opcodes --- ml-proto/host/encode.ml | 39 +++++++++++---------- ml-proto/host/format.ml | 3 +- ml-proto/spec/check.ml | 4 +++ ml-proto/spec/decode.ml | 74 +++++++++++++++++++++------------------- ml-proto/spec/desugar.ml | 5 +-- ml-proto/spec/eval.ml | 5 +++ ml-proto/spec/kernel.ml | 1 + 7 files changed, 72 insertions(+), 59 deletions(-) diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index 918dc1cb0f..66071aedfe 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -105,33 +105,32 @@ let encode m = let rec expr e = match e.it with | Nop -> op 0x00 - | Block es -> op 0x01; list expr es; op 0x17 - | Loop es -> op 0x02; list expr es; op 0x17 + | Block es -> op 0x01; list expr es; op 0x0f + | Loop es -> op 0x02; list expr es; op 0x0f | If (e, es1, es2) -> expr e; op 0x03; list expr es1; - if es2 <> [] then op 0x04; list expr es2; op 0x17 + if es2 <> [] then op 0x04; list expr es2; op 0x0f | Select (e1, e2, e3) -> expr e1; expr e2; expr e3; op 0x05 | Br (x, eo) -> opt expr eo; op 0x06; arity1 eo; var x | Br_if (x, eo, e) -> opt expr eo; expr e; op 0x07; arity1 eo; var x | Br_table (xs, x, eo, e) -> opt expr eo; expr e; op 0x08; arity1 eo; vec var32 xs; var32 x - - | Ast.Drop e -> unary e 0x09 - - | Ast.I32_const c -> op 0x0a; vs32 c.it - | Ast.I64_const c -> op 0x0b; vs64 c.it - | Ast.F32_const c -> op 0x0c; f32 c.it - | Ast.F64_const c -> op 0x0d; f64 c.it - - | Ast.Get_local x -> op 0x0e; var x - | Ast.Set_local (x, e) -> unary e 0x0f; var x - | Ast.Tee_local (x, e) -> unary e 0x10; var x - - | Ast.Call (x, es) -> nary es 0x12; var x - | Ast.Call_import (x, es) -> nary es 0x1f; var x - | Ast.Call_indirect (x, e, es) -> expr e; nary es 0x13; var x - | Ast.Return eo -> nary1 eo 0x14 - | Ast.Unreachable -> op 0x15 + | Ast.Return eo -> nary1 eo 0x09 + | Ast.Unreachable -> op 0x0a + | Ast.Drop e -> unary e 0x0b + + | Ast.I32_const c -> op 0x10; vs32 c.it + | Ast.I64_const c -> op 0x11; vs64 c.it + | Ast.F32_const c -> op 0x12; f32 c.it + | Ast.F64_const c -> op 0x13; f64 c.it + + | Ast.Get_local x -> op 0x14; var x + | Ast.Set_local (x, e) -> unary e 0x15; var x + | Ast.Tee_local (x, e) -> unary e 0x19; var x + + | Ast.Call (x, es) -> nary es 0x16; var x + | Ast.Call_indirect (x, e, es) -> expr e; nary es 0x17; var x + | Ast.Call_import (x, es) -> nary es 0x18; var x | I32_load8_s (o, a, e) -> unary e 0x20; memop o a | I32_load8_u (o, a, e) -> unary e 0x21; memop o a diff --git a/ml-proto/host/format.ml b/ml-proto/host/format.ml index 8feac5b886..80001e421a 100644 --- a/ml-proto/host/format.ml +++ b/ml-proto/host/format.ml @@ -215,7 +215,8 @@ let rec expr e = | CallImport (x, es) -> "call_import " ^ var x, list expr es | CallIndirect (x, e, es) -> "call_indirect " ^ var x, list expr (e::es) | GetLocal x -> "get_local " ^ var x, [] - | SetLocal (x, e) -> "tee_local " ^ var x, [expr e] + | SetLocal (x, e) -> "set_local " ^ var x, [expr e] + | TeeLocal (x, e) -> "tee_local " ^ var x, [expr e] | Load (op, e) -> memop "load" op, [expr e] | Store (op, e1, e2) -> memop "store" op, [expr e1; expr e2] | LoadExtend (op, e) -> extop op, [expr e] diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index 2582c7b804..c53480728f 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -187,6 +187,10 @@ let rec check_expr c et e = check_type (Some (local c x)) et e.at | SetLocal (x, e1) -> + check_expr c (some (local c x)) e1; + check_type None et e.at + + | TeeLocal (x, e1) -> check_expr c (some (local c x)) e1; check_type (Some (local c x)) et e.at diff --git a/ml-proto/spec/decode.ml b/ml-proto/spec/decode.ml index 543b2660d8..21a3d577b9 100644 --- a/ml-proto/spec/decode.ml +++ b/ml-proto/spec/decode.ml @@ -168,25 +168,25 @@ let rec expr stack s = Nop, es | 0x01, es -> let es' = expr_block s in - expect 0x17 s "end opcode expected"; + expect 0x0f s "END opcode expected"; Block es', es | 0x02, es -> let es' = expr_block s in - expect 0x17 s "end opcode expected"; + expect 0x0f s "END opcode expected"; Loop es', es | 0x03, e :: es -> let es1 = expr_block s in if peek s = Some 0x04 then begin - expect 0x04 s "else or end opcode expected"; + expect 0x04 s "ELSE or END opcode expected"; let es2 = expr_block s in - expect 0x17 s "end opcode expected"; + expect 0x0f s "END opcode expected"; If (e, es1, es2), es end else begin - expect 0x17 s "end opcode expected"; + expect 0x0f s "END opcode expected"; If (e, es1, []), es end | 0x04, _ -> - assert false (* else *) + error s pos "misplaced ELSE opcode" | 0x05, e3 :: e2 :: e1 :: es -> Select (e1, e2, e3), es | 0x06, es -> @@ -205,55 +205,54 @@ let rec expr stack s = let x = at var s in let eo, es' = args1 b es s pos in Br_table (xs, x, eo, e), es' + | 0x09, es -> + let b = arity1 s in + let eo, es' = args1 b es s pos in + Return eo, es' + | 0x0a, es -> + Unreachable, es + | 0x0b, e :: es -> + Drop e, es + | 0x0c | 0x0d | 0x0e as b, _ -> + illegal s pos b + | 0x0f, _ -> + error s pos "misplaced END opcode" - | 0x09, e :: es -> Drop e, es - - | 0x0a, es -> I32_const (at vs32 s), es - | 0x0b, es -> I64_const (at vs64 s), es - | 0x0c, es -> F32_const (at f32 s), es - | 0x0d, es -> F64_const (at f64 s), es + | 0x10, es -> I32_const (at vs32 s), es + | 0x11, es -> I64_const (at vs64 s), es + | 0x12, es -> F32_const (at f32 s), es + | 0x13, es -> F64_const (at f64 s), es - | 0x0e, es -> + | 0x14, es -> let x = at var s in Get_local x, es - | 0x0f, e :: es -> + | 0x15, e :: es -> let x = at var s in Set_local (x, e), es - | 0x10, e :: es -> - let x = at var s in - Tee_local (x, e), es - - | 0x11 as b, _ -> illegal s pos b - | 0x12, es -> + | 0x16, es -> let n = arity s in let x = at var s in let es1, es' = args n es s pos in Call (x, es1), es' - | 0x13, es -> + | 0x17, es -> let n = arity s in let x = at var s in let es1, es' = args (n + 1) es s pos in Call_indirect (x, List.hd es1, List.tl es1), es' - - | 0x14, es -> - let b = arity1 s in - let eo, es' = args1 b es s pos in - Return eo, es' - | 0x15, es -> - Unreachable, es - - | 0x16, _ -> assert false (* next *) - | 0x17, _ -> assert false (* end *) - | 0x18 | 0x19 | 0x1a | 0x1b | 0x1c | 0x1d | 0x1e as b, _ -> - illegal s pos b - - | 0x1f, es -> + | 0x18, es -> let n = arity s in let x = at var s in let es1, es' = args n es s pos in Call_import (x, es1), es' + | 0x19, e :: es -> + let x = at var s in + Tee_local (x, e), es + + | 0x1a | 0x1b | 0x1c | 0x1d | 0x1e | 0x1f as b, _ -> + illegal s pos b + | 0x20, e :: es -> let o, a = memop s in I32_load8_s (o, a, e), es | 0x21, e :: es -> let o, a = memop s in I32_load8_u (o, a, e), es | 0x22, e :: es -> let o, a = memop s in I32_load16_s (o, a, e), es @@ -280,10 +279,13 @@ let rec expr stack s = | 0x36, e2 :: e1 :: es -> let o, a = memop s in F64_store (o, a, e1, e2), es | 0x37 | 0x38 as b, _ -> illegal s pos b + | 0x39, e :: es -> Grow_memory e, es | 0x3a as b, _ -> illegal s pos b | 0x3b, es -> Current_memory, es + | 0x3c | 0x3d | 0x3e | 0x3f as b, _ -> illegal s pos b + | 0x40, e2 :: e1 :: es -> I32_add (e1, e2), es | 0x41, e2 :: e1 :: es -> I32_sub (e1, e2), es | 0x42, e2 :: e1 :: es -> I32_mul (e1, e2), es @@ -421,7 +423,7 @@ and expr_block s = List.rev (expr_block' [] s) and expr_block' stack s = if eos s then stack else match peek s with - | None | Some (0x04 | 0x16 | 0x17) -> stack + | None | Some (0x04 | 0x0f) -> stack | _ -> let pos = pos s in let e', stack' = expr stack s in diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index e3df391cc7..b48b09a24c 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -32,6 +32,7 @@ and relabel' f n = function CallIndirect (x, relabel f n e, List.map (relabel f n) es) | GetLocal x -> GetLocal x | SetLocal (x, e) -> SetLocal (x, relabel f n e) + | TeeLocal (x, e) -> TeeLocal (x, relabel f n e) | Load (memop, e) -> Load (memop, relabel f n e) | Store (memop, e1, e2) -> Store (memop, relabel f n e1, relabel f n e2) | LoadExtend (extop, e) -> LoadExtend (extop, relabel f n e) @@ -80,8 +81,8 @@ and expr' at = function | Ast.Call_indirect (x, e, es) -> CallIndirect (x, expr e, List.map expr es) | Ast.Get_local x -> GetLocal x - | Ast.Set_local (x, e) -> Drop (SetLocal (x, expr e) @@ at) - | Ast.Tee_local (x, e) -> SetLocal (x, expr e) + | Ast.Set_local (x, e) -> SetLocal (x, expr e) + | Ast.Tee_local (x, e) -> TeeLocal (x, expr e) | Ast.I32_load (offset, align, e) -> Load ({ty = Int32Type; offset; align}, expr e) diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index ce67762292..a7260a01f5 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -195,6 +195,11 @@ let rec eval_expr (c : config) (e : expr) = Some !(local c x) | SetLocal (x, e1) -> + let v1 = some (eval_expr c e1) e1.at in + local c x := v1; + None + + | TeeLocal (x, e1) -> let v1 = some (eval_expr c e1) e1.at in local c x := v1; Some v1 diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index dc5d7f0ec5..50137a498b 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -91,6 +91,7 @@ and expr' = | CallIndirect of var * expr * expr list (* call function through table *) | GetLocal of var (* read local variable *) | SetLocal of var * expr (* write local variable *) + | TeeLocal of var * expr (* write local variable and keep value *) | Load of memop * expr (* read memory at address *) | Store of memop * expr * expr (* write memory at address *) | LoadExtend of extop * expr (* read memory at address and extend *) From aadb3b53b77c1eb091d960228bea7ee912b40afb Mon Sep 17 00:00:00 2001 From: rossberg-chromium Date: Tue, 5 Jul 2016 11:42:05 +0200 Subject: [PATCH 8/9] Require arity 1 for select --- ml-proto/spec/check.ml | 1 + ml-proto/test/select.wast | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index c53480728f..508317ea42 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -163,6 +163,7 @@ let rec check_expr c et e = check_expr c et e3 | Select (e1, e2, e3) -> + require (is_some et) e.at "arity mismatch"; check_expr c et e1; check_expr c et e2; check_expr c (some Int32Type) e3 diff --git a/ml-proto/test/select.wast b/ml-proto/test/select.wast index 44e4c2fb7d..29919f0831 100644 --- a/ml-proto/test/select.wast +++ b/ml-proto/test/select.wast @@ -57,3 +57,8 @@ (assert_trap (invoke "select_trap_l" (i32.const 0)) "unreachable executed") (assert_trap (invoke "select_trap_r" (i32.const 1)) "unreachable executed") (assert_trap (invoke "select_trap_r" (i32.const 0)) "unreachable executed") + +(assert_invalid + (module (func $arity-0 (select (nop) (nop) (i32.const 1)))) + "arity mismatch" +) From fa129a626fe6f0f2c54185d1fd101eca682da96c Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 6 Jul 2016 06:41:38 -0700 Subject: [PATCH 9/9] Add tests for conflicting-but-ultimately-dropped values. (#305) Add tests for conflicting-but-ultimately-dropped values. --- ml-proto/test/br.wast | 23 +++++++++++++++++++++++ ml-proto/test/br_if.wast | 22 ++++++++++++++++++++++ ml-proto/test/br_table.wast | 22 ++++++++++++++++++++++ ml-proto/test/typecheck.wast | 10 ++++++++++ 4 files changed, 77 insertions(+) diff --git a/ml-proto/test/br.wast b/ml-proto/test/br.wast index ce34922420..d439ee1ce6 100644 --- a/ml-proto/test/br.wast +++ b/ml-proto/test/br.wast @@ -417,3 +417,26 @@ (module (func $large-label (br 0x100000001))) "unknown label" ) + +;; Test that the value operand of br matches the result type of the block +;; it branches to, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) + (drop + (block $green + (br $green (get_local $x)) + (get_local $y))))) + "type mismatch") + +;; Test that the value operand of br matches the result type of other +;; branches to the same block, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) + (drop + (block $green + (br $green (get_local $x)) + (br $green (get_local $y)) + (get_local $x))))) + "type mismatch") diff --git a/ml-proto/test/br_if.wast b/ml-proto/test/br_if.wast index d0a79b5d14..fa72482c9f 100644 --- a/ml-proto/test/br_if.wast +++ b/ml-proto/test/br_if.wast @@ -306,3 +306,25 @@ "unknown label" ) +;; Test that the value operand of br_if matches the result type of the block +;; it branches to, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) (param $cond i32) + (drop + (block $green + (br_if $green (get_local $x) (get_local $cond)) + (get_local $y))))) + "type mismatch") + +;; Test that the value operand of br_if matches the result type of other +;; branches to the same block, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) (param $cond i32) + (drop + (block $green + (br_if $green (get_local $x) (get_local $cond)) + (br_if $green (get_local $y) (get_local $cond)) + (get_local $x))))) + "type mismatch") diff --git a/ml-proto/test/br_table.wast b/ml-proto/test/br_table.wast index aab0a61c70..e81592bd3d 100644 --- a/ml-proto/test/br_table.wast +++ b/ml-proto/test/br_table.wast @@ -1385,3 +1385,25 @@ "unknown label" ) +;; Test that the value operand of br_table matches the result type of the block +;; it branches to, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) (param $index i32) + (drop + (block $green + (br_table $green $green (get_local $x) (get_local $index)) + (get_local $y))))) + "type mismatch") + +;; Test that the value operand of br_table matches the result type of other +;; branches to the same block, even if the result of the block is dropped. +(assert_invalid + (module + (func $bar (param $x i32) (param $y f32) (param $index i32) + (drop + (block $green + (br_table $green $green (get_local $x) (get_local $index)) + (br_table $green $green (get_local $y) (get_local $index)) + (get_local $x))))) + "type mismatch") diff --git a/ml-proto/test/typecheck.wast b/ml-proto/test/typecheck.wast index 8522f754f1..d251e94dd1 100644 --- a/ml-proto/test/typecheck.wast +++ b/ml-proto/test/typecheck.wast @@ -4,6 +4,16 @@ ;; if condition (assert_invalid (module (func (if (f32.const 0) (nop) (nop)))) "type mismatch") +;; if arms +(assert_invalid + (module + (func $foo (param $x i32) (param $y f32) (param $cond i32) + (drop + (if (get_local $cond) + (get_local $y) + (get_local $x))))) + "type mismatch") + ;; br_if condition (assert_invalid (module (func (block (br_if 0 (f32.const 0))))) "type mismatch")