diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index c92d907aae..66071aedfe 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -105,30 +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.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.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 8961d23c0b..80001e421a 100644 --- a/ml-proto/host/format.ml +++ b/ml-proto/host/format.ml @@ -195,6 +195,7 @@ 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 -> assert false @@ -215,6 +216,7 @@ let rec expr e = | 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] + | 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/host/lexer.mll b/ml-proto/host/lexer.mll index 61b4d62f7d..9824be3673 100644 --- a/ml-proto/host/lexer.mll +++ b/ml-proto/host/lexer.mll @@ -142,6 +142,7 @@ rule token = parse | "nop" { NOP } | "unreachable" { UNREACHABLE } + | "drop" { DROP } | "block" { BLOCK } | "loop" { LOOP } | "br" { BR } @@ -158,6 +159,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) -> @@ -172,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 @@ -189,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 @@ -381,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/host/parser.mly b/ml-proto/host/parser.mly index 6ad96b633e..c503474bc6 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -125,9 +125,9 @@ let implicit_decl c t at = %} %token NAT 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 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 @@ -231,6 +231,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'') } @@ -260,6 +261,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 efff76c307..6e9fddb957 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 @@ -28,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 a64b88f7df..508317ea42 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_future = [`Known of expr_type | `SomeUnknown] 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_future list; has_memory : bool } @@ -36,12 +38,23 @@ let local c x = lookup "local" c.locals x let label c x = lookup "label" c.labels x -(* Type comparison *) +(* Type Unification *) + +let string_of_future = function + | `Known et -> string_of_expr_type et + | `SomeUnknown -> "" let check_type actual expected at = - require (expected = None || 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_expr_type expected) + " but the context requires " ^ string_of_future !expected) + +let some_unknown () = ref `SomeUnknown +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 *) @@ -99,7 +112,7 @@ let type_hostop = function (* Type Analysis *) (* - * check_expr : context -> expr_type -> expr -> unit + * check_expr : context -> expr_type_future -> expr -> unit * * Conventions: * c : context @@ -107,7 +120,7 @@ let type_hostop = function * eo : expr option * v : value * t : value_type - * et : expr_type + * et : expr_type_future *) let rec check_expr c et e = @@ -118,13 +131,17 @@ let rec check_expr c et e = | Unreachable -> () + | Drop 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 - 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 +149,24 @@ 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) -> + require (is_some et) e.at "arity mismatch"; 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 +180,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 +188,12 @@ 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 + + | TeeLocal (x, e1) -> + check_expr c (some (local c x)) e1; + check_type (Some (local c x)) et e.at | Load (memop, e1) -> check_load c et memop e1 e.at @@ -193,29 +214,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) -> @@ -226,13 +247,14 @@ let rec check_expr c et e = and check_exprs c ts es at = require (List.length ts = List.length es) at "arity mismatch"; - let ets = List.map (fun x -> Some x) ts in + let ets = List.map some ts in List.iter2 (check_expr c) ets es 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 @@ -240,15 +262,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 +302,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..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,52 +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 as b, es -> illegal s pos b - - | 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 | 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 @@ -277,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 @@ -418,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 91ed5f0912..b48b09a24c 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) @@ -31,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) @@ -61,6 +63,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) @@ -79,6 +82,7 @@ and expr' at = function | Ast.Get_local x -> GetLocal x | 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 d892d74f52..a7260a01f5 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 -> + ignore (eval_expr c e); + None + | Block (es, e) -> let module L = MakeLabel () in let c' = {c with labels = L.label :: c.labels} in @@ -191,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 @@ -207,7 +216,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 +230,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 +278,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..50137a498b 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 *) @@ -90,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 *) 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 60e6f58ee5..ea68ad6e71 100644 --- a/ml-proto/test/block.wast +++ b/ml-proto/test/block.wast @@ -1,6 +1,9 @@ -;; Test `block` opcode +;; Test `block` operator (module + ;; Auxiliary definition + (func $dummy) + (func "empty" (block) (block $l) @@ -11,14 +14,16 @@ (block (i32.const 7)) ) - (func $nop) (func "multi" (result i32) - (block (call $nop) (call $nop) (call $nop) (call $nop)) - (block (call $nop) (call $nop) (call $nop) (i32.const 8)) + (block (call $dummy) (call $dummy) (call $dummy) (call $dummy)) + (block (call $dummy) (call $dummy) (call $dummy) (i32.const 8)) ) (func "nested" (result i32) - (block (block (call $nop) (block) (nop)) (block (call $nop) (i32.const 9))) + (block + (block (call $dummy) (block) (nop)) + (block (call $dummy) (i32.const 9)) + ) ) (func "deep" (result i32) @@ -26,7 +31,7 @@ (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block (block - (block (block (block (block (block (call $nop) (i32.const 150)))))) + (block (block (block (block (call $dummy) (i32.const 150))))) )))))))))) )))))))))) )))))))))) @@ -34,16 +39,22 @@ ) (func "as-unary-operand" (result i32) - (i32.ctz (block (call $nop) (i32.const 13))) + (i32.ctz (block (call $dummy) (i32.const 13))) ) (func "as-binary-operand" (result i32) - (i32.mul (block (call $nop) (i32.const 3)) (block (call $nop) (i32.const 4))) + (i32.mul + (block (call $dummy) (i32.const 3)) + (block (call $dummy) (i32.const 4)) + ) ) (func "as-test-operand" (result i32) - (i32.eqz (block (call $nop) (i32.const 13))) + (i32.eqz (block (call $dummy) (i32.const 13))) ) (func "as-compare-operand" (result i32) - (f32.gt (block (call $nop) (f32.const 3)) (block (call $nop) (f32.const 3))) + (f32.gt + (block (call $dummy) (f32.const 3)) + (block (call $dummy) (f32.const 3)) + ) ) (func "break-bare" (result i32) @@ -73,44 +84,15 @@ (set_local 0 (i32.const 0)) (set_local 0 (i32.add (get_local 0) (block (block (br 1 (i32.const 0x1)))))) (set_local 0 (i32.add (get_local 0) (block (block (br 0)) (i32.const 0x2)))) - (set_local 0 (i32.add (get_local 0) (block (i32.ctz (br 0 (i32.const 0x4)))))) - (set_local 0 (i32.add (get_local 0) (block (i32.ctz (block (br 1 (i32.const 0x8))))))) + (set_local 0 + (i32.add (get_local 0) (block (i32.ctz (br 0 (i32.const 0x4))))) + ) + (set_local 0 + (i32.add (get_local 0) (block (i32.ctz (block (br 1 (i32.const 0x8)))))) + ) (get_local 0) ) - (func "drop-mid" (result i32) - (block (call $fx) (i32.const 7) (call $nop) (i32.const 8)) - ) - (func "drop-last" - (block (call $nop) (call $fx) (nop) (i32.const 8)) - ) - (func "drop-break-void" - (block (br 0 (nop))) - (block (br 0 (call $nop))) - (block (br_if 0 (nop) (i32.const 0))) - (block (br_if 0 (nop) (i32.const 1))) - (block (br_if 0 (call $nop) (i32.const 0))) - (block (br_if 0 (call $nop) (i32.const 1))) - (block (br_table 0 (nop) (i32.const 3))) - (block (br_table 0 0 0 (nop) (i32.const 2))) - ) - (func "drop-break-value" - (block (br 0 (i32.const 12))) - (block (br_if 0 (i32.const 11) (i32.const 0))) - (block (br_if 0 (i32.const 10) (i32.const 1))) - (block (br_table 0 (i32.const 9) (i32.const 5))) - (block (br_table 0 0 0 (i32.const 8) (i32.const 1))) - ) - (func "drop-break-value-heterogeneous" - (block (br 0 (i32.const 8)) (br 0 (f64.const 8)) (br 0 (f32.const 8))) - (block (br 0 (i32.const 8)) (br 0) (br 0 (f64.const 8))) - (block (br 0 (i32.const 8)) (br 0 (call $nop)) (br 0 (f64.const 8))) - (block (br 0 (i32.const 8)) (br 0) (br 0 (f32.const 8)) (i64.const 3)) - (block (br 0) (br 0 (i32.const 8)) (br 0 (f64.const 8)) (br 0 (nop))) - (block (br 0) (br 0 (i32.const 8)) (br 0 (f32.const 8)) (i64.const 3)) - (block (block (br 0) (br 1 (i32.const 8))) (br 0 (f32.const 8)) (i64.const 3)) - ) - (func "effects" $fx (result i32) (local i32) (block @@ -141,12 +123,6 @@ (assert_return (invoke "break-repeated") (i32.const 18)) (assert_return (invoke "break-inner") (i32.const 0xf)) -(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_invalid @@ -166,6 +142,25 @@ "type mismatch" ) +(assert_invalid + (module (func $type-first-num-vs-void (result i32) + (block (i32.const 7) (nop) (i32.const 8)) + )) + "type mismatch" +) +(assert_invalid + (module (func $type-mid-num-vs-void (result i32) + (block (nop) (i32.const 7) (nop) (i32.const 8)) + )) + "type mismatch" +) + +(assert_invalid + (module (func $type-value-num-vs-void + (block (i32.const 1)) + )) + "type mismatch" +) (assert_invalid (module (func $type-value-void-vs-num (result i32) (block (nop)) @@ -178,6 +173,12 @@ )) "type mismatch" ) +(assert_invalid + (module (func $type-value-num-vs-void-after-break + (block (br 0) (i32.const 1)) + )) + "type mismatch" +) (assert_invalid (module (func $type-value-void-vs-num-after-break (result i32) (block (br 0 (i32.const 1)) (nop)) @@ -192,15 +193,47 @@ ) (assert_invalid - (module (func $type-break-last-void-vs-num (result i32) + (module (func $type-break-last-void-vs-empty + (block (br 0 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-num-vs-empty + (block (br 0 (i32.const 66))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-last-empty-vs-num (result i32) (block (br 0)) )) - "type mismatch" + "arity mismatch" ) + (assert_invalid - (module (func $type-break-void-vs-num (result i32) + (module (func $type-break-void-vs-empty + (block (br 0 (nop))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-num-vs-empty + (block (br 0 (i32.const 1))) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-empty-vs-num (result i32) (block (br 0) (i32.const 1)) )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-break-void-vs-num (result i32) + (block (br 0 (nop)) (i32.const 1)) + )) "type mismatch" ) (assert_invalid @@ -209,12 +242,24 @@ )) "type mismatch" ) +(assert_invalid + (module (func $type-break-first-void-vs-num (result i32) + (block (br 0 (nop)) (br 0 (i32.const 1))) + )) + "type mismatch" +) (assert_invalid (module (func $type-break-first-num-vs-num (result i32) (block (br 0 (i64.const 1)) (br 0 (i32.const 1))) )) "type mismatch" ) +(assert_invalid + (module (func $type-break-second-void-vs-num (result i32) + (block (br 0 (i32.const 1)) (br 0 (nop))) + )) + "type mismatch" +) (assert_invalid (module (func $type-break-second-num-vs-num (result i32) (block (br 0 (i32.const 1)) (br 0 (f64.const 1))) @@ -223,9 +268,28 @@ ) (assert_invalid - (module (func $type-break-nested-void-vs-num (result i32) + (module (func $type-break-nested-void-vs-empty + (block (block (br 1 (nop))) (br 0)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-num-vs-empty + (block (block (br 1 (i32.const 1))) (br 0)) + )) + "arity mismatch" +) +(assert_invalid + (module (func $type-break-nested-empty-vs-num (result i32) (block (block (br 1)) (br 0 (i32.const 1))) )) + "arity mismatch" +) + +(assert_invalid + (module (func $type-break-nested-void-vs-num (result i32) + (block (block (br 1 (nop))) (br 0 (i32.const 1))) + )) "type mismatch" ) (assert_invalid @@ -234,24 +298,23 @@ )) "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 (block (br 0))) )) - "type mismatch" + "arity mismatch" ) + (assert_invalid - (module (func $type-break-operand-num-vs-num (result i32) - (i64.ctz (block (br 0 (i64.const 9)))) + (module (func $type-break-operand-void-vs-num (result i32) + (i64.ctz (block (br 0 (nop)))) )) "type mismatch" ) (assert_invalid - (module (func (result i32) (block (br 0)))) - "type mismatch" -) -(assert_invalid - (module (func (result i32) (i32.ctz (block (br 0))))) + (module (func $type-break-operand-num-vs-num (result i32) + (i64.ctz (block (br 0 (i64.const 9)))) + )) "type mismatch" ) - diff --git a/ml-proto/test/br.wast b/ml-proto/test/br.wast index a370f88af7..d439ee1ce6 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 @@ -362,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 dfa989e2a3..fa72482c9f 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" ) @@ -289,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 4378ea4e76..e81592bd3d 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 @@ -1332,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/break-drop.wast b/ml-proto/test/break-drop.wast index 30b05b7df6..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 (i32.const 1)))) - (export "br-drop" $br-drop) - - (func $br-block-nop (block (br 0 (block (i32.const 1) (nop))))) - (export "br-block-nop" $br-block-nop) - - (func $br-block-drop (block (br 0 (block (nop) (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 (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)))) - (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)))) - (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 (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)))) - (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) (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/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/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 33e793e0b7..70b9cc47f4 100644 --- a/ml-proto/test/func.wast +++ b/ml-proto/test/func.wast @@ -53,13 +53,14 @@ (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) - (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-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) @@ -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) ) @@ -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/get_local.wast b/ml-proto/test/get_local.wast index a31c527a28..a5d09833df 100644 --- a/ml-proto/test/get_local.wast +++ b/ml-proto/test/get_local.wast @@ -13,17 +13,17 @@ (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) (result f64) + (func "type-mixed" (param i64 f32 f64 i32 i32) (local f32 i64 i64 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)) + (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 @@ -75,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 diff --git a/ml-proto/test/labels.wast b/ml-proto/test/labels.wast index 84a75e7439..c1cd2bf1fa 100644 --- a/ml-proto/test/labels.wast +++ b/ml-proto/test/labels.wast @@ -151,13 +151,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) ) @@ -174,7 +172,6 @@ ) ;; 0 (return (i32.const 0)) ) ;; 1 - (i32.const 1) ) ;; default (i32.const 2) ) @@ -190,13 +187,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) ) ) @@ -215,25 +212,26 @@ (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) ) - (func $br_if4 - (block $l0 (br_if $l0 (nop) (i32.const 1))) - ) - (func $br (result i32) (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) ) @@ -249,10 +247,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) @@ -269,7 +268,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) @@ -297,7 +295,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)) @@ -317,7 +314,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 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/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/memory.wast b/ml-proto/test/memory.wast index 390717e4cd..f98118839d 100644 --- a/ml-proto/test/memory.wast +++ b/ml-proto/test/memory.wast @@ -46,29 +46,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/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/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/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/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" +) diff --git a/ml-proto/test/set_local.wast b/ml-proto/test/set_local.wast index 615eeae6ab..52aced9a26 100644 --- a/ml-proto/test/set_local.wast +++ b/ml-proto/test/set_local.wast @@ -3,26 +3,26 @@ (module ;; Typing - (func "type-local-i32" (result i32) (local i32) (set_local 0 (i32.const 0))) - (func "type-local-i64" (result i64) (local i64) (set_local 0 (i64.const 0))) - (func "type-local-f32" (result f32) (local f32) (set_local 0 (f32.const 0))) - (func "type-local-f64" (result f64) (local 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 @@ -63,48 +63,17 @@ ) ) ) - - ;; Result - - (func "result" (param i64 f32 f64 i32 i32) (result f64) - (local f32 i64 i64 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" @@ -119,26 +88,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 (result i64) (local i32) (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/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/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" +) + 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/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") diff --git a/ml-proto/test/unreachable.wast b/ml-proto/test/unreachable.wast index 446940f796..3ec8f9d870 100644 --- a/ml-proto/test/unreachable.wast +++ b/ml-proto/test/unreachable.wast @@ -1,7 +1,9 @@ ;; Test `unreachable` operator (module + ;; Auxiliary definitions (func $dummy) + (func $dummy3 (param i32 i32 i32)) (func "type-i32" (result i32) (unreachable)) (func "type-i64" (result i32) (unreachable)) @@ -98,7 +100,6 @@ (select (i32.const 0) (i32.const 1) (unreachable)) ) - (func $dummy3 (param i32 i32 i32)) (func "as-call-first" (call $dummy3 (unreachable) (i32.const 2) (i32.const 3)) )