diff --git a/ml-proto/README.md b/ml-proto/README.md index f4c294a28d..2898bdcae9 100644 --- a/ml-proto/README.md +++ b/ml-proto/README.md @@ -140,22 +140,28 @@ offset: offset= align: align=(1|2|4|8|...) cvtop: trunc_s | trunc_u | extend_s | extend_u | ... +block_sig : * +func_sig: ( type ) | * * +global_sig: | ( mut ) +table_sig: ? +memory_sig: ? + expr: ( ) ( + ) ;; = + () - ( block ? * ) - ( loop ? * ) - ( if ( then ? * ) ( else ? * )? ) - ( if ( then ? * ) ( else ? * )? ) ;; = (if (then ? *) (else ? *)?) - ( if ? ) ;; = (if (then ) (else ?)) + ( block ? ? * ) + ( loop ? ? * ) + ( if ? ? ( then * ) ( else * )? ) + ( if ? ? ( then * ) ( else * )? ) ;; = (if ? ? (then *) (else *)?) + ( if ? ? ? ) ;; = (if ? ? (then ) (else ?)) instr: ;; = () - block ? * end ;; = (block ? *) - loop ? * end ;; = (loop ? *) - if ? * end ;; = (if (then ? *)) - if ? * else ? * end ;; = (if (then ? instr>*) (else ? *)) + block ? ? * end ;; = (block ? ? *) + loop ? ? * end ;; = (loop ? ? *) + if ? ? * end ;; = (if ? ? (then *)) + if ? ? * else * end ;; = (if ? ? (then *) (else *)) op: unreachable @@ -189,11 +195,6 @@ param: ( param * ) | ( param ) result: ( result ) local: ( local * ) | ( local ) -func_sig: ( type ) | * ? -global_sig: | ( mut ) -table_sig: ? -memory_sig: ? - global: ( global ? ) ( global ? ( export ) ) ;; = (export (global )) (global ? ) ( global ? ( import ) ) ;; = (import ? (global )) diff --git a/ml-proto/host/arrange.ml b/ml-proto/host/arrange.ml index e2a5b97e33..311f6cc559 100644 --- a/ml-proto/host/arrange.ml +++ b/ml-proto/host/arrange.ml @@ -53,6 +53,8 @@ let elem_type t = string_of_elem_type t let decls kind ts = tab kind (atom value_type) ts +let stack_type ts = list (atom value_type) ts + let func_type (FuncType (ins, out)) = Node ("func", decls "param" ins @ decls "result" out) @@ -214,15 +216,16 @@ let rec instr e = | Unreachable -> "unreachable", [] | Nop -> "nop", [] | Drop -> "drop", [] - | Block es -> "block", list instr es - | Loop es -> "loop", list instr es - | Br (n, x) -> "br " ^ int n ^ " " ^ var x, [] - | BrIf (n, x) -> "br_if " ^ int n ^ " " ^ var x, [] - | BrTable (n, xs, x) -> - "br_table " ^ int n ^ " " ^ String.concat " " (list var (xs @ [x])), [] + | Block (ts, es) -> "block", stack_type ts @ list instr es + | Loop (ts, es) -> "loop", stack_type ts @ list instr es + | Br x -> "br " ^ var x, [] + | BrIf x -> "br_if " ^ var x, [] + | BrTable (xs, x) -> + "br_table " ^ String.concat " " (list var (xs @ [x])), [] | Return -> "return", [] - | If (es1, es2) -> - "if", [Node ("then", list instr es1); Node ("else", list instr es2)] + | If (ts, es1, es2) -> + "if", stack_type ts @ + [Node ("then", list instr es1); Node ("else", list instr es2)] | Select -> "select", [] | Call x -> "call " ^ var x, [] | CallIndirect x -> "call_indirect " ^ var x, [] diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index 783c149c1e..5fc125087d 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -3,6 +3,12 @@ let version = 0x0cl +(* Errors *) + +module Code = Error.Make () +exception Code = Code.Error + + (* Encoding stream *) type stream = @@ -52,15 +58,20 @@ let encode m = let vu32 i = vu64 (Int64.of_int32 i) let vs32 i = vs64 (Int64.of_int32 i) - let vu i = vu64 (Int64.of_int i) let f32 x = u32 (F32.to_bits x) let f64 x = u64 (F64.to_bits x) + let len i = + if Int32.to_int (Int32.of_int i) <> i then + Code.error Source.no_region + "cannot encode length with more than 32 bit"; + vu32 (Int32.of_int i) + let bool b = u8 (if b then 1 else 0) - let string bs = vu (String.length bs); put_string s bs + let string bs = len (String.length bs); put_string s bs let list f xs = List.iter f xs let opt f xo = Lib.Option.app f xo - let vec f xs = vu (List.length xs); list f xs + let vec f xs = len (List.length xs); list f xs let vec1 f xo = bool (xo <> None); opt f xo let gap32 () = let p = pos s in u32 0l; u8 0; p @@ -86,6 +97,13 @@ let encode m = let elem_type = function | AnyFuncType -> u8 0x20 + let stack_type = function + | [] -> u8 0x00 + | [t] -> value_type t + | _ -> + Code.error Source.no_region + "cannot encode stack type with arity > 1 (yet)" + let func_type = function | FuncType (ins, out) -> u8 0x40; vec value_type ins; vec value_type out @@ -105,22 +123,6 @@ let encode m = let global_type = function | GlobalType (t, mut) -> value_type t; mutability mut - let limits vu {min; max} = - bool (max <> None); vu min; opt vu max - - let table_type = function - | TableType (lim, t) -> elem_type t; limits vu32 lim - - let memory_type = function - | MemoryType lim -> limits vu32 lim - - let mutability = function - | Immutable -> u8 0 - | Mutable -> u8 1 - - let global_type = function - | GlobalType (t, mut) -> value_type t; mutability mut - (* Expressions *) open Source @@ -128,9 +130,6 @@ let encode m = open Values open Memory - let arity xs = vu (List.length xs) - let arity1 xo = bool (xo <> None) - let op n = u8 n let memop {align; offset; _} = vu32 (I32.ctz (Int32.of_int align)); @@ -141,16 +140,16 @@ let encode m = let rec instr e = match e.it with | Unreachable -> op 0x00 - | Block es -> op 0x01; list instr es; op 0x0f - | Loop es -> op 0x02; list instr es; op 0x0f - | If (es1, es2) -> - op 0x03; list instr es1; + | Block (ts, es) -> op 0x01; stack_type ts; list instr es; op 0x0f + | Loop (ts, es) -> op 0x02; stack_type ts; list instr es; op 0x0f + | If (ts, es1, es2) -> + op 0x03; stack_type ts; list instr es1; if es2 <> [] then op 0x04; list instr es2; op 0x0f | Select -> op 0x05 - | Br (n, x) -> op 0x06; vu n; var x - | BrIf (n, x) -> op 0x07; vu n; var x - | BrTable (n, xs, x) -> op 0x08; vu n; vec var xs; var x + | Br x -> op 0x06; var x + | BrIf x -> op 0x07; var x + | BrTable (xs, x) -> op 0x08; vec var xs; var x | Return -> op 0x09 | Nop -> op 0x0a | Drop -> op 0x0b @@ -449,7 +448,7 @@ let encode m = | ts -> (t, 1) :: ts in List.fold_right combine ts [] - let local (t, n) = vu n; value_type t + let local (t, n) = len n; value_type t let code f = let {locals; body; _} = f.it in diff --git a/ml-proto/host/encode.mli b/ml-proto/host/encode.mli index 7dc4966b3f..3a7e99734d 100644 --- a/ml-proto/host/encode.mli +++ b/ml-proto/host/encode.mli @@ -1,3 +1,5 @@ +exception Code of Source.region * string + val version : int32 val encode : Ast.module_ -> string diff --git a/ml-proto/host/js.ml b/ml-proto/host/js.ml index 6eb014f2ad..ea93225fed 100644 --- a/ml-proto/host/js.ml +++ b/ml-proto/host/js.ml @@ -126,7 +126,7 @@ let assert_return lits ts at = [ Const lit @@ at; Compare (eq_of (Values.type_of lit.it)) @@ at; Test (Values.I32 I32Op.Eqz) @@ at; - BrIf (0, 0l @@ at) @@ at ] + BrIf (0l @@ at) @@ at ] in [], List.flatten (List.rev_map test lits) let assert_return_nan ts at = @@ -136,7 +136,7 @@ let assert_return_nan ts at = [ GetLocal (var i) @@ at; GetLocal (var i) @@ at; Compare (eq_of t) @@ at; - BrIf (0, 0l @@ at) @@ at ] + BrIf (0l @@ at) @@ at ] in ts, List.flatten (List.mapi init ts @ List.mapi test ts) let wrap module_name item_name wrap_action wrap_assertion at = @@ -148,7 +148,9 @@ let wrap module_name item_name wrap_action wrap_assertion at = let ekind = FuncExport @@ at in let exports = [{name = "run"; ekind; item} @@ at] in let body = - [Block (action @ assertion @ [Return @@ at]) @@ at; Unreachable @@ at] in + [ Block ([], action @ assertion @ [Return @@ at]) @@ at; + Unreachable @@ at ] + in let funcs = [{ftype = 0l @@ at; locals; body} @@ at] in let m = {empty_module with types; funcs; imports; exports} @@ at in Encode.encode m diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index 35b35f928e..8123216372 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -254,10 +254,6 @@ type_use : /* Expressions */ -nat : - | NAT { int_of_string $1 } -; - literal : | NAT { $1 @@ at () } | INT { $1 @@ at () } @@ -297,7 +293,7 @@ align_opt : instr : | plain_instr { let at = at () in fun c -> [$1 c @@ at] } - | ctrl_instr { let at = at () in fun c -> [$1 c @@ at] } + | block_instr { let at = at () in fun c -> [$1 c @@ at] } | expr { $1 } /* Sugar */ ; plain_instr : @@ -305,13 +301,11 @@ plain_instr : | NOP { fun c -> nop } | DROP { fun c -> drop } | SELECT { fun c -> select } - | BR nat var { fun c -> br $2 ($3 c label) } - | BR_IF nat var { fun c -> br_if $2 ($3 c label) } - | BR_TABLE var /*nat*/ var var_list - { fun c -> let xs, x = Lib.List.split_last ($3 c label :: $4 c label) in - (* TODO: remove hack once arities are gone *) - let n = $2 c (fun _ -> error x.at "syntax error") in - br_table (Int32.to_int n.it) xs x } + | BR var { fun c -> br ($2 c label) } + | BR_IF var { fun c -> br_if ($2 c label) } + | BR_TABLE var var_list + { fun c -> let xs, x = Lib.List.split_last ($2 c label :: $3 c label) in + br_table xs x } | RETURN { fun c -> return } | CALL var { fun c -> call ($2 c func) } | CALL_INDIRECT var { fun c -> call_indirect ($2 c type_) } @@ -331,15 +325,18 @@ plain_instr : | CURRENT_MEMORY { fun c -> current_memory } | GROW_MEMORY { fun c -> grow_memory } ; -ctrl_instr : - | BLOCK labeling_opt instr_list END - { fun c -> let c' = $2 c in block ($3 c') } - | LOOP labeling_opt instr_list END - { fun c -> let c' = $2 c in loop ($3 c') } - | IF labeling_opt instr_list END - { fun c -> let c' = $2 c in if_ ($3 c') [] } - | IF labeling_opt instr_list ELSE labeling_opt instr_list END - { fun c -> let c1 = $2 c in let c2 = $5 c in if_ ($3 c1) ($6 c2) } +block_instr : + | BLOCK labeling_opt block END + { fun c -> let c' = $2 c in let ts, es = $3 c' in block ts es } + | LOOP labeling_opt block END + { fun c -> let c' = $2 c in let ts, es = $3 c' in loop ts es } + | IF labeling_opt block END + { fun c -> let c' = $2 c in let ts, es = $3 c' in if_ ts es [] } + | IF labeling_opt block ELSE instr_list END + { fun c -> let c' = $2 c in let ts, es1 = $3 c' in if_ ts es1 ($5 c') } +; +block : + | value_type_list instr_list { fun c -> $1, $2 c } ; expr : /* Sugar */ @@ -348,31 +345,27 @@ expr : /* Sugar */ ; expr1 : /* Sugar */ | plain_instr expr_list { fun c -> snd ($2 c), $1 c } - /* TODO: remove special-casing of branches here once arities are gone */ - | BR var expr_list { fun c -> let n, es = $3 c in es, br n ($2 c label) } - | BR_IF var expr expr_list - { fun c -> - let es1 = $3 c and n, es2 = $4 c in es1 @ es2, br_if n ($2 c label) } - | BR_TABLE var var_list expr expr_list - { fun c -> let xs, x = Lib.List.split_last ($2 c label :: $3 c label) in - let es1 = $4 c and n, es2 = $5 c in es1 @ es2, br_table n xs x } - | BLOCK labeling_opt instr_list - { fun c -> let c' = $2 c in [], block ($3 c') } - | LOOP labeling_opt instr_list - { fun c -> let c' = $2 c in [], loop ($3 c') } - | IF expr expr { fun c -> let c' = anon_label c in $2 c, if_ ($3 c') [] } - | IF expr expr expr - { fun c -> let c' = anon_label c in $2 c, if_ ($3 c') ($4 c') } - | IF expr LPAR THEN labeling_opt instr_list RPAR - { fun c -> let c' = $5 c in $2 c, if_ ($6 c') [] } - | IF expr LPAR THEN labeling_opt instr_list RPAR LPAR - ELSE labeling_opt instr_list RPAR - { fun c -> let c1 = $5 c in let c2 = $10 c in $2 c, if_ ($6 c1) ($11 c2) } - | IF LPAR THEN labeling_opt instr_list RPAR - { fun c -> let c' = $4 c in [], if_ ($5 c') [] } - | IF LPAR THEN labeling_opt instr_list RPAR - LPAR ELSE labeling_opt instr_list RPAR - { fun c -> let c1 = $4 c in let c2 = $9 c in [], if_ ($5 c1) ($10 c2) } + | BLOCK labeling_opt block + { fun c -> let c' = $2 c in let ts, es = $3 c' in [], block ts es } + | LOOP labeling_opt block + { fun c -> let c' = $2 c in let ts, es = $3 c' in [], loop ts es } + | IF labeling_opt value_type_list if_ + { fun c -> let c' = $2 c in + let es, es1, es2 = $4 c c' in es, if_ $3 es1 es2 } +; +if_ : + | LPAR THEN instr_list RPAR LPAR ELSE instr_list RPAR + { fun c c' -> [], $3 c', $7 c' } + | LPAR THEN instr_list RPAR /* Sugar */ + { fun c c' -> [], $3 c', [] } + | expr LPAR THEN instr_list RPAR LPAR ELSE instr_list RPAR /* Sugar */ + { fun c c' -> $1 c, $4 c', $8 c' } + | expr LPAR THEN instr_list RPAR /* Sugar */ + { fun c c' -> $1 c, $4 c', [] } + | expr expr expr /* Sugar */ + { fun c c' -> $1 c, $2 c', $3 c' } + | expr expr /* Sugar */ + { fun c c' -> $1 c, $2 c', [] } ; instr_list : diff --git a/ml-proto/host/run.ml b/ml-proto/host/run.ml index e13bed01d7..e603d8af9c 100644 --- a/ml-proto/host/run.ml +++ b/ml-proto/host/run.ml @@ -104,6 +104,7 @@ let input_from get_script run = | Eval.Link (at, msg) -> error at "link failure" msg | Eval.Trap (at, msg) -> error at "runtime trap" msg | Eval.Crash (at, msg) -> error at "runtime crash" msg + | Encode.Code (at, msg) -> error at "encoding error" msg | IO (at, msg) -> error at "i/o error" msg | Assert (at, msg) -> error at "assertion failure" msg | Abort _ -> false diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index 87f0f603af..b5426e9d4e 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -72,13 +72,13 @@ and instr' = | Nop (* do nothing *) | Drop (* forget a value *) | Select (* branchless conditional *) - | Block of instr list (* execute in sequence *) - | Loop of instr list (* loop header *) - | Br of int * var (* break to n-th surrounding label *) - | BrIf of int * var (* conditional break *) - | BrTable of int * var list * var (* indexed break *) + | Block of stack_type * instr list (* execute in sequence *) + | Loop of stack_type * instr list (* loop header *) + | Br of var (* break to n-th surrounding label *) + | BrIf of var (* conditional break *) + | BrTable of var list * var (* indexed break *) | Return (* break from function body *) - | If of instr list * instr list (* conditional *) + | If of stack_type * instr list * instr list (* conditional *) | Call of var (* call function *) | CallIndirect of var (* call function through table *) | GetLocal of var (* read local variable *) diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index 6cf24ae00a..1af804ae33 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -31,7 +31,7 @@ type context = globals : global_type list; locals : value_type list; results : value_type list; - labels : result_type ref list; + labels : stack_type list; } let context m = @@ -54,15 +54,10 @@ let memory c x = lookup "memory" c.memories x (* Join *) -let join r1 r2 at = - match r1, r2 with - | Bot, r | r, Bot -> r - | r1, r2 when r1 = r2 -> r1 - | _ -> result_error at r1 r2 - -let unknown () = ref Bot -let known ts = ref (Stack ts) -let unify v ts at = v := join !v (Stack ts) at +let check_join ts r at = + match r with + | Bot -> () + | Stack ts' -> if ts <> ts' then result_error at (Stack ts) r (* Type Synthesis *) @@ -164,49 +159,38 @@ let rec check_instr (c : context) (e : instr) (stack : stack_type) : op_type = | Drop -> [peek 0 stack] --> Stack [] - | Block es -> - let vr = unknown () in - let c' = {c with labels = vr :: c.labels} in - let r = check_block c' es in - check_result_arity r e.at; - [] --> join !vr r e.at - - | Loop es -> - let c' = {c with labels = known [] :: c.labels} in - let r = check_block c' es in - check_result_arity r e.at; - [] --> r - - | Br (n, x) -> - check_arity n e.at; - let ts = peek_n n stack in - unify (label c x) ts e.at; - ts --> Bot - - | BrIf (n, x) -> - check_arity n e.at; - let ts = List.tl (peek_n (n + 1) stack) in - unify (label c x) ts e.at; - (ts @ [I32Type]) --> Stack ts - - | BrTable (n, xs, x) -> - check_arity n e.at; - let ts = List.tl (peek_n (n + 1) stack) in - unify (label c x) ts x.at; - List.iter (fun x' -> unify (label c x') ts x'.at) xs; + | Block (ts, es) -> + check_arity (List.length ts) e.at; + let c' = {c with labels = ts :: c.labels} in + check_block c' es ts e.at; + [] --> Stack ts + + | Loop (ts, es) -> + check_arity (List.length ts) e.at; + let c' = {c with labels = [] :: c.labels} in + check_block c' es ts e.at; + [] --> Stack ts + + | Br x -> + label c x --> Bot + + | BrIf x -> + (label c x @ [I32Type]) --> Stack (label c x) + + | BrTable (xs, x) -> + let ts = label c x in + List.iter (fun x' -> check_join ts (Stack (label c x')) x'.at) xs; (ts @ [I32Type]) --> Bot | Return -> c.results --> Bot - | If (es1, es2) -> - let vr = unknown () in - let c' = {c with labels = vr :: c.labels} in - let r1 = check_block c' es1 in - let r2 = check_block c' es2 in - let r = join r1 r2 e.at in - check_result_arity r e.at; - [I32Type] --> join !vr r e.at + | If (ts, es1, es2) -> + check_arity (List.length ts) e.at; + let c' = {c with labels = ts :: c.labels} in + check_block c' es1 ts e.at; + check_block c' es2 ts e.at; + [I32Type] --> Stack ts | Select -> let t = peek 1 stack in @@ -279,14 +263,14 @@ let rec check_instr (c : context) (e : instr) (stack : stack_type) : op_type = ignore (memory c (0l @@ e.at)); [I32Type] --> Stack [I32Type] -and check_block (c : context) (es : instr list) : result_type = +and check_seq (c : context) (es : instr list) : result_type = match es with | [] -> Stack [] | _ -> let es', e = Lib.List.split_last es in - let r1 = check_block c es' in + let r1 = check_seq c es' in match r1 with | Bot -> Bot | Stack ts0 -> @@ -299,6 +283,9 @@ and check_block (c : context) (es : instr list) : result_type = | Bot -> Bot | Stack ts3 -> Stack (ts1 @ ts3) +and check_block (c : context) (es : instr list) (ts : stack_type) at = + check_join ts (check_seq c es) at + (* Functions & Constants *) @@ -317,10 +304,8 @@ let check_func (c : context) (f : func) = let {ftype; locals; body} = f.it in let FuncType (ins, out) = type_ c ftype in check_arity (List.length out) f.at; - let vr = known out in - let c' = {c with locals = ins @ locals; results = out; labels = [vr]} in - let r = check_block c' body in - ignore (join !vr r f.at) + let c' = {c with locals = ins @ locals; results = out; labels = [out]} in + check_block c' body out f.at let is_const e = @@ -331,9 +316,7 @@ let is_const e = let check_const (c : context) (const : const) (t : value_type) = require (List.for_all is_const const.it) const.at "constant expression required"; - match check_block c const.it with - | Stack [t'] when t = t' -> () - | r -> result_error const.at (Stack [t]) r + check_block c const.it [t] const.at (* Tables, Memories, & Globals *) @@ -421,7 +404,8 @@ let check_import im c = check_memory_type t ikind.at; {c with memories = t :: c.memories} | GlobalImport t -> let GlobalType (_, mut) = t in - require (mut = Immutable) ikind.at "mutable globals cannot be imported (yet)"; + require (mut = Immutable) ikind.at + "mutable globals cannot be imported (yet)"; {c with globals = t :: c.globals} module NameSet = Set.Make(String) @@ -434,7 +418,8 @@ let check_export c set ex = | MemoryExport -> ignore (memory c item) | GlobalExport -> let GlobalType (_, mut) = global c item in - require (mut = Immutable) ekind.at "mutable globals cannot be exported (yet)" + require (mut = Immutable) ekind.at + "mutable globals cannot be exported (yet)" ); require (not (NameSet.mem name set)) ex.at "duplicate export name"; NameSet.add name set diff --git a/ml-proto/spec/decode.ml b/ml-proto/spec/decode.ml index eb4357c44c..0230e262a8 100644 --- a/ml-proto/spec/decode.ml +++ b/ml-proto/spec/decode.ml @@ -80,8 +80,7 @@ let u64 s = let rec vuN n s = require (n > 0) s (pos s) "integer representation too long"; let b = u8 s in - require (n >= 7 || b land 0x7f < 1 lsl n) s (pos s - 1) - "integer out of range"; + require (n >= 7 || b land 0x7f < 1 lsl n) s (pos s - 1) "integer too large"; let x = Int64.of_int (b land 0x7f) in if b land 0x80 = 0 then x else Int64.(logor x (shift_left (vuN (n - 7) s) 7)) @@ -143,6 +142,11 @@ let elem_type s = | 0x20 -> AnyFuncType | _ -> error s (pos s - 1) "invalid element type" +let stack_type s = + match peek s with + | Some 0x00 -> skip 1 s; [] + | _ -> [value_type s] + let func_type s = expect 0x40 s "invalid function type"; let ins = vec value_type s in @@ -236,39 +240,35 @@ let rec instr s = match op s with | 0x00 -> unreachable | 0x01 -> + let ts = stack_type s in let es' = instr_block s in expect 0x0f s "END opcode expected"; - block es' + block ts es' | 0x02 -> + let ts = stack_type s in let es' = instr_block s in expect 0x0f s "END opcode expected"; - loop es' + loop ts es' | 0x03 -> + let ts = stack_type s in let es1 = instr_block s in if peek s = Some 0x04 then begin expect 0x04 s "`else` or `end` opcode expected"; let es2 = instr_block s in expect 0x0f s "END opcode expected"; - if_ es1 es2 + if_ ts es1 es2 end else begin expect 0x0f s "END opcode expected"; - if_ es1 [] + if_ ts es1 [] end | 0x04 -> error s pos "misplaced ELSE opcode" | 0x05 -> select - | 0x06 -> - let n = arity s in - let x = at var s in - br n x - | 0x07 -> - let n = arity s in - let x = at var s in - br_if n x + | 0x06 -> br (at var s) + | 0x07 -> br_if (at var s) | 0x08 -> - let n = arity s in let xs = vec (at var) s in let x = at var s in - br_table n xs x + br_table xs x | 0x09 -> return | 0x0a -> nop | 0x0b -> drop diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 8e10b2073c..113d314bff 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -66,8 +66,8 @@ type eval_context = instr list * value stack * block stack * call stack and call_context = instr list * value stack * block stack and block_context = instr list * value stack -and block = {target : instr list; bcontext : block_context} -and call = {instance : instance; locals : value list; arity : int; +and block = {target : instr list; barity : int; bcontext : block_context} +and call = {instance : instance; locals : value list; carity : int; ccontext : call_context} let resource_limit = 1000 @@ -151,8 +151,8 @@ let eval_call (clos : closure) (es, vs, bs, cs : eval_context) at = match clos with | AstFunc (inst, f) -> let locals = List.rev args @ List.map default_value f.it.locals in - [Block f.it.body @@ f.at], [], [], - {instance = !inst; locals; arity = m; ccontext = es, vs', bs} :: cs + [Block (out, f.it.body) @@ f.at], [], [], + {instance = !inst; locals; carity = m; ccontext = es, vs', bs} :: cs | HostFunc (t, f) -> try es, List.rev (f (List.rev args)) @ vs', bs, cs @@ -169,40 +169,40 @@ let eval_instr (e : instr) (es, vs, bs, cs : eval_context) : eval_context = | Drop, v :: vs', _, _ -> es, vs', bs, cs - | Block es', vs, bs, _ -> - es', [], {target = []; bcontext = es, vs} :: bs, cs + | Block (ts, es'), vs, bs, _ -> + es', [], {target = []; barity = List.length ts; bcontext = es, vs} :: bs, cs - | Loop es', vs, bs, _ -> - es', [], {target = [e]; bcontext = es, vs} :: bs, cs + | Loop (ts, es'), vs, bs, _ -> + es', [], {target = [e]; barity = 0; bcontext = es, vs} :: bs, cs - | Br (n, x), vs, bs, _ -> + | Br x, vs, bs, _ -> let bs' = drop32 x.it bs e.at in let b = List.hd (take 1 bs' e.at) in let es', vs' = b.bcontext in - b.target @ es', take n vs e.at @ vs', drop 1 bs' e.at, cs + b.target @ es', take b.barity vs e.at @ vs', drop 1 bs' e.at, cs - | BrIf (n, x), I32 0l :: vs', _, _ -> + | BrIf x, I32 0l :: vs', _, _ -> es, vs', bs, cs - | BrIf (n, x), I32 i :: vs', _, _ -> - (Br (n, x) @@ e.at) :: es, vs', bs, cs + | BrIf x, I32 i :: vs', _, _ -> + (Br x @@ e.at) :: es, vs', bs, cs - | BrTable (n, xs, x), I32 i :: vs', _, _ + | BrTable (xs, x), I32 i :: vs', _, _ when I32.ge_u i (Lib.List32.length xs) -> - (Br (n, x) @@ e.at) :: es, vs', bs, cs + (Br x @@ e.at) :: es, vs', bs, cs - | BrTable (n, xs, x), I32 i :: vs', _, _ -> - (Br (n, Lib.List32.nth xs i) @@ e.at) :: es, vs', bs, cs + | BrTable (xs, x), I32 i :: vs', _, _ -> + (Br (Lib.List32.nth xs i) @@ e.at) :: es, vs', bs, cs | Return, vs, _, c :: cs' -> let es', vs', bs' = c.ccontext in - es', take c.arity vs e.at @ vs', bs', cs' + es', take c.carity vs e.at @ vs', bs', cs' - | If (es1, es2), I32 0l :: vs', _, _ -> - (Block es2 @@ e.at) :: es, vs', bs, cs + | If (ts, es1, es2), I32 0l :: vs', _, _ -> + (Block (ts, es2) @@ e.at) :: es, vs', bs, cs - | If (es1, es2), I32 i :: vs', _, _ -> - (Block es1 @@ e.at) :: es, vs', bs, cs + | If (ts, es1, es2), I32 i :: vs', _, _ -> + (Block (ts, es1) @@ e.at) :: es, vs', bs, cs | Select, I32 0l :: v2 :: v1 :: vs', _, _ -> es, v2 :: vs', bs, cs @@ -304,8 +304,8 @@ let rec eval_seq (es, vs, bs, cs : eval_context) = eval_seq (es', vs @ vs', bs', cs) | [], [], c :: cs' -> -(* if List.length vs <> c.arity then - Crash.error no_region "wrong number of values on stack";*) + if List.length vs <> c.carity then + Crash.error no_region "wrong number of return values on stack"; let es', vs', bs' = c.ccontext in eval_seq (es', vs @ vs', bs', cs') @@ -322,7 +322,7 @@ let eval_func (clos : closure) (vs : value list) at : value list = List.rev (eval_seq (eval_call clos ([], List.rev vs, [], []) at)) let eval_const inst const = - let c = {instance = inst; locals = []; arity = 1; ccontext = [], [], []} in + let c = {instance = inst; locals = []; carity = 1; ccontext = [], [], []} in List.hd (eval_seq (const.it, [], [], [c])) let const (m : module_) const = diff --git a/ml-proto/spec/operators.ml b/ml-proto/spec/operators.ml index 12b9a7d42d..b207b193db 100644 --- a/ml-proto/spec/operators.ml +++ b/ml-proto/spec/operators.ml @@ -13,13 +13,13 @@ let f64_const n = Const (F64 n.it @@ n.at) let unreachable = Unreachable let nop = Nop let drop = Drop -let block es = Block es -let loop es = Loop es -let br n x = Br (n, x) -let br_if n x = BrIf (n, x) -let br_table n xs x = BrTable (n, xs, x) +let block ts es = Block (ts, es) +let loop ts es = Loop (ts, es) +let br x = Br x +let br_if x = BrIf x +let br_table xs x = BrTable (xs, x) let return = Return -let if_ es1 es2 = If (es1, es2) +let if_ ts es1 es2 = If (ts, es1, es2) let select = Select let call x = Call x diff --git a/ml-proto/test/address-offset-range.fail.wast b/ml-proto/test/address-offset-range.fail.wast new file mode 100644 index 0000000000..127327a260 --- /dev/null +++ b/ml-proto/test/address-offset-range.fail.wast @@ -0,0 +1,4 @@ +(module + (memory 1) + (func $bad (drop (i32.load offset=4294967296 (i32.const 0)))) +) diff --git a/ml-proto/test/block.wast b/ml-proto/test/block.wast index 763c693f45..f1a3011e2e 100644 --- a/ml-proto/test/block.wast +++ b/ml-proto/test/block.wast @@ -11,49 +11,53 @@ (func (export "singular") (result i32) (block (nop)) - (block (i32.const 7)) + (block i32 (i32.const 7)) ) (func (export "multi") (result i32) (block (call $dummy) (call $dummy) (call $dummy) (call $dummy)) - (block (call $dummy) (call $dummy) (call $dummy) (i32.const 8)) + (block i32 (call $dummy) (call $dummy) (call $dummy) (i32.const 8)) ) (func (export "nested") (result i32) - (block + (block i32 (block (call $dummy) (block) (nop)) - (block (call $dummy) (i32.const 9)) + (block i32 (call $dummy) (i32.const 9)) ) ) (func (export "deep") (result i32) - (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 (block (block (block (block (block - (block (block (block (block (call $dummy) (i32.const 150))))) - )))))))))) - )))))))))) - )))))))))) - )))))))))) + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (block i32 (block i32 (block i32 (block i32 + (block i32 (block i32 (call $dummy) (i32.const 150))) + )))))) + )))))) + )))))) + )))))) + )))))) + )))))) ) (func (export "as-unary-operand") (result i32) - (i32.ctz (block (call $dummy) (i32.const 13))) + (i32.ctz (block i32 (call $dummy) (i32.const 13))) ) (func (export "as-binary-operand") (result i32) (i32.mul - (block (call $dummy) (i32.const 3)) - (block (call $dummy) (i32.const 4)) + (block i32 (call $dummy) (i32.const 3)) + (block i32 (call $dummy) (i32.const 4)) ) ) (func (export "as-test-operand") (result i32) - (i32.eqz (block (call $dummy) (i32.const 13))) + (i32.eqz (block i32 (call $dummy) (i32.const 13))) ) (func (export "as-compare-operand") (result i32) (f32.gt - (block (call $dummy) (f32.const 3)) - (block (call $dummy) (f32.const 3)) + (block f32 (call $dummy) (f32.const 3)) + (block f32 (call $dummy) (f32.const 3)) ) ) @@ -65,10 +69,10 @@ (i32.const 19) ) (func (export "break-value") (result i32) - (block (br 0 (i32.const 18)) (i32.const 19)) + (block i32 (br 0 (i32.const 18)) (i32.const 19)) ) (func (export "break-repeated") (result i32) - (block + (block i32 (br 0 (i32.const 18)) (br 0 (i32.const 19)) (br_if 0 (i32.const 20) (i32.const 0)) @@ -82,13 +86,13 @@ (func (export "break-inner") (result i32) (local i32) (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 (block i32 (br 1 (i32.const 0x1)))))) + (set_local 0 (i32.add (get_local 0) (block i32 (block (br 0)) (i32.const 0x2)))) (set_local 0 - (i32.add (get_local 0) (block (i32.ctz (br 0 (i32.const 0x4))))) + (i32.add (get_local 0) (block i32 (i32.ctz (br 0 (i32.const 0x4))))) ) (set_local 0 - (i32.add (get_local 0) (block (i32.ctz (block (br 1 (i32.const 0x8)))))) + (i32.add (get_local 0) (block i32 (i32.ctz (block i32 (br 1 (i32.const 0x8)))))) ) (get_local 0) ) @@ -142,19 +146,6 @@ "type mismatch" ) -(assert_invalid - (module (func $type-binary (result i64) - (block (i64.const 1) (i64.const 2)) i64.add - )) - "invalid result arity" -) -(assert_invalid - (module (func $type-binary-with-nop (result i32) - (block (nop) (i32.const 7) (nop) (i32.const 8)) i32.add - )) - "invalid result arity" -) - (assert_invalid (module (func $type-value-num-vs-void (block (i32.const 1)) @@ -173,7 +164,8 @@ )) "type mismatch" ) -(; TODO(stack): Should these become legal? + +(; TODO(stack): soft failure (assert_invalid (module (func $type-value-num-vs-void-after-break (block (br 0) (i32.const 1)) @@ -182,52 +174,44 @@ ) (assert_invalid (module (func $type-value-void-vs-num-after-break (result i32) - (block (br 0 (i32.const 1)) (nop)) + (block (i32.const 1) (br 0) (nop)) )) "type mismatch" ) (assert_invalid (module (func $type-value-num-vs-num-after-break (result i32) - (block (br 0 (i32.const 1)) (f32.const 0)) - )) - "type mismatch" -) -;) - -(assert_invalid - (module (func $type-break-last-void-vs-empty - (block (br 0 (nop))) + (block (i32.const 1) (br 0) (f32.const 0)) )) "type mismatch" ) (assert_invalid - (module (func $type-break-last-num-vs-empty - (block (br 0 (i32.const 66))) + (module (func $type-break-second-void-vs-num (result i32) + (block i32 (br 0 (i32.const 1)) (br 0 (nop))) )) "type mismatch" ) (assert_invalid - (module (func $type-break-last-empty-vs-num (result i32) - (block (br 0)) + (module (func $type-break-second-num-vs-num (result i32) + (block i32 (br 0 (i32.const 1)) (br 0 (f64.const 1))) )) "type mismatch" ) +;) + +;; TODO(stack): move this elsewhere +(module (func $type-break-num-vs-void + (block (i32.const 66) (br 0)) +)) (assert_invalid - (module (func $type-break-void-vs-empty - (block (br 0 (nop))) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-break-num-vs-empty - (block (br 0 (i32.const 1))) + (module (func $type-break-last-void-vs-num (result i32) + (block i32 (br 0)) )) "type mismatch" ) (assert_invalid - (module (func $type-break-empty-vs-num (result i32) - (block (br 0) (i32.const 1)) + (module (func $type-break-void-vs-num (result i32) + (block i32 (br 0) (i32.const 1)) )) "type mismatch" ) @@ -256,30 +240,10 @@ )) "type mismatch" ) -(; TODO(stack): Should these become legal? -(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))) - )) - "type mismatch" -) -;) (assert_invalid - (module (func $type-break-nested-void-vs-empty - (block (block (br 1 (nop))) (br 0)) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-break-nested-num-vs-empty - (block (block (br 1 (i32.const 1))) (br 0)) + (module (func $type-break-nested-num-vs-void + (block i32 (block i32 (br 1 (i32.const 1))) (br 0)) )) "type mismatch" ) diff --git a/ml-proto/test/br.wast b/ml-proto/test/br.wast index 833341d94b..2aa325f986 100644 --- a/ml-proto/test/br.wast +++ b/ml-proto/test/br.wast @@ -9,10 +9,18 @@ (func (export "type-f32") (block (drop (f32.neg (br 0))))) (func (export "type-f64") (block (drop (f64.neg (br 0))))) - (func (export "type-i32-value") (result i32) (block (i32.ctz (br 0 (i32.const 1))))) - (func (export "type-i64-value") (result i64) (block (i64.ctz (br 0 (i64.const 2))))) - (func (export "type-f32-value") (result f32) (block (f32.neg (br 0 (f32.const 3))))) - (func (export "type-f64-value") (result f64) (block (f64.neg (br 0 (f64.const 4))))) + (func (export "type-i32-value") (result i32) + (block i32 (i32.ctz (br 0 (i32.const 1)))) + ) + (func (export "type-i64-value") (result i64) + (block i64 (i64.ctz (br 0 (i64.const 2)))) + ) + (func (export "type-f32-value") (result f32) + (block f32 (f32.neg (br 0 (f32.const 3)))) + ) + (func (export "type-f64-value") (result f64) + (block f64 (f64.neg (br 0 (f64.const 4)))) + ) (func (export "as-block-first") (block (br 0) (call $dummy)) @@ -24,82 +32,86 @@ (block (nop) (call $dummy) (br 0)) ) (func (export "as-block-value") (result i32) - (block (nop) (call $dummy) (br 0 (i32.const 2))) + (block i32 (nop) (call $dummy) (br 0 (i32.const 2))) ) (func (export "as-loop-first") (result i32) - (loop (br 1 (i32.const 3)) (i32.const 2)) + (block i32 (loop i32 (br 1 (i32.const 3)) (i32.const 2))) ) (func (export "as-loop-mid") (result i32) - (loop (call $dummy) (br 1 (i32.const 4)) (i32.const 2)) + (block i32 (loop i32 (call $dummy) (br 1 (i32.const 4)) (i32.const 2))) ) (func (export "as-loop-last") (result i32) - (loop (nop) (call $dummy) (br 1 (i32.const 5))) + (block i32 (loop i32 (nop) (call $dummy) (br 1 (i32.const 5)))) ) (func (export "as-br-value") (result i32) - (block (br 0 (br 0 (i32.const 9)))) + (block i32 (br 0 (br 0 (i32.const 9)))) ) (func (export "as-br_if-cond") (block (br_if 0 (br 0))) ) (func (export "as-br_if-value") (result i32) - (block (br_if 0 (br 0 (i32.const 8)) (i32.const 1)) (i32.const 7)) + (block i32 (br_if 0 (br 0 (i32.const 8)) (i32.const 1)) (i32.const 7)) ) (func (export "as-br_if-value-cond") (result i32) - (block (br_if 0 (i32.const 6) (br 0 (i32.const 9))) (i32.const 7)) + (block i32 (br_if 0 (i32.const 6) (br 0 (i32.const 9))) (i32.const 7)) ) (func (export "as-br_table-index") (block (br_table 0 0 0 (br 0))) ) (func (export "as-br_table-value") (result i32) - (block (br_table 0 0 0 (br 0 (i32.const 10)) (i32.const 1)) (i32.const 7)) + (block i32 + (br_table 0 0 0 (br 0 (i32.const 10)) (i32.const 1)) (i32.const 7) + ) ) (func (export "as-br_table-value-index") (result i32) - (block (br_table 0 0 (i32.const 6) (br 0 (i32.const 11))) (i32.const 7)) + (block i32 + (br_table 0 0 (i32.const 6) (br 0 (i32.const 11))) (i32.const 7) + ) ) (func (export "as-return-value") (result i64) - (block (return (br 0 (i64.const 7)))) + (block i64 (return (br 0 (i64.const 7)))) ) (func (export "as-if-cond") (result i32) - (block (if (br 0 (i32.const 2)) (i32.const 0) (i32.const 1))) + (block i32 (if i32 (br 0 (i32.const 2)) (i32.const 0) (i32.const 1))) ) (func (export "as-if-then") (param i32 i32) (result i32) - (block (if (get_local 0) (br 1 (i32.const 3)) (get_local 1))) + (block i32 (if i32 (get_local 0) (br 1 (i32.const 3)) (get_local 1))) ) (func (export "as-if-else") (param i32 i32) (result i32) - (block (if (get_local 0) (get_local 1) (br 1 (i32.const 4)))) + (block i32 (if i32 (get_local 0) (get_local 1) (br 1 (i32.const 4)))) ) (func (export "as-select-first") (param i32 i32) (result i32) - (block (select (br 0 (i32.const 5)) (get_local 0) (get_local 1))) + (block i32 (select (br 0 (i32.const 5)) (get_local 0) (get_local 1))) ) (func (export "as-select-second") (param i32 i32) (result i32) - (block (select (get_local 0) (br 0 (i32.const 6)) (get_local 1))) + (block i32 (select (get_local 0) (br 0 (i32.const 6)) (get_local 1))) ) (func (export "as-select-cond") (result i32) - (block (select (i32.const 0) (i32.const 1) (br 0 (i32.const 7)))) + (block i32 (select (i32.const 0) (i32.const 1) (br 0 (i32.const 7)))) ) (func $f (param i32 i32 i32) (result i32) (i32.const -1)) (func (export "as-call-first") (result i32) - (block (call $f (br 0 (i32.const 12)) (i32.const 2) (i32.const 3))) + (block i32 (call $f (br 0 (i32.const 12)) (i32.const 2) (i32.const 3))) ) (func (export "as-call-mid") (result i32) - (block (call $f (i32.const 1) (br 0 (i32.const 13)) (i32.const 3))) + (block i32 (call $f (i32.const 1) (br 0 (i32.const 13)) (i32.const 3))) ) (func (export "as-call-last") (result i32) - (block (call $f (i32.const 1) (i32.const 2) (br 0 (i32.const 14)))) + (block i32 (call $f (i32.const 1) (i32.const 2) (br 0 (i32.const 14)))) ) (type $sig (func (param i32 i32 i32) (result i32))) (table anyfunc (elem $f)) (func (export "as-call_indirect-func") (result i32) - (block + (block i32 (call_indirect $sig (br 0 (i32.const 20)) (i32.const 1) (i32.const 2) (i32.const 3) @@ -107,7 +119,7 @@ ) ) (func (export "as-call_indirect-first") (result i32) - (block + (block i32 (call_indirect $sig (i32.const 0) (br 0 (i32.const 21)) (i32.const 2) (i32.const 3) @@ -115,7 +127,7 @@ ) ) (func (export "as-call_indirect-mid") (result i32) - (block + (block i32 (call_indirect $sig (i32.const 0) (i32.const 1) (br 0 (i32.const 22)) (i32.const 3) @@ -123,7 +135,7 @@ ) ) (func (export "as-call_indirect-last") (result i32) - (block + (block i32 (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (br 0 (i32.const 23)) @@ -132,65 +144,65 @@ ) (func (export "as-set_local-value") (result i32) (local f32) - (block (set_local 0 (br 0 (i32.const 17))) (i32.const -1)) + (block i32 (set_local 0 (br 0 (i32.const 17))) (i32.const -1)) ) (memory 1) (func (export "as-load-address") (result f32) - (block (f32.load (br 0 (f32.const 1.7)))) + (block f32 (f32.load (br 0 (f32.const 1.7)))) ) (func (export "as-loadN-address") (result i64) - (block (i64.load8_s (br 0 (i64.const 30)))) + (block i64 (i64.load8_s (br 0 (i64.const 30)))) ) (func (export "as-store-address") (result i32) - (block (f64.store (br 0 (i32.const 30)) (f64.const 7)) (i32.const -1)) + (block i32 (f64.store (br 0 (i32.const 30)) (f64.const 7)) (i32.const -1)) ) (func (export "as-store-value") (result i32) - (block (i64.store (i32.const 2) (br 0 (i32.const 31))) (i32.const -1)) + (block i32 (i64.store (i32.const 2) (br 0 (i32.const 31))) (i32.const -1)) ) (func (export "as-storeN-address") (result i32) - (block (i32.store8 (br 0 (i32.const 32)) (i32.const 7)) (i32.const -1)) + (block i32 (i32.store8 (br 0 (i32.const 32)) (i32.const 7)) (i32.const -1)) ) (func (export "as-storeN-value") (result i32) - (block (i64.store16 (i32.const 2) (br 0 (i32.const 33))) (i32.const -1)) + (block i32 (i64.store16 (i32.const 2) (br 0 (i32.const 33))) (i32.const -1)) ) (func (export "as-unary-operand") (result f32) - (block (f32.neg (br 0 (f32.const 3.4)))) + (block f32 (f32.neg (br 0 (f32.const 3.4)))) ) (func (export "as-binary-left") (result i32) - (block (i32.add (br 0 (i32.const 3)) (i32.const 10))) + (block i32 (i32.add (br 0 (i32.const 3)) (i32.const 10))) ) (func (export "as-binary-right") (result i64) - (block (i64.sub (i64.const 10) (br 0 (i64.const 45)))) + (block i64 (i64.sub (i64.const 10) (br 0 (i64.const 45)))) ) (func (export "as-test-operand") (result i32) - (block (i32.eqz (br 0 (i32.const 44)))) + (block i32 (i32.eqz (br 0 (i32.const 44)))) ) (func (export "as-compare-left") (result i32) - (block (f64.le (br 0 (i32.const 43)) (f64.const 10))) + (block i32 (f64.le (br 0 (i32.const 43)) (f64.const 10))) ) (func (export "as-compare-right") (result i32) - (block (f32.ne (f32.const 10) (br 0 (i32.const 42)))) + (block i32 (f32.ne (f32.const 10) (br 0 (i32.const 42)))) ) (func (export "as-convert-operand") (result i32) - (block (i32.wrap/i64 (br 0 (i32.const 41)))) + (block i32 (i32.wrap/i64 (br 0 (i32.const 41)))) ) (func (export "as-grow_memory-size") (result i32) - (block (grow_memory (br 0 (i32.const 40)))) + (block i32 (grow_memory (br 0 (i32.const 40)))) ) (func (export "nested-block-value") (result i32) (i32.add (i32.const 1) - (block + (block i32 (call $dummy) (i32.add (i32.const 4) (br 0 (i32.const 8))) ) @@ -200,10 +212,10 @@ (func (export "nested-br-value") (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br 0 (br 1 (i32.const 8))) ) @@ -216,10 +228,10 @@ (func (export "nested-br_if-value") (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br_if 0 (br 1 (i32.const 8)) (i32.const 1)) (i32.const 32) @@ -233,7 +245,7 @@ (func (export "nested-br_if-value-cond") (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_if 0 (i32.const 4) (br 0 (i32.const 8))) (i32.const 16) @@ -244,10 +256,10 @@ (func (export "nested-br_table-value") (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br_table 0 (br 1 (i32.const 8)) (i32.const 1)) ) @@ -260,7 +272,7 @@ (func (export "nested-br_table-value-index") (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_table 0 (i32.const 4) (br 0 (i32.const 8))) (i32.const 16) @@ -358,19 +370,13 @@ )) "type mismatch" ) -(assert_invalid - (module (func $type-arg-void-vs-empty - (block (br 0 (nop))) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-arg-num-vs-empty - (block (br 0 (i32.const 0))) - )) - "type mismatch" -) -(; TODO(stack): Should this become legal? + +;; TODO(stack): move this elsewhere +(module (func $type-arg-num-vs-void + (block (i32.const 0) (br 0)) +)) + +(; TODO(stack): soft failure (assert_invalid (module (func $type-arg-poly-vs-empty (block (br 0 (unreachable))) @@ -392,19 +398,6 @@ "type mismatch" ) -(assert_invalid - (module (func $type-binary (result i64) - (block (i64.const 1) (i64.const 2) br 2 0) i64.add - )) - "invalid result arity" -) -(assert_invalid - (module (func $type-binary-with-nop (result i32) - (block (nop) (i32.const 7) (nop) (i32.const 8) br 2 0) i32.add - )) - "invalid result arity" -) - (assert_invalid (module (func $unbound-label (br 1))) "unknown label" diff --git a/ml-proto/test/br_if.wast b/ml-proto/test/br_if.wast index b6d9df3927..5e2b5d5019 100644 --- a/ml-proto/test/br_if.wast +++ b/ml-proto/test/br_if.wast @@ -14,13 +14,15 @@ (block (call $dummy) (call $dummy) (br_if 0 (get_local 0))) ) (func (export "as-block-first-value") (param i32) (result i32) - (block (br_if 0 (i32.const 10) (get_local 0)) (return (i32.const 11))) + (block i32 (br_if 0 (i32.const 10) (get_local 0)) (return (i32.const 11))) ) (func (export "as-block-mid-value") (param i32) (result i32) - (block (call $dummy) (br_if 0 (i32.const 20) (get_local 0)) (return (i32.const 21))) + (block i32 (call $dummy) (br_if 0 (i32.const 20) (get_local 0)) (return (i32.const 21))) ) (func (export "as-block-last-value") (param i32) (result i32) - (block (call $dummy) (call $dummy) (br_if 0 (i32.const 11) (get_local 0))) + (block i32 + (call $dummy) (call $dummy) (br_if 0 (i32.const 11) (get_local 0)) + ) ) (func (export "as-loop-first") (param i32) (result i32) @@ -44,11 +46,14 @@ (func (export "nested-block-value") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (i32.add (i32.const 4) - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 16)) + (block i32 + (drop (br_if 1 (i32.const 8) (get_local 0))) + (i32.const 16) + ) ) ) ) @@ -57,10 +62,10 @@ (func (export "nested-br-value") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br 0 - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) + (block i32 (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) ) (i32.const 16) ) @@ -70,10 +75,10 @@ (func (export "nested-br_if-value") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop (br_if 0 - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) + (block i32 (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) (i32.const 1) )) (i32.const 16) @@ -84,11 +89,11 @@ (func (export "nested-br_if-value-cond") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop (br_if 0 (i32.const 4) - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 1)) + (block i32 (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 1)) )) (i32.const 16) ) @@ -98,10 +103,10 @@ (func (export "nested-br_table-value") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_table 0 - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) + (block i32 (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 4)) (i32.const 1) ) (i32.const 16) @@ -112,11 +117,11 @@ (func (export "nested-br_table-value-index") (param i32) (result i32) (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_table 0 (i32.const 4) - (block (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 1)) + (block i32 (drop (br_if 1 (i32.const 8) (get_local 0))) (i32.const 1)) ) (i32.const 16) ) @@ -197,42 +202,31 @@ ) (assert_invalid - (module (func $type-false-arg-empty-vs-num (result i32) - (block (br_if 0 (i32.const 0)) (i32.const 1)) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-true-arg-empty-vs-num (result i32) - (block (br_if 0 (i32.const 1)) (i32.const 1)) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-false-arg-void-vs-empty - (block (br_if 0 (nop) (i32.const 0))) + (module (func $type-false-arg-void-vs-num (result i32) + (block i32 (br_if 0 (i32.const 0)) (i32.const 1)) )) "type mismatch" ) (assert_invalid - (module (func $type-true-arg-void-vs-empty - (block (br_if 0 (nop) (i32.const 1))) + (module (func $type-true-arg-void-vs-num (result i32) + (block i32 (br_if 0 (i32.const 1)) (i32.const 1)) )) "type mismatch" ) (assert_invalid - (module (func $type-false-arg-num-vs-empty + (module (func $type-false-arg-num-vs-void (block (br_if 0 (i32.const 0) (i32.const 0))) )) "type mismatch" ) (assert_invalid - (module (func $type-true-arg-num-vs-empty + (module (func $type-true-arg-num-vs-void (block (br_if 0 (i32.const 0) (i32.const 1))) )) "type mismatch" ) -(; TODO(stack): Should these become legal? + +(; TODO(stack): soft failure (assert_invalid (module (func $type-false-arg-poly-vs-empty (block (br_if 0 (unreachable) (i32.const 0))) @@ -249,25 +243,25 @@ (assert_invalid (module (func $type-false-arg-void-vs-num (result i32) - (block (br_if 0 (nop) (i32.const 0)) (i32.const 1)) + (block i32 (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 (nop) (i32.const 1)) (i32.const 1)) + (block i32 (br_if 0 (nop) (i32.const 1)) (i32.const 1)) )) "type mismatch" ) (assert_invalid (module (func $type-false-arg-num-vs-num (result i32) - (block (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1)) + (block i32 (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1)) )) "type mismatch" ) (assert_invalid (module (func $type-true-arg-num-vs-num (result i32) - (block (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1)) + (block i32 (drop (br_if 0 (i64.const 1) (i32.const 0))) (i32.const 1)) )) "type mismatch" ) @@ -286,32 +280,17 @@ ) (assert_invalid (module (func $type-arg-cond-void-vs-i32 (result i32) - (block (br_if 0 (i32.const 0) (nop)) (i32.const 1)) + (block i32 (br_if 0 (i32.const 0) (nop)) (i32.const 1)) )) "type mismatch" ) (assert_invalid (module (func $type-arg-cond-num-vs-i32 (result i32) - (block (br_if 0 (i32.const 0) (i64.const 0)) (i32.const 1)) + (block i32 (br_if 0 (i32.const 0) (i64.const 0)) (i32.const 1)) )) "type mismatch" ) -(assert_invalid - (module (func $type-binary (result i64) - (block (i64.const 1) (i64.const 2) (i64.const 3) br_if 2 0) - i64.add - )) - "invalid result arity" -) -(assert_invalid - (module (func $type-binary-with-nop (result i32) - (block (nop) (i32.const 7) (nop) (i32.const 8) (i64.const 3) br_if 2 0) - i32.add - )) - "invalid result arity" -) - (assert_invalid (module (func $unbound-label (br_if 1 (i32.const 1)))) "unknown label" diff --git a/ml-proto/test/br_table.wast b/ml-proto/test/br_table.wast index 104ddecb2d..568a25e650 100644 --- a/ml-proto/test/br_table.wast +++ b/ml-proto/test/br_table.wast @@ -4,22 +4,30 @@ ;; Auxiliary definition (func $dummy) - (func (export "type-i32") (block (drop (i32.ctz (br_table 0 0 (i32.const 0)))))) - (func (export "type-i64") (block (drop (i64.ctz (br_table 0 0 (i32.const 0)))))) - (func (export "type-f32") (block (drop (f32.neg (br_table 0 0 (i32.const 0)))))) - (func (export "type-f64") (block (drop (f64.neg (br_table 0 0 (i32.const 0)))))) + (func (export "type-i32") + (block (drop (i32.ctz (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-i64") + (block (drop (i64.ctz (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-f32") + (block (drop (f32.neg (br_table 0 0 (i32.const 0))))) + ) + (func (export "type-f64") + (block (drop (f64.neg (br_table 0 0 (i32.const 0))))) + ) (func (export "type-i32-value") (result i32) - (block (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0)))) + (block i32 (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0)))) ) (func (export "type-i64-value") (result i64) - (block (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0)))) + (block i64 (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0)))) ) (func (export "type-f32-value") (result f32) - (block (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0)))) + (block f32 (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0)))) ) (func (export "type-f64-value") (result f64) - (block (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0)))) + (block f64 (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0)))) ) (func (export "empty") (param i32) (result i32) @@ -27,7 +35,7 @@ (i32.const 22) ) (func (export "empty-value") (param i32) (result i32) - (block (br_table 0 (i32.const 33) (get_local 0)) (i32.const 31)) + (block i32 (br_table 0 (i32.const 33) (get_local 0)) (i32.const 31)) ) (func (export "singleton") (param i32) (result i32) @@ -42,9 +50,9 @@ ) (func (export "singleton-value") (param i32) (result i32) - (block + (block i32 (drop - (block + (block i32 (br_table 0 1 (i32.const 33) (get_local 0)) (return (i32.const 31)) ) @@ -75,11 +83,11 @@ (func (export "multiple-value") (param i32) (result i32) (local i32) - (set_local 1 (block - (set_local 1 (block - (set_local 1 (block - (set_local 1 (block - (set_local 1 (block + (set_local 1 (block i32 + (set_local 1 (block i32 + (set_local 1 (block i32 + (set_local 1 (block i32 + (set_local 1 (block i32 (br_table 3 2 1 0 4 (i32.const 200) (get_local 0)) (return (i32.add (get_local 1) (i32.const 99))) )) @@ -841,162 +849,260 @@ (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 0))) ) (func (export "as-block-value") (result i32) - (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 2) (i32.const 0))) + (block i32 (nop) (call $dummy) (br_table 0 0 0 (i32.const 2) (i32.const 0))) ) (func (export "as-loop-first") (result i32) - (loop (br_table 1 1 (i32.const 3) (i32.const 0)) (i32.const 1)) + (loop i32 (br_table 1 1 (i32.const 3) (i32.const 0)) (i32.const 1)) ) (func (export "as-loop-mid") (result i32) - (loop + (loop i32 (call $dummy) (br_table 1 1 1 (i32.const 4) (i32.const -1)) (i32.const 2) ) ) (func (export "as-loop-last") (result i32) - (loop (nop) (call $dummy) (br_table 1 1 1 (i32.const 5) (i32.const 1))) + (loop i32 (nop) (call $dummy) (br_table 1 1 1 (i32.const 5) (i32.const 1))) ) (func (export "as-br-value") (result i32) - (block (br 0 (br 0 (i32.const 9)))) + (block i32 (br 0 (br 0 (i32.const 9)))) ) (func (export "as-br_if-cond") (block (br_if 0 (br_table 0 0 0 (i32.const 1)))) ) (func (export "as-br_if-value") (result i32) - (block (br_if 0 (br_table 0 (i32.const 8) (i32.const 0)) (i32.const 1)) (i32.const 7)) + (block i32 + (br_if 0 (br_table 0 (i32.const 8) (i32.const 0)) (i32.const 1)) + (i32.const 7) + ) ) (func (export "as-br_if-value-cond") (result i32) - (block (br_if 0 (i32.const 6) (br_table 0 0 (i32.const 9) (i32.const 0))) (i32.const 7)) + (block i32 + (br_if 0 (i32.const 6) (br_table 0 0 (i32.const 9) (i32.const 0))) + (i32.const 7) + ) ) (func (export "as-br_table-index") (block (br_table 0 0 0 (br_table 0 (i32.const 1)))) ) (func (export "as-br_table-value") (result i32) - (block (br_table 0 0 0 (br_table 0 (i32.const 10) (i32.const 0)) (i32.const 1)) (i32.const 7)) + (block i32 + (br_table 0 0 0 (br_table 0 (i32.const 10) (i32.const 0)) (i32.const 1)) + (i32.const 7) + ) ) (func (export "as-br_table-value-index") (result i32) - (block (br_table 0 0 (i32.const 6) (br_table 0 (i32.const 11) (i32.const 1))) (i32.const 7)) + (block i32 + (br_table 0 0 (i32.const 6) (br_table 0 (i32.const 11) (i32.const 1))) + (i32.const 7) + ) ) (func (export "as-return-value") (result i64) - (block (return (br_table 0 (i64.const 7) (i32.const 0)))) + (block i64 (return (br_table 0 (i64.const 7) (i32.const 0)))) ) (func (export "as-if-cond") (result i32) - (block (if (br_table 0 (i32.const 2) (i32.const 0)) (i32.const 0) (i32.const 1))) + (block i32 + (if i32 + (br_table 0 (i32.const 2) (i32.const 0)) + (i32.const 0) + (i32.const 1) + ) + ) ) (func (export "as-if-then") (param i32 i32) (result i32) - (block (if (get_local 0) (br_table 1 (i32.const 3) (i32.const 0)) (get_local 1))) + (block i32 + (if i32 + (get_local 0) + (br_table 1 (i32.const 3) (i32.const 0)) + (get_local 1) + ) + ) ) (func (export "as-if-else") (param i32 i32) (result i32) - (block (if (get_local 0) (get_local 1) (br_table 1 0 (i32.const 4) (i32.const 0)))) + (block i32 + (if i32 + (get_local 0) + (get_local 1) + (br_table 1 0 (i32.const 4) (i32.const 0)) + ) + ) ) (func (export "as-select-first") (param i32 i32) (result i32) - (block (select (br_table 0 (i32.const 5) (i32.const 0)) (get_local 0) (get_local 1))) + (block i32 + (select + (br_table 0 (i32.const 5) (i32.const 0)) (get_local 0) (get_local 1) + ) + ) ) (func (export "as-select-second") (param i32 i32) (result i32) - (block (select (get_local 0) (br_table 0 (i32.const 6) (i32.const 1)) (get_local 1))) + (block i32 + (select + (get_local 0) (br_table 0 (i32.const 6) (i32.const 1)) (get_local 1) + ) + ) ) (func (export "as-select-cond") (result i32) - (block (select (i32.const 0) (i32.const 1) (br_table 0 (i32.const 7) (i32.const 1)))) + (block i32 + (select + (i32.const 0) (i32.const 1) (br_table 0 (i32.const 7) (i32.const 1)) + ) + ) ) (func $f (param i32 i32 i32) (result i32) (i32.const -1)) (func (export "as-call-first") (result i32) - (block (call $f (br_table 0 (i32.const 12) (i32.const 1)) (i32.const 2) (i32.const 3))) + (block i32 + (call $f + (br_table 0 (i32.const 12) (i32.const 1)) (i32.const 2) (i32.const 3) + ) + ) ) (func (export "as-call-mid") (result i32) - (block (call $f (i32.const 1) (br_table 0 (i32.const 13) (i32.const 1)) (i32.const 3))) + (block i32 + (call $f + (i32.const 1) (br_table 0 (i32.const 13) (i32.const 1)) (i32.const 3) + ) + ) ) (func (export "as-call-last") (result i32) - (block (call $f (i32.const 1) (i32.const 2) (br_table 0 (i32.const 14) (i32.const 1)))) + (block i32 + (call $f + (i32.const 1) (i32.const 2) (br_table 0 (i32.const 14) (i32.const 1)) + ) + ) ) (type $sig (func (param i32 i32 i32) (result i32))) (table anyfunc (elem $f)) - (func (export "as-call_indirect-func") (result i32) - (block (call_indirect $sig (br_table 0 (i32.const 20) (i32.const 1)) (i32.const 1) (i32.const 2) (i32.const 3))) - ) (func (export "as-call_indirect-first") (result i32) - (block (call_indirect $sig (i32.const 0) (br_table 0 (i32.const 21) (i32.const 1)) (i32.const 2) (i32.const 3))) + (block i32 + (call_indirect $sig + (br_table 0 (i32.const 20) (i32.const 1)) (i32.const 1) (i32.const 2) + (i32.const 3) + ) + ) ) (func (export "as-call_indirect-mid") (result i32) - (block (call_indirect $sig (i32.const 0) (i32.const 1) (br_table 0 (i32.const 22) (i32.const 1)) (i32.const 3))) + (block i32 + (call_indirect $sig + (i32.const 0) (br_table 0 (i32.const 21) (i32.const 1)) (i32.const 2) + (i32.const 3) + ) + ) ) (func (export "as-call_indirect-last") (result i32) - (block (call_indirect $sig (i32.const 0) (i32.const 1) (i32.const 2) (br_table 0 (i32.const 23) (i32.const 1)))) + (block i32 + (call_indirect $sig + (i32.const 0) (i32.const 1) (br_table 0 (i32.const 22) (i32.const 1)) + (i32.const 3) + ) + ) + ) + (func (export "as-call_indirect-func") (result i32) + (block i32 + (call_indirect $sig + (i32.const 0) (i32.const 1) (i32.const 2) + (br_table 0 (i32.const 23) (i32.const 1)) + ) + ) ) - (func (export "as-set_local-value") (result i32) (local f32) - (block (set_local 0 (br_table 0 (i32.const 17) (i32.const 1))) (i32.const -1)) + (func (export "as-set_local-value") (result i32) + (local f32) + (block i32 + (set_local 0 (br_table 0 (i32.const 17) (i32.const 1))) + (i32.const -1) + ) ) (memory 1) (func (export "as-load-address") (result f32) - (block (f32.load (br_table 0 (f32.const 1.7) (i32.const 1)))) + (block f32 (f32.load (br_table 0 (f32.const 1.7) (i32.const 1)))) ) (func (export "as-loadN-address") (result i64) - (block (i64.load8_s (br_table 0 (i64.const 30) (i32.const 1)))) + (block i64 (i64.load8_s (br_table 0 (i64.const 30) (i32.const 1)))) ) (func (export "as-store-address") (result i32) - (block (f64.store (br_table 0 (i32.const 30) (i32.const 1)) (f64.const 7)) (i32.const -1)) + (block i32 + (f64.store (br_table 0 (i32.const 30) (i32.const 1)) (f64.const 7)) + (i32.const -1) + ) ) (func (export "as-store-value") (result i32) - (block (i64.store (i32.const 2) (br_table 0 (i32.const 31) (i32.const 1))) (i32.const -1)) + (block i32 + (i64.store (i32.const 2) (br_table 0 (i32.const 31) (i32.const 1))) + (i32.const -1) + ) ) (func (export "as-storeN-address") (result i32) - (block (i32.store8 (br_table 0 (i32.const 32) (i32.const 0)) (i32.const 7)) (i32.const -1)) + (block i32 + (i32.store8 (br_table 0 (i32.const 32) (i32.const 0)) (i32.const 7)) + (i32.const -1) + ) ) (func (export "as-storeN-value") (result i32) - (block (i64.store16 (i32.const 2) (br_table 0 (i32.const 33) (i32.const 0))) (i32.const -1)) + (block i32 + (i64.store16 (i32.const 2) (br_table 0 (i32.const 33) (i32.const 0))) + (i32.const -1) + ) ) (func (export "as-unary-operand") (result f32) - (block (f32.neg (br_table 0 (f32.const 3.4) (i32.const 0)))) + (block f32 (f32.neg (br_table 0 (f32.const 3.4) (i32.const 0)))) ) (func (export "as-binary-left") (result i32) - (block (i32.add (br_table 0 0 (i32.const 3) (i32.const 0)) (i32.const 10))) + (block i32 + (i32.add (br_table 0 0 (i32.const 3) (i32.const 0)) (i32.const 10)) + ) ) (func (export "as-binary-right") (result i64) - (block (i64.sub (i64.const 10) (br_table 0 (i64.const 45) (i32.const 0)))) + (block i64 + (i64.sub (i64.const 10) (br_table 0 (i64.const 45) (i32.const 0))) + ) ) (func (export "as-test-operand") (result i32) - (block (i32.eqz (br_table 0 (i32.const 44) (i32.const 0)))) + (block i32 (i32.eqz (br_table 0 (i32.const 44) (i32.const 0)))) ) (func (export "as-compare-left") (result i32) - (block (f64.le (br_table 0 0 (i32.const 43) (i32.const 0)) (f64.const 10))) + (block i32 + (f64.le (br_table 0 0 (i32.const 43) (i32.const 0)) (f64.const 10)) + ) ) (func (export "as-compare-right") (result i32) - (block (f32.ne (f32.const 10) (br_table 0 (i32.const 42) (i32.const 0)))) + (block i32 + (f32.ne (f32.const 10) (br_table 0 (i32.const 42) (i32.const 0))) + ) ) (func (export "as-convert-operand") (result i32) - (block (i32.wrap/i64 (br_table 0 (i32.const 41) (i32.const 0)))) + (block i32 (i32.wrap/i64 (br_table 0 (i32.const 41) (i32.const 0)))) ) (func (export "as-grow_memory-size") (result i32) - (block (grow_memory (br_table 0 (i32.const 40) (i32.const 0)))) + (block i32 (grow_memory (br_table 0 (i32.const 40) (i32.const 0)))) ) (func (export "nested-block-value") (param i32) (result i32) - (block + (block i32 (drop (i32.const -1)) (i32.add (i32.const 1) - (block + (block i32 (i32.add (i32.const 2) - (block + (block i32 (drop (i32.const 4)) (i32.add (i32.const 8) @@ -1010,13 +1116,13 @@ ) (func (export "nested-br-value") (param i32) (result i32) - (block + (block i32 (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br 0 (br_table 2 1 0 (i32.const 8) (get_local 0))) ) @@ -1028,13 +1134,13 @@ ) (func (export "nested-br_if-value") (param i32) (result i32) - (block + (block i32 (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br_if 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) (i32.const 32) @@ -1047,10 +1153,10 @@ ) (func (export "nested-br_if-value-cond") (param i32) (result i32) - (block + (block i32 (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_if 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (get_local 0))) (i32.const 16) @@ -1060,13 +1166,13 @@ ) (func (export "nested-br_table-value") (param i32) (result i32) - (block + (block i32 (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (drop - (block + (block i32 (drop (i32.const 4)) (br_table 0 (br_table 0 1 2 (i32.const 8) (get_local 0)) (i32.const 1)) (i32.const 32) @@ -1079,10 +1185,10 @@ ) (func (export "nested-br_table-value-index") (param i32) (result i32) - (block + (block i32 (i32.add (i32.const 1) - (block + (block i32 (drop (i32.const 2)) (br_table 0 (i32.const 4) (br_table 0 1 0 (i32.const 8) (get_local 0))) (i32.const 16) @@ -1198,10 +1304,10 @@ (assert_return (invoke "as-call-mid") (i32.const 13)) (assert_return (invoke "as-call-last") (i32.const 14)) -(assert_return (invoke "as-call_indirect-func") (i32.const 20)) -(assert_return (invoke "as-call_indirect-first") (i32.const 21)) -(assert_return (invoke "as-call_indirect-mid") (i32.const 22)) -(assert_return (invoke "as-call_indirect-last") (i32.const 23)) +(assert_return (invoke "as-call_indirect-first") (i32.const 20)) +(assert_return (invoke "as-call_indirect-mid") (i32.const 21)) +(assert_return (invoke "as-call_indirect-last") (i32.const 22)) +(assert_return (invoke "as-call_indirect-func") (i32.const 23)) (assert_return (invoke "as-set_local-value") (i32.const 17)) @@ -1270,24 +1376,18 @@ (assert_return (invoke "nested-br_table-value-index" (i32.const 9423975)) (i32.const 9)) (assert_invalid - (module (func $type-arg-empty-vs-num (result i32) + (module (func $type-arg-void-vs-num (result i32) (block (br_table 0 (i32.const 1)) (i32.const 1)) )) "type mismatch" ) -(assert_invalid - (module (func $type-arg-void-vs-empty - (block (br_table 0 (nop) (i32.const 1))) - )) - "type mismatch" -) -(assert_invalid - (module (func $type-arg-num-vs-empty - (block (br_table 0 (i32.const 0) (i32.const 1))) - )) - "type mismatch" -) -(; TODO(stack): Should this become legal? + +;; TODO(stack): move this elsewhere +(module (func $type-arg-num-vs-void + (block (br_table 0 (i32.const 0) (i32.const 1))) +)) + +(; TODO(stack): soft failure (assert_invalid (module (func $type-arg-poly-vs-empty (block (br_table 0 (unreachable) (i32.const 1))) @@ -1298,13 +1398,13 @@ (assert_invalid (module (func $type-arg-void-vs-num (result i32) - (block (br_table 0 (nop) (i32.const 1)) (i32.const 1)) + (block i32 (br_table 0 (nop) (i32.const 1)) (i32.const 1)) )) "type mismatch" ) (assert_invalid (module (func $type-arg-num-vs-num (result i32) - (block (br_table 0 0 0 (i64.const 1) (i32.const 1)) (i32.const 1)) + (block i32 (br_table 0 0 0 (i64.const 1) (i32.const 1)) (i32.const 1)) )) "type mismatch" ) @@ -1323,32 +1423,17 @@ ) (assert_invalid (module (func $type-arg-index-void-vs-i32 (result i32) - (block (br_table 0 0 (i32.const 0) (nop)) (i32.const 1)) + (block i32 (br_table 0 0 (i32.const 0) (nop)) (i32.const 1)) )) "type mismatch" ) (assert_invalid (module (func $type-arg-index-num-vs-i32 (result i32) - (block (br_table 0 0 (i32.const 0) (i64.const 0)) (i32.const 1)) + (block i32 (br_table 0 0 (i32.const 0) (i64.const 0)) (i32.const 1)) )) "type mismatch" ) -(assert_invalid - (module (func $type-binary (result i64) - (block (i64.const 1) (i64.const 2) (i64.const 3) br_table 2 0 0) - i64.add - )) - "invalid result arity" -) -(assert_invalid - (module (func $type-binary-with-nop (result i32) - (block (nop) (i32.const 7) (nop) (i32.const 8) (i64.const 3) br_table 2 0) - i32.add - )) - "invalid result arity" -) - (assert_invalid (module (func $unbound-label (block (br_table 2 1 (i32.const 1))) diff --git a/ml-proto/test/break-drop.wast b/ml-proto/test/break-drop.wast index a09f27148e..e10df66715 100644 --- a/ml-proto/test/break-drop.wast +++ b/ml-proto/test/break-drop.wast @@ -7,19 +7,3 @@ (assert_return (invoke "br")) (assert_return (invoke "br_if")) (assert_return (invoke "br_table")) - -(assert_invalid - (module (func (block (br 0 (nop))))) - "type mismatch" -) - -(assert_invalid - (module (func (block (br_if 0 (nop) (i32.const 0))))) - "type mismatch" -) - -(assert_invalid - (module (func (block (br_table 0 (nop) (i32.const 0))))) - "type mismatch" -) - diff --git a/ml-proto/test/call.wast b/ml-proto/test/call.wast index 548b473a4c..c3eba353e5 100644 --- a/ml-proto/test/call.wast +++ b/ml-proto/test/call.wast @@ -45,14 +45,14 @@ ;; Recursion (func $fac (export "fac") (param i64) (result i64) - (if (i64.eqz (get_local 0)) + (if i64 (i64.eqz (get_local 0)) (i64.const 1) (i64.mul (get_local 0) (call $fac (i64.sub (get_local 0) (i64.const 1)))) ) ) (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) - (if (i64.eqz (get_local 0)) + (if i64 (i64.eqz (get_local 0)) (get_local 1) (call $fac-acc (i64.sub (get_local 0) (i64.const 1)) @@ -62,7 +62,7 @@ ) (func $fib (export "fib") (param i64) (result i64) - (if (i64.le_u (get_local 0) (i64.const 1)) + (if i64 (i64.le_u (get_local 0) (i64.const 1)) (i64.const 1) (i64.add (call $fib (i64.sub (get_local 0) (i64.const 2))) @@ -72,13 +72,13 @@ ) (func $even (export "even") (param i64) (result i32) - (if (i64.eqz (get_local 0)) + (if i32 (i64.eqz (get_local 0)) (i32.const 44) (call $odd (i64.sub (get_local 0) (i64.const 1))) ) ) (func $odd (export "odd") (param i64) (result i32) - (if (i64.eqz (get_local 0)) + (if i32 (i64.eqz (get_local 0)) (i32.const 99) (call $even (i64.sub (get_local 0) (i64.const 1))) ) diff --git a/ml-proto/test/call_indirect.wast b/ml-proto/test/call_indirect.wast index 74afe2f2af..cdbb55ccd3 100644 --- a/ml-proto/test/call_indirect.wast +++ b/ml-proto/test/call_indirect.wast @@ -102,7 +102,7 @@ ;; Recursion (func $fac (export "fac") (type $over-i64) - (if (i64.eqz (get_local 0)) + (if i64 (i64.eqz (get_local 0)) (i64.const 1) (i64.mul (get_local 0) @@ -115,7 +115,7 @@ ) (func $fib (export "fib") (type $over-i64) - (if (i64.le_u (get_local 0) (i64.const 1)) + (if i64 (i64.le_u (get_local 0) (i64.const 1)) (i64.const 1) (i64.add (call_indirect $over-i64 @@ -131,7 +131,7 @@ ) (func $even (export "even") (param i32) (result i32) - (if (i32.eqz (get_local 0)) + (if i32 (i32.eqz (get_local 0)) (i32.const 44) (call_indirect $over-i32 (i32.sub (get_local 0) (i32.const 1)) @@ -140,7 +140,7 @@ ) ) (func $odd (export "odd") (param i32) (result i32) - (if (i32.eqz (get_local 0)) + (if i32 (i32.eqz (get_local 0)) (i32.const 99) (call_indirect $over-i32 (i32.sub (get_local 0) (i32.const 1)) diff --git a/ml-proto/test/expected-output/if-label-scope.fail.wast.log b/ml-proto/test/expected-output/if-label-scope.fail.wast.log new file mode 100644 index 0000000000..a3e1d79e11 --- /dev/null +++ b/ml-proto/test/expected-output/if-label-scope.fail.wast.log @@ -0,0 +1 @@ +test/if-label-scope.fail.wast:1.26-1.28: syntax error: unknown label $l diff --git a/ml-proto/test/expected-output/if_label_scope.fail.wast.log b/ml-proto/test/expected-output/if_label_scope.fail.wast.log deleted file mode 100644 index 4fa590d00c..0000000000 --- a/ml-proto/test/expected-output/if_label_scope.fail.wast.log +++ /dev/null @@ -1 +0,0 @@ -test/if_label_scope.fail.wast:6.19-6.21: syntax error: unknown label $l diff --git a/ml-proto/test/fac.wast b/ml-proto/test/fac.wast index 445dcfb012..be587520ca 100644 --- a/ml-proto/test/fac.wast +++ b/ml-proto/test/fac.wast @@ -1,7 +1,7 @@ (module ;; Recursive factorial (func (export "fac-rec") (param i64) (result i64) - (if (i64.eq (get_local 0) (i64.const 0)) + (if i64 (i64.eq (get_local 0) (i64.const 0)) (i64.const 1) (i64.mul (get_local 0) (call 0 (i64.sub (get_local 0) (i64.const 1)))) ) @@ -9,7 +9,7 @@ ;; Recursive factorial named (func $fac-rec-named (export "fac-rec-named") (param $n i64) (result i64) - (if (i64.eq (get_local $n) (i64.const 0)) + (if i64 (i64.eq (get_local $n) (i64.const 0)) (i64.const 1) (i64.mul (get_local $n) diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index f00d25ca52..ad8f769f0d 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -897,15 +897,15 @@ ;; Test that x