diff --git a/ml-proto/README.md b/ml-proto/README.md index 63b8d0842c..5f40a050c7 100644 --- a/ml-proto/README.md +++ b/ml-proto/README.md @@ -123,10 +123,10 @@ cvtop: trunc_s | trunc_u | extend_s | extend_u | ... expr: ( nop ) ( block ? * ) - ( loop ? ? * ) ;; = (block ? (loop ? (block *))) + ( loop ? ? * ) ;; = (block ? (loop ? (block *))) ( select ) ( if ( then ? * ) ( else ? * )? ) - ( if ? ) ;; = (if (then ) (else ?)) + ( if ? ) ;; = (if (then ) (else ?)) ( br ? ) ( br_if ? ) ( br_table ? ) @@ -147,24 +147,49 @@ expr: ( current_memory ) ( grow_memory ) -func: ( func ? * * ) - ( func ? * * ) ;; = (export ) (func ? * *) -sig: ( type ) | * ? -param: ( param * ) | ( param ) -result: ( result ) -local: ( local * ) | ( local ) - -module: ( module * * * * ? ? * * ? ) | (module +) -typedef: ( type ? ( func * ? ) ) -import: ( import ? ) -export: ( export ) | ( export memory) -start: ( start ) -table: ( table ? ) - ( table ( elem * ) ) ;; = (table ) (elem (i32.const 0) *) +func: ( func ? * * ) + ( func ? ( export ) * * ) ;; = (export (func ) (func ? * *) + ( func ? ( import ) ) ;; = (import ? (func )) +param: ( param * ) | ( param ) +result: ( result ) +local: ( local * ) | ( local ) + +func_sig: ( type ) | * ? +global_sig: +table_sig: ? +memory_sig: ? + +global: ( global ? ) + ( global ? ( export ) ) ;; = (export (global )) (global ? ) + ( global ? ( import ) ) ;; = (import ? (global )) +table: ( table ? ) + ( table ? ( export ) ) ;; = (export (table )) (table ? ) + ( table ? ( import ) ) ;; = (import ? (table )) + ( table ? ( export )? ( elem * ) ) ;; = (table ? ( export )? ) (elem (i32.const 0) *) elem: ( elem * ) -memory: ( memory ? ) - ( memory ( data * ) ) ;; = (memory ) (data (i32.const 0) *) +memory: ( memory ? ) + ( memory ? ( export ) ) ;; = (export (memory )) (memory ? ) + ( memory ? ( import ) ) ;; = (import ? (memory )) + ( memory ? ( export )? ( data * ) ;; = (memory ? ( export )? ) (data (i32.const 0) *) data: ( data * ) + +start: ( start ) + +typedef: ( type ? ( func ) ) + +import: ( import ) +imkind: ( func ? ) + ( global ? ) + ( table ? ) + ( memory ? ) +export: ( export ) +exkind: ( func ) + ( global ) + ( table ) + ( memory ) + +module: ( module * * * *
? ? * * ? ) + ( module + ) ``` Here, productions marked with respective comments are abbreviation forms for equivalent expansions (see the explanation of the kernel AST below). diff --git a/ml-proto/host/arrange.ml b/ml-proto/host/arrange.ml index 1bd9c00ce0..18e8db611f 100644 --- a/ml-proto/host/arrange.ml +++ b/ml-proto/host/arrange.ml @@ -53,6 +53,9 @@ let func_type {ins; out} = let struct_type = func_type +let limits int {min; max} = + String.concat " " (int min :: opt int max) + (* Operators *) @@ -218,7 +221,6 @@ let rec expr e = ) | Select (e1, e2, e3) -> "select", [expr e1; expr e2; expr e3] | Call (x, es) -> "call " ^ var x, list expr es - | CallImport (x, es) -> "call_import " ^ var x, list expr es | CallIndirect (x, e, es) -> "call_indirect " ^ var x, list expr (e::es) | GetLocal x -> "get_local " ^ var x, [] | SetLocal (x, e) -> "set_local " ^ var x, [expr e] @@ -247,9 +249,9 @@ and block e = (* Functions *) -let func i f = +let func off i f = let {ftype; locals; body} = f.it in - Node ("func $" ^ string_of_int i, + Node ("func $" ^ string_of_int (off + i), [Node ("type " ^ var ftype, [])] @ decls "local" locals @ block body @@ -262,21 +264,19 @@ let table xs = tab "table" (atom var) xs (* Tables & memories *) -let limits int lim = - let {min; max} = lim.it in - String.concat " " (int min :: opt int max) - -let table tab = - let {tlimits = lim; etype} = tab.it in - Node ("table " ^ limits int32 lim, [atom elem_type etype]) +let table off i tab = + let {ttype = TableType (lim, t)} = tab.it in + Node ("table $" ^ string_of_int (off + i) ^ " " ^ limits int32 lim, + [atom elem_type t] + ) -let memory mem = - let {mlimits = lim} = mem.it in - Node ("memory " ^ limits int32 lim, []) +let memory off i mem = + let {mtype = MemoryType lim} = mem.it in + Node ("memory $" ^ string_of_int (off + i) ^ " " ^ limits int32 lim, []) let segment head dat seg = - let {offset; init} = seg.it in - Node (head, expr offset :: dat init) + let {index; offset; init} = seg.it in + Node (head, atom var index :: expr offset :: dat init) let elems seg = segment "elem" (list (atom var)) seg @@ -290,33 +290,67 @@ let data seg = let typedef i t = Node ("type $" ^ string_of_int i, [struct_type t]) +let import_kind i k = + match k.it with + | FuncImport x -> + Node ("func $" ^ string_of_int i, [Node ("type", [atom var x])]) + | TableImport t -> table 0 i ({ttype = t} @@ k.at) + | MemoryImport t -> memory 0 i ({mtype = t} @@ k.at) + | GlobalImport t -> + Node ("global $" ^ string_of_int i, [atom value_type t]) + let import i im = - let {itype; module_name; func_name} = im.it in - let ty = Node ("type " ^ var itype, []) in - Node ("import $" ^ string_of_int i, - [atom string module_name; atom string func_name; ty] + let {module_name; item_name; ikind} = im.it in + Node ("import", + [atom string module_name; atom string item_name; import_kind i ikind] ) -let global g = - let {gtype; value} = g.it in - Node ("global", [atom value_type gtype; expr value]) +let export_kind k = + match k.it with + | FuncExport -> "func" + | TableExport -> "table" + | MemoryExport -> "memory" + | GlobalExport -> "global" let export ex = - let {name; kind} = ex.it in - let desc = match kind with `Func x -> var x | `Memory -> "memory" in - Node ("export", [atom string name; Atom desc]) + let {name; ekind; item} = ex.it in + Node ("export", + [atom string name; Node (export_kind ekind, [atom var item])] + ) + +let global off i g = + let {gtype; value} = g.it in + Node ("global $" ^ string_of_int (off + i), + [atom value_type gtype; expr value] + ) (* Modules *) +let is_func_import im = + match im.it.ikind.it with FuncImport _ -> true | _ -> false +let is_table_import im = + match im.it.ikind.it with TableImport _ -> true | _ -> false +let is_memory_import im = + match im.it.ikind.it with MemoryImport _ -> true | _ -> false +let is_global_import im = + match im.it.ikind.it with GlobalImport _ -> true | _ -> false + let module_ m = + let func_imports = List.filter is_func_import m.it.imports in + let table_imports = List.filter is_table_import m.it.imports in + let memory_imports = List.filter is_memory_import m.it.imports in + let global_imports = List.filter is_global_import m.it.imports in Node ("module", listi typedef m.it.types @ - listi import m.it.imports @ - opt table m.it.table @ - opt memory m.it.memory @ - list global m.it.globals @ - listi func m.it.funcs @ + listi import table_imports @ + listi import memory_imports @ + listi import global_imports @ + listi import func_imports @ + listi (table (List.length table_imports)) m.it.tables @ + listi (memory (List.length memory_imports)) m.it.memories @ + listi (global (List.length global_imports)) m.it.globals @ + listi (func (List.length func_imports)) m.it.funcs @ list export m.it.exports @ opt start m.it.start @ list elems m.it.elems @ diff --git a/ml-proto/host/encode.ml b/ml-proto/host/encode.ml index a2c4213310..af4aa77d7e 100644 --- a/ml-proto/host/encode.ml +++ b/ml-proto/host/encode.ml @@ -63,14 +63,15 @@ let encode m = let vec f xs = vu (List.length xs); list f xs let vec1 f xo = bool (xo <> None); opt f xo - let gap () = let p = pos s in u32 0l; p + let gap () = let p = pos s in u32 0l; u8 0; p let patch_gap p n = assert (n <= 0x0fff_ffff); (* Strings cannot excess 2G anyway *) let lsb i = Char.chr (i land 0xff) in patch s p (lsb (n lor 0x80)); patch s (p + 1) (lsb ((n lsr 7) lor 0x80)); patch s (p + 2) (lsb ((n lsr 14) lor 0x80)); - patch s (p + 3) (lsb (n lsr 21)) + patch s (p + 3) (lsb ((n lsr 21) lor 0x80)); + patch s (p + 4) (lsb (n lsr 28)) (* Types *) @@ -90,6 +91,15 @@ let encode m = let func_type = function | {ins; out} -> u8 0x40; vec value_type ins; expr_type out + 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 + (* Expressions *) open Source @@ -135,7 +145,6 @@ let encode m = | 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 @@ -316,9 +325,16 @@ let encode m = section "type" (vec func_type) ts (ts <> []) (* Import section *) + let import_kind k = + match k.it with + | FuncImport x -> u8 0x00; var x + | TableImport t -> u8 0x01; table_type t + | MemoryImport t -> u8 0x02; memory_type t + | GlobalImport t -> u8 0x03; value_type t + let import imp = - let {itype; module_name; func_name} = imp.it in - var itype; string module_name; string func_name + let {module_name; item_name; ikind} = imp.it in + string module_name; string item_name; import_kind ikind let import_section imps = section "import" (vec import) imps (imps <> []) @@ -330,45 +346,42 @@ let encode m = section "function" (vec func) fs (fs <> []) (* Table section *) - let limits vu lim = - let {min; max} = lim.it in - bool (max <> None); vu min; opt vu max - let table tab = - let {etype; tlimits} = tab.it in - elem_type etype; - limits vu32 tlimits + let {ttype} = tab.it in + table_type ttype - let table_section tabo = - section "table" (opt table) tabo (tabo <> None) + let table_section tabs = + section "table" (vec table) tabs (tabs <> []) (* Memory section *) let memory mem = - let {mlimits} = mem.it in - limits vu32 mlimits + let {mtype} = mem.it in + memory_type mtype - let memory_section memo = - section "memory" (opt memory) memo (memo <> None) + let memory_section mems = + section "memory" (vec memory) mems (mems <> []) (* Global section *) let global g = - let {gtype = t; value = e} = g.it in - value_type t; expr e; op 0x0f + let {gtype; value} = g.it in + value_type gtype; expr value; op 0x0f let global_section gs = section "global" (vec global) gs (gs <> []) (* Export section *) + let export_kind k = + match k.it with + | FuncExport -> u8 0 + | TableExport -> u8 1 + | MemoryExport -> u8 2 + | GlobalExport -> u8 3 + let export exp = - let {Kernel.name; kind} = exp.it in - (match kind with - | `Func x -> var x - | `Memory -> () (*TODO: pending resolution*) - ); string name + let {name; ekind; item} = exp.it in + string name; export_kind ekind; var item let export_section exps = - (*TODO: pending resolution*) - let exps = List.filter (fun exp -> exp.it.kind <> `Memory) exps in section "export" (vec export) exps (exps <> []) (* Start section *) @@ -397,8 +410,8 @@ let encode m = (* Element section *) let segment dat seg = - let {offset; init} = seg.it in - const offset; dat init + let {index; offset; init} = seg.it in + var index; const offset; dat init let table_segment seg = segment (vec var) seg @@ -421,8 +434,8 @@ let encode m = type_section m.it.types; import_section m.it.imports; func_section m.it.funcs; - table_section m.it.table; - memory_section m.it.memory; + table_section m.it.tables; + memory_section m.it.memories; global_section m.it.globals; export_section m.it.exports; start_section m.it.start; diff --git a/ml-proto/host/import.ml b/ml-proto/host/import.ml index ebd0969816..481046e470 100644 --- a/ml-proto/host/import.ml +++ b/ml-proto/host/import.ml @@ -11,11 +11,18 @@ let registry = ref Registry.empty let register name lookup = registry := Registry.add name lookup !registry -let lookup m i = - let {module_name; func_name; itype} = i.it in - let ty = List.nth m.it.types itype.it in - try Registry.find module_name !registry func_name ty with Not_found -> - Unknown.error i.at - ("no function \"" ^ module_name ^ "." ^ func_name ^ "\" of requested type") +let external_type_of_import_kind m ikind = + match ikind.it with + | FuncImport x -> ExternalFuncType (List.nth m.it.types x.it) + | TableImport t -> ExternalTableType t + | MemoryImport t -> ExternalMemoryType t + | GlobalImport t -> ExternalGlobalType t + +let lookup (m : module_) (imp : import) : Instance.extern = + let {module_name; item_name; ikind} = imp.it in + let ty = external_type_of_import_kind m ikind in + try Registry.find module_name !registry item_name ty with Not_found -> + Unknown.error imp.at + ("unknown import \"" ^ module_name ^ "." ^ item_name ^ "\"") let link m = List.map (lookup m) m.it.imports diff --git a/ml-proto/host/import.mli b/ml-proto/host/import.mli index a882eda6d6..3eb201212b 100644 --- a/ml-proto/host/import.mli +++ b/ml-proto/host/import.mli @@ -1,4 +1,5 @@ exception Unknown of Source.region * string -val link : Kernel.module_ -> Eval.import list (* raises Unknown *) -val register: string -> (string -> Types.func_type -> Values.func) -> unit +val link : Kernel.module_ -> Instance.extern list (* raises Unknown *) + +val register : string -> (string -> Types.external_type -> Instance.extern) -> unit diff --git a/ml-proto/host/import/env.ml b/ml-proto/host/import/env.ml index d25b510675..6fc7e4a236 100644 --- a/ml-proto/host/import/env.ml +++ b/ml-proto/host/import/env.ml @@ -13,7 +13,7 @@ let error msg = raise (Eval.Crash (Source.no_region, msg)) let type_error v t = error ("type error, expected " ^ string_of_value_type t ^ - ", got " ^ string_of_value_type (type_of v)) + ", got " ^ string_of_value_type (type_of v)) let empty = function | [] -> () @@ -38,8 +38,10 @@ let exit vs = exit (int (single vs)) -let lookup name ty = - match name, ty.ins, ty.out with - | "abort", [], None -> abort - | "exit", [Int32Type], None -> exit +open Instance + +let lookup name t = + match name with + | "abort" -> ExternalFunc (HostFunc abort) + | "exit" -> ExternalFunc (HostFunc exit) | _ -> raise Not_found diff --git a/ml-proto/host/import/spectest.ml b/ml-proto/host/import/spectest.ml index 6b03ba8c6a..ef25246ecf 100644 --- a/ml-proto/host/import/spectest.ml +++ b/ml-proto/host/import/spectest.ml @@ -3,14 +3,31 @@ *) open Types +open Values -let print vs = +let global = function + | Int32Type -> Int32 666l + | Int64Type -> Int64 666L + | Float32Type -> Float32 (F32.of_float 666.0) + | Float64Type -> Float64 (F64.of_float 666.0) + +let table = Table.create {min = 10l; max = Some 20l} +let memory = Memory.create {min = 1l; max = Some 2l} + +let print out vs = List.iter Print.print_value (List.map (fun v -> Some v) vs); - None + Lib.Option.map default_value out + +open Instance -let lookup name ty = - match name, ty.ins, ty.out with - | "print", _, None -> print +let lookup name t = + match name, t with + | "print", ExternalFuncType ft -> ExternalFunc (HostFunc (print ft.out)) + | "print", _ -> ExternalFunc (HostFunc (print None)) + | "global", ExternalGlobalType t -> ExternalGlobal (global t) + | "global", _ -> ExternalGlobal (global Int32Type) + | "table", _ -> ExternalTable table + | "memory", _ -> ExternalMemory memory | _ -> raise Not_found diff --git a/ml-proto/host/lexer.mll b/ml-proto/host/lexer.mll index 131a2bceb2..a115d6c651 100644 --- a/ml-proto/host/lexer.mll +++ b/ml-proto/host/lexer.mll @@ -155,7 +155,6 @@ rule token = parse | "else" { ELSE } | "select" { SELECT } | "call" { CALL } - | "call_import" { CALL_IMPORT } | "call_indirect" { CALL_INDIRECT } | "get_local" { GET_LOCAL } @@ -373,6 +372,7 @@ rule token = parse | "export" { EXPORT } | "assert_invalid" { ASSERT_INVALID } + | "assert_unlinkable" { ASSERT_UNLINKABLE } | "assert_return" { ASSERT_RETURN } | "assert_return_nan" { ASSERT_RETURN_NAN } | "assert_trap" { ASSERT_TRAP } diff --git a/ml-proto/host/parser.mly b/ml-proto/host/parser.mly index e6e0ebf1e1..f059bba3fb 100644 --- a/ml-proto/host/parser.mly +++ b/ml-proto/host/parser.mly @@ -63,12 +63,12 @@ type types = {mutable tmap : int VarMap.t; mutable tlist : Types.func_type list} let empty_types () = {tmap = VarMap.empty; tlist = []} type context = - {types : types; funcs : space; imports : space; + {types : types; tables : space; memories : space; funcs : space; locals : space; globals : space; labels : int VarMap.t} let empty_context () = - {types = empty_types (); funcs = empty (); imports = empty (); - locals = empty (); globals = empty (); labels = VarMap.empty} + {types = empty_types (); tables = empty (); memories = empty (); + funcs = empty (); locals = empty (); globals = empty (); labels = VarMap.empty} let enter_func c = assert (VarMap.is_empty c.labels); @@ -83,9 +83,10 @@ let lookup category space x = with Not_found -> error x.at ("unknown " ^ category ^ " " ^ x.it) let func c x = lookup "function" c.funcs x -let import c x = lookup "import" c.imports x let local c x = lookup "local" c.locals x let global c x = lookup "global" c.globals x +let table c x = lookup "table" c.tables x +let memory c x = lookup "memory" c.memories x let label c x = try VarMap.find x.it c.labels with Not_found -> error x.at ("unknown label " ^ x.it) @@ -103,9 +104,10 @@ let bind category space x = space.count <- space.count + 1 let bind_func c x = bind "function" c.funcs x -let bind_import c x = bind "import" c.imports x let bind_local c x = bind "local" c.locals x let bind_global c x = bind "global" c.globals x +let bind_table c x = bind "table" c.tables x +let bind_memory c x = bind "memory" c.memories x let bind_label c x = {c with labels = VarMap.add x.it 0 (VarMap.map ((+) 1) c.labels)} @@ -115,15 +117,16 @@ let anon_type c ty = let anon space n = space.count <- space.count + n let anon_func c = anon c.funcs 1 -let anon_import c = anon c.imports 1 let anon_locals c ts = anon c.locals (List.length ts) let anon_global c = anon c.globals 1 +let anon_table c = anon c.tables 1 +let anon_memory c = anon c.memories 1 let anon_label c = {c with labels = VarMap.map ((+) 1) c.labels} let empty_type = {ins = []; out = None} -let explicit_decl c name t at = - let x = name c type_ in +let explicit_sig c var t at = + let x = var c type_ in if x.it < List.length c.types.tlist && t <> empty_type && @@ -132,7 +135,7 @@ let explicit_decl c name t at = error at "signature mismatch"; x -let implicit_decl c t at = +let inline_type c t at = match Lib.List.index_of t c.types.tlist with | None -> let i = List.length c.types.tlist in anon_type c t; i @@ at | Some i -> i @@ at @@ -141,14 +144,15 @@ let implicit_decl c t at = %token NAT INT FLOAT TEXT VAR VALUE_TYPE ANYFUNC LPAR RPAR %token NOP DROP BLOCK IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE -%token CALL CALL_IMPORT CALL_INDIRECT RETURN +%token CALL CALL_INDIRECT RETURN %token GET_LOCAL SET_LOCAL TEE_LOCAL GET_GLOBAL SET_GLOBAL %token LOAD STORE OFFSET ALIGN %token CONST UNARY BINARY COMPARE CONVERT %token UNREACHABLE CURRENT_MEMORY GROW_MEMORY %token FUNC START TYPE PARAM RESULT LOCAL GLOBAL %token MODULE TABLE ELEM MEMORY DATA IMPORT EXPORT TABLE -%token ASSERT_INVALID ASSERT_RETURN ASSERT_RETURN_NAN ASSERT_TRAP INVOKE +%token ASSERT_INVALID ASSERT_UNLINKABLE +%token ASSERT_RETURN ASSERT_RETURN_NAN ASSERT_TRAP INVOKE %token INPUT OUTPUT %token EOF @@ -198,14 +202,34 @@ elem_type : ; func_type : - | /* empty */ - { {ins = []; out = None} } - | LPAR PARAM value_type_list RPAR - { {ins = $3; out = None} } - | LPAR PARAM value_type_list RPAR LPAR RESULT VALUE_TYPE RPAR - { {ins = $3; out = Some $7} } - | LPAR RESULT VALUE_TYPE RPAR - { {ins = []; out = Some $3} } + | LPAR FUNC func_sig RPAR { $3 } +; + +func_sig : + | /* empty */ { {ins = []; out = None} } + | LPAR RESULT VALUE_TYPE RPAR func_sig + { if $5.out <> None then error (at ()) "multiple return types"; + {$5 with out = Some $3} } + | LPAR PARAM value_type_list RPAR func_sig + { {$5 with ins = $3 @ $5.ins} } + | LPAR PARAM bind_var VALUE_TYPE RPAR func_sig /* Sugar */ + { {$6 with ins = $4 :: $6.ins} } +; + +table_sig : + | limits elem_type { TableType ($1, $2) } +; +memory_sig : + | limits { MemoryType $1 } +; +limits : + | NAT { {min = int32 $1 (ati 1); max = None} } + | NAT NAT + { {min = int32 $1 (ati 1); max = Some (int32 $2 (ati 2))} } +; + +type_use : + | LPAR TYPE var RPAR { $3 } ; @@ -225,15 +249,20 @@ var_list : | /* empty */ { fun c lookup -> [] } | var var_list { fun c lookup -> $1 c lookup :: $2 c lookup } ; + +bind_var_opt : + | /* empty */ { fun c anon bind -> anon c } + | bind_var { fun c anon bind -> bind c $1 } /* Sugar */ +; bind_var : | VAR { $1 @@ at () } ; -labeling : +labeling_opt : | /* empty */ %prec LOW { fun c -> anon_label c } - | labeling1 { $1 } + | labeling { $1 } ; -labeling1 : +labeling : | bind_var { fun c -> bind_label c $1 } ; @@ -253,10 +282,10 @@ 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 + | BLOCK labeling_opt expr_list { fun c -> let c' = $2 c in Block ($3 c') } + | LOOP labeling_opt expr_list { fun c -> let c' = anon_label c in let c'' = $2 c' in Loop ($3 c'') } - | LOOP labeling1 labeling1 expr_list + | LOOP labeling labeling expr_list { fun c -> let c' = $2 c in let c'' = $3 c' in Loop ($4 c'') } | BR var expr_opt { fun c -> Br ($2 c label, $3 c) } | BR_IF var expr { fun c -> Br_if ($2 c label, None, $3 c) } @@ -271,13 +300,12 @@ expr1 : | IF expr expr { fun c -> let c' = anon_label c in If ($2 c, [$3 c'], []) } | IF expr expr expr { fun c -> let c' = anon_label c in If ($2 c, [$3 c'], [$4 c']) } - | IF expr LPAR THEN labeling expr_list RPAR + | IF expr LPAR THEN labeling_opt expr_list RPAR { fun c -> let c' = $5 c in If ($2 c, $6 c', []) } - | IF expr LPAR THEN labeling expr_list RPAR LPAR ELSE labeling expr_list RPAR + | IF expr LPAR THEN labeling_opt expr_list RPAR LPAR ELSE labeling_opt expr_list RPAR { fun c -> let c1 = $5 c in let c2 = $10 c in If ($2 c, $6 c1, $11 c2) } | SELECT expr expr expr { fun c -> Select ($2 c, $3 c, $4 c) } | CALL var expr_list { fun c -> Call ($2 c func, $3 c) } - | CALL_IMPORT var expr_list { fun c -> Call_import ($2 c import, $3 c) } | CALL_INDIRECT var expr expr_list { fun c -> Call_indirect ($2 c type_, $3 c, $4 c) } | GET_LOCAL var { fun c -> Get_local ($2 c local) } @@ -335,127 +363,177 @@ func_body : fun c -> bind_local c $3; let f = (snd $6) c in {f with locals = $4 :: f.locals} } ; -type_use : - | LPAR TYPE var RPAR { $3 } -; func : - | LPAR FUNC export_opt type_use func_fields RPAR + | LPAR FUNC bind_var_opt inline_export type_use func_fields RPAR { let at = at () in - fun c -> anon_func c; let t = explicit_decl c $4 (fst $5) at in - let exs = $3 c in - fun () -> {(snd $5 (enter_func c)) with ftype = t} @@ at, exs } - | LPAR FUNC export_opt bind_var type_use func_fields RPAR /* Sugar */ + fun c -> $3 c anon_func bind_func; + let t = explicit_sig c $5 (fst $6) at in + (fun () -> {(snd $6 (enter_func c)) with ftype = t} @@ at), + $4 FuncExport c.funcs.count c } + /* Need to duplicate above for empty inline_export_opt to avoid LR(1) conflict. */ + | LPAR FUNC bind_var_opt type_use func_fields RPAR { let at = at () in - fun c -> bind_func c $4; let t = explicit_decl c $5 (fst $6) at in - let exs = $3 c in - fun () -> {(snd $6 (enter_func c)) with ftype = t} @@ at, exs } - | LPAR FUNC export_opt func_fields RPAR /* Sugar */ + fun c -> $3 c anon_func bind_func; + let t = explicit_sig c $4 (fst $5) at in + (fun () -> {(snd $5 (enter_func c)) with ftype = t} @@ at), + [] } + | LPAR FUNC bind_var_opt inline_export func_fields RPAR /* Sugar */ { let at = at () in - fun c -> anon_func c; let t = implicit_decl c (fst $4) at in - let exs = $3 c in - fun () -> {(snd $4 (enter_func c)) with ftype = t} @@ at, exs } - | LPAR FUNC export_opt bind_var func_fields RPAR /* Sugar */ + fun c -> $3 c anon_func bind_func; + let t = inline_type c (fst $5) at in + (fun () -> {(snd $5 (enter_func c)) with ftype = t} @@ at), + $4 FuncExport c.funcs.count c } + /* Need to duplicate above for empty inline_export_opt to avoid LR(1) conflict. */ + | LPAR FUNC bind_var_opt func_fields RPAR /* Sugar */ { let at = at () in - fun c -> bind_func c $4; let t = implicit_decl c (fst $5) at in - let exs = $3 c in - fun () -> {(snd $5 (enter_func c)) with ftype = t} @@ at, exs } -; -export_opt : - | /* empty */ { fun c -> [] } - | TEXT - { let at = at () in - fun c -> [{name = $1; kind = `Func (c.funcs.count - 1 @@ at)} @@ at] } + fun c -> $3 c anon_func bind_func; + let t = inline_type c (fst $4) at in + (fun () -> {(snd $4 (enter_func c)) with ftype = t} @@ at), + [] } ; /* Tables & Memories */ elem : - | LPAR ELEM expr var_list RPAR + | LPAR ELEM var expr var_list RPAR { let at = at () in - fun c -> {offset = $3 c; init = $4 c func} @@ at } + fun c -> {index = $3 c table; offset = $4 c; init = $5 c func} @@ at } + | LPAR ELEM expr var_list RPAR /* Sugar */ + { let at = at () in + fun c -> {index = 0 @@ at; offset = $3 c; init = $4 c func} @@ at } ; -table_limits : - | NAT { {min = int32 $1 (ati 1); max = None} @@ at () } - | NAT NAT - { {min = int32 $1 (ati 1); max = Some (int32 $2 (ati 2))} @@ at () } -; table : - | LPAR TABLE table_limits elem_type RPAR - { let at = at () in fun c -> {tlimits = $3; etype = $4} @@ at, [] } - | LPAR TABLE elem_type LPAR ELEM var_list RPAR RPAR /* Sugar */ + | LPAR TABLE bind_var_opt inline_export_opt table_sig RPAR { let at = at () in - fun c -> let init = $6 c func in - let size = Int32.of_int (List.length init) in - {tlimits = {min = size; max = Some size} @@ at; etype = $3} @@ at, - [{offset = I32_const (0l @@ at) @@ at; init} @@ at] } + fun c -> $3 c anon_table bind_table; + {ttype = $5} @@ at, [], $4 TableExport c.tables.count c } + | LPAR TABLE bind_var_opt inline_export_opt elem_type LPAR ELEM var_list RPAR RPAR /* Sugar */ + { let at = at () in + fun c -> $3 c anon_table bind_table; + let init = $8 c func in let size = Int32.of_int (List.length init) in + {ttype = TableType ({min = size; max = Some size}, $5)} @@ at, + [{index = c.tables.count - 1 @@ at; offset = I32_const (0l @@ at) @@ at; init} @@ at], + $4 TableExport c.tables.count c } ; data : - | LPAR DATA expr text_list RPAR - { fun c -> {offset = $3 c; init = $4} @@ at () } + | LPAR DATA var expr text_list RPAR + { let at = at () in + fun c -> {index = $3 c memory; offset = $4 c; init = $5} @@ at } + | LPAR DATA expr text_list RPAR /* Sugar */ + { let at = at () in + fun c -> {index = 0 @@ at; offset = $3 c; init = $4} @@ at } ; -memory_limits : - | NAT { {min = int32 $1 (ati 1); max = None} @@ at () } - | NAT NAT - { {min = int32 $1 (ati 1); max = Some (int32 $2 (ati 2))} @@ at () } -; memory : - | LPAR MEMORY memory_limits RPAR - { fun c -> {mlimits = $3} @@ at (), [] } - | LPAR MEMORY LPAR DATA text_list RPAR RPAR /* Sugar */ + | LPAR MEMORY bind_var_opt inline_export_opt memory_sig RPAR + { let at = at () in + fun c -> $3 c anon_memory bind_memory; + {mtype = $5} @@ at, [], $4 MemoryExport c.memories.count c } + | LPAR MEMORY bind_var_opt inline_export LPAR DATA text_list RPAR RPAR /* Sugar */ { let at = at () in - fun c -> - let size = Int32.(div (add (of_int (String.length $5)) 65535l) 65536l) in - {mlimits = {min = size; max = Some size} @@ at} @@ at, - [{offset = I32_const (0l @@ at) @@ at; init = $5} @@ at] } + fun c -> $3 c anon_memory bind_memory; + let size = Int32.(div (add (of_int (String.length $7)) 65535l) 65536l) in + {mtype = MemoryType {min = size; max = Some size}} @@ at, + [{index = c.memories.count - 1 @@ at; offset = I32_const (0l @@ at) @@ at; init = $7} @@ at], + $4 MemoryExport c.memories.count c } + /* Need to duplicate above for empty inline_export_opt to avoid LR(1) conflict. */ + | LPAR MEMORY bind_var_opt LPAR DATA text_list RPAR RPAR /* Sugar */ + { let at = at () in + fun c -> $3 c anon_memory bind_memory; + let size = Int32.(div (add (of_int (String.length $6)) 65535l) 65536l) in + {mtype = MemoryType {min = size; max = Some size}} @@ at, + [{index = c.memories.count - 1 @@ at; offset = I32_const (0l @@ at) @@ at; init = $6} @@ at], + [] } ; -/* Modules */ +/* Imports & Exports */ -type_def : - | LPAR TYPE LPAR FUNC func_type RPAR RPAR - { fun c -> anon_type c $5 } - | LPAR TYPE bind_var LPAR FUNC func_type RPAR RPAR - { fun c -> bind_type c $3 $6 } +import_kind : + | LPAR FUNC bind_var_opt type_use RPAR + { fun c -> $3 c anon_func bind_func; FuncImport ($4 c type_) } + | LPAR FUNC bind_var_opt func_sig RPAR /* Sugar */ + { let at4 = ati 4 in + fun c -> $3 c anon_func bind_func; FuncImport (inline_type c $4 at4) } + | LPAR TABLE bind_var_opt table_sig RPAR + { fun c -> $3 c anon_table bind_table; TableImport $4 } + | LPAR MEMORY bind_var_opt memory_sig RPAR + { fun c -> $3 c anon_memory bind_memory; MemoryImport $4 } + | LPAR GLOBAL bind_var_opt VALUE_TYPE RPAR + { fun c -> $3 c anon_global bind_global; GlobalImport $4 } ; - import : - | LPAR IMPORT TEXT TEXT type_use RPAR + | LPAR IMPORT TEXT TEXT import_kind RPAR + { let at = at () and at5 = ati 5 in + fun c -> {module_name = $3; item_name = $4; ikind = $5 c @@ at5} @@ at } + | LPAR FUNC bind_var_opt inline_import type_use RPAR /* Sugar */ { let at = at () in - fun c -> anon_import c; let itype = explicit_decl c $5 empty_type at in - {itype; module_name = $3; func_name = $4} @@ at } - | LPAR IMPORT bind_var TEXT TEXT type_use RPAR /* Sugar */ + fun c -> $3 c anon_func bind_func; + {module_name = fst $4; item_name = snd $4; ikind = FuncImport ($5 c type_) @@ at} @@ at } + | LPAR FUNC bind_var_opt inline_import func_sig RPAR /* Sugar */ + { let at = at () and at5 = ati 5 in + fun c -> $3 c anon_func bind_func; + {module_name = fst $4; item_name = snd $4; ikind = FuncImport (inline_type c $5 at5) @@ at} @@ at } + | LPAR TABLE bind_var_opt inline_import table_sig RPAR /* Sugar */ { let at = at () in - fun c -> bind_import c $3; let itype = explicit_decl c $6 empty_type at in - {itype; module_name = $4; func_name = $5} @@ at } - | LPAR IMPORT TEXT TEXT func_type RPAR /* Sugar */ + fun c -> $3 c anon_table bind_table; + {module_name = fst $4; item_name = snd $4; ikind = TableImport $5 @@ at} @@ at } + | LPAR MEMORY bind_var_opt inline_import memory_sig RPAR /* Sugar */ { let at = at () in - fun c -> anon_import c; let itype = implicit_decl c $5 at in - {itype; module_name = $3; func_name = $4} @@ at } - | LPAR IMPORT bind_var TEXT TEXT func_type RPAR /* Sugar */ + fun c -> $3 c anon_memory bind_memory; + {module_name = fst $4; item_name = snd $4; ikind = MemoryImport $5 @@ at} @@ at } + | LPAR GLOBAL bind_var_opt inline_import VALUE_TYPE RPAR /* Sugar */ { let at = at () in - fun c -> bind_import c $3; let itype = implicit_decl c $6 at in - {itype; module_name = $4; func_name = $5} @@ at } + fun c -> $3 c anon_global bind_global; + {module_name = fst $4; item_name = snd $4; ikind = GlobalImport $5 @@ at} @@ at } +; + +inline_import : + | LPAR IMPORT TEXT TEXT RPAR { $3, $4 } ; +export_kind : + | LPAR FUNC var RPAR { fun c -> FuncExport, $3 c func } + | LPAR TABLE var RPAR { fun c -> TableExport, $3 c table } + | LPAR MEMORY var RPAR { fun c -> MemoryExport, $3 c memory } + | LPAR GLOBAL var RPAR { fun c -> GlobalExport, $3 c global } +; export : - | LPAR EXPORT TEXT var RPAR - { let at = at () in fun c -> {name = $3; kind = `Func ($4 c func)} @@ at } - | LPAR EXPORT TEXT MEMORY RPAR - { let at = at () in fun c -> {name = $3; kind = `Memory} @@ at } + | LPAR EXPORT TEXT export_kind RPAR + { let at = at () and at4 = ati 4 in + fun c -> let k, x = $4 c in + {name = $3; ekind = k @@ at4; item = x} @@ at } ; -global : - | LPAR GLOBAL VALUE_TYPE expr RPAR +inline_export_opt : + | /* empty */ { fun k count c -> [] } + | inline_export { $1 } +; +inline_export : + | LPAR EXPORT TEXT RPAR { let at = at () in - fun c -> anon_global c; fun () -> {gtype = $3; value = $4 c} @@ at } - | LPAR GLOBAL bind_var VALUE_TYPE expr RPAR /* Sugar */ + fun k count c -> [{name = $3; ekind = k @@ at; item = count - 1 @@ at} @@ at] } +; + + +/* Modules */ + +type_def : + | LPAR TYPE func_type RPAR + { fun c -> anon_type c $3 } + | LPAR TYPE bind_var func_type RPAR /* Sugar */ + { fun c -> bind_type c $3 $4 } +; + +global : + | LPAR GLOBAL bind_var_opt inline_export_opt VALUE_TYPE expr RPAR { let at = at () in - fun c -> bind_global c $3; fun () -> {gtype = $4; value = $5 c} @@ at } + fun c -> $3 c anon_global bind_global; + (fun () -> {gtype = $5; value = $6 c} @@ at), + $4 GlobalExport c.globals.count c } ; start : @@ -469,8 +547,8 @@ module_fields : { types = c.types.tlist; globals = []; - table = None; - memory = None; + tables = []; + memories = []; funcs = []; elems = []; data = []; @@ -481,20 +559,24 @@ module_fields : | type_def module_fields { fun c -> $1 c; $2 c } | global module_fields - { fun c -> let g = $1 c in let m = $2 c in - {m with globals = g () :: m.globals} } + { fun c -> let g, exs = $1 c in let m = $2 c in + if m.imports <> [] then + error (List.hd m.imports).at "import after global definition"; + {m with globals = g () :: m.globals; exports = exs @ m.exports} } | table module_fields - { fun c -> let m = $2 c in let tab, elems = $1 c in - match m.table with - | Some _ -> error tab.at "multiple table sections" - | None -> {m with table = Some tab; elems = elems @ m.elems} } + { fun c -> let m = $2 c in let tab, elems, exs = $1 c in + if m.imports <> [] then + error (List.hd m.imports).at "import after table definition"; + {m with tables = tab :: m.tables; elems = elems @ m.elems; exports = exs @ m.exports} } | memory module_fields - { fun c -> let m = $2 c in let mem, data = $1 c in - match m.memory with - | Some _ -> error mem.at "multiple memory sections" - | None -> {m with memory = Some mem; data = data @ m.data} } + { fun c -> let m = $2 c in let mem, data, exs = $1 c in + if m.imports <> [] then + error (List.hd m.imports).at "import after memory definition"; + {m with memories = mem :: m.memories; data = data @ m.data; exports = exs @ m.exports} } | func module_fields - { fun c -> let f = $1 c in let m = $2 c in let func, exs = f () in + { fun c -> let f, exs = $1 c in let m = $2 c in let func = f () in + if m.imports <> [] then + error (List.hd m.imports).at "import after function definition"; {m with funcs = func :: m.funcs; exports = exs @ m.exports} } | elem module_fields { fun c -> let m = $2 c in @@ -527,6 +609,7 @@ cmd : | module_ { Define $1 @@ at () } | LPAR INVOKE TEXT const_list RPAR { Invoke ($3, $4) @@ at () } | LPAR ASSERT_INVALID module_ TEXT RPAR { AssertInvalid ($3, $4) @@ at () } + | LPAR ASSERT_UNLINKABLE module_ TEXT RPAR { AssertUnlinkable ($3, $4) @@ at () } | LPAR ASSERT_RETURN LPAR INVOKE TEXT const_list RPAR const_opt RPAR { AssertReturn ($5, $6, $8) @@ at () } | LPAR ASSERT_RETURN_NAN LPAR INVOKE TEXT const_list RPAR RPAR diff --git a/ml-proto/host/print.ml b/ml-proto/host/print.ml index 5450fcba43..5495265c20 100644 --- a/ml-proto/host/print.ml +++ b/ml-proto/host/print.ml @@ -7,27 +7,31 @@ open Printf open Types -let func_type m f = - List.nth m.it.types f.it.ftype.it +let print_no_sig prefix i = + printf "%s %d\n" prefix i -let string_of_table_type = function - | None -> "()" - | Some t -> "(" ^ string_of_func_type t ^ ")*" +let print_var_sig prefix i t = + printf "%s %d : %s\n" prefix i (string_of_value_type t) +let print_func_sig m prefix i x = + let t = List.nth m.it.types x.it in + printf "%s %d : %s\n" prefix i (string_of_func_type t) -let print_var_sig prefix i t = - printf "%s %d : %s\n" prefix i (string_of_value_type t.it) +let print_table_sig prefix i t = + printf "%s %d : %s\n" prefix i (string_of_table_type t) -let print_func_sig m prefix i f = - printf "%s %d : %s\n" prefix i (string_of_func_type (func_type m f)) +let print_memory_sig prefix i t = + printf "%s %d : %s\n" prefix i (string_of_memory_type t) let print_export m i ex = - let {name; kind} = ex.it in - let ascription = - match kind with - | `Func x -> string_of_func_type (func_type m (List.nth m.it.funcs x.it)) - | `Memory -> "memory" - in printf "export \"%s\" : %s\n" name ascription + let {name; ekind; item} = ex.it in + let kind = + match ekind.it with + | FuncExport -> "func" + | TableExport -> "table" + | MemoryExport -> "memory" + | GlobalExport -> "global" + in printf "export \"%s\" = %s %d\n" name kind item.it let print_start start = Lib.Option.app (fun x -> printf "start = func %d\n" x.it) start @@ -36,12 +40,24 @@ let print_start start = (* Ast *) let print_func m i f = - print_func_sig m "func" i f + print_func_sig m "func" i f.it.ftype + +let print_global m i glob = + print_var_sig "global" i glob.it.gtype + +let print_table m i tab = + print_table_sig "table" i tab.it.ttype + +let print_memory m i mem = + print_memory_sig "memory" i mem.it.mtype let print_module m = (* TODO: more complete print function *) - let {funcs; start; exports; table; _} = m.it in + let {funcs; globals; tables; memories; start; exports; _} = m.it in List.iteri (print_func m) funcs; + List.iteri (print_global m) globals; + List.iteri (print_table m) tables; + List.iteri (print_memory m) memories; List.iteri (print_export m) exports; print_start start; flush_all () diff --git a/ml-proto/host/run.ml b/ml-proto/host/run.ml index 0bd3ff3b3f..2c4b6b63e5 100644 --- a/ml-proto/host/run.ml +++ b/ml-proto/host/run.ml @@ -30,6 +30,7 @@ let run_from get_script = | Parse.Syntax (at, msg) -> error at "syntax error" msg | Script.Assert (at, msg) -> error at "assertion failure" msg | Check.Invalid (at, msg) -> error at "invalid module" msg + | Eval.Link (at, msg) -> error at "linking failure" ("link failure: " ^ msg) | Eval.Trap (at, msg) -> error at "runtime trap" ("trap: " ^ msg) | Eval.Crash (at, msg) -> error at "runtime crash" ("crash: " ^ msg) | Import.Unknown (at, msg) -> error at "unknown import" msg diff --git a/ml-proto/host/script.ml b/ml-proto/host/script.ml index a7505bebdb..7cf8a7dfbe 100644 --- a/ml-proto/host/script.ml +++ b/ml-proto/host/script.ml @@ -13,6 +13,7 @@ and command' = | Define of definition | Invoke of string * Kernel.literal list | AssertInvalid of definition * string + | AssertUnlinkable of definition * string | AssertReturn of string * Kernel.literal list * Kernel.literal option | AssertReturnNaN of string * Kernel.literal list | AssertTrap of string * Kernel.literal list * string @@ -37,7 +38,7 @@ exception IO = IO.Error let trace name = if !Flags.trace then print_endline ("-- " ^ name) let current_module : Ast.module_ option ref = ref None -let current_instance : Eval.instance option ref = ref None +let current_instance : Instance.instance option ref = ref None let get_module at = match !current_module with | Some m -> m @@ -71,9 +72,9 @@ let run_cmd cmd = Print.print_module_sig m' end end; - current_module := Some m; trace "Initializing..."; let imports = Import.link m' in + current_module := Some m; current_instance := Some (Eval.init m' imports) | Invoke (name, es) -> @@ -99,6 +100,25 @@ let run_cmd cmd = Assert.error cmd.at "expected validation error" ) + | AssertUnlinkable (def, re) -> + trace "Asserting unlinkable..."; + let m = run_def def in + let m' = Desugar.desugar m in + if not !Flags.unchecked then Check.check_module m'; + (match + let imports = Import.link m' in + ignore (Eval.init m' imports) + with + | exception (Import.Unknown (_, msg) | Eval.Link (_, msg)) -> + if not (Str.string_match (Str.regexp re) msg 0) then begin + print_endline ("Result: \"" ^ msg ^ "\""); + print_endline ("Expect: \"" ^ re ^ "\""); + Assert.error cmd.at "wrong linking error" + end + | _ -> + Assert.error cmd.at "expected linking error" + ) + | AssertReturn (name, es, expect_e) -> trace ("Asserting return \"" ^ name ^ "\"..."); let m = get_instance cmd.at in @@ -185,6 +205,7 @@ let dry_cmd cmd = with Sys_error msg -> IO.error cmd.at msg) | Invoke _ | AssertInvalid _ + | AssertUnlinkable _ | AssertReturn _ | AssertReturnNaN _ | AssertTrap _ -> () diff --git a/ml-proto/host/script.mli b/ml-proto/host/script.mli index a745aa162b..ca03e3a78a 100644 --- a/ml-proto/host/script.mli +++ b/ml-proto/host/script.mli @@ -8,6 +8,7 @@ and command' = | Define of definition | Invoke of string * Kernel.literal list | AssertInvalid of definition * string + | AssertUnlinkable of definition * string | AssertReturn of string * Kernel.literal list * Kernel.literal option | AssertReturnNaN of string * Kernel.literal list | AssertTrap of string * Kernel.literal list * string diff --git a/ml-proto/spec/ast.ml b/ml-proto/spec/ast.ml index a66bd65230..b82509f758 100644 --- a/ml-proto/spec/ast.ml +++ b/ml-proto/spec/ast.ml @@ -23,7 +23,6 @@ and expr' = | If of expr * expr list * expr list | Select of expr * expr * expr | Call of var * expr list - | Call_import of var * expr list | Call_indirect of var * expr * expr list (* Variables *) @@ -219,6 +218,7 @@ and func' = type 'data segment = 'data segment' Source.phrase and 'data segment' = { + index : var; offset : expr; init : 'data; } @@ -228,8 +228,8 @@ and module' = { types : Types.func_type list; globals : global list; - table : Kernel.table option; - memory : Kernel.memory option; + tables : Kernel.table list; + memories : Kernel.memory list; funcs : func list; start : var option; elems : var list segment list; diff --git a/ml-proto/spec/check.ml b/ml-proto/spec/check.ml index a339dd58cf..47d87e7818 100644 --- a/ml-proto/spec/check.ml +++ b/ml-proto/spec/check.ml @@ -21,33 +21,30 @@ type context = module_ : module_; types : func_type list; funcs : func_type list; - imports : func_type list; locals : value_type list; globals : value_type list; return : expr_type; labels : expr_type_future list; - table : Table.size option; - memory : Memory.size option; + tables : table_type list; + memories : memory_type list; } +let empty_context m = + { module_ = m; types = []; funcs = []; tables = []; memories = []; + globals = []; locals = []; return = None; labels = [] } + let lookup category list x = try List.nth list x.it with Failure _ -> error x.at ("unknown " ^ category ^ " " ^ string_of_int x.it) -let type_ types x = lookup "function type" types x +let type_ c x = lookup "type" c.types x let func c x = lookup "function" c.funcs x let import c x = lookup "import" c.imports x let local c x = lookup "local" c.locals x let global c x = lookup "global" c.globals x let label c x = lookup "label" c.labels x - -let lookup_size category opt at = - match opt with - | Some n -> n - | None -> error at ("no " ^ category ^ " defined") - -let table c at = lookup_size "table" c.table at -let memory c at = lookup_size "memory" c.memory at +let table c x = lookup "table" c.tables x +let memory c x = lookup "memory" c.memories x (* Type Unification *) @@ -185,14 +182,9 @@ let rec check_expr c et e = check_exprs c ins es e.at; check_type out et e.at - | CallImport (x, es) -> - let {ins; out} = import c x in - check_exprs c ins es e.at; - check_type out et e.at - | CallIndirect (x, e1, es) -> - let {ins; out} = type_ c.types x in - ignore (table c e.at); + let {ins; out} = type_ c x in + ignore (table c (0 @@ e.at)); check_expr c (some Int32Type) e1; check_exprs c ins es e.at; check_type out et e.at @@ -261,7 +253,7 @@ let rec check_expr c et e = | Host (hostop, es) -> let {ins; out}, has_mem = type_hostop hostop in - if has_mem then ignore (memory c e.at); + if has_mem then ignore (memory c (0 @@ e.at)); check_exprs c ins es e.at; check_type out et e.at @@ -280,13 +272,13 @@ and check_literal c et l = check_type (Some (type_value l.it)) et l.at and check_load c et memop mem_size e1 at = - ignore (memory c at); + ignore (memory c (0 @@ at)); check_memop memop mem_size at; check_expr c (some Int32Type) e1; check_type (Some memop.ty) et at and check_store c et memop mem_size e1 e2 at = - ignore (memory c at); + ignore (memory c (0 @@ at)); check_memop memop mem_size at; check_expr c (some Int32Type) e1; check_expr c (some memop.ty) e2; @@ -325,74 +317,77 @@ let check_const c et e = let check_func c f = let {ftype; locals; body} = f.it in - let s = type_ c.types ftype in + let s = type_ c ftype in let c' = {c with locals = s.ins @ locals; return = s.out} in check_expr c' (known s.out) body (* Tables & Memories *) -let check_table_limits (lim : Table.size limits) = - let {min; max} = lim.it in +let check_table_type (t : table_type) at = + let TableType ({min; max}, _) = t in match max with | None -> () | Some max -> - require (I32.le_u min max) lim.at + require (I32.le_u min max) at "table size minimum must not be greater than maximum" let check_table (c : context) (tab : table) = - let {tlimits = lim; etype = t} = tab.it in - check_table_limits lim + let {ttype} = tab.it in + check_table_type ttype tab.at -let check_memory_limits (lim : Memory.size limits) = - let {min; max} = lim.it in - require (I32.lt_u min 65536l) lim.at +let check_memory_type (t : memory_type) at = + let MemoryType {min; max} = t in + require (I32.lt_u min 65536l) at "memory size must be less than 65536 pages (4GiB)"; match max with | None -> () | Some max -> - require (I32.lt_u max 65536l) lim.at + require (I32.lt_u max 65536l) at "memory size must be less than 65536 pages (4GiB)"; - require (I32.le_u min max) lim.at + require (I32.le_u min max) at "memory size minimum must not be greater than maximum" let check_memory (c : context) (mem : memory) = - let {mlimits = lim} = mem.it in - check_memory_limits lim + let {mtype} = mem.it in + check_memory_type mtype mem.at let check_table_segment c prev_end seg = - let {offset; init} = seg.it in + let {index; offset; init} = seg.it in check_const c Int32Type offset; let start = Values.int32_of_value (Eval.const c.module_ offset) in let len = Int32.of_int (List.length init) in let end_ = Int32.add start len in + let TableType (lim, _) = table c index in require (I32.le_u prev_end start) seg.at "table segment not disjoint and ordered"; - require (I32.le_u end_ (table c seg.at)) seg.at - "table segment does not fit memory"; + require (I32.le_u end_ lim.min) seg.at + "table segment does not fit into table"; ignore (List.map (func c) init); end_ let check_memory_segment c prev_end seg = - let {offset; init} = seg.it in + let {index; offset; init} = seg.it in check_const c Int32Type offset; let start = Int64.of_int32 (Values.int32_of_value (Eval.const c.module_ offset)) in let len = Int64.of_int (String.length init) in let end_ = Int64.add start len in - let limit = Int64.mul (Int64.of_int32 (memory c seg.at)) Memory.page_size in + let MemoryType lim = memory c index in + let limit = Int64.mul (Int64.of_int32 lim.min) Memory.page_size in require (I64.le_u prev_end start) seg.at "data segment not disjoint and ordered"; require (I64.le_u end_ limit) seg.at - "data segment does not fit memory"; + "data segment does not fit into memory"; end_ (* Modules *) -let check_global c g = - let {gtype; value} = g.it in - check_const c gtype value +let check_global c glob = + let {gtype; value} = glob.it in + check_const c gtype value; + {c with globals = c.globals @ [gtype]} let check_start c start = Lib.Option.app (fun x -> @@ -403,42 +398,50 @@ let check_start c start = "start function must not return anything"; ) start +let check_import im c = + let {module_name = _; item_name = _; ikind} = im.it in + match ikind.it with + | FuncImport x -> + {c with funcs = type_ c x :: c.funcs} + | TableImport t -> + check_table_type t ikind.at; {c with tables = t :: c.tables} + | MemoryImport t -> + check_memory_type t ikind.at; {c with memories = t :: c.memories} + | GlobalImport t -> + {c with globals = t :: c.globals} + module NameSet = Set.Make(String) let check_export c set ex = - let {name; kind} = ex.it in - (match kind with - | `Func x -> ignore (func c x) - | `Memory -> ignore (memory c ex.at) + let {name; ekind; item} = ex.it in + (match ekind.it with + | FuncExport -> ignore (func c item) + | TableExport -> ignore (table c item) + | MemoryExport -> ignore (memory c item) + | GlobalExport -> ignore (global c item) ); require (not (NameSet.mem name set)) ex.at "duplicate export name"; NameSet.add name set let check_module m = let - {types; table; memory; globals; funcs; start; elems; data; - imports; exports} = m.it in - let c = - { - module_ = m; - types; - funcs = List.map (fun f -> type_ types f.it.ftype) funcs; - imports = List.map (fun i -> type_ types i.it.itype) imports; - globals = []; - locals = []; - return = None; - labels = []; - table = Lib.Option.map (fun tab -> tab.it.tlimits.it.min) table; - memory = Lib.Option.map (fun mem -> mem.it.mlimits.it.min) memory; + {types; imports; tables; memories; globals; funcs; start; elems; data; + exports} = m.it in + let c = List.fold_right check_import imports {(empty_context m) with types} in + let c' = + { (List.fold_left check_global c globals) with + funcs = c.funcs @ List.map (fun f -> type_ c f.it.ftype) funcs; + tables = c.tables @ List.map (fun tab -> tab.it.ttype) tables; + memories = c.memories @ List.map (fun mem -> mem.it.mtype) memories; } in - List.iter (check_global c) globals; - let c' = {c with globals = List.map (fun g -> g.it.gtype) globals} in + require (List.length c'.tables <= 1) m.at "multiple tables"; + require (List.length c'.memories <= 1) m.at "multiple memories"; List.iter (check_func c') funcs; - Lib.Option.app (check_table c') table; - Lib.Option.app (check_memory c') memory; - ignore (List.fold_left (check_export c') NameSet.empty exports); + List.iter (check_table c') tables; + List.iter (check_memory c') memories; ignore (List.fold_left (check_table_segment c') 0l elems); ignore (List.fold_left (check_memory_segment c') 0L data); + ignore (List.fold_left (check_export c') NameSet.empty exports); check_start c' start diff --git a/ml-proto/spec/decode.ml b/ml-proto/spec/decode.ml index c7938f0131..7ab971efa9 100644 --- a/ml-proto/spec/decode.ml +++ b/ml-proto/spec/decode.ml @@ -114,7 +114,7 @@ let vec1 f s = let b = bool s in opt f b s open Types let value_type s = - match get s with + match u8 s with | 0x01 -> Int32Type | 0x02 -> Int64Type | 0x03 -> Float32Type @@ -122,7 +122,7 @@ let value_type s = | _ -> error s (pos s - 1) "invalid value type" let elem_type s = - match get s with + match u8 s with | 0x20 -> AnyFuncType | _ -> error s (pos s - 1) "invalid element type" @@ -134,6 +134,21 @@ let func_type s = let out = expr_type s in {ins; out} +let limits vu s = + let has_max = bool s in + let min = vu s in + let max = opt vu has_max s in + {min; max} + +let table_type s = + let t = elem_type s in + let lim = limits vu32 s in + TableType (lim, t) + +let memory_type s = + let lim = limits vu32 s in + MemoryType lim + (* Decode expressions *) @@ -245,11 +260,6 @@ let rec expr stack s = 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' - | 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 @@ -490,11 +500,19 @@ let type_section s = (* Import section *) +let import_kind s = + match u8 s with + | 0x00 -> FuncImport (at var s) + | 0x01 -> TableImport (table_type s) + | 0x02 -> MemoryImport (memory_type s) + | 0x03 -> GlobalImport (value_type s) + | _ -> error s (pos s - 1) "invalid import kind" + let import s = - let itype = at var s in let module_name = string s in - let func_name = string s in - {itype; module_name; func_name} + let item_name = string s in + let ikind = at import_kind s in + {module_name; item_name; ikind} let import_section s = section `ImportSection (vec (at import)) [] s @@ -508,29 +526,22 @@ let func_section s = (* Table section *) -let limits vu s = - let has_max = bool s in - let min = vu s in - let max = opt vu has_max s in - {min; max} - let table s = - let t = elem_type s in - let lim = at (limits vu32) s in - {etype = t; tlimits = lim} + let ttype = table_type s in + {ttype} let table_section s = - section `TableSection (opt (at table) true) None s + section `TableSection (vec (at table)) [] s (* Memory section *) let memory s = - let lim = at (limits vu32) s in - {mlimits = lim} + let mtype = memory_type s in + {mtype} let memory_section s = - section `MemorySection (opt (at memory) true) None s + section `MemorySection (vec (at memory)) [] s (* Global section *) @@ -549,10 +560,19 @@ let global_section s = (* Export section *) +let export_kind s = + match u8 s with + | 0x00 -> FuncExport + | 0x01 -> TableExport + | 0x02 -> MemoryExport + | 0x03 -> GlobalExport + | _ -> error s (pos s - 1) "invalid export kind" + let export s = - let x = at var s in let name = string s in - {name; kind = `Func x} (*TODO: pending resolution*) + let ekind = at export_kind s in + let item = at var s in + {name; ekind; item} let export_section s = section `ExportSection (vec (at export)) [] s @@ -584,9 +604,10 @@ let code_section s = (* Element section *) let segment dat s = + let index = at var s in let offset = const s in let init = dat s in - {offset; init} + {index; offset; init} let table_segment s = segment (vec (at var)) s @@ -626,9 +647,9 @@ let module_ s = iterate unknown_section s; let func_types = func_section s in iterate unknown_section s; - let table = table_section s in + let tables = table_section s in iterate unknown_section s; - let memory = memory_section s in + let memories = memory_section s in iterate unknown_section s; let globals = global_section s in iterate unknown_section s; @@ -650,7 +671,7 @@ let module_ s = let funcs = List.map2 Source.(fun t f -> {f.it with ftype = t} @@ f.at) func_types func_bodies - in {types; table; memory; globals; funcs; imports; exports; elems; data; start} + in {types; tables; memories; globals; funcs; imports; exports; elems; data; start} let decode name bs = at module_ (stream name bs) diff --git a/ml-proto/spec/desugar.ml b/ml-proto/spec/desugar.ml index 6f5e514be3..d7b88195f9 100644 --- a/ml-proto/spec/desugar.ml +++ b/ml-proto/spec/desugar.ml @@ -27,7 +27,6 @@ and relabel' f n = function | Select (e1, e2, e3) -> Select (relabel f n e1, relabel f n e2, relabel f n e3) | Call (x, es) -> Call (x, List.map (relabel f n) es) - | CallImport (x, es) -> CallImport (x, List.map (relabel f n) es) | CallIndirect (x, e, es) -> CallIndirect (x, relabel f n e, List.map (relabel f n) es) | GetLocal x -> GetLocal x @@ -79,7 +78,6 @@ and expr' at = function | Ast.Select (e1, e2, e3) -> Select (expr e1, expr e2, expr e3) | Ast.Call (x, es) -> Call (x, List.map expr es) - | Ast.Call_import (x, es) -> CallImport (x, List.map expr es) | Ast.Call_indirect (x, e, es) -> CallIndirect (x, expr e, List.map expr es) | Ast.Get_local x -> GetLocal x @@ -309,15 +307,15 @@ and func' = function let rec segment seg = segment' seg.it @@ seg.at and segment' = function - | {Ast.offset = e; init} -> {offset = expr e; init} + | {index; Ast.offset = e; init} -> {index; offset = expr e; init} let rec module_ m = module' m.it @@ m.at and module' = function - | {Ast.funcs = fs; start; globals = gs; memory; types; imports; exports; table; elems; data} -> + | {Ast.funcs = fs; start; globals = gs; memories; types; imports; exports; tables; elems; data} -> let globals = List.map global gs in let elems = List.map segment elems in let funcs = List.map func fs in let data = List.map segment data in - {funcs; start; globals; memory; types; imports; exports; table; elems; data} + {funcs; start; globals; memories; types; imports; exports; tables; elems; data} let desugar = module_ diff --git a/ml-proto/spec/eval.ml b/ml-proto/spec/eval.ml index 280e15ecd8..e730846fae 100644 --- a/ml-proto/spec/eval.ml +++ b/ml-proto/spec/eval.ml @@ -1,33 +1,17 @@ open Values open Types open Kernel +open Instance open Source -(* Module Instances *) - -type value = Values.value -type import = value list -> value option - -module ExportMap = Map.Make(String) -type export_map = func ExportMap.t - -type instance = -{ - module_ : module_; - imports : import list; - exports : export_map; - table : Table.t option; - memory : Memory.t option; - globals : value ref list; -} - - (* Errors *) +module Link = Error.Make () module Trap = Error.Make () module Crash = Error.Make () +exception Link = Link.Error exception Trap = Trap.Error exception Crash = Crash.Error (* A crash is an execution failure that cannot legally happen in checked @@ -41,7 +25,7 @@ let memory_error at = function let type_error at v t = Crash.error at ("type error, expected " ^ Types.string_of_value_type t ^ - ", got " ^ Types.string_of_value_type (type_of v)) + ", got " ^ Types.string_of_value_type (type_of v)) let arithmetic_error at at_op1 at_op2 = function | Arithmetic.TypeError (i, v, t) -> @@ -66,32 +50,37 @@ type config = labels : label list } +let empty_config inst = {instance = inst; locals = []; labels = []} + let lookup category list x = try List.nth list x.it with Failure _ -> Crash.error x.at ("undefined " ^ category ^ " " ^ string_of_int x.it) -let type_ c x = lookup "type" c.instance.module_.it.types x -let func c x = lookup "function" c.instance.module_.it.funcs x -let import c x = lookup "import" c.instance.imports x +let type_ inst x = lookup "type" inst.module_.it.types x +let func c x = lookup "function" c.instance.funcs x +let table c x = lookup "table" c.instance.tables x +let memory c x = lookup "memory" c.instance.memories x let global c x = lookup "global" c.instance.globals x let local c x = lookup "local" c.locals x let label c x = lookup "label" c.labels x -let export m name = - try ExportMap.find name.it m.exports with Not_found -> +let export inst name = + try ExportMap.find name.it inst.exports with Not_found -> Crash.error name.at ("undefined export \"" ^ name.it ^ "\"") -let elem c i t at = - match c.instance.table with - | None -> Crash.error at "no table" - | Some tab -> - match Table.load tab i t with +let elem c x i t at = + match Table.load (table c x) i t with | Some j -> j | None -> - Trap.error at ("undefined element " ^ Int32.to_string i) + Trap.error at ("uninitialized element " ^ Int32.to_string i) | exception Table.Bounds -> Trap.error at ("undefined element " ^ Int32.to_string i) +let func_type_of t at = + match t with + | AstFunc (inst, f) -> lookup "type" (!inst).module_.it.types f.it.ftype + | HostFunc _ -> Link.error at "invalid use of host function" + module MakeLabel () = struct exception Label of value option @@ -119,11 +108,6 @@ let int64 v at = let address32 v at = Int64.logand (Int64.of_int32 (int32 v at)) 0xffffffffL -let memory c at = - match c.instance.memory with - | Some m -> m - | _ -> Trap.error at "memory operation with no memory" - (* Evaluation *) @@ -188,19 +172,15 @@ let rec eval_expr (c : config) (e : expr) : value option = | Call (x, es) -> let vs = List.map (fun vo -> some (eval_expr c vo) vo.at) es in - eval_func c.instance (func c x) vs - - | CallImport (x, es) -> - let vs = List.map (fun ev -> some (eval_expr c ev) ev.at) es in - (try (import c x) vs with Crash (_, msg) -> Crash.error e.at msg) + eval_func (func c x) vs e.at | CallIndirect (x, e1, es) -> let i = int32 (eval_expr c e1) e1.at in let vs = List.map (fun vo -> some (eval_expr c vo) vo.at) es in - let f = func c (elem c i AnyFuncType e1.at @@ e1.at) in - if type_ c x <> type_ c f.it.ftype then + let f = func c (elem c (0 @@ e.at) i AnyFuncType e1.at @@ e1.at) in + if type_ c.instance x <> func_type_of f e1.at then Trap.error e1.at "indirect call signature mismatch"; - eval_func c.instance f vs + eval_func f vs e.at | GetLocal x -> Some !(local c x) @@ -224,13 +204,13 @@ let rec eval_expr (c : config) (e : expr) : value option = None | Load ({ty; offset; align = _}, e1) -> - let mem = memory c e.at in + let mem = memory c (0 @@ e.at) in let v1 = address32 (eval_expr c e1) e1.at in (try Some (Memory.load mem v1 offset ty) with exn -> memory_error e.at exn) | Store ({ty = _; offset; align = _}, e1, e2) -> - let mem = memory c e.at in + let mem = memory c (0 @@ e.at) in let v1 = address32 (eval_expr c e1) e1.at in let v2 = some (eval_expr c e2) e2.at in (try Memory.store mem v1 offset v2 @@ -238,13 +218,13 @@ let rec eval_expr (c : config) (e : expr) : value option = None | LoadExtend ({memop = {ty; offset; align = _}; sz; ext}, e1) -> - let mem = memory c e.at in + let mem = memory c (0 @@ e.at) in let v1 = address32 (eval_expr c e1) e1.at in (try Some (Memory.load_extend mem v1 offset sz ext ty) with exn -> memory_error e.at exn) | StoreWrap ({memop = {ty; offset; align = _}; sz}, e1, e2) -> - let mem = memory c e.at in + let mem = memory c (0 @@ e.at) in let v1 = address32 (eval_expr c e1) e1.at in let v2 = some (eval_expr c e2) e2.at in (try Memory.store_wrap mem v1 offset sz v2 @@ -289,15 +269,18 @@ and eval_expr_opt c = function | Some e -> eval_expr c e | None -> None -and eval_func instance f vs = - let args = List.map ref vs in - let vars = List.map (fun t -> ref (default_value t)) f.it.locals in - let locals = args @ vars in - let c = {instance; locals; labels = []} in - 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"; - eval_expr c f.it.body +and eval_func func vs at = + match func with + | AstFunc (inst, f) -> + if List.length vs <> List.length (func_type_of func at).ins then + Crash.error at "function called with wrong number of arguments"; + let args = List.map ref vs in + let vars = List.map (fun t -> ref (default_value t)) f.it.locals in + let locals = args @ vars in + eval_expr {(empty_config !inst) with locals} f.it.body + + | HostFunc f -> + try f vs with Crash (_, msg) -> Crash.error at msg (* Host operators *) @@ -305,12 +288,12 @@ and eval_func instance f vs = and eval_hostop c hostop vs at = match hostop, vs with | CurrentMemory, [] -> - let mem = memory c at in + let mem = memory c (0 @@ at) in let size = Memory.size mem in Some (Int32 size) | GrowMemory, [v] -> - let mem = memory c at in + let mem = memory c (0 @@ at) in let delta = int32 v at in let old_size = Memory.size mem in let result = @@ -324,62 +307,120 @@ and eval_hostop c hostop vs at = (* Modules *) -let const m e = - (* TODO: allow referring to earlier glboals *) - let inst = - { module_ = m; imports = []; exports = ExportMap.empty; - table = None; memory = None; globals = [] } - in some (eval_expr {instance = inst; locals = []; labels = []} e) e.at - -let offset m seg = - int32 (Some (const m seg.it.offset)) seg.it.offset.at - -let init_table m elems table = - let {tlimits = lim; _} = table.it in - let tab = Table.create lim.it.min lim.it.max in - let entries xs = List.map (fun x -> Some x.it) xs in - List.iter - (fun seg -> Table.blit tab (offset m seg) (entries seg.it.init)) - elems; - tab - -let init_memory m data memory = - let {mlimits = lim} = memory.it in - let mem = Memory.create lim.it.min lim.it.max in - List.iter - (fun seg -> Memory.blit mem (Int64.of_int32 (offset m seg)) seg.it.init) - data; - mem - -let init_global inst ref global = - let {value = e; _} = global.it in - let c = {instance = inst; locals = []; labels = []} in - ref := some (eval_expr c e) e.at +let create_func m f = + AstFunc (ref (instance m), f) + +let create_table tab = + let {ttype = TableType (lim, t)} = tab.it in + Table.create lim (* TODO: elem_type *) + +let create_memory mem = + let {mtype = MemoryType lim} = mem.it in + Memory.create lim + +let create_global glob = + let {gtype = t; _} = glob.it in + ref (default_value t) + +let init_func c f = + match f with + | AstFunc (inst, _) -> inst := c.instance + | _ -> assert false + +let non_host_func c x = + ignore (func_type_of (func c x) x.at); + Some x.it -let add_export funcs ex = - let {name; kind} = ex.it in - match kind with - | `Func x -> ExportMap.add name (List.nth funcs x.it) - | `Memory -> fun x -> x +let init_table c seg = + let {index; offset = e; init} = seg.it in + let tab = table c index in + let offset = int32 (eval_expr c e) e.at in + Table.blit tab offset (List.map (non_host_func c) init) -let init m imports = - assert (List.length imports = List.length m.it.Kernel.imports); - let {table; memory; globals; funcs; exports; elems; data; start; _} = m.it in +let init_memory c seg = + let {index; offset = e; init} = seg.it in + let mem = memory c index in + let offset = Int64.of_int32 (int32 (eval_expr c e) e.at) in + Memory.blit mem offset init + +let init_global c ref glob = + let {value = e; _} = glob.it in + ref := some (eval_expr c e) e.at + +let check_limits actual expected at = + if I32.lt_u actual.min expected.min then + Link.error at "actual size smaller than declared"; + if + match actual.max, expected.max with + | _, None -> false + | None, Some _ -> true + | Some i, Some j -> I32.gt_u i j + then Link.error at "maximum size larger than declared" + +let add_import (ext : extern) (imp : import) (inst : instance) : instance = + match ext, imp.it.ikind.it with + | ExternalFunc f, FuncImport x -> + (match f with + | AstFunc _ when func_type_of f x.at <> type_ inst x -> + Link.error imp.it.ikind.at "type mismatch"; + | _ -> () + ); + {inst with funcs = f :: inst.funcs} + | ExternalTable tab, TableImport (TableType (lim, _)) -> + (* TODO: no checking of element type? *) + check_limits (Table.limits tab) lim imp.it.ikind.at; + {inst with tables = tab :: inst.tables} + | ExternalMemory mem, MemoryImport (MemoryType lim) -> + check_limits (Memory.limits mem) lim imp.it.ikind.at; + {inst with memories = mem :: inst.memories} + | ExternalGlobal glob, GlobalImport _ -> + (* TODO: no checking of value type? *) + {inst with globals = ref glob :: inst.globals} + | _ -> + Link.error imp.it.ikind.at "type mismatch" + +let add_export c ex map = + let {name; ekind; item} = ex.it in + let ext = + match ekind.it with + | FuncExport -> ExternalFunc (func c item) + | TableExport -> ExternalTable (table c item) + | MemoryExport -> ExternalMemory (memory c item) + | GlobalExport -> ExternalGlobal !(global c item) + in ExportMap.add name ext map + +let init m externals = + let + { imports; tables; memories; globals; funcs; + exports; elems; data; start } = m.it + in + assert (List.length externals = List.length imports); (* TODO: better exception? *) + let fs = List.map (create_func m) funcs in + let gs = List.map create_global globals in let inst = - { module_ = m; - imports; - exports = List.fold_right (add_export funcs) exports ExportMap.empty; - table = Lib.Option.map (init_table m elems) table; - memory = Lib.Option.map (init_memory m data) memory; - globals = List.map (fun g -> ref (default_value g.it.gtype)) globals; - } + List.fold_right2 add_import externals imports + { (instance m) with + funcs = fs; + tables = List.map create_table tables; + memories = List.map create_memory memories; + globals = gs; + } in - List.iter2 (init_global inst) inst.globals globals; - Lib.Option.app - (fun x -> ignore (eval_func inst (lookup "function" funcs x) [])) start; - inst + let c = empty_config inst in + List.iter (init_func c) fs; + List.iter (init_table c) elems; + List.iter (init_memory c) data; + List.iter2 (init_global c) gs globals; + Lib.Option.app (fun x -> ignore (eval_func (func c x) [] x.at)) start; + {inst with exports = List.fold_right (add_export c) exports inst.exports} let invoke inst name vs = - try - eval_func inst (export inst (name @@ no_region)) vs - with Stack_overflow -> Trap.error Source.no_region "call stack exhausted" + match export inst (name @@ no_region) with + | ExternalFunc f -> + (try eval_func f vs no_region + with Stack_overflow -> Trap.error no_region "call stack exhausted") + | _ -> + Crash.error no_region ("export \"" ^ name ^ "\" is not a function") + +let const m e = + some (eval_expr (empty_config (instance m)) e) e.at diff --git a/ml-proto/spec/eval.mli b/ml-proto/spec/eval.mli index 703a242170..8e37e65633 100644 --- a/ml-proto/spec/eval.mli +++ b/ml-proto/spec/eval.mli @@ -1,11 +1,11 @@ -type instance -type value = Values.value -type import = value list -> value option +open Values +open Instance +exception Link of Source.region * string exception Trap of Source.region * string exception Crash of Source.region * string -val init : Kernel.module_ -> import list -> instance +val init : Kernel.module_ -> extern list -> instance val invoke : instance -> string -> value list -> value option (* raises Trap, Crash *) val const : Kernel.module_ -> Kernel.expr -> value diff --git a/ml-proto/spec/instance.ml b/ml-proto/spec/instance.ml new file mode 100644 index 0000000000..a7e1f35c81 --- /dev/null +++ b/ml-proto/spec/instance.ml @@ -0,0 +1,29 @@ +open Values + +module ExportMap = Map.Make(String) + +type global = value ref + +type func = + | AstFunc of instance ref * Kernel.func + | HostFunc of (value list -> value option) + +and extern = + | ExternalFunc of func + | ExternalTable of Table.t + | ExternalMemory of Memory.t + | ExternalGlobal of value + +and instance = +{ + module_ : Kernel.module_; + funcs : func list; + tables : Table.t list; + memories : Memory.t list; + globals : global list; + exports : extern ExportMap.t; +} + +let instance m = + { module_ = m; funcs = []; tables = []; memories = []; globals = []; + exports = ExportMap.empty } diff --git a/ml-proto/spec/kernel.ml b/ml-proto/spec/kernel.ml index d89b12debf..5267d5dbfe 100644 --- a/ml-proto/spec/kernel.ml +++ b/ml-proto/spec/kernel.ml @@ -83,7 +83,6 @@ and expr' = | If of expr * expr * expr (* conditional *) | Select of expr * expr * expr (* branchless conditional *) | Call of var * expr list (* call function *) - | CallImport of var * expr list (* call imported function *) | CallIndirect of var * expr * expr list (* call function through table *) | GetLocal of var (* read local variable *) | SetLocal of var * expr (* write local variable *) @@ -108,7 +107,7 @@ and expr' = type global = global' Source.phrase and global' = { - gtype : Types.value_type; + gtype : value_type; value : expr; } @@ -123,29 +122,22 @@ and func' = (* Tables & Memories *) -type 'size limits = 'size limits' Source.phrase -and 'size limits' = -{ - min : 'size; - max : 'size option; -} - type table = table' Source.phrase and table' = { - tlimits : Table.size limits; - etype : elem_type; + ttype : table_type; } type memory = memory' Source.phrase and memory' = { - mlimits : Memory.size limits; + mtype : memory_type; } type 'data segment = 'data segment' Source.phrase and 'data segment' = { + index : var; offset : expr; init : 'data; } @@ -156,19 +148,30 @@ type memory_segment = string segment (* Modules *) +type export_kind = export_kind' Source.phrase +and export_kind' = FuncExport | TableExport | MemoryExport | GlobalExport + type export = export' Source.phrase and export' = { name : string; - kind : [`Func of var | `Memory] + ekind : export_kind; + item : var; } +type import_kind = import_kind' Source.phrase +and import_kind' = + | FuncImport of var + | TableImport of table_type + | MemoryImport of memory_type + | GlobalImport of value_type + type import = import' Source.phrase and import' = { - itype : var; module_name : string; - func_name : string; + item_name : string; + ikind : import_kind; } type module_ = module_' Source.phrase @@ -176,8 +179,8 @@ and module_' = { types : Types.func_type list; globals : global list; - table : table option; - memory : memory option; + tables : table list; + memories : memory list; funcs : func list; start : var option; elems : table_segment list; diff --git a/ml-proto/spec/memory.ml b/ml-proto/spec/memory.ml index 536638f241..45ea4e1b00 100644 --- a/ml-proto/spec/memory.ml +++ b/ml-proto/spec/memory.ml @@ -11,6 +11,7 @@ type extension = SX | ZX type value = Values.value type value_type = Types.value_type +type 'a limits = 'a Types.limits type memory' = (int, int8_unsigned_elt, c_layout) Array1.t type memory = {mutable content : memory'; max : size option} @@ -65,14 +66,17 @@ let create' n = mem with Out_of_memory -> raise OutOfMemory -let create n max = - assert (within_limits n max); - {content = create' n; max} +let create {min; max} = + assert (within_limits min max); + {content = create' min; max} let size mem = Int64.to_int32 (Int64.div (int64_of_host_size (Array1.dim mem.content)) page_size) +let limits mem = + {min = size mem; max = mem.max} + let grow mem delta = let host_old_size = Array1.dim mem.content in let old_size = size mem in diff --git a/ml-proto/spec/memory.mli b/ml-proto/spec/memory.mli index b0695ed936..7c446da6c6 100644 --- a/ml-proto/spec/memory.mli +++ b/ml-proto/spec/memory.mli @@ -10,6 +10,7 @@ type extension = SX | ZX type value = Values.value type value_type = Types.value_type +type 'a limits = 'a Types.limits exception Type exception Bounds @@ -18,11 +19,11 @@ exception SizeLimit exception OutOfMemory val page_size : offset - val mem_size : mem_size -> int -val create : size -> size option -> memory (* raise SizeOverflow, OutOfMemory *) +val create : size limits -> memory (* raise SizeOverflow, OutOfMemory *) val size : memory -> size +val limits : memory -> size limits val grow : memory -> size -> unit (* raise SizeOverflow, OutOfMemory *) val load : memory -> address -> offset -> value_type -> value diff --git a/ml-proto/spec/table.ml b/ml-proto/spec/table.ml index a2b96375a0..3c9afc8743 100644 --- a/ml-proto/spec/table.ml +++ b/ml-proto/spec/table.ml @@ -6,6 +6,7 @@ type index = int32 type elem = int option type elem_type = Types.elem_type +type 'a limits = 'a Types.limits type table' = elem array type table = {mutable content : table'; max : size option} @@ -41,13 +42,16 @@ let within_limits size = function let create' size = Array.make (host_size_of_int32 size) None -let create size max = - assert (within_limits size max); - {content = create' size; max} +let create {min; max} = + assert (within_limits min max); + {content = create' min; max} let size tab = int32_of_host_size (Array.length tab.content) +let limits tab = + {min = size tab; max = tab.max} + let grow tab delta = let old_size = size tab in let new_size = Int32.add old_size delta in diff --git a/ml-proto/spec/table.mli b/ml-proto/spec/table.mli index 579c917545..d7098f074a 100644 --- a/ml-proto/spec/table.mli +++ b/ml-proto/spec/table.mli @@ -6,13 +6,15 @@ type index = int32 type elem = int option type elem_type = Types.elem_type +type 'a limits = 'a Types.limits exception Bounds exception SizeOverflow exception SizeLimit -val create : size -> size option -> table +val create : size limits -> table val size : table -> size +val limits : table -> size limits val grow : table -> size -> unit val load : table -> index -> elem_type -> elem diff --git a/ml-proto/spec/types.ml b/ml-proto/spec/types.ml index 9fb869fc4a..d1d9ae244a 100644 --- a/ml-proto/spec/types.ml +++ b/ml-proto/spec/types.ml @@ -5,6 +5,15 @@ type elem_type = AnyFuncType type expr_type = value_type option type func_type = {ins : value_type list; out : expr_type} +type 'a limits = {min : 'a; max : 'a option} +type table_type = TableType of Int32.t limits * elem_type +type memory_type = MemoryType of Int32.t limits +type external_type = + | ExternalFuncType of func_type + | ExternalTableType of table_type + | ExternalMemoryType of memory_type + | ExternalGlobalType of value_type + (* Attributes *) @@ -28,6 +37,16 @@ let string_of_value_type_list = function let string_of_elem_type = function | AnyFuncType -> "anyfunc" +let string_of_limits {min; max} = + I32.to_string min ^ + (match max with None -> "" | Some n -> I32.to_string n) + +let string_of_memory_type = function + | MemoryType lim -> string_of_limits lim + +let string_of_table_type = function + | TableType (lim, t) -> string_of_limits lim ^ " " ^ string_of_elem_type t + let string_of_expr_type = function | None -> "()" | Some t -> string_of_value_type t diff --git a/ml-proto/spec/values.ml b/ml-proto/spec/values.ml index 28f6870633..aa6440670b 100644 --- a/ml-proto/spec/values.ml +++ b/ml-proto/spec/values.ml @@ -7,7 +7,6 @@ type ('i32, 'i64, 'f32, 'f64) op = Int32 of 'i32 | Int64 of 'i64 | Float32 of 'f32 | Float64 of 'f64 type value = (I32.t, I64.t, F32.t, F64.t) op -type func = value list -> value option (* Typing *) diff --git a/ml-proto/test/address.wast b/ml-proto/test/address.wast index 9007af064e..709c5798f7 100644 --- a/ml-proto/test/address.wast +++ b/ml-proto/test/address.wast @@ -1,35 +1,34 @@ (module + (import "spectest" "print" (func $print (param i32))) + (memory 1) (data (i32.const 0) "abcdefghijklmnopqrstuvwxyz") - (import $print "spectest" "print" (param i32)) - (func $good (param $i i32) - (call_import $print (i32.load8_u offset=0 (get_local $i))) ;; 97 'a' - (call_import $print (i32.load8_u offset=1 (get_local $i))) ;; 98 'b' - (call_import $print (i32.load8_u offset=2 (get_local $i))) ;; 99 'c' - (call_import $print (i32.load8_u offset=25 (get_local $i))) ;; 122 'z' + (func (export "good") (param $i i32) + (call $print (i32.load8_u offset=0 (get_local $i))) ;; 97 'a' + (call $print (i32.load8_u offset=1 (get_local $i))) ;; 98 'b' + (call $print (i32.load8_u offset=2 (get_local $i))) ;; 99 'c' + (call $print (i32.load8_u offset=25 (get_local $i))) ;; 122 'z' - (call_import $print (i32.load16_u offset=0 (get_local $i))) ;; 25185 'ab' - (call_import $print (i32.load16_u align=1 (get_local $i))) ;; 25185 'ab' - (call_import $print (i32.load16_u offset=1 align=1 (get_local $i))) ;; 25442 'bc' - (call_import $print (i32.load16_u offset=2 (get_local $i))) ;; 25699 'cd' - (call_import $print (i32.load16_u offset=25 align=1 (get_local $i))) ;; 122 'z\0' + (call $print (i32.load16_u offset=0 (get_local $i))) ;; 25185 'ab' + (call $print (i32.load16_u align=1 (get_local $i))) ;; 25185 'ab' + (call $print (i32.load16_u offset=1 align=1 (get_local $i))) ;; 25442 'bc' + (call $print (i32.load16_u offset=2 (get_local $i))) ;; 25699 'cd' + (call $print (i32.load16_u offset=25 align=1 (get_local $i))) ;; 122 'z\0' - (call_import $print (i32.load offset=0 (get_local $i))) ;; 1684234849 'abcd' - (call_import $print (i32.load offset=1 align=1 (get_local $i))) ;; 1701077858 'bcde' - (call_import $print (i32.load offset=2 align=2 (get_local $i))) ;; 1717920867 'cdef' - (call_import $print (i32.load offset=25 align=1 (get_local $i))) ;; 122 'z\0\0\0' + (call $print (i32.load offset=0 (get_local $i))) ;; 1684234849 'abcd' + (call $print (i32.load offset=1 align=1 (get_local $i))) ;; 1701077858 'bcde' + (call $print (i32.load offset=2 align=2 (get_local $i))) ;; 1717920867 'cdef' + (call $print (i32.load offset=25 align=1 (get_local $i))) ;; 122 'z\0\0\0' ) - (export "good" $good) - (func $bad2 (param $i i32) (drop (i32.load offset=4294967295 (get_local $i)))) - (export "bad2" $bad2) + (func (export "bad") (param $i i32) (drop (i32.load offset=4294967295 (get_local $i)))) ) (invoke "good" (i32.const 0)) (invoke "good" (i32.const 65507)) (assert_trap (invoke "good" (i32.const 65508)) "out of bounds memory access") -(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_trap (invoke "bad" (i32.const 0)) "out of bounds memory access") +(assert_trap (invoke "bad" (i32.const 1)) "out of bounds memory access") -(assert_invalid (module (memory 1) (func $bad1 (param $i i32) (drop (i32.load offset=4294967296 (get_local $i))))) "offset too large") +(assert_invalid (module (memory 1) (func $bad (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 ea68ad6e71..c134062bb9 100644 --- a/ml-proto/test/block.wast +++ b/ml-proto/test/block.wast @@ -4,29 +4,29 @@ ;; Auxiliary definition (func $dummy) - (func "empty" + (func (export "empty") (block) (block $l) ) - (func "singular" (result i32) + (func (export "singular") (result i32) (block (nop)) (block (i32.const 7)) ) - (func "multi" (result i32) + (func (export "multi") (result i32) (block (call $dummy) (call $dummy) (call $dummy) (call $dummy)) (block (call $dummy) (call $dummy) (call $dummy) (i32.const 8)) ) - (func "nested" (result i32) + (func (export "nested") (result i32) (block (block (call $dummy) (block) (nop)) (block (call $dummy) (i32.const 9)) ) ) - (func "deep" (result i32) + (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 @@ -38,36 +38,36 @@ )))))))))) ) - (func "as-unary-operand" (result i32) + (func (export "as-unary-operand") (result i32) (i32.ctz (block (call $dummy) (i32.const 13))) ) - (func "as-binary-operand" (result i32) + (func (export "as-binary-operand") (result i32) (i32.mul (block (call $dummy) (i32.const 3)) (block (call $dummy) (i32.const 4)) ) ) - (func "as-test-operand" (result i32) + (func (export "as-test-operand") (result i32) (i32.eqz (block (call $dummy) (i32.const 13))) ) - (func "as-compare-operand" (result i32) + (func (export "as-compare-operand") (result i32) (f32.gt (block (call $dummy) (f32.const 3)) (block (call $dummy) (f32.const 3)) ) ) - (func "break-bare" (result i32) + (func (export "break-bare") (result i32) (block (br 0) (unreachable)) (block (br_if 0 (i32.const 1)) (unreachable)) (block (br_table 0 (i32.const 0)) (unreachable)) (block (br_table 0 0 0 (i32.const 1)) (unreachable)) (i32.const 19) ) - (func "break-value" (result i32) + (func (export "break-value") (result i32) (block (br 0 (i32.const 18)) (i32.const 19)) ) - (func "break-repeated" (result i32) + (func (export "break-repeated") (result i32) (block (br 0 (i32.const 18)) (br 0 (i32.const 19)) @@ -79,7 +79,7 @@ (i32.const 21) ) ) - (func "break-inner" (result i32) + (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)))))) @@ -93,7 +93,7 @@ (get_local 0) ) - (func "effects" $fx (result i32) + (func (export "effects") (result i32) (local i32) (block (set_local 0 (i32.const 1)) diff --git a/ml-proto/test/br.wast b/ml-proto/test/br.wast index e2cf2a1b47..0fa70eb12e 100644 --- a/ml-proto/test/br.wast +++ b/ml-proto/test/br.wast @@ -4,112 +4,101 @@ ;; 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 (export "type-i32") (block (drop (i32.ctz (br 0))))) + (func (export "type-i64") (block (drop (i64.ctz (br 0))))) + (func (export "type-f32") (block (drop (f32.neg (br 0))))) + (func (export "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))))) - (func "type-f32-value" (result f32) (block (f32.neg (br 0 (f32.const 3))))) - (func "type-f64-value" (result f64) (block (f64.neg (br 0 (f64.const 4))))) + (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 "as-block-first" + (func (export "as-block-first") (block (br 0) (call $dummy)) ) - (func "as-block-mid" + (func (export "as-block-mid") (block (call $dummy) (br 0) (call $dummy)) ) - (func "as-block-last" + (func (export "as-block-last") (block (nop) (call $dummy) (br 0)) ) - (func "as-block-value" (result i32) + (func (export "as-block-value") (result i32) (block (nop) (call $dummy) (br 0 (i32.const 2))) ) - (func "as-loop-first" (result i32) + (func (export "as-loop-first") (result i32) (loop (br 1 (i32.const 3)) (i32.const 2)) ) - (func "as-loop-mid" (result i32) + (func (export "as-loop-mid") (result i32) (loop (call $dummy) (br 1 (i32.const 4)) (i32.const 2)) ) - (func "as-loop-last" (result i32) + (func (export "as-loop-last") (result i32) (loop (nop) (call $dummy) (br 1 (i32.const 5))) ) - (func "as-br-value" (result i32) + (func (export "as-br-value") (result i32) (block (br 0 (br 0 (i32.const 9)))) ) - (func "as-br_if-cond" + (func (export "as-br_if-cond") (block (br_if 0 (br 0))) ) - (func "as-br_if-value" (result i32) + (func (export "as-br_if-value") (result i32) (block (br_if 0 (br 0 (i32.const 8)) (i32.const 1)) (i32.const 7)) ) - (func "as-br_if-value-cond" (result i32) + (func (export "as-br_if-value-cond") (result i32) (block (br_if 0 (i32.const 6) (br 0 (i32.const 9))) (i32.const 7)) ) - (func "as-br_table-index" + (func (export "as-br_table-index") (block (br_table 0 0 0 (br 0))) ) - (func "as-br_table-value" (result i32) + (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)) ) - (func "as-br_table-value-index" (result i32) + (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)) ) - (func "as-return-value" (result i64) + (func (export "as-return-value") (result i64) (block (return (br 0 (i64.const 7)))) ) - (func "as-if-cond" (result i32) + (func (export "as-if-cond") (result i32) (block (if (br 0 (i32.const 2)) (i32.const 0) (i32.const 1))) ) - (func "as-if-then" (param i32 i32) (result i32) + (func (export "as-if-then") (param i32 i32) (result i32) (block (if (get_local 0) (br 1 (i32.const 3)) (get_local 1))) ) - (func "as-if-else" (param i32 i32) (result i32) + (func (export "as-if-else") (param i32 i32) (result i32) (block (if (get_local 0) (get_local 1) (br 1 (i32.const 4)))) ) - (func "as-select-first" (param i32 i32) (result i32) + (func (export "as-select-first") (param i32 i32) (result i32) (block (select (br 0 (i32.const 5)) (get_local 0) (get_local 1))) ) - (func "as-select-second" (param i32 i32) (result i32) + (func (export "as-select-second") (param i32 i32) (result i32) (block (select (get_local 0) (br 0 (i32.const 6)) (get_local 1))) ) - (func "as-select-cond" (result i32) + (func (export "as-select-cond") (result i32) (block (select (i32.const 0) (i32.const 1) (br 0 (i32.const 7)))) ) (func $f (param i32 i32 i32) (result i32) (i32.const -1)) - (func "as-call-first" (result i32) + (func (export "as-call-first") (result i32) (block (call $f (br 0 (i32.const 12)) (i32.const 2) (i32.const 3))) ) - (func "as-call-mid" (result i32) + (func (export "as-call-mid") (result i32) (block (call $f (i32.const 1) (br 0 (i32.const 13)) (i32.const 3))) ) - (func "as-call-last" (result i32) + (func (export "as-call-last") (result i32) (block (call $f (i32.const 1) (i32.const 2) (br 0 (i32.const 14)))) ) - (import "spectest" "print" (param i32 i32 i32)) - (func "as-call_import-first" - (block (call_import 0 (br 0) (i32.const 2) (i32.const 3))) - ) - (func "as-call_import-mid" - (block (call_import 0 (i32.const 1) (br 0) (i32.const 3))) - ) - (func "as-call_import-last" - (block (call_import 0 (i32.const 1) (i32.const 2) (br 0))) - ) - (type $sig (func (param i32 i32 i32) (result i32))) (table anyfunc (elem $f)) - (func "as-call_indirect-func" (result i32) + (func (export "as-call_indirect-func") (result i32) (block (call_indirect $sig (br 0 (i32.const 20)) @@ -117,7 +106,7 @@ ) ) ) - (func "as-call_indirect-first" (result i32) + (func (export "as-call_indirect-first") (result i32) (block (call_indirect $sig (i32.const 0) @@ -125,7 +114,7 @@ ) ) ) - (func "as-call_indirect-mid" (result i32) + (func (export "as-call_indirect-mid") (result i32) (block (call_indirect $sig (i32.const 0) @@ -133,7 +122,7 @@ ) ) ) - (func "as-call_indirect-last" (result i32) + (func (export "as-call_indirect-last") (result i32) (block (call_indirect $sig (i32.const 0) @@ -142,63 +131,63 @@ ) ) - (func "as-set_local-value" (result i32) (local f32) + (func (export "as-set_local-value") (result i32) (local f32) (block (set_local 0 (br 0 (i32.const 17))) (i32.const -1)) ) (memory 1) - (func "as-load-address" (result f32) + (func (export "as-load-address") (result f32) (block (f32.load (br 0 (f32.const 1.7)))) ) - (func "as-loadN-address" (result i64) + (func (export "as-loadN-address") (result i64) (block (i64.load8_s (br 0 (i64.const 30)))) ) - (func "as-store-address" (result i32) + (func (export "as-store-address") (result i32) (block (f64.store (br 0 (i32.const 30)) (f64.const 7)) (i32.const -1)) ) - (func "as-store-value" (result i32) + (func (export "as-store-value") (result i32) (block (i64.store (i32.const 2) (br 0 (i32.const 31))) (i32.const -1)) ) - (func "as-storeN-address" (result i32) + (func (export "as-storeN-address") (result i32) (block (i32.store8 (br 0 (i32.const 32)) (i32.const 7)) (i32.const -1)) ) - (func "as-storeN-value" (result i32) + (func (export "as-storeN-value") (result i32) (block (i64.store16 (i32.const 2) (br 0 (i32.const 33))) (i32.const -1)) ) - (func "as-unary-operand" (result f32) + (func (export "as-unary-operand") (result f32) (block (f32.neg (br 0 (f32.const 3.4)))) ) - (func "as-binary-left" (result i32) + (func (export "as-binary-left") (result i32) (block (i32.add (br 0 (i32.const 3)) (i32.const 10))) ) - (func "as-binary-right" (result i64) + (func (export "as-binary-right") (result i64) (block (i64.sub (i64.const 10) (br 0 (i64.const 45)))) ) - (func "as-test-operand" (result i32) + (func (export "as-test-operand") (result i32) (block (i32.eqz (br 0 (i32.const 44)))) ) - (func "as-compare-left" (result i32) + (func (export "as-compare-left") (result i32) (block (f64.le (br 0 (i32.const 43)) (f64.const 10))) ) - (func "as-compare-right" (result i32) + (func (export "as-compare-right") (result i32) (block (f32.ne (f32.const 10) (br 0 (i32.const 42)))) ) - (func "as-convert-operand" (result i32) + (func (export "as-convert-operand") (result i32) (block (i32.wrap/i64 (br 0 (i32.const 41)))) ) - (func "as-grow_memory-size" (result i32) + (func (export "as-grow_memory-size") (result i32) (block (grow_memory (br 0 (i32.const 40)))) ) - (func "nested-block-value" (result i32) + (func (export "nested-block-value") (result i32) (i32.add (i32.const 1) (block @@ -208,7 +197,7 @@ ) ) - (func "nested-br-value" (result i32) + (func (export "nested-br-value") (result i32) (i32.add (i32.const 1) (block @@ -224,7 +213,7 @@ ) ) - (func "nested-br_if-value" (result i32) + (func (export "nested-br_if-value") (result i32) (i32.add (i32.const 1) (block @@ -241,7 +230,7 @@ ) ) - (func "nested-br_if-value-cond" (result i32) + (func (export "nested-br_if-value-cond") (result i32) (i32.add (i32.const 1) (block @@ -252,7 +241,7 @@ ) ) - (func "nested-br_table-value" (result i32) + (func (export "nested-br_table-value") (result i32) (i32.add (i32.const 1) (block @@ -268,7 +257,7 @@ ) ) - (func "nested-br_table-value-index" (result i32) + (func (export "nested-br_table-value-index") (result i32) (i32.add (i32.const 1) (block @@ -327,10 +316,6 @@ (assert_return (invoke "as-call-mid") (i32.const 13)) (assert_return (invoke "as-call-last") (i32.const 14)) -(assert_return (invoke "as-call_import-first")) -(assert_return (invoke "as-call_import-mid")) -(assert_return (invoke "as-call_import-last")) - (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)) diff --git a/ml-proto/test/br_if.wast b/ml-proto/test/br_if.wast index d0a79b5d14..0676831bd9 100644 --- a/ml-proto/test/br_if.wast +++ b/ml-proto/test/br_if.wast @@ -3,40 +3,40 @@ (module (func $dummy) - (func "as-block-first" (param i32) (result i32) + (func (export "as-block-first") (param i32) (result i32) (block (br_if 0 (get_local 0)) (return (i32.const 2))) (i32.const 3) ) - (func "as-block-mid" (param i32) (result i32) + (func (export "as-block-mid") (param i32) (result i32) (block (call $dummy) (br_if 0 (get_local 0)) (return (i32.const 2))) (i32.const 3) ) - (func "as-block-last" (param i32) + (func (export "as-block-last") (param i32) (block (call $dummy) (call $dummy) (br_if 0 (get_local 0))) ) - (func "as-block-first-value" (param i32) (result i32) + (func (export "as-block-first-value") (param i32) (result i32) (block (br_if 0 (i32.const 10) (get_local 0)) (i32.const 11)) ) - (func "as-block-mid-value" (param i32) (result i32) + (func (export "as-block-mid-value") (param i32) (result i32) (block (call $dummy) (br_if 0 (i32.const 20) (get_local 0)) (i32.const 21)) ) - (func "as-loop-first" (param i32) (result i32) + (func (export "as-loop-first") (param i32) (result i32) (loop (br_if 1 (i32.const 3) (get_local 0)) (i32.const 2)) ) - (func "as-loop-mid" (param i32) (result i32) + (func (export "as-loop-mid") (param i32) (result i32) (loop (call $dummy) (br_if 1 (i32.const 4) (get_local 0)) (i32.const 2)) ) - (func "as-loop-last" (param i32) + (func (export "as-loop-last") (param i32) (loop (call $dummy) (br_if 1 (get_local 0))) ) - (func "as-if-then" (param i32 i32) + (func (export "as-if-then") (param i32 i32) (block (if (get_local 0) (br_if 1 (get_local 1)) (call $dummy))) ) - (func "as-if-else" (param i32 i32) + (func (export "as-if-else") (param i32 i32) (block (if (get_local 0) (call $dummy) (br_if 1 (get_local 1)))) ) - (func "nested-block-value" (param i32) (result i32) + (func (export "nested-block-value") (param i32) (result i32) (i32.add (i32.const 1) (block @@ -49,7 +49,7 @@ ) ) - (func "nested-br-value" (param i32) (result i32) + (func (export "nested-br-value") (param i32) (result i32) (i32.add (i32.const 1) (block @@ -62,7 +62,7 @@ ) ) - (func "nested-br_if-value" (param i32) (result i32) + (func (export "nested-br_if-value") (param i32) (result i32) (i32.add (i32.const 1) (block @@ -76,7 +76,7 @@ ) ) - (func "nested-br_if-value-cond" (param i32) (result i32) + (func (export "nested-br_if-value-cond") (param i32) (result i32) (i32.add (i32.const 1) (block @@ -90,7 +90,7 @@ ) ) - (func "nested-br_table-value" (param i32) (result i32) + (func (export "nested-br_table-value") (param i32) (result i32) (i32.add (i32.const 1) (block @@ -104,7 +104,7 @@ ) ) - (func "nested-br_table-value-index" (param i32) (result i32) + (func (export "nested-br_table-value-index") (param i32) (result i32) (i32.add (i32.const 1) (block diff --git a/ml-proto/test/br_table.wast b/ml-proto/test/br_table.wast index 8ee433fea4..2dcab6bb82 100644 --- a/ml-proto/test/br_table.wast +++ b/ml-proto/test/br_table.wast @@ -4,33 +4,33 @@ ;; Auxiliary definition (func $dummy) - (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 (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 "type-i32-value" (result i32) + (func (export "type-i32-value") (result i32) (block (i32.ctz (br_table 0 0 (i32.const 1) (i32.const 0)))) ) - (func "type-i64-value" (result i64) + (func (export "type-i64-value") (result i64) (block (i64.ctz (br_table 0 0 (i64.const 2) (i32.const 0)))) ) - (func "type-f32-value" (result f32) + (func (export "type-f32-value") (result f32) (block (f32.neg (br_table 0 0 (f32.const 3) (i32.const 0)))) ) - (func "type-f64-value" (result f64) + (func (export "type-f64-value") (result f64) (block (f64.neg (br_table 0 0 (f64.const 4) (i32.const 0)))) ) - (func "empty" (param i32) (result i32) + (func (export "empty") (param i32) (result i32) (block (br_table 0 (get_local 0)) (return (i32.const 21))) (i32.const 22) ) - (func "empty-value" (param i32) (result i32) + (func (export "empty-value") (param i32) (result i32) (block (br_table 0 (i32.const 33) (get_local 0)) (i32.const 31)) ) - (func "singleton" (param i32) (result i32) + (func (export "singleton") (param i32) (result i32) (block (block (br_table 1 0 (get_local 0)) @@ -41,7 +41,7 @@ (i32.const 22) ) - (func "singleton-value" (param i32) (result i32) + (func (export "singleton-value") (param i32) (result i32) (block (drop (block @@ -53,7 +53,7 @@ ) ) - (func "multiple" (param i32) (result i32) + (func (export "multiple") (param i32) (result i32) (block (block (block @@ -73,7 +73,7 @@ (i32.const 104) ) - (func "multiple-value" (param i32) (result i32) + (func (export "multiple-value") (param i32) (result i32) (local i32) (set_local 1 (block (set_local 1 (block @@ -94,7 +94,7 @@ (i32.add (get_local 1) (i32.const 14)) ) - (func "large" (param i32) (result i32) + (func (export "large") (param i32) (result i32) (block (block (br_table @@ -831,175 +831,164 @@ (return (i32.const 1)) ) - (func "as-block-first" + (func (export "as-block-first") (block (br_table 0 0 0 (i32.const 0)) (call $dummy)) ) - (func "as-block-mid" + (func (export "as-block-mid") (block (call $dummy) (br_table 0 0 0 (i32.const 0)) (call $dummy)) ) - (func "as-block-last" + (func (export "as-block-last") (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 0))) ) - (func "as-block-value" (result i32) + (func (export "as-block-value") (result i32) (block (nop) (call $dummy) (br_table 0 0 0 (i32.const 2) (i32.const 0))) ) - (func "as-loop-first" (result i32) + (func (export "as-loop-first") (result i32) (loop (br_table 1 1 (i32.const 3) (i32.const 0)) (i32.const 1)) ) - (func "as-loop-mid" (result i32) + (func (export "as-loop-mid") (result i32) (loop (call $dummy) (br_table 1 1 1 (i32.const 4) (i32.const -1)) (i32.const 2) ) ) - (func "as-loop-last" (result i32) + (func (export "as-loop-last") (result i32) (loop (nop) (call $dummy) (br_table 1 1 1 (i32.const 5) (i32.const 1))) ) - (func "as-br-value" (result i32) + (func (export "as-br-value") (result i32) (block (br 0 (br 0 (i32.const 9)))) ) - (func "as-br_if-cond" + (func (export "as-br_if-cond") (block (br_if 0 (br_table 0 0 0 (i32.const 1)))) ) - (func "as-br_if-value" (result i32) + (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)) ) - (func "as-br_if-value-cond" (result i32) + (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)) ) - (func "as-br_table-index" + (func (export "as-br_table-index") (block (br_table 0 0 0 (br_table 0 (i32.const 1)))) ) - (func "as-br_table-value" (result i32) + (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)) ) - (func "as-br_table-value-index" (result i32) + (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)) ) - (func "as-return-value" (result i64) + (func (export "as-return-value") (result i64) (block (return (br_table 0 (i64.const 7) (i32.const 0)))) ) - (func "as-if-cond" (result i32) + (func (export "as-if-cond") (result i32) (block (if (br_table 0 (i32.const 2) (i32.const 0)) (i32.const 0) (i32.const 1))) ) - (func "as-if-then" (param i32 i32) (result i32) + (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))) ) - (func "as-if-else" (param i32 i32) (result i32) + (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)))) ) - (func "as-select-first" (param i32 i32) (result i32) + (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))) ) - (func "as-select-second" (param i32 i32) (result i32) + (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))) ) - (func "as-select-cond" (result i32) + (func (export "as-select-cond") (result i32) (block (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 "as-call-first" (result i32) + (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))) ) - (func "as-call-mid" (result i32) + (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))) ) - (func "as-call-last" (result i32) + (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)))) ) - (import "spectest" "print" (param i32 i32 i32)) - (func "as-call_import-first" - (block (call_import 0 (br_table 0 (i32.const 1)) (i32.const 2) (i32.const 3))) - ) - (func "as-call_import-mid" - (block (call_import 0 (i32.const 1) (br_table 0 (i32.const 1)) (i32.const 3))) - ) - (func "as-call_import-last" - (block (call_import 0 (i32.const 1) (i32.const 2) (br_table 0 (i32.const 1)))) - ) - (type $sig (func (param i32 i32 i32) (result i32))) (table anyfunc (elem $f)) - (func "as-call_indirect-func" (result i32) + (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 "as-call_indirect-first" (result i32) + (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))) ) - (func "as-call_indirect-mid" (result i32) + (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))) ) - (func "as-call_indirect-last" (result i32) + (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)))) ) - (func "as-set_local-value" (result i32) (local f32) + (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)) ) (memory 1) - (func "as-load-address" (result f32) + (func (export "as-load-address") (result f32) (block (f32.load (br_table 0 (f32.const 1.7) (i32.const 1)))) ) - (func "as-loadN-address" (result i64) + (func (export "as-loadN-address") (result i64) (block (i64.load8_s (br_table 0 (i64.const 30) (i32.const 1)))) ) - (func "as-store-address" (result i32) + (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)) ) - (func "as-store-value" (result i32) + (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)) ) - (func "as-storeN-address" (result i32) + (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)) ) - (func "as-storeN-value" (result i32) + (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)) ) - (func "as-unary-operand" (result f32) + (func (export "as-unary-operand") (result f32) (block (f32.neg (br_table 0 (f32.const 3.4) (i32.const 0)))) ) - (func "as-binary-left" (result i32) + (func (export "as-binary-left") (result i32) (block (i32.add (br_table 0 0 (i32.const 3) (i32.const 0)) (i32.const 10))) ) - (func "as-binary-right" (result i64) + (func (export "as-binary-right") (result i64) (block (i64.sub (i64.const 10) (br_table 0 (i64.const 45) (i32.const 0)))) ) - (func "as-test-operand" (result i32) + (func (export "as-test-operand") (result i32) (block (i32.eqz (br_table 0 (i32.const 44) (i32.const 0)))) ) - (func "as-compare-left" (result i32) + (func (export "as-compare-left") (result i32) (block (f64.le (br_table 0 0 (i32.const 43) (i32.const 0)) (f64.const 10))) ) - (func "as-compare-right" (result i32) + (func (export "as-compare-right") (result i32) (block (f32.ne (f32.const 10) (br_table 0 (i32.const 42) (i32.const 0)))) ) - (func "as-convert-operand" (result i32) + (func (export "as-convert-operand") (result i32) (block (i32.wrap/i64 (br_table 0 (i32.const 41) (i32.const 0)))) ) - (func "as-grow_memory-size" (result i32) + (func (export "as-grow_memory-size") (result i32) (block (grow_memory (br_table 0 (i32.const 40) (i32.const 0)))) ) - (func "nested-block-value" (param i32) (result i32) + (func (export "nested-block-value") (param i32) (result i32) (block (drop (i32.const -1)) (i32.add @@ -1020,7 +1009,7 @@ ) ) - (func "nested-br-value" (param i32) (result i32) + (func (export "nested-br-value") (param i32) (result i32) (block (i32.add (i32.const 1) @@ -1038,7 +1027,7 @@ ) ) - (func "nested-br_if-value" (param i32) (result i32) + (func (export "nested-br_if-value") (param i32) (result i32) (block (i32.add (i32.const 1) @@ -1057,7 +1046,7 @@ ) ) - (func "nested-br_if-value-cond" (param i32) (result i32) + (func (export "nested-br_if-value-cond") (param i32) (result i32) (block (i32.add (i32.const 1) @@ -1070,7 +1059,7 @@ ) ) - (func "nested-br_table-value" (param i32) (result i32) + (func (export "nested-br_table-value") (param i32) (result i32) (block (i32.add (i32.const 1) @@ -1089,7 +1078,7 @@ ) ) - (func "nested-br_table-value-index" (param i32) (result i32) + (func (export "nested-br_table-value-index") (param i32) (result i32) (block (i32.add (i32.const 1) @@ -1209,10 +1198,6 @@ (assert_return (invoke "as-call-mid") (i32.const 13)) (assert_return (invoke "as-call-last") (i32.const 14)) -(assert_return (invoke "as-call_import-first")) -(assert_return (invoke "as-call_import-mid")) -(assert_return (invoke "as-call_import-last")) - (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)) diff --git a/ml-proto/test/break-drop.wast b/ml-proto/test/break-drop.wast index 8477175e73..5493e2b3af 100644 --- a/ml-proto/test/break-drop.wast +++ b/ml-proto/test/break-drop.wast @@ -1,12 +1,7 @@ (module - (func $br (block (br 0))) - (export "br" $br) - - (func $br_if (block (br_if 0 (i32.const 1)))) - (export "br_if" $br_if) - - (func $br_table (block (br_table 0 (i32.const 0)))) - (export "br_table" $br_table) + (func (export "br") (block (br 0))) + (func (export "br_if") (block (br_if 0 (i32.const 1)))) + (func (export "br_table") (block (br_table 0 (i32.const 0)))) ) (assert_return (invoke "br")) diff --git a/ml-proto/test/call.wast b/ml-proto/test/call.wast index b903a8d056..dde2f949f9 100644 --- a/ml-proto/test/call.wast +++ b/ml-proto/test/call.wast @@ -19,39 +19,39 @@ ;; Typing - (func "type-i32" (result i32) (call $const-i32)) - (func "type-i64" (result i64) (call $const-i64)) - (func "type-f32" (result f32) (call $const-f32)) - (func "type-f64" (result f64) (call $const-f64)) + (func (export "type-i32") (result i32) (call $const-i32)) + (func (export "type-i64") (result i64) (call $const-i64)) + (func (export "type-f32") (result f32) (call $const-f32)) + (func (export "type-f64") (result f64) (call $const-f64)) - (func "type-first-i32" (result i32) (call $id-i32 (i32.const 32))) - (func "type-first-i64" (result i64) (call $id-i64 (i64.const 64))) - (func "type-first-f32" (result f32) (call $id-f32 (f32.const 1.32))) - (func "type-first-f64" (result f64) (call $id-f64 (f64.const 1.64))) + (func (export "type-first-i32") (result i32) (call $id-i32 (i32.const 32))) + (func (export "type-first-i64") (result i64) (call $id-i64 (i64.const 64))) + (func (export "type-first-f32") (result f32) (call $id-f32 (f32.const 1.32))) + (func (export "type-first-f64") (result f64) (call $id-f64 (f64.const 1.64))) - (func "type-second-i32" (result i32) + (func (export "type-second-i32") (result i32) (call $f32-i32 (f32.const 32.1) (i32.const 32)) ) - (func "type-second-i64" (result i64) + (func (export "type-second-i64") (result i64) (call $i32-i64 (i32.const 32) (i64.const 64)) ) - (func "type-second-f32" (result f32) + (func (export "type-second-f32") (result f32) (call $f64-f32 (f64.const 64) (f32.const 32)) ) - (func "type-second-f64" (result f64) + (func (export "type-second-f64") (result f64) (call $i64-f64 (i64.const 64) (f64.const 64.1)) ) ;; Recursion - (func "fac" $fac (param i64) (result i64) + (func $fac (export "fac") (param i64) (result i64) (if (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" $fac-acc (param i64 i64) (result i64) + (func $fac-acc (export "fac-acc") (param i64 i64) (result i64) (if (i64.eqz (get_local 0)) (get_local 1) (call $fac-acc @@ -61,7 +61,7 @@ ) ) - (func "fib" $fib (param i64) (result i64) + (func $fib (export "fib") (param i64) (result i64) (if (i64.le_u (get_local 0) (i64.const 1)) (i64.const 1) (i64.add @@ -71,13 +71,13 @@ ) ) - (func "even" $even (param i64) (result i32) + (func $even (export "even") (param i64) (result i32) (if (i64.eqz (get_local 0)) (i32.const 44) (call $odd (i64.sub (get_local 0) (i64.const 1))) ) ) - (func "odd" $odd (param i64) (result i32) + (func $odd (export "odd") (param i64) (result i32) (if (i64.eqz (get_local 0)) (i32.const 99) (call $even (i64.sub (get_local 0) (i64.const 1))) @@ -93,9 +93,9 @@ ;; implementations and be incompatible with implementations that don't do ;; it (or don't do it under the same circumstances). - (func "runaway" $runaway (call $runaway)) + (func $runaway (export "runaway") (call $runaway)) - (func "mutual-runaway" $mutual-runaway1 (call $mutual-runaway2)) + (func $mutual-runaway1 (export "mutual-runaway") (call $mutual-runaway2)) (func $mutual-runaway2 (call $mutual-runaway1)) ) diff --git a/ml-proto/test/call_indirect.wast b/ml-proto/test/call_indirect.wast index 70b160402b..6d2dc46b82 100644 --- a/ml-proto/test/call_indirect.wast +++ b/ml-proto/test/call_indirect.wast @@ -54,54 +54,54 @@ ;; Typing - (func "type-i32" (result i32) (call_indirect $out-i32 (i32.const 0))) - (func "type-i64" (result i64) (call_indirect $out-i64 (i32.const 1))) - (func "type-f32" (result f32) (call_indirect $out-f32 (i32.const 2))) - (func "type-f64" (result f64) (call_indirect $out-f64 (i32.const 3))) + (func (export "type-i32") (result i32) (call_indirect $out-i32 (i32.const 0))) + (func (export "type-i64") (result i64) (call_indirect $out-i64 (i32.const 1))) + (func (export "type-f32") (result f32) (call_indirect $out-f32 (i32.const 2))) + (func (export "type-f64") (result f64) (call_indirect $out-f64 (i32.const 3))) - (func "type-index" (result i64) + (func (export "type-index") (result i64) (call_indirect $over-i64 (i32.const 5) (i64.const 100)) ) - (func "type-first-i32" (result i32) + (func (export "type-first-i32") (result i32) (call_indirect $over-i32 (i32.const 4) (i32.const 32)) ) - (func "type-first-i64" (result i64) + (func (export "type-first-i64") (result i64) (call_indirect $over-i64 (i32.const 5) (i64.const 64)) ) - (func "type-first-f32" (result f32) + (func (export "type-first-f32") (result f32) (call_indirect $over-f32 (i32.const 6) (f32.const 1.32)) ) - (func "type-first-f64" (result f64) + (func (export "type-first-f64") (result f64) (call_indirect $over-f64 (i32.const 7) (f64.const 1.64)) ) - (func "type-second-i32" (result i32) + (func (export "type-second-i32") (result i32) (call_indirect $f32-i32 (i32.const 8) (f32.const 32.1) (i32.const 32)) ) - (func "type-second-i64" (result i64) + (func (export "type-second-i64") (result i64) (call_indirect $i32-i64 (i32.const 9) (i32.const 32) (i64.const 64)) ) - (func "type-second-f32" (result f32) + (func (export "type-second-f32") (result f32) (call_indirect $f64-f32 (i32.const 10) (f64.const 64) (f32.const 32)) ) - (func "type-second-f64" (result f64) + (func (export "type-second-f64") (result f64) (call_indirect $i64-f64 (i32.const 11) (i64.const 64) (f64.const 64.1)) ) ;; Dispatch - (func "dispatch" (param i32 i64) (result i64) + (func (export "dispatch") (param i32 i64) (result i64) (call_indirect $over-i64 (get_local 0) (get_local 1)) ) - (func "dispatch-structural" (param i32) (result i64) + (func (export "dispatch-structural") (param i32) (result i64) (call_indirect $over-i64-duplicate (get_local 0) (i64.const 9)) ) ;; Recursion - (func "fac" $fac (type $over-i64) + (func $fac (export "fac") (type $over-i64) (if (i64.eqz (get_local 0)) (i64.const 1) (i64.mul @@ -113,7 +113,7 @@ ) ) - (func "fib" $fib (type $over-i64) + (func $fib (export "fib") (type $over-i64) (if (i64.le_u (get_local 0) (i64.const 1)) (i64.const 1) (i64.add @@ -127,7 +127,7 @@ ) ) - (func "even" $even (param i32) (result i32) + (func $even (export "even") (param i32) (result i32) (if (i32.eqz (get_local 0)) (i32.const 44) (call_indirect $over-i32 (i32.const 15) @@ -135,7 +135,7 @@ ) ) ) - (func "odd" $odd (param i32) (result i32) + (func $odd (export "odd") (param i32) (result i32) (if (i32.eqz (get_local 0)) (i32.const 99) (call_indirect $over-i32 (i32.const 14) @@ -153,9 +153,9 @@ ;; implementations and be incompatible with implementations that don't do ;; it (or don't do it under the same circumstances). - (func "runaway" $runaway (call_indirect $proc (i32.const 16))) + (func $runaway (export "runaway") (call_indirect $proc (i32.const 16))) - (func "mutual-runaway" $mutual-runaway1 (call_indirect $proc (i32.const 18))) + (func $mutual-runaway1 (export "mutual-runaway") (call_indirect $proc (i32.const 18))) (func $mutual-runaway2 (call_indirect $proc (i32.const 17))) ) @@ -225,7 +225,7 @@ (type (func)) (func $no-table (call_indirect 0 (i32.const 0))) ) - "no table" + "unknown table" ) (assert_invalid @@ -377,12 +377,12 @@ (table 0 anyfunc) (func $unbound-type (call_indirect 1 (i32.const 0))) ) - "unknown function type" + "unknown type" ) (assert_invalid (module (table 0 anyfunc) (func $large-type (call_indirect 10001232130000 (i32.const 0))) ) - "unknown function type" + "unknown type" ) diff --git a/ml-proto/test/conversions.wast b/ml-proto/test/conversions.wast index a102f9bb68..17036a75ff 100644 --- a/ml-proto/test/conversions.wast +++ b/ml-proto/test/conversions.wast @@ -1,78 +1,29 @@ (module - (func $i64.extend_s_i32 (param $x i32) (result i64) (i64.extend_s/i32 (get_local $x))) - (export "i64.extend_s_i32" $i64.extend_s_i32) - - (func $i64.extend_u_i32 (param $x i32) (result i64) (i64.extend_u/i32 (get_local $x))) - (export "i64.extend_u_i32" $i64.extend_u_i32) - - (func $i32.wrap_i64 (param $x i64) (result i32) (i32.wrap/i64 (get_local $x))) - (export "i32.wrap_i64" $i32.wrap_i64) - - (func $i32.trunc_s_f32 (param $x f32) (result i32) (i32.trunc_s/f32 (get_local $x))) - (export "i32.trunc_s_f32" $i32.trunc_s_f32) - - (func $i32.trunc_u_f32 (param $x f32) (result i32) (i32.trunc_u/f32 (get_local $x))) - (export "i32.trunc_u_f32" $i32.trunc_u_f32) - - (func $i32.trunc_s_f64 (param $x f64) (result i32) (i32.trunc_s/f64 (get_local $x))) - (export "i32.trunc_s_f64" $i32.trunc_s_f64) - - (func $i32.trunc_u_f64 (param $x f64) (result i32) (i32.trunc_u/f64 (get_local $x))) - (export "i32.trunc_u_f64" $i32.trunc_u_f64) - - (func $i64.trunc_s_f32 (param $x f32) (result i64) (i64.trunc_s/f32 (get_local $x))) - (export "i64.trunc_s_f32" $i64.trunc_s_f32) - - (func $i64.trunc_u_f32 (param $x f32) (result i64) (i64.trunc_u/f32 (get_local $x))) - (export "i64.trunc_u_f32" $i64.trunc_u_f32) - - (func $i64.trunc_s_f64 (param $x f64) (result i64) (i64.trunc_s/f64 (get_local $x))) - (export "i64.trunc_s_f64" $i64.trunc_s_f64) - - (func $i64.trunc_u_f64 (param $x f64) (result i64) (i64.trunc_u/f64 (get_local $x))) - (export "i64.trunc_u_f64" $i64.trunc_u_f64) - - (func $f32.convert_s_i32 (param $x i32) (result f32) (f32.convert_s/i32 (get_local $x))) - (export "f32.convert_s_i32" $f32.convert_s_i32) - - (func $f32.convert_s_i64 (param $x i64) (result f32) (f32.convert_s/i64 (get_local $x))) - (export "f32.convert_s_i64" $f32.convert_s_i64) - - (func $f64.convert_s_i32 (param $x i32) (result f64) (f64.convert_s/i32 (get_local $x))) - (export "f64.convert_s_i32" $f64.convert_s_i32) - - (func $f64.convert_s_i64 (param $x i64) (result f64) (f64.convert_s/i64 (get_local $x))) - (export "f64.convert_s_i64" $f64.convert_s_i64) - - (func $f32.convert_u_i32 (param $x i32) (result f32) (f32.convert_u/i32 (get_local $x))) - (export "f32.convert_u_i32" $f32.convert_u_i32) - - (func $f32.convert_u_i64 (param $x i64) (result f32) (f32.convert_u/i64 (get_local $x))) - (export "f32.convert_u_i64" $f32.convert_u_i64) - - (func $f64.convert_u_i32 (param $x i32) (result f64) (f64.convert_u/i32 (get_local $x))) - (export "f64.convert_u_i32" $f64.convert_u_i32) - - (func $f64.convert_u_i64 (param $x i64) (result f64) (f64.convert_u/i64 (get_local $x))) - (export "f64.convert_u_i64" $f64.convert_u_i64) - - (func $f64.promote_f32 (param $x f32) (result f64) (f64.promote/f32 (get_local $x))) - (export "f64.promote_f32" $f64.promote_f32) - - (func $f32.demote_f64 (param $x f64) (result f32) (f32.demote/f64 (get_local $x))) - (export "f32.demote_f64" $f32.demote_f64) - - (func $f32.reinterpret_i32 (param $x i32) (result f32) (f32.reinterpret/i32 (get_local $x))) - (export "f32.reinterpret_i32" $f32.reinterpret_i32) - - (func $f64.reinterpret_i64 (param $x i64) (result f64) (f64.reinterpret/i64 (get_local $x))) - (export "f64.reinterpret_i64" $f64.reinterpret_i64) - - (func $i32.reinterpret_f32 (param $x f32) (result i32) (i32.reinterpret/f32 (get_local $x))) - (export "i32.reinterpret_f32" $i32.reinterpret_f32) - - (func $i64.reinterpret_f64 (param $x f64) (result i64) (i64.reinterpret/f64 (get_local $x))) - (export "i64.reinterpret_f64" $i64.reinterpret_f64) + (func (export "i64.extend_s_i32") (param $x i32) (result i64) (i64.extend_s/i32 (get_local $x))) + (func (export "i64.extend_u_i32") (param $x i32) (result i64) (i64.extend_u/i32 (get_local $x))) + (func (export "i32.wrap_i64") (param $x i64) (result i32) (i32.wrap/i64 (get_local $x))) + (func (export "i32.trunc_s_f32") (param $x f32) (result i32) (i32.trunc_s/f32 (get_local $x))) + (func (export "i32.trunc_u_f32") (param $x f32) (result i32) (i32.trunc_u/f32 (get_local $x))) + (func (export "i32.trunc_s_f64") (param $x f64) (result i32) (i32.trunc_s/f64 (get_local $x))) + (func (export "i32.trunc_u_f64") (param $x f64) (result i32) (i32.trunc_u/f64 (get_local $x))) + (func (export "i64.trunc_s_f32") (param $x f32) (result i64) (i64.trunc_s/f32 (get_local $x))) + (func (export "i64.trunc_u_f32") (param $x f32) (result i64) (i64.trunc_u/f32 (get_local $x))) + (func (export "i64.trunc_s_f64") (param $x f64) (result i64) (i64.trunc_s/f64 (get_local $x))) + (func (export "i64.trunc_u_f64") (param $x f64) (result i64) (i64.trunc_u/f64 (get_local $x))) + (func (export "f32.convert_s_i32") (param $x i32) (result f32) (f32.convert_s/i32 (get_local $x))) + (func (export "f32.convert_s_i64") (param $x i64) (result f32) (f32.convert_s/i64 (get_local $x))) + (func (export "f64.convert_s_i32") (param $x i32) (result f64) (f64.convert_s/i32 (get_local $x))) + (func (export "f64.convert_s_i64") (param $x i64) (result f64) (f64.convert_s/i64 (get_local $x))) + (func (export "f32.convert_u_i32") (param $x i32) (result f32) (f32.convert_u/i32 (get_local $x))) + (func (export "f32.convert_u_i64") (param $x i64) (result f32) (f32.convert_u/i64 (get_local $x))) + (func (export "f64.convert_u_i32") (param $x i32) (result f64) (f64.convert_u/i32 (get_local $x))) + (func (export "f64.convert_u_i64") (param $x i64) (result f64) (f64.convert_u/i64 (get_local $x))) + (func (export "f64.promote_f32") (param $x f32) (result f64) (f64.promote/f32 (get_local $x))) + (func (export "f32.demote_f64") (param $x f64) (result f32) (f32.demote/f64 (get_local $x))) + (func (export "f32.reinterpret_i32") (param $x i32) (result f32) (f32.reinterpret/i32 (get_local $x))) + (func (export "f64.reinterpret_i64") (param $x i64) (result f64) (f64.reinterpret/i64 (get_local $x))) + (func (export "i32.reinterpret_f32") (param $x f32) (result i32) (i32.reinterpret/f32 (get_local $x))) + (func (export "i64.reinterpret_f64") (param $x f64) (result i64) (i64.reinterpret/f64 (get_local $x))) ) (assert_return (invoke "i64.extend_s_i32" (i32.const 0)) (i64.const 0)) diff --git a/ml-proto/test/endianness.wast b/ml-proto/test/endianness.wast index 17a4b22c4b..8dc0c2e2eb 100644 --- a/ml-proto/test/endianness.wast +++ b/ml-proto/test/endianness.wast @@ -43,115 +43,91 @@ ) ) - (func $i32_load16_s (param $value i32) (result i32) + (func (export "i32_load16_s") (param $value i32) (result i32) (call $i16_store_little (i32.const 0) (get_local $value)) (i32.load16_s (i32.const 0)) ) - (func $i32_load16_u (param $value i32) (result i32) + (func (export "i32_load16_u") (param $value i32) (result i32) (call $i16_store_little (i32.const 0) (get_local $value)) (i32.load16_u (i32.const 0)) ) - (func $i32_load (param $value i32) (result i32) + (func (export "i32_load") (param $value i32) (result i32) (call $i32_store_little (i32.const 0) (get_local $value)) (i32.load (i32.const 0)) ) - (func $i64_load16_s (param $value i64) (result i64) + (func (export "i64_load16_s") (param $value i64) (result i64) (call $i16_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) (i64.load16_s (i32.const 0)) ) - (func $i64_load16_u (param $value i64) (result i64) + (func (export "i64_load16_u") (param $value i64) (result i64) (call $i16_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) (i64.load16_u (i32.const 0)) ) - (func $i64_load32_s (param $value i64) (result i64) + (func (export "i64_load32_s") (param $value i64) (result i64) (call $i32_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) (i64.load32_s (i32.const 0)) ) - (func $i64_load32_u (param $value i64) (result i64) + (func (export "i64_load32_u") (param $value i64) (result i64) (call $i32_store_little (i32.const 0) (i32.wrap/i64 (get_local $value))) (i64.load32_u (i32.const 0)) ) - (func $i64_load (param $value i64) (result i64) + (func (export "i64_load") (param $value i64) (result i64) (call $i64_store_little (i32.const 0) (get_local $value)) (i64.load (i32.const 0)) ) - (func $f32_load (param $value f32) (result f32) + (func (export "f32_load") (param $value f32) (result f32) (call $i32_store_little (i32.const 0) (i32.reinterpret/f32 (get_local $value))) (f32.load (i32.const 0)) ) - (func $f64_load (param $value f64) (result f64) + (func (export "f64_load") (param $value f64) (result f64) (call $i64_store_little (i32.const 0) (i64.reinterpret/f64 (get_local $value))) (f64.load (i32.const 0)) ) - (func $i32_store16 (param $value i32) (result i32) + (func (export "i32_store16") (param $value i32) (result i32) (i32.store16 (i32.const 0) (get_local $value)) (call $i16_load_little (i32.const 0)) ) - (func $i32_store (param $value i32) (result i32) + (func (export "i32_store") (param $value i32) (result i32) (i32.store (i32.const 0) (get_local $value)) (call $i32_load_little (i32.const 0)) ) - (func $i64_store16 (param $value i64) (result i64) + (func (export "i64_store16") (param $value i64) (result i64) (i64.store16 (i32.const 0) (get_local $value)) (i64.extend_u/i32 (call $i16_load_little (i32.const 0))) ) - (func $i64_store32 (param $value i64) (result i64) + (func (export "i64_store32") (param $value i64) (result i64) (i64.store32 (i32.const 0) (get_local $value)) (i64.extend_u/i32 (call $i32_load_little (i32.const 0))) ) - (func $i64_store (param $value i64) (result i64) + (func (export "i64_store") (param $value i64) (result i64) (i64.store (i32.const 0) (get_local $value)) (call $i64_load_little (i32.const 0)) ) - (func $f32_store (param $value f32) (result f32) + (func (export "f32_store") (param $value f32) (result f32) (f32.store (i32.const 0) (get_local $value)) (f32.reinterpret/i32 (call $i32_load_little (i32.const 0))) ) - (func $f64_store (param $value f64) (result f64) + (func (export "f64_store") (param $value f64) (result f64) (f64.store (i32.const 0) (get_local $value)) (f64.reinterpret/i64 (call $i64_load_little (i32.const 0))) ) - - (export "i32_load16_s" $i32_load16_s) - (export "i32_load16_u" $i32_load16_u) - (export "i32_load" $i32_load) - - (export "i64_load16_s" $i64_load16_s) - (export "i64_load16_u" $i64_load16_u) - (export "i64_load32_s" $i64_load32_s) - (export "i64_load32_u" $i64_load32_u) - (export "i64_load" $i64_load) - - (export "f32_load" $f32_load) - (export "f64_load" $f64_load) - - - (export "i32_store16" $i32_store16) - (export "i32_store" $i32_store) - - (export "i64_store16" $i64_store16) - (export "i64_store32" $i64_store32) - (export "i64_store" $i64_store) - - (export "f32_store" $f32_store) - (export "f64_store" $f64_store) ) (assert_return (invoke "i32_load16_s" (i32.const -1)) (i32.const -1)) diff --git a/ml-proto/test/expected-output/imports.wast.log b/ml-proto/test/expected-output/imports.wast.log index ed2f3784a6..cd34c23997 100644 --- a/ml-proto/test/expected-output/imports.wast.log +++ b/ml-proto/test/expected-output/imports.wast.log @@ -1,6 +1,10 @@ +13 : i32 14 : i32 42. : f32 13 : i32 +13 : i32 +24 : i64 25 : i64 53. : f64 24 : i64 +24 : i64 diff --git a/ml-proto/test/exports.wast b/ml-proto/test/exports.wast index 3cdbb352f7..16f495239f 100644 --- a/ml-proto/test/exports.wast +++ b/ml-proto/test/exports.wast @@ -1,17 +1,34 @@ -(module (func) (export "a" 0)) -(module (func) (export "a" 0) (export "b" 0)) -(module (func) (func) (export "a" 0) (export "b" 1)) +;; Functions +(module (func) (export "a" (func 0))) +(module (func) (export "a" (func 0)) (export "b" (func 0))) +(module (func) (func) (export "a" (func 0)) (export "b" (func 1))) + +(module (func (export "a"))) +(module (func $a (export "a"))) + +(assert_invalid + (module (func) (export "a" (func 1))) + "unknown function" +) +(assert_invalid + (module (func) (export "a" (func 0)) (export "a" (func 0))) + "duplicate export name" +) (assert_invalid - (module (func) (export "a" 1)) - "unknown function 1" + (module (func) (func) (export "a" (func 0)) (export "a" (func 1))) + "duplicate export name" ) (assert_invalid - (module (func) (func) (export "a" 0) (export "a" 1)) + (module (func) (global i32 (i32.const 0)) (export "a" (func 0)) (export "a" (global 0))) "duplicate export name" ) (assert_invalid - (module (func) (export "a" 0) (export "a" 0)) + (module (func) (table 0 anyfunc) (export "a" (func 0)) (export "a" (table 0))) + "duplicate export name" +) +(assert_invalid + (module (func) (memory 0) (export "a" (func 0)) (export "a" (memory 0))) "duplicate export name" ) @@ -20,11 +37,127 @@ (return (i32.add (get_local $n) (i32.const 1))) ) - (export "e" $f) + (export "e" (func $f)) ) (assert_return (invoke "e" (i32.const 42)) (i32.const 43)) -(module (memory 0 0) (export "a" memory)) -(module (memory 0 0) (export "a" memory) (export "b" memory)) -(assert_invalid (module (export "a" memory)) "no memory") + +;; Globals + +(module (global i32 (i32.const 0)) (export "a" (global 0))) +(module (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 0))) +(module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "b" (global 1))) + +(module (global (export "a") i32 (i32.const 0))) +(module (global $a (export "a") i32 (i32.const 0))) + +(assert_invalid + (module (global i32 (i32.const 0)) (export "a" (global 1))) + "unknown global" +) +(assert_invalid + (module (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (global i32 (i32.const 0)) (export "a" (global 0)) (export "a" (global 1))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (func) (export "a" (global 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (table 0 anyfunc) (export "a" (global 0)) (export "a" (table 0))) + "duplicate export name" +) +(assert_invalid + (module (global i32 (i32.const 0)) (memory 0) (export "a" (global 0)) (export "a" (memory 0))) + "duplicate export name" +) + +(; TODO: get global value ;) + + +;; Tables + +(module (table 0 anyfunc) (export "a" (table 0))) +(module (table 0 anyfunc) (export "a" (table 0)) (export "b" (table 0))) +;; No multiple tables yet. +;; (module (table 0 anyfunc) (table 0 anyfunc) (export "a" (table 0)) (export "b" (table 1))) + +(module (table (export "a") 0 anyfunc)) +(module (table (export "a") 0 1 anyfunc)) +(module (table $a (export "a") 0 anyfunc)) +(module (table $a (export "a") 0 1 anyfunc)) + +(assert_invalid + (module (table 0 anyfunc) (export "a" (table 1))) + "unknown table" +) +(assert_invalid + (module (table 0 anyfunc) (export "a" (table 0)) (export "a" (table 0))) + "duplicate export name" +) +;; No multiple tables yet. +;; (assert_invalid +;; (module (table 0 anyfunc) (table 0 anyfunc) (export "a" (table 0)) (export "a" (table 1))) +;; "duplicate export name" +;; ) +(assert_invalid + (module (table 0 anyfunc) (func) (export "a" (table 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (table 0 anyfunc) (global i32 (i32.const 0)) (export "a" (table 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (table 0 anyfunc) (memory 0) (export "a" (table 0)) (export "a" (memory 0))) + "duplicate export name" +) + +(; TODO: access table ;) + + +;; Memories + +(module (memory 0) (export "a" (memory 0))) +(module (memory 0) (export "a" (memory 0)) (export "b" (memory 0))) +;; No multiple memories yet. +;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "b" (memory 1))) + +(module (memory (export "a") 0)) +(module (memory (export "a") 0 1)) +(module (memory $a (export "a") 0)) +(module (memory $a (export "a") 0 1)) + +(assert_invalid + (module (memory 0) (export "a" (memory 1))) + "unknown memory" +) +(assert_invalid + (module (memory 0) (export "a" (memory 0)) (export "a" (memory 0))) + "duplicate export name" +) +;; No multiple memories yet. +;; (assert_invalid +;; (module (memory 0) (memory 0) (export "a" (memory 0)) (export "a" (memory 1))) +;; "duplicate export name" +;; ) +(assert_invalid + (module (memory 0) (func) (export "a" (memory 0)) (export "a" (func 0))) + "duplicate export name" +) +(assert_invalid + (module (memory 0) (global i32 (i32.const 0)) (export "a" (memory 0)) (export "a" (global 0))) + "duplicate export name" +) +(assert_invalid + (module (memory 0) (table 0 anyfunc) (export "a" (memory 0)) (export "a" (table 0))) + "duplicate export name" +) + +(; TODO: access memory ;) + diff --git a/ml-proto/test/f32.wast b/ml-proto/test/f32.wast index 9924f24fd2..9f58f9bd10 100644 --- a/ml-proto/test/f32.wast +++ b/ml-proto/test/f32.wast @@ -2,35 +2,20 @@ ;; values (except comparison operators, which are tested in f32_cmp.wast). (module - (func $add (param $x f32) (param $y f32) (result f32) (f32.add (get_local $x) (get_local $y))) - (func $sub (param $x f32) (param $y f32) (result f32) (f32.sub (get_local $x) (get_local $y))) - (func $mul (param $x f32) (param $y f32) (result f32) (f32.mul (get_local $x) (get_local $y))) - (func $div (param $x f32) (param $y f32) (result f32) (f32.div (get_local $x) (get_local $y))) - (func $sqrt (param $x f32) (result f32) (f32.sqrt (get_local $x))) - (func $min (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y))) - (func $max (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y))) - (func $ceil (param $x f32) (result f32) (f32.ceil (get_local $x))) - (func $floor (param $x f32) (result f32) (f32.floor (get_local $x))) - (func $trunc (param $x f32) (result f32) (f32.trunc (get_local $x))) - (func $nearest (param $x f32) (result f32) (f32.nearest (get_local $x))) - (func $abs (param $x f32) (result f32) (f32.abs (get_local $x))) - (func $neg (param $x f32) (result f32) (f32.neg (get_local $x))) - (func $copysign (param $x f32) (param $y f32) (result f32) (f32.copysign (get_local $x) (get_local $y))) - - (export "add" $add) - (export "sub" $sub) - (export "mul" $mul) - (export "div" $div) - (export "sqrt" $sqrt) - (export "min" $min) - (export "max" $max) - (export "ceil" $ceil) - (export "floor" $floor) - (export "trunc" $trunc) - (export "nearest" $nearest) - (export "abs" $abs) - (export "neg" $neg) - (export "copysign" $copysign) + (func (export "add") (param $x f32) (param $y f32) (result f32) (f32.add (get_local $x) (get_local $y))) + (func (export "sub") (param $x f32) (param $y f32) (result f32) (f32.sub (get_local $x) (get_local $y))) + (func (export "mul") (param $x f32) (param $y f32) (result f32) (f32.mul (get_local $x) (get_local $y))) + (func (export "div") (param $x f32) (param $y f32) (result f32) (f32.div (get_local $x) (get_local $y))) + (func (export "sqrt") (param $x f32) (result f32) (f32.sqrt (get_local $x))) + (func (export "min") (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y))) + (func (export "max") (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y))) + (func (export "ceil") (param $x f32) (result f32) (f32.ceil (get_local $x))) + (func (export "floor") (param $x f32) (result f32) (f32.floor (get_local $x))) + (func (export "trunc") (param $x f32) (result f32) (f32.trunc (get_local $x))) + (func (export "nearest") (param $x f32) (result f32) (f32.nearest (get_local $x))) + (func (export "abs") (param $x f32) (result f32) (f32.abs (get_local $x))) + (func (export "neg") (param $x f32) (result f32) (f32.neg (get_local $x))) + (func (export "copysign") (param $x f32) (param $y f32) (result f32) (f32.copysign (get_local $x) (get_local $y))) ) (assert_return (invoke "add" (f32.const -0x0p+0) (f32.const -0x0p+0)) (f32.const -0x0p+0)) diff --git a/ml-proto/test/f32_cmp.wast b/ml-proto/test/f32_cmp.wast index f4d4637cb0..9458069c30 100644 --- a/ml-proto/test/f32_cmp.wast +++ b/ml-proto/test/f32_cmp.wast @@ -2,19 +2,12 @@ ;; special values. (module - (func $eq (param $x f32) (param $y f32) (result i32) (f32.eq (get_local $x) (get_local $y))) - (func $ne (param $x f32) (param $y f32) (result i32) (f32.ne (get_local $x) (get_local $y))) - (func $lt (param $x f32) (param $y f32) (result i32) (f32.lt (get_local $x) (get_local $y))) - (func $le (param $x f32) (param $y f32) (result i32) (f32.le (get_local $x) (get_local $y))) - (func $gt (param $x f32) (param $y f32) (result i32) (f32.gt (get_local $x) (get_local $y))) - (func $ge (param $x f32) (param $y f32) (result i32) (f32.ge (get_local $x) (get_local $y))) - - (export "eq" $eq) - (export "ne" $ne) - (export "lt" $lt) - (export "le" $le) - (export "gt" $gt) - (export "ge" $ge) + (func (export "eq") (param $x f32) (param $y f32) (result i32) (f32.eq (get_local $x) (get_local $y))) + (func (export "ne") (param $x f32) (param $y f32) (result i32) (f32.ne (get_local $x) (get_local $y))) + (func (export "lt") (param $x f32) (param $y f32) (result i32) (f32.lt (get_local $x) (get_local $y))) + (func (export "le") (param $x f32) (param $y f32) (result i32) (f32.le (get_local $x) (get_local $y))) + (func (export "gt") (param $x f32) (param $y f32) (result i32) (f32.gt (get_local $x) (get_local $y))) + (func (export "ge") (param $x f32) (param $y f32) (result i32) (f32.ge (get_local $x) (get_local $y))) ) (assert_return (invoke "eq" (f32.const -0x0p+0) (f32.const -0x0p+0)) (i32.const 1)) diff --git a/ml-proto/test/f64.wast b/ml-proto/test/f64.wast index eb6e7da40a..26a058a253 100644 --- a/ml-proto/test/f64.wast +++ b/ml-proto/test/f64.wast @@ -2,35 +2,20 @@ ;; values (except comparison operators, which are tested in f64_cmp.wast). (module - (func $add (param $x f64) (param $y f64) (result f64) (f64.add (get_local $x) (get_local $y))) - (func $sub (param $x f64) (param $y f64) (result f64) (f64.sub (get_local $x) (get_local $y))) - (func $mul (param $x f64) (param $y f64) (result f64) (f64.mul (get_local $x) (get_local $y))) - (func $div (param $x f64) (param $y f64) (result f64) (f64.div (get_local $x) (get_local $y))) - (func $sqrt (param $x f64) (result f64) (f64.sqrt (get_local $x))) - (func $min (param $x f64) (param $y f64) (result f64) (f64.min (get_local $x) (get_local $y))) - (func $max (param $x f64) (param $y f64) (result f64) (f64.max (get_local $x) (get_local $y))) - (func $ceil (param $x f64) (result f64) (f64.ceil (get_local $x))) - (func $floor (param $x f64) (result f64) (f64.floor (get_local $x))) - (func $trunc (param $x f64) (result f64) (f64.trunc (get_local $x))) - (func $nearest (param $x f64) (result f64) (f64.nearest (get_local $x))) - (func $abs (param $x f64) (result f64) (f64.abs (get_local $x))) - (func $neg (param $x f64) (result f64) (f64.neg (get_local $x))) - (func $copysign (param $x f64) (param $y f64) (result f64) (f64.copysign (get_local $x) (get_local $y))) - - (export "add" $add) - (export "sub" $sub) - (export "mul" $mul) - (export "div" $div) - (export "sqrt" $sqrt) - (export "min" $min) - (export "max" $max) - (export "ceil" $ceil) - (export "floor" $floor) - (export "trunc" $trunc) - (export "nearest" $nearest) - (export "abs" $abs) - (export "neg" $neg) - (export "copysign" $copysign) + (func (export "add") (param $x f64) (param $y f64) (result f64) (f64.add (get_local $x) (get_local $y))) + (func (export "sub") (param $x f64) (param $y f64) (result f64) (f64.sub (get_local $x) (get_local $y))) + (func (export "mul") (param $x f64) (param $y f64) (result f64) (f64.mul (get_local $x) (get_local $y))) + (func (export "div") (param $x f64) (param $y f64) (result f64) (f64.div (get_local $x) (get_local $y))) + (func (export "sqrt") (param $x f64) (result f64) (f64.sqrt (get_local $x))) + (func (export "min") (param $x f64) (param $y f64) (result f64) (f64.min (get_local $x) (get_local $y))) + (func (export "max") (param $x f64) (param $y f64) (result f64) (f64.max (get_local $x) (get_local $y))) + (func (export "ceil") (param $x f64) (result f64) (f64.ceil (get_local $x))) + (func (export "floor") (param $x f64) (result f64) (f64.floor (get_local $x))) + (func (export "trunc") (param $x f64) (result f64) (f64.trunc (get_local $x))) + (func (export "nearest") (param $x f64) (result f64) (f64.nearest (get_local $x))) + (func (export "abs") (param $x f64) (result f64) (f64.abs (get_local $x))) + (func (export "neg") (param $x f64) (result f64) (f64.neg (get_local $x))) + (func (export "copysign") (param $x f64) (param $y f64) (result f64) (f64.copysign (get_local $x) (get_local $y))) ) (assert_return (invoke "add" (f64.const -0x0p+0) (f64.const -0x0p+0)) (f64.const -0x0p+0)) diff --git a/ml-proto/test/f64_cmp.wast b/ml-proto/test/f64_cmp.wast index 9d822deda2..f4958b8f98 100644 --- a/ml-proto/test/f64_cmp.wast +++ b/ml-proto/test/f64_cmp.wast @@ -2,19 +2,12 @@ ;; special values. (module - (func $eq (param $x f64) (param $y f64) (result i32) (f64.eq (get_local $x) (get_local $y))) - (func $ne (param $x f64) (param $y f64) (result i32) (f64.ne (get_local $x) (get_local $y))) - (func $lt (param $x f64) (param $y f64) (result i32) (f64.lt (get_local $x) (get_local $y))) - (func $le (param $x f64) (param $y f64) (result i32) (f64.le (get_local $x) (get_local $y))) - (func $gt (param $x f64) (param $y f64) (result i32) (f64.gt (get_local $x) (get_local $y))) - (func $ge (param $x f64) (param $y f64) (result i32) (f64.ge (get_local $x) (get_local $y))) - - (export "eq" $eq) - (export "ne" $ne) - (export "lt" $lt) - (export "le" $le) - (export "gt" $gt) - (export "ge" $ge) + (func (export "eq") (param $x f64) (param $y f64) (result i32) (f64.eq (get_local $x) (get_local $y))) + (func (export "ne") (param $x f64) (param $y f64) (result i32) (f64.ne (get_local $x) (get_local $y))) + (func (export "lt") (param $x f64) (param $y f64) (result i32) (f64.lt (get_local $x) (get_local $y))) + (func (export "le") (param $x f64) (param $y f64) (result i32) (f64.le (get_local $x) (get_local $y))) + (func (export "gt") (param $x f64) (param $y f64) (result i32) (f64.gt (get_local $x) (get_local $y))) + (func (export "ge") (param $x f64) (param $y f64) (result i32) (f64.ge (get_local $x) (get_local $y))) ) (assert_return (invoke "eq" (f64.const -0x0p+0) (f64.const -0x0p+0)) (i32.const 1)) diff --git a/ml-proto/test/fac.wast b/ml-proto/test/fac.wast index 6ac120b145..4a97ba5557 100644 --- a/ml-proto/test/fac.wast +++ b/ml-proto/test/fac.wast @@ -1,6 +1,6 @@ (module ;; Recursive factorial - (func (param i64) (result i64) + (func (export "fac-rec") (param i64) (result i64) (if (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)))) @@ -8,18 +8,18 @@ ) ;; Recursive factorial named - (func $fac-rec (param $n i64) (result i64) + (func $fac-rec-named (export "fac-rec-named") (param $n i64) (result i64) (if (i64.eq (get_local $n) (i64.const 0)) (i64.const 1) (i64.mul (get_local $n) - (call $fac-rec (i64.sub (get_local $n) (i64.const 1))) + (call $fac-rec-named (i64.sub (get_local $n) (i64.const 1))) ) ) ) ;; Iterative factorial - (func (param i64) (result i64) + (func (export "fac-iter") (param i64) (result i64) (local i64 i64) (set_local 1 (get_local 0)) (set_local 2 (i64.const 1)) @@ -38,7 +38,7 @@ ) ;; Iterative factorial named - (func $fac-iter (param $n i64) (result i64) + (func $fac-iter-named (export "fac-iter-named") (param $n i64) (result i64) (local $i i64) (local $res i64) (set_local $i (get_local $n)) @@ -57,8 +57,8 @@ (get_local $res) ) - ;; More-realistically optimized factorial. - (func $fac-opt (param i64) (result i64) + ;; Optimized factorial. + (func (export "fac-optimised") (param i64) (result i64) (local i64) (set_local 1 (i64.const 1)) (block @@ -71,17 +71,11 @@ ) (get_local 1) ) - - (export "fac-rec" 0) - (export "fac-iter" 2) - (export "fac-rec-named" $fac-rec) - (export "fac-iter-named" $fac-iter) - (export "fac-opt" $fac-opt) ) (assert_return (invoke "fac-rec" (i64.const 25)) (i64.const 7034535277573963776)) (assert_return (invoke "fac-iter" (i64.const 25)) (i64.const 7034535277573963776)) (assert_return (invoke "fac-rec-named" (i64.const 25)) (i64.const 7034535277573963776)) (assert_return (invoke "fac-iter-named" (i64.const 25)) (i64.const 7034535277573963776)) -(assert_return (invoke "fac-opt" (i64.const 25)) (i64.const 7034535277573963776)) +(assert_return (invoke "fac-optimised" (i64.const 25)) (i64.const 7034535277573963776)) (assert_trap (invoke "fac-rec" (i64.const 1073741824)) "call stack exhausted") diff --git a/ml-proto/test/float_exprs.wast b/ml-proto/test/float_exprs.wast index 2f968f6bb5..fc4a2a5b63 100644 --- a/ml-proto/test/float_exprs.wast +++ b/ml-proto/test/float_exprs.wast @@ -4,9 +4,8 @@ ;; Test that x*y+z is not done with x87-style intermediate precision. (module - (func $f64.no_contraction (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_contraction") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.add (f64.mul (get_local $x) (get_local $y)) (get_local $z))) - (export "f64.no_contraction" $f64.no_contraction) ) (assert_return (invoke "f64.no_contraction" (f64.const -0x1.9e87ce14273afp-103) (f64.const 0x1.2515ad31db63ep+664) (f64.const 0x1.868c6685e6185p+533)) (f64.const -0x1.da94885b11493p+561)) @@ -18,13 +17,10 @@ ;; Test that x*y+z is not folded to fma. (module - (func $f32.no_fma (param $x f32) (param $y f32) (param $z f32) (result f32) + (func (export "f32.no_fma") (param $x f32) (param $y f32) (param $z f32) (result f32) (f32.add (f32.mul (get_local $x) (get_local $y)) (get_local $z))) - (export "f32.no_fma" $f32.no_fma) - - (func $f64.no_fma (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_fma") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.add (f64.mul (get_local $x) (get_local $y)) (get_local $z))) - (export "f64.no_fma" $f64.no_fma) ) (assert_return (invoke "f32.no_fma" (f32.const 0x1.a78402p+124) (f32.const 0x1.cf8548p-23) (f32.const 0x1.992adap+107)) (f32.const 0x1.a5262cp+107)) @@ -42,13 +38,10 @@ ;; See IEEE 754-2008 10.4 "Literal meaning and value-changing optimizations". (module - (func $f32.no_fold_add_zero (param $x f32) (result f32) + (func (export "f32.no_fold_add_zero") (param $x f32) (result f32) (f32.add (get_local $x) (f32.const 0.0))) - (export "f32.no_fold_add_zero" $f32.no_fold_add_zero) - - (func $f64.no_fold_add_zero (param $x f64) (result f64) + (func (export "f64.no_fold_add_zero") (param $x f64) (result f64) (f64.add (get_local $x) (f64.const 0.0))) - (export "f64.no_fold_add_zero" $f64.no_fold_add_zero) ) (assert_return (invoke "f32.no_fold_add_zero" (f32.const -0.0)) (f32.const 0.0)) @@ -59,13 +52,10 @@ ;; Test that 0.0 - x is not folded to -x. (module - (func $f32.no_fold_zero_sub (param $x f32) (result f32) + (func (export "f32.no_fold_zero_sub") (param $x f32) (result f32) (f32.sub (f32.const 0.0) (get_local $x))) - (export "f32.no_fold_zero_sub" $f32.no_fold_zero_sub) - - (func $f64.no_fold_zero_sub (param $x f64) (result f64) + (func (export "f64.no_fold_zero_sub") (param $x f64) (result f64) (f64.sub (f64.const 0.0) (get_local $x))) - (export "f64.no_fold_zero_sub" $f64.no_fold_zero_sub) ) (assert_return (invoke "f32.no_fold_zero_sub" (f32.const 0.0)) (f32.const 0.0)) @@ -76,13 +66,10 @@ ;; Test that x - 0.0 is not folded to x. (module - (func $f32.no_fold_sub_zero (param $x f32) (result f32) + (func (export "f32.no_fold_sub_zero") (param $x f32) (result f32) (f32.sub (get_local $x) (f32.const 0.0))) - (export "f32.no_fold_sub_zero" $f32.no_fold_sub_zero) - - (func $f64.no_fold_sub_zero (param $x f64) (result f64) + (func (export "f64.no_fold_sub_zero") (param $x f64) (result f64) (f64.sub (get_local $x) (f64.const 0.0))) - (export "f64.no_fold_sub_zero" $f64.no_fold_sub_zero) ) (assert_return (invoke "f32.no_fold_sub_zero" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -91,13 +78,10 @@ ;; Test that x*0.0 is not folded to 0.0. (module - (func $f32.no_fold_mul_zero (param $x f32) (result f32) + (func (export "f32.no_fold_mul_zero") (param $x f32) (result f32) (f32.mul (get_local $x) (f32.const 0.0))) - (export "f32.no_fold_mul_zero" $f32.no_fold_mul_zero) - - (func $f64.no_fold_mul_zero (param $x f64) (result f64) + (func (export "f64.no_fold_mul_zero") (param $x f64) (result f64) (f64.mul (get_local $x) (f64.const 0.0))) - (export "f64.no_fold_mul_zero" $f64.no_fold_mul_zero) ) (assert_return (invoke "f32.no_fold_mul_zero" (f32.const -0.0)) (f32.const -0.0)) @@ -113,13 +97,10 @@ ;; See IEEE 754-2008 10.4 "Literal meaning and value-changing optimizations". (module - (func $f32.no_fold_mul_one (param $x f32) (result f32) + (func (export "f32.no_fold_mul_one") (param $x f32) (result f32) (f32.mul (get_local $x) (f32.const 1.0))) - (export "f32.no_fold_mul_one" $f32.no_fold_mul_one) - - (func $f64.no_fold_mul_one (param $x f64) (result f64) + (func (export "f64.no_fold_mul_one") (param $x f64) (result f64) (f64.mul (get_local $x) (f64.const 1.0))) - (export "f64.no_fold_mul_one" $f64.no_fold_mul_one) ) (assert_return (invoke "f32.no_fold_mul_one" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -128,13 +109,10 @@ ;; Test that 0.0/x is not folded to 0.0. (module - (func $f32.no_fold_zero_div (param $x f32) (result f32) + (func (export "f32.no_fold_zero_div") (param $x f32) (result f32) (f32.div (f32.const 0.0) (get_local $x))) - (export "f32.no_fold_zero_div" $f32.no_fold_zero_div) - - (func $f64.no_fold_zero_div (param $x f64) (result f64) + (func (export "f64.no_fold_zero_div") (param $x f64) (result f64) (f64.div (f64.const 0.0) (get_local $x))) - (export "f64.no_fold_zero_div" $f64.no_fold_zero_div) ) (assert_return_nan (invoke "f32.no_fold_zero_div" (f32.const 0.0))) @@ -149,13 +127,10 @@ ;; Test that x/1.0 is not folded to x. (module - (func $f32.no_fold_div_one (param $x f32) (result f32) + (func (export "f32.no_fold_div_one") (param $x f32) (result f32) (f32.div (get_local $x) (f32.const 1.0))) - (export "f32.no_fold_div_one" $f32.no_fold_div_one) - - (func $f64.no_fold_div_one (param $x f64) (result f64) + (func (export "f64.no_fold_div_one") (param $x f64) (result f64) (f64.div (get_local $x) (f64.const 1.0))) - (export "f64.no_fold_div_one" $f64.no_fold_div_one) ) (assert_return (invoke "f32.no_fold_div_one" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -164,13 +139,10 @@ ;; Test that x/-1.0 is not folded to -x. (module - (func $f32.no_fold_div_neg1 (param $x f32) (result f32) + (func (export "f32.no_fold_div_neg1") (param $x f32) (result f32) (f32.div (get_local $x) (f32.const -1.0))) - (export "f32.no_fold_div_neg1" $f32.no_fold_div_neg1) - - (func $f64.no_fold_div_neg1 (param $x f64) (result f64) + (func (export "f64.no_fold_div_neg1") (param $x f64) (result f64) (f64.div (get_local $x) (f64.const -1.0))) - (export "f64.no_fold_div_neg1" $f64.no_fold_div_neg1) ) (assert_return (invoke "f32.no_fold_div_neg1" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -179,13 +151,10 @@ ;; Test that -0.0 - x is not folded to -x. (module - (func $f32.no_fold_neg0_sub (param $x f32) (result f32) + (func (export "f32.no_fold_neg0_sub") (param $x f32) (result f32) (f32.sub (f32.const -0.0) (get_local $x))) - (export "f32.no_fold_neg0_sub" $f32.no_fold_neg0_sub) - - (func $f64.no_fold_neg0_sub (param $x f64) (result f64) + (func (export "f64.no_fold_neg0_sub") (param $x f64) (result f64) (f64.sub (f64.const -0.0) (get_local $x))) - (export "f64.no_fold_neg0_sub" $f64.no_fold_neg0_sub) ) (assert_return (invoke "f32.no_fold_neg0_sub" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -194,13 +163,10 @@ ;; Test that -1.0 * x is not folded to -x. (module - (func $f32.no_fold_neg1_mul (param $x f32) (result f32) + (func (export "f32.no_fold_neg1_mul") (param $x f32) (result f32) (f32.mul (f32.const -1.0) (get_local $x))) - (export "f32.no_fold_neg1_mul" $f32.no_fold_neg1_mul) - - (func $f64.no_fold_neg1_mul (param $x f64) (result f64) + (func (export "f64.no_fold_neg1_mul") (param $x f64) (result f64) (f64.mul (f64.const -1.0) (get_local $x))) - (export "f64.no_fold_neg1_mul" $f64.no_fold_neg1_mul) ) (assert_return (invoke "f32.no_fold_neg1_mul" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -209,13 +175,10 @@ ;; Test that x == x is not folded to true. (module - (func $f32.no_fold_eq_self (param $x f32) (result i32) + (func (export "f32.no_fold_eq_self") (param $x f32) (result i32) (f32.eq (get_local $x) (get_local $x))) - (export "f32.no_fold_eq_self" $f32.no_fold_eq_self) - - (func $f64.no_fold_eq_self (param $x f64) (result i32) + (func (export "f64.no_fold_eq_self") (param $x f64) (result i32) (f64.eq (get_local $x) (get_local $x))) - (export "f64.no_fold_eq_self" $f64.no_fold_eq_self) ) (assert_return (invoke "f32.no_fold_eq_self" (f32.const nan)) (i32.const 0)) @@ -224,13 +187,10 @@ ;; Test that x != x is not folded to false. (module - (func $f32.no_fold_ne_self (param $x f32) (result i32) + (func (export "f32.no_fold_ne_self") (param $x f32) (result i32) (f32.ne (get_local $x) (get_local $x))) - (export "f32.no_fold_ne_self" $f32.no_fold_ne_self) - - (func $f64.no_fold_ne_self (param $x f64) (result i32) + (func (export "f64.no_fold_ne_self") (param $x f64) (result i32) (f64.ne (get_local $x) (get_local $x))) - (export "f64.no_fold_ne_self" $f64.no_fold_ne_self) ) (assert_return (invoke "f32.no_fold_ne_self" (f32.const nan)) (i32.const 1)) @@ -239,13 +199,10 @@ ;; Test that x - x is not folded to 0.0. (module - (func $f32.no_fold_sub_self (param $x f32) (result f32) + (func (export "f32.no_fold_sub_self") (param $x f32) (result f32) (f32.sub (get_local $x) (get_local $x))) - (export "f32.no_fold_sub_self" $f32.no_fold_sub_self) - - (func $f64.no_fold_sub_self (param $x f64) (result f64) + (func (export "f64.no_fold_sub_self") (param $x f64) (result f64) (f64.sub (get_local $x) (get_local $x))) - (export "f64.no_fold_sub_self" $f64.no_fold_sub_self) ) (assert_return_nan (invoke "f32.no_fold_sub_self" (f32.const infinity))) @@ -256,13 +213,10 @@ ;; Test that x/3 is not folded to x*(1/3). (module - (func $f32.no_fold_div_3 (param $x f32) (result f32) + (func (export "f32.no_fold_div_3") (param $x f32) (result f32) (f32.div (get_local $x) (f32.const 3.0))) - (export "f32.no_fold_div_3" $f32.no_fold_div_3) - - (func $f64.no_fold_div_3 (param $x f64) (result f64) + (func (export "f64.no_fold_div_3") (param $x f64) (result f64) (f64.div (get_local $x) (f64.const 3.0))) - (export "f64.no_fold_div_3" $f64.no_fold_div_3) ) (assert_return (invoke "f32.no_fold_div_3" (f32.const -0x1.359c26p+50)) (f32.const -0x1.9cd032p+48)) @@ -279,13 +233,10 @@ ;; Test that (x*z)+(y*z) is not folded to (x+y)*z (module - (func $f32.no_factor (param $x f32) (param $y f32) (param $z f32) (result f32) + (func (export "f32.no_factor") (param $x f32) (param $y f32) (param $z f32) (result f32) (f32.add (f32.mul (get_local $x) (get_local $z)) (f32.mul (get_local $y) (get_local $z)))) - (export "f32.no_factor" $f32.no_factor) - - (func $f64.no_factor (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_factor") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.add (f64.mul (get_local $x) (get_local $z)) (f64.mul (get_local $y) (get_local $z)))) - (export "f64.no_factor" $f64.no_factor) ) (assert_return (invoke "f32.no_factor" (f32.const -0x1.4e2352p+40) (f32.const -0x1.842e2cp+49) (f32.const 0x1.eea602p+59)) (f32.const -0x1.77a7dp+109)) @@ -302,13 +253,10 @@ ;; Test that (x+y)*z is not folded to (x*z)+(y*z) (module - (func $f32.no_distribute (param $x f32) (param $y f32) (param $z f32) (result f32) + (func (export "f32.no_distribute") (param $x f32) (param $y f32) (param $z f32) (result f32) (f32.mul (f32.add (get_local $x) (get_local $y)) (get_local $z))) - (export "f32.no_distribute" $f32.no_distribute) - - (func $f64.no_distribute (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_distribute") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.mul (f64.add (get_local $x) (get_local $y)) (get_local $z))) - (export "f64.no_distribute" $f64.no_distribute) ) (assert_return (invoke "f32.no_distribute" (f32.const -0x1.4e2352p+40) (f32.const -0x1.842e2cp+49) (f32.const 0x1.eea602p+59)) (f32.const -0x1.77a7d2p+109)) @@ -325,13 +273,10 @@ ;; Test that x*(y/z) is not folded to (x*y)/z (module - (func $f32.no_regroup_div_mul (param $x f32) (param $y f32) (param $z f32) (result f32) + (func (export "f32.no_regroup_div_mul") (param $x f32) (param $y f32) (param $z f32) (result f32) (f32.mul (get_local $x) (f32.div (get_local $y) (get_local $z)))) - (export "f32.no_regroup_div_mul" $f32.no_regroup_div_mul) - - (func $f64.no_regroup_div_mul (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_regroup_div_mul") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.mul (get_local $x) (f64.div (get_local $y) (get_local $z)))) - (export "f64.no_regroup_div_mul" $f64.no_regroup_div_mul) ) (assert_return (invoke "f32.no_regroup_div_mul" (f32.const -0x1.2d14a6p-115) (f32.const -0x1.575a6cp-64) (f32.const 0x1.5cee0ep-116)) (f32.const 0x1.2844cap-63)) @@ -348,13 +293,10 @@ ;; Test that (x*y)/z is not folded to x*(y/z) (module - (func $f32.no_regroup_mul_div (param $x f32) (param $y f32) (param $z f32) (result f32) + (func (export "f32.no_regroup_mul_div") (param $x f32) (param $y f32) (param $z f32) (result f32) (f32.div (f32.mul (get_local $x) (get_local $y)) (get_local $z))) - (export "f32.no_regroup_mul_div" $f32.no_regroup_mul_div) - - (func $f64.no_regroup_mul_div (param $x f64) (param $y f64) (param $z f64) (result f64) + (func (export "f64.no_regroup_mul_div") (param $x f64) (param $y f64) (param $z f64) (result f64) (f64.div (f64.mul (get_local $x) (get_local $y)) (get_local $z))) - (export "f64.no_regroup_mul_div" $f64.no_regroup_mul_div) ) (assert_return (invoke "f32.no_regroup_mul_div" (f32.const -0x1.2d14a6p-115) (f32.const -0x1.575a6cp-64) (f32.const 0x1.5cee0ep-116)) (f32.const 0x0p+0)) @@ -371,13 +313,10 @@ ;; Test that x+y+z+w is not reassociated. (module - (func $f32.no_reassociate_add (param $x f32) (param $y f32) (param $z f32) (param $w f32) (result f32) + (func (export "f32.no_reassociate_add") (param $x f32) (param $y f32) (param $z f32) (param $w f32) (result f32) (f32.add (f32.add (f32.add (get_local $x) (get_local $y)) (get_local $z)) (get_local $w))) - (export "f32.no_reassociate_add" $f32.no_reassociate_add) - - (func $f64.no_reassociate_add (param $x f64) (param $y f64) (param $z f64) (param $w f64) (result f64) + (func (export "f64.no_reassociate_add") (param $x f64) (param $y f64) (param $z f64) (param $w f64) (result f64) (f64.add (f64.add (f64.add (get_local $x) (get_local $y)) (get_local $z)) (get_local $w))) - (export "f64.no_reassociate_add" $f64.no_reassociate_add) ) (assert_return (invoke "f32.no_reassociate_add" (f32.const -0x1.5f7ddcp+44) (f32.const 0x1.854e1p+34) (f32.const -0x1.b2068cp+47) (f32.const -0x1.209692p+41)) (f32.const -0x1.e26c76p+47)) @@ -394,13 +333,10 @@ ;; Test that x*y*z*w is not reassociated. (module - (func $f32.no_reassociate_mul (param $x f32) (param $y f32) (param $z f32) (param $w f32) (result f32) + (func (export "f32.no_reassociate_mul") (param $x f32) (param $y f32) (param $z f32) (param $w f32) (result f32) (f32.mul (f32.mul (f32.mul (get_local $x) (get_local $y)) (get_local $z)) (get_local $w))) - (export "f32.no_reassociate_mul" $f32.no_reassociate_mul) - - (func $f64.no_reassociate_mul (param $x f64) (param $y f64) (param $z f64) (param $w f64) (result f64) + (func (export "f64.no_reassociate_mul") (param $x f64) (param $y f64) (param $z f64) (param $w f64) (result f64) (f64.mul (f64.mul (f64.mul (get_local $x) (get_local $y)) (get_local $z)) (get_local $w))) - (export "f64.no_reassociate_mul" $f64.no_reassociate_mul) ) (assert_return (invoke "f32.no_reassociate_mul" (f32.const 0x1.950ba8p-116) (f32.const 0x1.efdacep-33) (f32.const -0x1.5f9bcp+102) (f32.const 0x1.f04508p-56)) (f32.const -0x1.ff356ep-101)) @@ -417,13 +353,10 @@ ;; Test that x/0 is not folded away. (module - (func $f32.no_fold_div_0 (param $x f32) (result f32) + (func (export "f32.no_fold_div_0") (param $x f32) (result f32) (f32.div (get_local $x) (f32.const 0.0))) - (export "f32.no_fold_div_0" $f32.no_fold_div_0) - - (func $f64.no_fold_div_0 (param $x f64) (result f64) + (func (export "f64.no_fold_div_0") (param $x f64) (result f64) (f64.div (get_local $x) (f64.const 0.0))) - (export "f64.no_fold_div_0" $f64.no_fold_div_0) ) (assert_return (invoke "f32.no_fold_div_0" (f32.const 1.0)) (f32.const infinity)) @@ -446,13 +379,10 @@ ;; Test that x/-0 is not folded away. (module - (func $f32.no_fold_div_neg0 (param $x f32) (result f32) + (func (export "f32.no_fold_div_neg0") (param $x f32) (result f32) (f32.div (get_local $x) (f32.const -0.0))) - (export "f32.no_fold_div_neg0" $f32.no_fold_div_neg0) - - (func $f64.no_fold_div_neg0 (param $x f64) (result f64) + (func (export "f64.no_fold_div_neg0") (param $x f64) (result f64) (f64.div (get_local $x) (f64.const -0.0))) - (export "f64.no_fold_div_neg0" $f64.no_fold_div_neg0) ) (assert_return (invoke "f32.no_fold_div_neg0" (f32.const 1.0)) (f32.const -infinity)) @@ -475,15 +405,12 @@ ;; Test that sqrt(x*x+y*y) is not folded to hypot. (module - (func $f32.no_fold_to_hypot (param $x f32) (param $y f32) (result f32) + (func (export "f32.no_fold_to_hypot") (param $x f32) (param $y f32) (result f32) (f32.sqrt (f32.add (f32.mul (get_local $x) (get_local $x)) (f32.mul (get_local $y) (get_local $y))))) - (export "f32.no_fold_to_hypot" $f32.no_fold_to_hypot) - - (func $f64.no_fold_to_hypot (param $x f64) (param $y f64) (result f64) + (func (export "f64.no_fold_to_hypot") (param $x f64) (param $y f64) (result f64) (f64.sqrt (f64.add (f64.mul (get_local $x) (get_local $x)) (f64.mul (get_local $y) (get_local $y))))) - (export "f64.no_fold_to_hypot" $f64.no_fold_to_hypot) ) (assert_return (invoke "f32.no_fold_to_hypot" (f32.const 0x1.c2f338p-81) (f32.const 0x1.401b5ep-68)) (f32.const 0x1.401cccp-68)) @@ -500,9 +427,8 @@ ;; Test that 1.0/x isn't approximated. (module - (func $f32.no_approximate_reciprocal (param $x f32) (result f32) + (func (export "f32.no_approximate_reciprocal") (param $x f32) (result f32) (f32.div (f32.const 1.0) (get_local $x))) - (export "f32.no_approximate_reciprocal" $f32.no_approximate_reciprocal) ) (assert_return (invoke "f32.no_approximate_reciprocal" (f32.const -0x1.2900b6p-10)) (f32.const -0x1.b950d4p+9)) @@ -514,13 +440,10 @@ ;; Test that 1.0/sqrt(x) isn't approximated or fused. (module - (func $f32.no_approximate_reciprocal_sqrt (param $x f32) (result f32) + (func (export "f32.no_approximate_reciprocal_sqrt") (param $x f32) (result f32) (f32.div (f32.const 1.0) (f32.sqrt (get_local $x)))) - (export "f32.no_approximate_reciprocal_sqrt" $f32.no_approximate_reciprocal_sqrt) - - (func $f64.no_fuse_reciprocal_sqrt (param $x f64) (result f64) + (func (export "f64.no_fuse_reciprocal_sqrt") (param $x f64) (result f64) (f64.div (f64.const 1.0) (f64.sqrt (get_local $x)))) - (export "f64.no_fuse_reciprocal_sqrt" $f64.no_fuse_reciprocal_sqrt) ) (assert_return (invoke "f32.no_approximate_reciprocal_sqrt" (f32.const 0x1.6af12ap-43)) (f32.const 0x1.300ed4p+21)) @@ -538,9 +461,8 @@ ;; Test that sqrt(1.0/x) isn't approximated. (module - (func $f32.no_approximate_sqrt_reciprocal (param $x f32) (result f32) + (func (export "f32.no_approximate_sqrt_reciprocal") (param $x f32) (result f32) (f32.sqrt (f32.div (f32.const 1.0) (get_local $x)))) - (export "f32.no_approximate_sqrt_reciprocal" $f32.no_approximate_sqrt_reciprocal) ) (assert_return (invoke "f32.no_approximate_sqrt_reciprocal" (f32.const 0x1.a4c986p+60)) (f32.const 0x1.8f5ac6p-31)) @@ -552,21 +474,14 @@ ;; Test that converting i32/i64 to f32/f64 and back isn't folded away (module - (func $i32.no_fold_f32_s (param i32) (result i32) + (func (export "i32.no_fold_f32_s") (param i32) (result i32) (i32.trunc_s/f32 (f32.convert_s/i32 (get_local 0)))) - (export "i32.no_fold_f32_s" $i32.no_fold_f32_s) - - (func $i32.no_fold_f32_u (param i32) (result i32) + (func (export "i32.no_fold_f32_u") (param i32) (result i32) (i32.trunc_u/f32 (f32.convert_u/i32 (get_local 0)))) - (export "i32.no_fold_f32_u" $i32.no_fold_f32_u) - - (func $i64.no_fold_f64_s (param i64) (result i64) + (func (export "i64.no_fold_f64_s") (param i64) (result i64) (i64.trunc_s/f64 (f64.convert_s/i64 (get_local 0)))) - (export "i64.no_fold_f64_s" $i64.no_fold_f64_s) - - (func $i64.no_fold_f64_u (param i64) (result i64) + (func (export "i64.no_fold_f64_u") (param i64) (result i64) (i64.trunc_u/f64 (f64.convert_u/i64 (get_local 0)))) - (export "i64.no_fold_f64_u" $i64.no_fold_f64_u) ) (assert_return (invoke "i32.no_fold_f32_s" (i32.const 0x1000000)) (i32.const 0x1000000)) @@ -588,13 +503,10 @@ ;; Test that x+y-y is not folded to x. (module - (func $f32.no_fold_add_sub (param $x f32) (param $y f32) (result f32) + (func (export "f32.no_fold_add_sub") (param $x f32) (param $y f32) (result f32) (f32.sub (f32.add (get_local $x) (get_local $y)) (get_local $y))) - (export "f32.no_fold_add_sub" $f32.no_fold_add_sub) - - (func $f64.no_fold_add_sub (param $x f64) (param $y f64) (result f64) + (func (export "f64.no_fold_add_sub") (param $x f64) (param $y f64) (result f64) (f64.sub (f64.add (get_local $x) (get_local $y)) (get_local $y))) - (export "f64.no_fold_add_sub" $f64.no_fold_add_sub) ) (assert_return (invoke "f32.no_fold_add_sub" (f32.const 0x1.b553e4p-47) (f32.const -0x1.67db2cp-26)) (f32.const 0x1.cp-47)) @@ -612,13 +524,10 @@ ;; Test that x-y+y is not folded to x. (module - (func $f32.no_fold_sub_add (param $x f32) (param $y f32) (result f32) + (func (export "f32.no_fold_sub_add") (param $x f32) (param $y f32) (result f32) (f32.add (f32.sub (get_local $x) (get_local $y)) (get_local $y))) - (export "f32.no_fold_sub_add" $f32.no_fold_sub_add) - - (func $f64.no_fold_sub_add (param $x f64) (param $y f64) (result f64) + (func (export "f64.no_fold_sub_add") (param $x f64) (param $y f64) (result f64) (f64.add (f64.sub (get_local $x) (get_local $y)) (get_local $y))) - (export "f64.no_fold_sub_add" $f64.no_fold_sub_add) ) (assert_return (invoke "f32.no_fold_sub_add" (f32.const -0x1.523cb8p+9) (f32.const 0x1.93096cp+8)) (f32.const -0x1.523cbap+9)) @@ -636,13 +545,10 @@ ;; Test that x*y/y is not folded to x. (module - (func $f32.no_fold_mul_div (param $x f32) (param $y f32) (result f32) + (func (export "f32.no_fold_mul_div") (param $x f32) (param $y f32) (result f32) (f32.div (f32.mul (get_local $x) (get_local $y)) (get_local $y))) - (export "f32.no_fold_mul_div" $f32.no_fold_mul_div) - - (func $f64.no_fold_mul_div (param $x f64) (param $y f64) (result f64) + (func (export "f64.no_fold_mul_div") (param $x f64) (param $y f64) (result f64) (f64.div (f64.mul (get_local $x) (get_local $y)) (get_local $y))) - (export "f64.no_fold_mul_div" $f64.no_fold_mul_div) ) (assert_return (invoke "f32.no_fold_mul_div" (f32.const -0x1.cd859ap+54) (f32.const 0x1.6ca936p-47)) (f32.const -0x1.cd8598p+54)) @@ -660,13 +566,10 @@ ;; Test that x/y*y is not folded to x. (module - (func $f32.no_fold_div_mul (param $x f32) (param $y f32) (result f32) + (func (export "f32.no_fold_div_mul") (param $x f32) (param $y f32) (result f32) (f32.mul (f32.div (get_local $x) (get_local $y)) (get_local $y))) - (export "f32.no_fold_div_mul" $f32.no_fold_div_mul) - - (func $f64.no_fold_div_mul (param $x f64) (param $y f64) (result f64) + (func (export "f64.no_fold_div_mul") (param $x f64) (param $y f64) (result f64) (f64.mul (f64.div (get_local $x) (get_local $y)) (get_local $y))) - (export "f64.no_fold_div_mul" $f64.no_fold_div_mul) ) (assert_return (invoke "f32.no_fold_div_mul" (f32.const -0x1.dc6364p+38) (f32.const 0x1.d630ecp+29)) (f32.const -0x1.dc6362p+38)) @@ -684,9 +587,8 @@ ;; Test that promote(demote(x)) is not folded to x. (module - (func $no_fold_demote_promote (param $x f64) (result f64) + (func (export "no_fold_demote_promote") (param $x f64) (result f64) (f64.promote/f32 (f32.demote/f64 (get_local $x)))) - (export "no_fold_demote_promote" $no_fold_demote_promote) ) (assert_return (invoke "no_fold_demote_promote" (f64.const -0x1.dece272390f5dp-133)) (f64.const -0x1.decep-133)) @@ -699,9 +601,8 @@ ;; bit-preserving. (module - (func $no_fold_promote_demote (param $x f32) (result f32) + (func (export "no_fold_promote_demote") (param $x f32) (result f32) (f32.demote/f64 (f64.promote/f32 (get_local $x)))) - (export "no_fold_promote_demote" $no_fold_promote_demote) ) (assert_return (invoke "no_fold_promote_demote" (f32.const nan:0x200000)) (f32.const nan:0x600000)) @@ -721,13 +622,10 @@ ;; Test that demote(x+promote(y)) is not folded to demote(x)+y. (module - (func $no_demote_mixed_add (param $x f64) (param $y f32) (result f32) + (func (export "no_demote_mixed_add") (param $x f64) (param $y f32) (result f32) (f32.demote/f64 (f64.add (get_local $x) (f64.promote/f32 (get_local $y))))) - (export "no_demote_mixed_add" $no_demote_mixed_add) - - (func $no_demote_mixed_add_commuted (param $y f32) (param $x f64) (result f32) + (func (export "no_demote_mixed_add_commuted") (param $y f32) (param $x f64) (result f32) (f32.demote/f64 (f64.add (f64.promote/f32 (get_local $y)) (get_local $x)))) - (export "no_demote_mixed_add_commuted" $no_demote_mixed_add_commuted) ) (assert_return (invoke "no_demote_mixed_add" (f64.const 0x1.f51a9d04854f9p-95) (f32.const 0x1.3f4e9cp-119)) (f32.const 0x1.f51a9ep-95)) @@ -745,9 +643,8 @@ ;; Test that demote(x-promote(y)) is not folded to demote(x)-y. (module - (func $no_demote_mixed_sub (param $x f64) (param $y f32) (result f32) + (func (export "no_demote_mixed_sub") (param $x f64) (param $y f32) (result f32) (f32.demote/f64 (f64.sub (get_local $x) (f64.promote/f32 (get_local $y))))) - (export "no_demote_mixed_sub" $no_demote_mixed_sub) ) (assert_return (invoke "no_demote_mixed_sub" (f64.const 0x1.a0a183220e9b1p+82) (f32.const 0x1.c5acf8p+61)) (f32.const 0x1.a0a174p+82)) @@ -759,69 +656,38 @@ ;; Test that converting between integer and float and back isn't folded away. (module - (func $f32.i32.no_fold_trunc_s_convert_s (param $x f32) (result f32) + (func (export "f32.i32.no_fold_trunc_s_convert_s") (param $x f32) (result f32) (f32.convert_s/i32 (i32.trunc_s/f32 (get_local $x)))) - (export "f32.i32.no_fold_trunc_s_convert_s" $f32.i32.no_fold_trunc_s_convert_s) - - (func $f32.i32.no_fold_trunc_u_convert_s (param $x f32) (result f32) + (func (export "f32.i32.no_fold_trunc_u_convert_s") (param $x f32) (result f32) (f32.convert_s/i32 (i32.trunc_u/f32 (get_local $x)))) - (export "f32.i32.no_fold_trunc_u_convert_s" $f32.i32.no_fold_trunc_u_convert_s) - - (func $f32.i32.no_fold_trunc_s_convert_u (param $x f32) (result f32) + (func (export "f32.i32.no_fold_trunc_s_convert_u") (param $x f32) (result f32) (f32.convert_u/i32 (i32.trunc_s/f32 (get_local $x)))) - (export "f32.i32.no_fold_trunc_s_convert_u" $f32.i32.no_fold_trunc_s_convert_u) - - (func $f32.i32.no_fold_trunc_u_convert_u (param $x f32) (result f32) + (func (export "f32.i32.no_fold_trunc_u_convert_u") (param $x f32) (result f32) (f32.convert_u/i32 (i32.trunc_u/f32 (get_local $x)))) - (export "f32.i32.no_fold_trunc_u_convert_u" $f32.i32.no_fold_trunc_u_convert_u) - - (func $f64.i32.no_fold_trunc_s_convert_s (param $x f64) (result f64) + (func (export "f64.i32.no_fold_trunc_s_convert_s") (param $x f64) (result f64) (f64.convert_s/i32 (i32.trunc_s/f64 (get_local $x)))) - (export "f64.i32.no_fold_trunc_s_convert_s" $f64.i32.no_fold_trunc_s_convert_s) - - (func $f64.i32.no_fold_trunc_u_convert_s (param $x f64) (result f64) + (func (export "f64.i32.no_fold_trunc_u_convert_s") (param $x f64) (result f64) (f64.convert_s/i32 (i32.trunc_u/f64 (get_local $x)))) - (export "f64.i32.no_fold_trunc_u_convert_s" $f64.i32.no_fold_trunc_u_convert_s) - - (func $f64.i32.no_fold_trunc_s_convert_u (param $x f64) (result f64) + (func (export "f64.i32.no_fold_trunc_s_convert_u") (param $x f64) (result f64) (f64.convert_u/i32 (i32.trunc_s/f64 (get_local $x)))) - (export "f64.i32.no_fold_trunc_s_convert_u" $f64.i32.no_fold_trunc_s_convert_u) - - (func $f64.i32.no_fold_trunc_u_convert_u (param $x f64) (result f64) + (func (export "f64.i32.no_fold_trunc_u_convert_u") (param $x f64) (result f64) (f64.convert_u/i32 (i32.trunc_u/f64 (get_local $x)))) - (export "f64.i32.no_fold_trunc_u_convert_u" $f64.i32.no_fold_trunc_u_convert_u) - - (func $f32.i64.no_fold_trunc_s_convert_s (param $x f32) (result f32) + (func (export "f32.i64.no_fold_trunc_s_convert_s") (param $x f32) (result f32) (f32.convert_s/i64 (i64.trunc_s/f32 (get_local $x)))) - (export "f32.i64.no_fold_trunc_s_convert_s" $f32.i64.no_fold_trunc_s_convert_s) - - (func $f32.i64.no_fold_trunc_u_convert_s (param $x f32) (result f32) + (func (export "f32.i64.no_fold_trunc_u_convert_s") (param $x f32) (result f32) (f32.convert_s/i64 (i64.trunc_u/f32 (get_local $x)))) - (export "f32.i64.no_fold_trunc_u_convert_s" $f32.i64.no_fold_trunc_u_convert_s) - - (func $f32.i64.no_fold_trunc_s_convert_u (param $x f32) (result f32) + (func (export "f32.i64.no_fold_trunc_s_convert_u") (param $x f32) (result f32) (f32.convert_u/i64 (i64.trunc_s/f32 (get_local $x)))) - (export "f32.i64.no_fold_trunc_s_convert_u" $f32.i64.no_fold_trunc_s_convert_u) - - (func $f32.i64.no_fold_trunc_u_convert_u (param $x f32) (result f32) + (func (export "f32.i64.no_fold_trunc_u_convert_u") (param $x f32) (result f32) (f32.convert_u/i64 (i64.trunc_u/f32 (get_local $x)))) - (export "f32.i64.no_fold_trunc_u_convert_u" $f32.i64.no_fold_trunc_u_convert_u) - - (func $f64.i64.no_fold_trunc_s_convert_s (param $x f64) (result f64) + (func (export "f64.i64.no_fold_trunc_s_convert_s") (param $x f64) (result f64) (f64.convert_s/i64 (i64.trunc_s/f64 (get_local $x)))) - (export "f64.i64.no_fold_trunc_s_convert_s" $f64.i64.no_fold_trunc_s_convert_s) - - (func $f64.i64.no_fold_trunc_u_convert_s (param $x f64) (result f64) + (func (export "f64.i64.no_fold_trunc_u_convert_s") (param $x f64) (result f64) (f64.convert_s/i64 (i64.trunc_u/f64 (get_local $x)))) - (export "f64.i64.no_fold_trunc_u_convert_s" $f64.i64.no_fold_trunc_u_convert_s) - - (func $f64.i64.no_fold_trunc_s_convert_u (param $x f64) (result f64) + (func (export "f64.i64.no_fold_trunc_s_convert_u") (param $x f64) (result f64) (f64.convert_u/i64 (i64.trunc_s/f64 (get_local $x)))) - (export "f64.i64.no_fold_trunc_s_convert_u" $f64.i64.no_fold_trunc_s_convert_u) - - (func $f64.i64.no_fold_trunc_u_convert_u (param $x f64) (result f64) + (func (export "f64.i64.no_fold_trunc_u_convert_u") (param $x f64) (result f64) (f64.convert_u/i64 (i64.trunc_u/f64 (get_local $x)))) - (export "f64.i64.no_fold_trunc_u_convert_u" $f64.i64.no_fold_trunc_u_convert_u) ) (assert_return (invoke "f32.i32.no_fold_trunc_s_convert_s" (f32.const 1.5)) (f32.const 1.0)) @@ -866,10 +732,9 @@ (module (memory 1 1) - (func $init (param $i i32) (param $x f32) (f32.store (get_local $i) (get_local $x))) - (export "init" $init) + (func (export "init") (param $i i32) (param $x f32) (f32.store (get_local $i) (get_local $x))) - (func $run (param $n i32) (param $z f32) + (func (export "run") (param $n i32) (param $z f32) (local $i i32) (loop $exit $cont (f32.store (get_local $i) (f32.div (f32.load (get_local $i)) (get_local $z))) @@ -877,10 +742,8 @@ (br_if $cont (i32.lt_u (get_local $i) (get_local $n))) ) ) - (export "run" $run) - (func $check (param $i i32) (result f32) (f32.load (get_local $i))) - (export "check" $check) + (func (export "check") (param $i i32) (result f32) (f32.load (get_local $i))) ) (invoke "init" (i32.const 0) (f32.const 15.1)) @@ -899,10 +762,9 @@ (module (memory 1 1) - (func $init (param $i i32) (param $x f64) (f64.store (get_local $i) (get_local $x))) - (export "init" $init) + (func (export "init") (param $i i32) (param $x f64) (f64.store (get_local $i) (get_local $x))) - (func $run (param $n i32) (param $z f64) + (func (export "run") (param $n i32) (param $z f64) (local $i i32) (loop $exit $cont (f64.store (get_local $i) (f64.div (f64.load (get_local $i)) (get_local $z))) @@ -910,10 +772,8 @@ (br_if $cont (i32.lt_u (get_local $i) (get_local $n))) ) ) - (export "run" $run) - (func $check (param $i i32) (result f64) (f64.load (get_local $i))) - (export "check" $check) + (func (export "check") (param $i i32) (result f64) (f64.load (get_local $i))) ) (invoke "init" (i32.const 0) (f64.const 15.1)) @@ -933,24 +793,15 @@ ;; Test that ult/ugt/etc. aren't folded to olt/ogt/etc. (module - (func $f32.ult (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.ge (get_local $x) (get_local $y)))) - (func $f32.ule (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.gt (get_local $x) (get_local $y)))) - (func $f32.ugt (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.le (get_local $x) (get_local $y)))) - (func $f32.uge (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.lt (get_local $x) (get_local $y)))) - - (func $f64.ult (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.ge (get_local $x) (get_local $y)))) - (func $f64.ule (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.gt (get_local $x) (get_local $y)))) - (func $f64.ugt (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.le (get_local $x) (get_local $y)))) - (func $f64.uge (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.lt (get_local $x) (get_local $y)))) + (func (export "f32.ult") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.ge (get_local $x) (get_local $y)))) + (func (export "f32.ule") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.gt (get_local $x) (get_local $y)))) + (func (export "f32.ugt") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.le (get_local $x) (get_local $y)))) + (func (export "f32.uge") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.lt (get_local $x) (get_local $y)))) - (export "f32.ult" $f32.ult) - (export "f32.ule" $f32.ule) - (export "f32.ugt" $f32.ugt) - (export "f32.uge" $f32.uge) - (export "f64.ult" $f64.ult) - (export "f64.ule" $f64.ule) - (export "f64.ugt" $f64.ugt) - (export "f64.uge" $f64.uge) + (func (export "f64.ult") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.ge (get_local $x) (get_local $y)))) + (func (export "f64.ule") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.gt (get_local $x) (get_local $y)))) + (func (export "f64.ugt") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.le (get_local $x) (get_local $y)))) + (func (export "f64.uge") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.lt (get_local $x) (get_local $y)))) ) (assert_return (invoke "f32.ult" (f32.const 3.0) (f32.const 2.0)) (i32.const 0)) @@ -989,23 +840,15 @@ ;; Test that x= y and friends. (module - (func $f32.not_lt (param $x f32) (param $y f32) (result i32) + (func (export "f32.not_lt") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.lt (get_local $x) (get_local $y)))) - (export "f32.not_lt" $f32.not_lt) - (func $f32.not_le (param $x f32) (param $y f32) (result i32) + (func (export "f32.not_le") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.le (get_local $x) (get_local $y)))) - (export "f32.not_le" $f32.not_le) - (func $f32.not_gt (param $x f32) (param $y f32) (result i32) + (func (export "f32.not_gt") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.gt (get_local $x) (get_local $y)))) - (export "f32.not_gt" $f32.not_gt) - (func $f32.not_ge (param $x f32) (param $y f32) (result i32) + (func (export "f32.not_ge") (param $x f32) (param $y f32) (result i32) (i32.eqz (f32.ge (get_local $x) (get_local $y)))) - (export "f32.not_ge" $f32.not_ge) - (func $f64.not_lt (param $x f64) (param $y f64) (result i32) + (func (export "f64.not_lt") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.lt (get_local $x) (get_local $y)))) - (export "f64.not_lt" $f64.not_lt) - (func $f64.not_le (param $x f64) (param $y f64) (result i32) + (func (export "f64.not_le") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.le (get_local $x) (get_local $y)))) - (export "f64.not_le" $f64.not_le) - (func $f64.not_gt (param $x f64) (param $y f64) (result i32) + (func (export "f64.not_gt") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.gt (get_local $x) (get_local $y)))) - (export "f64.not_gt" $f64.not_gt) - (func $f64.not_ge (param $x f64) (param $y f64) (result i32) + (func (export "f64.not_ge") (param $x f64) (param $y f64) (result i32) (i32.eqz (f64.ge (get_local $x) (get_local $y)))) - (export "f64.not_ge" $f64.not_ge) ) (assert_return (invoke "f32.not_lt" (f32.const nan) (f32.const 0.0)) (i32.const 1)) @@ -2151,13 +1888,11 @@ ;; http://blogs.mathworks.com/cleve/2014/07/07/floating-point-numbers/#24cb4f4d-b8a9-4c19-b22b-9d2a9f7f3812 (module - (func $f32.epsilon (result f32) + (func (export "f32.epsilon") (result f32) (f32.sub (f32.const 1.0) (f32.mul (f32.const 3.0) (f32.sub (f32.div (f32.const 4.0) (f32.const 3.0)) (f32.const 1.0))))) - (export "f32.epsilon" $f32.epsilon) - (func $f64.epsilon (result f64) + (func (export "f64.epsilon") (result f64) (f64.sub (f64.const 1.0) (f64.mul (f64.const 3.0) (f64.sub (f64.div (f64.const 4.0) (f64.const 3.0)) (f64.const 1.0))))) - (export "f64.epsilon" $f64.epsilon) ) (assert_return (invoke "f32.epsilon") (f32.const -0x1p-23)) @@ -2167,31 +1902,23 @@ ;; trichotomy. (module - (func $f32.no_trichotomy_lt (param $x f32) (param $y f32) (result i32) + (func (export "f32.no_trichotomy_lt") (param $x f32) (param $y f32) (result i32) (i32.or (f32.lt (get_local $x) (get_local $y)) (f32.ge (get_local $x) (get_local $y)))) - (export "f32.no_trichotomy_lt" $f32.no_trichotomy_lt) - (func $f32.no_trichotomy_le (param $x f32) (param $y f32) (result i32) + (func (export "f32.no_trichotomy_le") (param $x f32) (param $y f32) (result i32) (i32.or (f32.le (get_local $x) (get_local $y)) (f32.gt (get_local $x) (get_local $y)))) - (export "f32.no_trichotomy_le" $f32.no_trichotomy_le) - (func $f32.no_trichotomy_gt (param $x f32) (param $y f32) (result i32) + (func (export "f32.no_trichotomy_gt") (param $x f32) (param $y f32) (result i32) (i32.or (f32.gt (get_local $x) (get_local $y)) (f32.le (get_local $x) (get_local $y)))) - (export "f32.no_trichotomy_gt" $f32.no_trichotomy_gt) - (func $f32.no_trichotomy_ge (param $x f32) (param $y f32) (result i32) + (func (export "f32.no_trichotomy_ge") (param $x f32) (param $y f32) (result i32) (i32.or (f32.ge (get_local $x) (get_local $y)) (f32.lt (get_local $x) (get_local $y)))) - (export "f32.no_trichotomy_ge" $f32.no_trichotomy_ge) - (func $f64.no_trichotomy_lt (param $x f64) (param $y f64) (result i32) + (func (export "f64.no_trichotomy_lt") (param $x f64) (param $y f64) (result i32) (i32.or (f64.lt (get_local $x) (get_local $y)) (f64.ge (get_local $x) (get_local $y)))) - (export "f64.no_trichotomy_lt" $f64.no_trichotomy_lt) - (func $f64.no_trichotomy_le (param $x f64) (param $y f64) (result i32) + (func (export "f64.no_trichotomy_le") (param $x f64) (param $y f64) (result i32) (i32.or (f64.le (get_local $x) (get_local $y)) (f64.gt (get_local $x) (get_local $y)))) - (export "f64.no_trichotomy_le" $f64.no_trichotomy_le) - (func $f64.no_trichotomy_gt (param $x f64) (param $y f64) (result i32) + (func (export "f64.no_trichotomy_gt") (param $x f64) (param $y f64) (result i32) (i32.or (f64.gt (get_local $x) (get_local $y)) (f64.le (get_local $x) (get_local $y)))) - (export "f64.no_trichotomy_gt" $f64.no_trichotomy_gt) - (func $f64.no_trichotomy_ge (param $x f64) (param $y f64) (result i32) + (func (export "f64.no_trichotomy_ge") (param $x f64) (param $y f64) (result i32) (i32.or (f64.ge (get_local $x) (get_local $y)) (f64.lt (get_local $x) (get_local $y)))) - (export "f64.no_trichotomy_ge" $f64.no_trichotomy_ge) ) (assert_return (invoke "f32.no_trichotomy_lt" (f32.const 0.0) (f32.const nan)) (i32.const 0)) diff --git a/ml-proto/test/float_literals.wast b/ml-proto/test/float_literals.wast index 8c95e35b6f..c69d81fb7d 100644 --- a/ml-proto/test/float_literals.wast +++ b/ml-proto/test/float_literals.wast @@ -2,138 +2,76 @@ (module ;; f32 special values - (func $f32.nan (result i32) (i32.reinterpret/f32 (f32.const nan))) - (func $f32.positive_nan (result i32) (i32.reinterpret/f32 (f32.const +nan))) - (func $f32.negative_nan (result i32) (i32.reinterpret/f32 (f32.const -nan))) - (func $f32.plain_nan (result i32) (i32.reinterpret/f32 (f32.const nan:0x400000))) - (func $f32.informally_known_as_plain_snan (result i32) (i32.reinterpret/f32 (f32.const nan:0x200000))) - (func $f32.allones_nan (result i32) (i32.reinterpret/f32 (f32.const -nan:0x7fffff))) - (func $f32.misc_nan (result i32) (i32.reinterpret/f32 (f32.const nan:0x012345))) - (func $f32.misc_positive_nan (result i32) (i32.reinterpret/f32 (f32.const +nan:0x304050))) - (func $f32.misc_negative_nan (result i32) (i32.reinterpret/f32 (f32.const -nan:0x2abcde))) - (func $f32.infinity (result i32) (i32.reinterpret/f32 (f32.const infinity))) - (func $f32.positive_infinity (result i32) (i32.reinterpret/f32 (f32.const +infinity))) - (func $f32.negative_infinity (result i32) (i32.reinterpret/f32 (f32.const -infinity))) + (func (export "f32.nan") (result i32) (i32.reinterpret/f32 (f32.const nan))) + (func (export "f32.positive_nan") (result i32) (i32.reinterpret/f32 (f32.const +nan))) + (func (export "f32.negative_nan") (result i32) (i32.reinterpret/f32 (f32.const -nan))) + (func (export "f32.plain_nan") (result i32) (i32.reinterpret/f32 (f32.const nan:0x400000))) + (func (export "f32.informally_known_as_plain_snan") (result i32) (i32.reinterpret/f32 (f32.const nan:0x200000))) + (func (export "f32.all_ones_nan") (result i32) (i32.reinterpret/f32 (f32.const -nan:0x7fffff))) + (func (export "f32.misc_nan") (result i32) (i32.reinterpret/f32 (f32.const nan:0x012345))) + (func (export "f32.misc_positive_nan") (result i32) (i32.reinterpret/f32 (f32.const +nan:0x304050))) + (func (export "f32.misc_negative_nan") (result i32) (i32.reinterpret/f32 (f32.const -nan:0x2abcde))) + (func (export "f32.infinity") (result i32) (i32.reinterpret/f32 (f32.const infinity))) + (func (export "f32.positive_infinity") (result i32) (i32.reinterpret/f32 (f32.const +infinity))) + (func (export "f32.negative_infinity") (result i32) (i32.reinterpret/f32 (f32.const -infinity))) ;; f32 numbers - (func $f32.zero (result i32) (i32.reinterpret/f32 (f32.const 0x0.0p0))) - (func $f32.positive_zero (result i32) (i32.reinterpret/f32 (f32.const +0x0.0p0))) - (func $f32.negative_zero (result i32) (i32.reinterpret/f32 (f32.const -0x0.0p0))) - (func $f32.misc (result i32) (i32.reinterpret/f32 (f32.const 0x1.921fb6p+2))) - (func $f32.min_positive (result i32) (i32.reinterpret/f32 (f32.const 0x1p-149))) - (func $f32.min_normal (result i32) (i32.reinterpret/f32 (f32.const 0x1p-126))) - (func $f32.max_finite (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffep+127))) - (func $f32.max_subnormal (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffcp-127))) - (func $f32.trailing_dot (result i32) (i32.reinterpret/f32 (f32.const 0x1.p10))) + (func (export "f32.zero") (result i32) (i32.reinterpret/f32 (f32.const 0x0.0p0))) + (func (export "f32.positive_zero") (result i32) (i32.reinterpret/f32 (f32.const +0x0.0p0))) + (func (export "f32.negative_zero") (result i32) (i32.reinterpret/f32 (f32.const -0x0.0p0))) + (func (export "f32.misc") (result i32) (i32.reinterpret/f32 (f32.const 0x1.921fb6p+2))) + (func (export "f32.min_positive") (result i32) (i32.reinterpret/f32 (f32.const 0x1p-149))) + (func (export "f32.min_normal") (result i32) (i32.reinterpret/f32 (f32.const 0x1p-126))) + (func (export "f32.max_finite") (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffep+127))) + (func (export "f32.max_subnormal") (result i32) (i32.reinterpret/f32 (f32.const 0x1.fffffcp-127))) + (func (export "f32.trailing_dot") (result i32) (i32.reinterpret/f32 (f32.const 0x1.p10))) ;; f32 in decimal format - (func $f32_dec.zero (result i32) (i32.reinterpret/f32 (f32.const 0.0e0))) - (func $f32_dec.positive_zero (result i32) (i32.reinterpret/f32 (f32.const +0.0e0))) - (func $f32_dec.negative_zero (result i32) (i32.reinterpret/f32 (f32.const -0.0e0))) - (func $f32_dec.misc (result i32) (i32.reinterpret/f32 (f32.const 6.28318548202514648))) - (func $f32_dec.min_positive (result i32) (i32.reinterpret/f32 (f32.const 1.4013e-45))) - (func $f32_dec.min_normal (result i32) (i32.reinterpret/f32 (f32.const 1.1754944e-38))) - (func $f32_dec.max_subnormal (result i32) (i32.reinterpret/f32 (f32.const 1.1754942e-38))) - (func $f32_dec.max_finite (result i32) (i32.reinterpret/f32 (f32.const 3.4028234e+38))) - (func $f32_dec.trailing_dot (result i32) (i32.reinterpret/f32 (f32.const 1.e10))) + (func (export "f32_dec.zero") (result i32) (i32.reinterpret/f32 (f32.const 0.0e0))) + (func (export "f32_dec.positive_zero") (result i32) (i32.reinterpret/f32 (f32.const +0.0e0))) + (func (export "f32_dec.negative_zero") (result i32) (i32.reinterpret/f32 (f32.const -0.0e0))) + (func (export "f32_dec.misc") (result i32) (i32.reinterpret/f32 (f32.const 6.28318548202514648))) + (func (export "f32_dec.min_positive") (result i32) (i32.reinterpret/f32 (f32.const 1.4013e-45))) + (func (export "f32_dec.min_normal") (result i32) (i32.reinterpret/f32 (f32.const 1.1754944e-38))) + (func (export "f32_dec.max_subnormal") (result i32) (i32.reinterpret/f32 (f32.const 1.1754942e-38))) + (func (export "f32_dec.max_finite") (result i32) (i32.reinterpret/f32 (f32.const 3.4028234e+38))) + (func (export "f32_dec.trailing_dot") (result i32) (i32.reinterpret/f32 (f32.const 1.e10))) ;; f64 special values - (func $f64.nan (result i64) (i64.reinterpret/f64 (f64.const nan))) - (func $f64.positive_nan (result i64) (i64.reinterpret/f64 (f64.const +nan))) - (func $f64.negative_nan (result i64) (i64.reinterpret/f64 (f64.const -nan))) - (func $f64.plain_nan (result i64) (i64.reinterpret/f64 (f64.const nan:0x8000000000000))) - (func $f64.informally_known_as_plain_snan (result i64) (i64.reinterpret/f64 (f64.const nan:0x4000000000000))) - (func $f64.allones_nan (result i64) (i64.reinterpret/f64 (f64.const -nan:0xfffffffffffff))) - (func $f64.misc_nan (result i64) (i64.reinterpret/f64 (f64.const nan:0x0123456789abc))) - (func $f64.misc_positive_nan (result i64) (i64.reinterpret/f64 (f64.const +nan:0x3040506070809))) - (func $f64.misc_negative_nan (result i64) (i64.reinterpret/f64 (f64.const -nan:0x2abcdef012345))) - (func $f64.infinity (result i64) (i64.reinterpret/f64 (f64.const infinity))) - (func $f64.positive_infinity (result i64) (i64.reinterpret/f64 (f64.const +infinity))) - (func $f64.negative_infinity (result i64) (i64.reinterpret/f64 (f64.const -infinity))) + (func (export "f64.nan") (result i64) (i64.reinterpret/f64 (f64.const nan))) + (func (export "f64.positive_nan") (result i64) (i64.reinterpret/f64 (f64.const +nan))) + (func (export "f64.negative_nan") (result i64) (i64.reinterpret/f64 (f64.const -nan))) + (func (export "f64.plain_nan") (result i64) (i64.reinterpret/f64 (f64.const nan:0x8000000000000))) + (func (export "f64.informally_known_as_plain_snan") (result i64) (i64.reinterpret/f64 (f64.const nan:0x4000000000000))) + (func (export "f64.all_ones_nan") (result i64) (i64.reinterpret/f64 (f64.const -nan:0xfffffffffffff))) + (func (export "f64.misc_nan") (result i64) (i64.reinterpret/f64 (f64.const nan:0x0123456789abc))) + (func (export "f64.misc_positive_nan") (result i64) (i64.reinterpret/f64 (f64.const +nan:0x3040506070809))) + (func (export "f64.misc_negative_nan") (result i64) (i64.reinterpret/f64 (f64.const -nan:0x2abcdef012345))) + (func (export "f64.infinity") (result i64) (i64.reinterpret/f64 (f64.const infinity))) + (func (export "f64.positive_infinity") (result i64) (i64.reinterpret/f64 (f64.const +infinity))) + (func (export "f64.negative_infinity") (result i64) (i64.reinterpret/f64 (f64.const -infinity))) ;; f64 numbers - (func $f64.zero (result i64) (i64.reinterpret/f64 (f64.const 0x0.0p0))) - (func $f64.positive_zero (result i64) (i64.reinterpret/f64 (f64.const +0x0.0p0))) - (func $f64.negative_zero (result i64) (i64.reinterpret/f64 (f64.const -0x0.0p0))) - (func $f64.misc (result i64) (i64.reinterpret/f64 (f64.const 0x1.921fb54442d18p+2))) - (func $f64.min_positive (result i64) (i64.reinterpret/f64 (f64.const 0x0.0000000000001p-1022))) - (func $f64.min_normal (result i64) (i64.reinterpret/f64 (f64.const 0x1p-1022))) - (func $f64.max_subnormal (result i64) (i64.reinterpret/f64 (f64.const 0x0.fffffffffffffp-1022))) - (func $f64.max_finite (result i64) (i64.reinterpret/f64 (f64.const 0x1.fffffffffffffp+1023))) - (func $f64.trailing_dot (result i64) (i64.reinterpret/f64 (f64.const 0x1.p100))) + (func (export "f64.zero") (result i64) (i64.reinterpret/f64 (f64.const 0x0.0p0))) + (func (export "f64.positive_zero") (result i64) (i64.reinterpret/f64 (f64.const +0x0.0p0))) + (func (export "f64.negative_zero") (result i64) (i64.reinterpret/f64 (f64.const -0x0.0p0))) + (func (export "f64.misc") (result i64) (i64.reinterpret/f64 (f64.const 0x1.921fb54442d18p+2))) + (func (export "f64.min_positive") (result i64) (i64.reinterpret/f64 (f64.const 0x0.0000000000001p-1022))) + (func (export "f64.min_normal") (result i64) (i64.reinterpret/f64 (f64.const 0x1p-1022))) + (func (export "f64.max_subnormal") (result i64) (i64.reinterpret/f64 (f64.const 0x0.fffffffffffffp-1022))) + (func (export "f64.max_finite") (result i64) (i64.reinterpret/f64 (f64.const 0x1.fffffffffffffp+1023))) + (func (export "f64.trailing_dot") (result i64) (i64.reinterpret/f64 (f64.const 0x1.p100))) ;; f64 numbers in decimal format - (func $f64_dec.zero (result i64) (i64.reinterpret/f64 (f64.const 0.0e0))) - (func $f64_dec.positive_zero (result i64) (i64.reinterpret/f64 (f64.const +0.0e0))) - (func $f64_dec.negative_zero (result i64) (i64.reinterpret/f64 (f64.const -0.0e0))) - (func $f64_dec.misc (result i64) (i64.reinterpret/f64 (f64.const 6.28318530717958623))) - (func $f64_dec.min_positive (result i64) (i64.reinterpret/f64 (f64.const 4.94066e-324))) - (func $f64_dec.min_normal (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072012e-308))) - (func $f64_dec.max_subnormal (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072011e-308))) - (func $f64_dec.max_finite (result i64) (i64.reinterpret/f64 (f64.const 1.7976931348623157e+308))) - (func $f64_dec.trailing_dot (result i64) (i64.reinterpret/f64 (f64.const 1.e100))) - - (export "f32.nan" $f32.nan) - (export "f32.positive_nan" $f32.positive_nan) - (export "f32.negative_nan" $f32.negative_nan) - (export "f32.plain_nan" $f32.plain_nan) - (export "f32.informally_known_as_plain_snan" $f32.informally_known_as_plain_snan) - (export "f32.allones_nan" $f32.allones_nan) - (export "f32.misc_nan" $f32.misc_nan) - (export "f32.misc_positive_nan" $f32.misc_positive_nan) - (export "f32.misc_negative_nan" $f32.misc_negative_nan) - (export "f32.infinity" $f32.infinity) - (export "f32.positive_infinity" $f32.positive_infinity) - (export "f32.negative_infinity" $f32.negative_infinity) - (export "f32.zero" $f32.zero) - (export "f32.positive_zero" $f32.positive_zero) - (export "f32.negative_zero" $f32.negative_zero) - (export "f32.misc" $f32.misc) - (export "f32.min_positive" $f32.min_positive) - (export "f32.min_normal" $f32.min_normal) - (export "f32.max_subnormal" $f32.max_subnormal) - (export "f32.max_finite" $f32.max_finite) - (export "f32.trailing_dot" $f32.trailing_dot) - (export "f32_dec.zero" $f32_dec.zero) - (export "f32_dec.positive_zero" $f32_dec.positive_zero) - (export "f32_dec.negative_zero" $f32_dec.negative_zero) - (export "f32_dec.misc" $f32_dec.misc) - (export "f32_dec.min_positive" $f32_dec.min_positive) - (export "f32_dec.min_normal" $f32_dec.min_normal) - (export "f32_dec.max_subnormal" $f32_dec.max_subnormal) - (export "f32_dec.max_finite" $f32_dec.max_finite) - (export "f32_dec.trailing_dot" $f32_dec.trailing_dot) - - (export "f64.nan" $f64.nan) - (export "f64.positive_nan" $f64.positive_nan) - (export "f64.negative_nan" $f64.negative_nan) - (export "f64.plain_nan" $f64.plain_nan) - (export "f64.informally_known_as_plain_snan" $f64.informally_known_as_plain_snan) - (export "f64.allones_nan" $f64.allones_nan) - (export "f64.misc_nan" $f64.misc_nan) - (export "f64.misc_positive_nan" $f64.misc_positive_nan) - (export "f64.misc_negative_nan" $f64.misc_negative_nan) - (export "f64.infinity" $f64.infinity) - (export "f64.positive_infinity" $f64.positive_infinity) - (export "f64.negative_infinity" $f64.negative_infinity) - (export "f64.zero" $f64.zero) - (export "f64.positive_zero" $f64.positive_zero) - (export "f64.negative_zero" $f64.negative_zero) - (export "f64.misc" $f64.misc) - (export "f64.min_positive" $f64.min_positive) - (export "f64.min_normal" $f64.min_normal) - (export "f64.max_subnormal" $f64.max_subnormal) - (export "f64.max_finite" $f64.max_finite) - (export "f64.trailing_dot" $f64.trailing_dot) - (export "f64_dec.zero" $f64_dec.zero) - (export "f64_dec.positive_zero" $f64_dec.positive_zero) - (export "f64_dec.negative_zero" $f64_dec.negative_zero) - (export "f64_dec.misc" $f64_dec.misc) - (export "f64_dec.min_positive" $f64_dec.min_positive) - (export "f64_dec.min_normal" $f64_dec.min_normal) - (export "f64_dec.max_subnormal" $f64_dec.max_subnormal) - (export "f64_dec.max_finite" $f64_dec.max_finite) - (export "f64_dec.trailing_dot" $f64_dec.trailing_dot) + (func (export "f64_dec.zero") (result i64) (i64.reinterpret/f64 (f64.const 0.0e0))) + (func (export "f64_dec.positive_zero") (result i64) (i64.reinterpret/f64 (f64.const +0.0e0))) + (func (export "f64_dec.negative_zero") (result i64) (i64.reinterpret/f64 (f64.const -0.0e0))) + (func (export "f64_dec.misc") (result i64) (i64.reinterpret/f64 (f64.const 6.28318530717958623))) + (func (export "f64_dec.min_positive") (result i64) (i64.reinterpret/f64 (f64.const 4.94066e-324))) + (func (export "f64_dec.min_normal") (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072012e-308))) + (func (export "f64_dec.max_subnormal") (result i64) (i64.reinterpret/f64 (f64.const 2.2250738585072011e-308))) + (func (export "f64_dec.max_finite") (result i64) (i64.reinterpret/f64 (f64.const 1.7976931348623157e+308))) + (func (export "f64_dec.trailing_dot") (result i64) (i64.reinterpret/f64 (f64.const 1.e100))) ) (assert_return (invoke "f32.nan") (i32.const 0x7fc00000)) @@ -141,7 +79,7 @@ (assert_return (invoke "f32.negative_nan") (i32.const 0xffc00000)) (assert_return (invoke "f32.plain_nan") (i32.const 0x7fc00000)) (assert_return (invoke "f32.informally_known_as_plain_snan") (i32.const 0x7fa00000)) -(assert_return (invoke "f32.allones_nan") (i32.const 0xffffffff)) +(assert_return (invoke "f32.all_ones_nan") (i32.const 0xffffffff)) (assert_return (invoke "f32.misc_nan") (i32.const 0x7f812345)) (assert_return (invoke "f32.misc_positive_nan") (i32.const 0x7fb04050)) (assert_return (invoke "f32.misc_negative_nan") (i32.const 0xffaabcde)) @@ -172,7 +110,7 @@ (assert_return (invoke "f64.negative_nan") (i64.const 0xfff8000000000000)) (assert_return (invoke "f64.plain_nan") (i64.const 0x7ff8000000000000)) (assert_return (invoke "f64.informally_known_as_plain_snan") (i64.const 0x7ff4000000000000)) -(assert_return (invoke "f64.allones_nan") (i64.const 0xffffffffffffffff)) +(assert_return (invoke "f64.all_ones_nan") (i64.const 0xffffffffffffffff)) (assert_return (invoke "f64.misc_nan") (i64.const 0x7ff0123456789abc)) (assert_return (invoke "f64.misc_positive_nan") (i64.const 0x7ff3040506070809)) (assert_return (invoke "f64.misc_negative_nan") (i64.const 0xfff2abcdef012345)) diff --git a/ml-proto/test/float_memory.wast b/ml-proto/test/float_memory.wast index 6a4f014152..3801158f92 100644 --- a/ml-proto/test/float_memory.wast +++ b/ml-proto/test/float_memory.wast @@ -5,20 +5,11 @@ (module (memory (data "\00\00\a0\7f")) - (func $f32.load (result f32) (f32.load (i32.const 0))) - (export "f32.load" $f32.load) - - (func $i32.load (result i32) (i32.load (i32.const 0))) - (export "i32.load" $i32.load) - - (func $f32.store (f32.store (i32.const 0) (f32.const nan:0x200000))) - (export "f32.store" $f32.store) - - (func $i32.store (i32.store (i32.const 0) (i32.const 0x7fa00000))) - (export "i32.store" $i32.store) - - (func $reset (i32.store (i32.const 0) (i32.const 0))) - (export "reset" $reset) + (func (export "f32.load") (result f32) (f32.load (i32.const 0))) + (func (export "i32.load") (result i32) (i32.load (i32.const 0))) + (func (export "f32.store") (f32.store (i32.const 0) (f32.const nan:0x200000))) + (func (export "i32.store") (i32.store (i32.const 0) (i32.const 0x7fa00000))) + (func (export "reset") (i32.store (i32.const 0) (i32.const 0))) ) (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) @@ -39,20 +30,11 @@ (module (memory (data "\00\00\00\00\00\00\f4\7f")) - (func $f64.load (result f64) (f64.load (i32.const 0))) - (export "f64.load" $f64.load) - - (func $i64.load (result i64) (i64.load (i32.const 0))) - (export "i64.load" $i64.load) - - (func $f64.store (f64.store (i32.const 0) (f64.const nan:0x4000000000000))) - (export "f64.store" $f64.store) - - (func $i64.store (i64.store (i32.const 0) (i64.const 0x7ff4000000000000))) - (export "i64.store" $i64.store) - - (func $reset (i64.store (i32.const 0) (i64.const 0))) - (export "reset" $reset) + (func (export "f64.load") (result f64) (f64.load (i32.const 0))) + (func (export "i64.load") (result i64) (i64.load (i32.const 0))) + (func (export "f64.store") (f64.store (i32.const 0) (f64.const nan:0x4000000000000))) + (func (export "i64.store") (i64.store (i32.const 0) (i64.const 0x7ff4000000000000))) + (func (export "reset") (i64.store (i32.const 0) (i64.const 0))) ) (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) @@ -75,20 +57,11 @@ (module (memory (data "\00\00\00\a0\7f")) - (func $f32.load (result f32) (f32.load (i32.const 1))) - (export "f32.load" $f32.load) - - (func $i32.load (result i32) (i32.load (i32.const 1))) - (export "i32.load" $i32.load) - - (func $f32.store (f32.store (i32.const 1) (f32.const nan:0x200000))) - (export "f32.store" $f32.store) - - (func $i32.store (i32.store (i32.const 1) (i32.const 0x7fa00000))) - (export "i32.store" $i32.store) - - (func $reset (i32.store (i32.const 1) (i32.const 0))) - (export "reset" $reset) + (func (export "f32.load") (result f32) (f32.load (i32.const 1))) + (func (export "i32.load") (result i32) (i32.load (i32.const 1))) + (func (export "f32.store") (f32.store (i32.const 1) (f32.const nan:0x200000))) + (func (export "i32.store") (i32.store (i32.const 1) (i32.const 0x7fa00000))) + (func (export "reset") (i32.store (i32.const 1) (i32.const 0))) ) (assert_return (invoke "i32.load") (i32.const 0x7fa00000)) @@ -109,20 +82,11 @@ (module (memory (data "\00\00\00\00\00\00\00\f4\7f")) - (func $f64.load (result f64) (f64.load (i32.const 1))) - (export "f64.load" $f64.load) - - (func $i64.load (result i64) (i64.load (i32.const 1))) - (export "i64.load" $i64.load) - - (func $f64.store (f64.store (i32.const 1) (f64.const nan:0x4000000000000))) - (export "f64.store" $f64.store) - - (func $i64.store (i64.store (i32.const 1) (i64.const 0x7ff4000000000000))) - (export "i64.store" $i64.store) - - (func $reset (i64.store (i32.const 1) (i64.const 0))) - (export "reset" $reset) + (func (export "f64.load") (result f64) (f64.load (i32.const 1))) + (func (export "i64.load") (result i64) (i64.load (i32.const 1))) + (func (export "f64.store") (f64.store (i32.const 1) (f64.const nan:0x4000000000000))) + (func (export "i64.store") (i64.store (i32.const 1) (i64.const 0x7ff4000000000000))) + (func (export "reset") (i64.store (i32.const 1) (i64.const 0))) ) (assert_return (invoke "i64.load") (i64.const 0x7ff4000000000000)) @@ -145,20 +109,11 @@ (module (memory (data "\01\00\d0\7f")) - (func $f32.load (result f32) (f32.load (i32.const 0))) - (export "f32.load" $f32.load) - - (func $i32.load (result i32) (i32.load (i32.const 0))) - (export "i32.load" $i32.load) - - (func $f32.store (f32.store (i32.const 0) (f32.const nan:0x500001))) - (export "f32.store" $f32.store) - - (func $i32.store (i32.store (i32.const 0) (i32.const 0x7fd00001))) - (export "i32.store" $i32.store) - - (func $reset (i32.store (i32.const 0) (i32.const 0))) - (export "reset" $reset) + (func (export "f32.load") (result f32) (f32.load (i32.const 0))) + (func (export "i32.load") (result i32) (i32.load (i32.const 0))) + (func (export "f32.store") (f32.store (i32.const 0) (f32.const nan:0x500001))) + (func (export "i32.store") (i32.store (i32.const 0) (i32.const 0x7fd00001))) + (func (export "reset") (i32.store (i32.const 0) (i32.const 0))) ) (assert_return (invoke "i32.load") (i32.const 0x7fd00001)) @@ -179,20 +134,11 @@ (module (memory (data "\01\00\00\00\00\00\fc\7f")) - (func $f64.load (result f64) (f64.load (i32.const 0))) - (export "f64.load" $f64.load) - - (func $i64.load (result i64) (i64.load (i32.const 0))) - (export "i64.load" $i64.load) - - (func $f64.store (f64.store (i32.const 0) (f64.const nan:0xc000000000001))) - (export "f64.store" $f64.store) - - (func $i64.store (i64.store (i32.const 0) (i64.const 0x7ffc000000000001))) - (export "i64.store" $i64.store) - - (func $reset (i64.store (i32.const 0) (i64.const 0))) - (export "reset" $reset) + (func (export "f64.load") (result f64) (f64.load (i32.const 0))) + (func (export "i64.load") (result i64) (i64.load (i32.const 0))) + (func (export "f64.store") (f64.store (i32.const 0) (f64.const nan:0xc000000000001))) + (func (export "i64.store") (i64.store (i32.const 0) (i64.const 0x7ffc000000000001))) + (func (export "reset") (i64.store (i32.const 0) (i64.const 0))) ) (assert_return (invoke "i64.load") (i64.const 0x7ffc000000000001)) diff --git a/ml-proto/test/float_misc.wast b/ml-proto/test/float_misc.wast index b01fb37f4d..41e29321d5 100644 --- a/ml-proto/test/float_misc.wast +++ b/ml-proto/test/float_misc.wast @@ -15,65 +15,35 @@ ;; interesting cases. (module - (func $f32.add (param $x f32) (param $y f32) (result f32) (f32.add (get_local $x) (get_local $y))) - (func $f32.sub (param $x f32) (param $y f32) (result f32) (f32.sub (get_local $x) (get_local $y))) - (func $f32.mul (param $x f32) (param $y f32) (result f32) (f32.mul (get_local $x) (get_local $y))) - (func $f32.div (param $x f32) (param $y f32) (result f32) (f32.div (get_local $x) (get_local $y))) - (func $f32.sqrt (param $x f32) (result f32) (f32.sqrt (get_local $x))) - (func $f32.abs (param $x f32) (result f32) (f32.abs (get_local $x))) - (func $f32.neg (param $x f32) (result f32) (f32.neg (get_local $x))) - (func $f32.copysign (param $x f32) (param $y f32) (result f32) (f32.copysign (get_local $x) (get_local $y))) - (func $f32.ceil (param $x f32) (result f32) (f32.ceil (get_local $x))) - (func $f32.floor (param $x f32) (result f32) (f32.floor (get_local $x))) - (func $f32.trunc (param $x f32) (result f32) (f32.trunc (get_local $x))) - (func $f32.nearest (param $x f32) (result f32) (f32.nearest (get_local $x))) - (func $f32.min (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y))) - (func $f32.max (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y))) - - (func $f64.add (param $x f64) (param $y f64) (result f64) (f64.add (get_local $x) (get_local $y))) - (func $f64.sub (param $x f64) (param $y f64) (result f64) (f64.sub (get_local $x) (get_local $y))) - (func $f64.mul (param $x f64) (param $y f64) (result f64) (f64.mul (get_local $x) (get_local $y))) - (func $f64.div (param $x f64) (param $y f64) (result f64) (f64.div (get_local $x) (get_local $y))) - (func $f64.sqrt (param $x f64) (result f64) (f64.sqrt (get_local $x))) - (func $f64.abs (param $x f64) (result f64) (f64.abs (get_local $x))) - (func $f64.neg (param $x f64) (result f64) (f64.neg (get_local $x))) - (func $f64.copysign (param $x f64) (param $y f64) (result f64) (f64.copysign (get_local $x) (get_local $y))) - (func $f64.ceil (param $x f64) (result f64) (f64.ceil (get_local $x))) - (func $f64.floor (param $x f64) (result f64) (f64.floor (get_local $x))) - (func $f64.trunc (param $x f64) (result f64) (f64.trunc (get_local $x))) - (func $f64.nearest (param $x f64) (result f64) (f64.nearest (get_local $x))) - (func $f64.min (param $x f64) (param $y f64) (result f64) (f64.min (get_local $x) (get_local $y))) - (func $f64.max (param $x f64) (param $y f64) (result f64) (f64.max (get_local $x) (get_local $y))) - - (export "f32.add" $f32.add) - (export "f32.sub" $f32.sub) - (export "f32.mul" $f32.mul) - (export "f32.div" $f32.div) - (export "f32.sqrt" $f32.sqrt) - (export "f32.abs" $f32.abs) - (export "f32.neg" $f32.neg) - (export "f32.copysign" $f32.copysign) - (export "f32.ceil" $f32.ceil) - (export "f32.floor" $f32.floor) - (export "f32.trunc" $f32.trunc) - (export "f32.nearest" $f32.nearest) - (export "f32.min" $f32.min) - (export "f32.max" $f32.max) - - (export "f64.add" $f64.add) - (export "f64.sub" $f64.sub) - (export "f64.mul" $f64.mul) - (export "f64.div" $f64.div) - (export "f64.sqrt" $f64.sqrt) - (export "f64.abs" $f64.abs) - (export "f64.neg" $f64.neg) - (export "f64.copysign" $f64.copysign) - (export "f64.ceil" $f64.ceil) - (export "f64.floor" $f64.floor) - (export "f64.trunc" $f64.trunc) - (export "f64.nearest" $f64.nearest) - (export "f64.min" $f64.min) - (export "f64.max" $f64.max) + (func (export "f32.add") (param $x f32) (param $y f32) (result f32) (f32.add (get_local $x) (get_local $y))) + (func (export "f32.sub") (param $x f32) (param $y f32) (result f32) (f32.sub (get_local $x) (get_local $y))) + (func (export "f32.mul") (param $x f32) (param $y f32) (result f32) (f32.mul (get_local $x) (get_local $y))) + (func (export "f32.div") (param $x f32) (param $y f32) (result f32) (f32.div (get_local $x) (get_local $y))) + (func (export "f32.sqrt") (param $x f32) (result f32) (f32.sqrt (get_local $x))) + (func (export "f32.abs") (param $x f32) (result f32) (f32.abs (get_local $x))) + (func (export "f32.neg") (param $x f32) (result f32) (f32.neg (get_local $x))) + (func (export "f32.copysign") (param $x f32) (param $y f32) (result f32) (f32.copysign (get_local $x) (get_local $y))) + (func (export "f32.ceil") (param $x f32) (result f32) (f32.ceil (get_local $x))) + (func (export "f32.floor") (param $x f32) (result f32) (f32.floor (get_local $x))) + (func (export "f32.trunc") (param $x f32) (result f32) (f32.trunc (get_local $x))) + (func (export "f32.nearest") (param $x f32) (result f32) (f32.nearest (get_local $x))) + (func (export "f32.min") (param $x f32) (param $y f32) (result f32) (f32.min (get_local $x) (get_local $y))) + (func (export "f32.max") (param $x f32) (param $y f32) (result f32) (f32.max (get_local $x) (get_local $y))) + + (func (export "f64.add") (param $x f64) (param $y f64) (result f64) (f64.add (get_local $x) (get_local $y))) + (func (export "f64.sub") (param $x f64) (param $y f64) (result f64) (f64.sub (get_local $x) (get_local $y))) + (func (export "f64.mul") (param $x f64) (param $y f64) (result f64) (f64.mul (get_local $x) (get_local $y))) + (func (export "f64.div") (param $x f64) (param $y f64) (result f64) (f64.div (get_local $x) (get_local $y))) + (func (export "f64.sqrt") (param $x f64) (result f64) (f64.sqrt (get_local $x))) + (func (export "f64.abs") (param $x f64) (result f64) (f64.abs (get_local $x))) + (func (export "f64.neg") (param $x f64) (result f64) (f64.neg (get_local $x))) + (func (export "f64.copysign") (param $x f64) (param $y f64) (result f64) (f64.copysign (get_local $x) (get_local $y))) + (func (export "f64.ceil") (param $x f64) (result f64) (f64.ceil (get_local $x))) + (func (export "f64.floor") (param $x f64) (result f64) (f64.floor (get_local $x))) + (func (export "f64.trunc") (param $x f64) (result f64) (f64.trunc (get_local $x))) + (func (export "f64.nearest") (param $x f64) (result f64) (f64.nearest (get_local $x))) + (func (export "f64.min") (param $x f64) (param $y f64) (result f64) (f64.min (get_local $x) (get_local $y))) + (func (export "f64.max") (param $x f64) (param $y f64) (result f64) (f64.max (get_local $x) (get_local $y))) ) ;; Miscellaneous values. diff --git a/ml-proto/test/forward.wast b/ml-proto/test/forward.wast index d5ba73b72b..644eb38047 100644 --- a/ml-proto/test/forward.wast +++ b/ml-proto/test/forward.wast @@ -1,15 +1,12 @@ (module - (export "even" $even) - (export "odd" $odd) - - (func $even (param $n i32) (result i32) + (func $even (export "even") (param $n i32) (result i32) (if (i32.eq (get_local $n) (i32.const 0)) (i32.const 1) (call $odd (i32.sub (get_local $n) (i32.const 1))) ) ) - (func $odd (param $n i32) (result i32) + (func $odd (export "odd") (param $n i32) (result i32) (if (i32.eq (get_local $n) (i32.const 0)) (i32.const 0) (call $even (i32.sub (get_local $n) (i32.const 1))) diff --git a/ml-proto/test/func.wast b/ml-proto/test/func.wast index 452bb24f03..c00d6c8be8 100644 --- a/ml-proto/test/func.wast +++ b/ml-proto/test/func.wast @@ -8,9 +8,9 @@ ;; Syntax (func) - (func "f") + (func (export "f")) (func $f) - (func "g" $h) + (func $h (export "g")) (func (local)) (func (local i32)) @@ -45,15 +45,15 @@ ;; Typing of locals - (func "local-first-i32" (result i32) (local i32 i32) (get_local 0)) - (func "local-first-i64" (result i64) (local i64 i64) (get_local 0)) - (func "local-first-f32" (result f32) (local f32 f32) (get_local 0)) - (func "local-first-f64" (result f64) (local f64 f64) (get_local 0)) - (func "local-second-i32" (result i32) (local i32 i32) (get_local 1)) - (func "local-second-i64" (result i64) (local i64 i64) (get_local 1)) - (func "local-second-f32" (result f32) (local f32 f32) (get_local 1)) - (func "local-second-f64" (result f64) (local f64 f64) (get_local 1)) - (func "local-mixed" (result f64) + (func (export "local-first-i32") (result i32) (local i32 i32) (get_local 0)) + (func (export "local-first-i64") (result i64) (local i64 i64) (get_local 0)) + (func (export "local-first-f32") (result f32) (local f32 f32) (get_local 0)) + (func (export "local-first-f64") (result f64) (local f64 f64) (get_local 0)) + (func (export "local-second-i32") (result i32) (local i32 i32) (get_local 1)) + (func (export "local-second-i64") (result i64) (local i64 i64) (get_local 1)) + (func (export "local-second-f32") (result f32) (local f32 f32) (get_local 1)) + (func (export "local-second-f64") (result f64) (local f64 f64) (get_local 1)) + (func (export "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))) @@ -66,15 +66,15 @@ ;; Typing of parameters - (func "param-first-i32" (param i32 i32) (result i32) (get_local 0)) - (func "param-first-i64" (param i64 i64) (result i64) (get_local 0)) - (func "param-first-f32" (param f32 f32) (result f32) (get_local 0)) - (func "param-first-f64" (param f64 f64) (result f64) (get_local 0)) - (func "param-second-i32" (param i32 i32) (result i32) (get_local 1)) - (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) + (func (export "param-first-i32") (param i32 i32) (result i32) (get_local 0)) + (func (export "param-first-i64") (param i64 i64) (result i64) (get_local 0)) + (func (export "param-first-f32") (param f32 f32) (result f32) (get_local 0)) + (func (export "param-first-f64") (param f64 f64) (result f64) (get_local 0)) + (func (export "param-second-i32") (param i32 i32) (result i32) (get_local 1)) + (func (export "param-second-i64") (param i64 i64) (result i64) (get_local 1)) + (func (export "param-second-f32") (param f32 f32) (result f32) (get_local 1)) + (func (export "param-second-f64") (param f64 f64) (result f64) (get_local 1)) + (func (export "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))) @@ -87,50 +87,50 @@ ;; Typing of result - (func "empty") - (func "value-void" (call $dummy)) - (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 (call $dummy) (call $dummy))) - (func "value-block-i32" (result i32) (block (call $dummy) (i32.const 77))) - - (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-i32" (result i32) + (func (export "empty")) + (func (export "value-void") (call $dummy)) + (func (export "value-i32") (result i32) (i32.const 77)) + (func (export "value-i64") (result i64) (i64.const 7777)) + (func (export "value-f32") (result f32) (f32.const 77.7)) + (func (export "value-f64") (result f64) (f64.const 77.77)) + (func (export "value-block-void") (block (call $dummy) (call $dummy))) + (func (export "value-block-i32") (result i32) (block (call $dummy) (i32.const 77))) + + (func (export "return-empty") (return)) + (func (export "return-i32") (result i32) (return (i32.const 78))) + (func (export "return-i64") (result i64) (return (i64.const 7878))) + (func (export "return-f32") (result f32) (return (f32.const 78.7))) + (func (export "return-f64") (result f64) (return (f64.const 78.78))) + (func (export "return-block-i32") (result i32) (return (block (call $dummy) (i32.const 77))) ) - (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-i32" (result i32) + (func (export "break-empty") (br 0)) + (func (export "break-i32") (result i32) (br 0 (i32.const 79))) + (func (export "break-i64") (result i64) (br 0 (i64.const 7979))) + (func (export "break-f32") (result f32) (br 0 (f32.const 79.9))) + (func (export "break-f64") (result f64) (br 0 (f64.const 79.79))) + (func (export "break-block-i32") (result i32) (br 0 (block (call $dummy) (i32.const 77))) ) - (func "break-br_if-empty" (param i32) + (func (export "break-br_if-empty") (param i32) (br_if 0 (get_local 0)) ) - (func "break-br_if-num" (param i32) (result i32) + (func (export "break-br_if-num") (param i32) (result i32) (br_if 0 (i32.const 50) (get_local 0)) (i32.const 51) ) - (func "break-br_table-empty" (param i32) + (func (export "break-br_table-empty") (param i32) (br_table 0 0 0 (get_local 0)) ) - (func "break-br_table-num" (param i32) (result i32) + (func (export "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-empty" (param i32) + (func (export "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) + (func (export "break-br_table-nested-num") (param i32) (result i32) (i32.add (block (br_table 0 1 0 (i32.const 50) (get_local 0)) (i32.const 51)) (i32.const 2) @@ -139,10 +139,10 @@ ;; Default initialization of locals - (func "init-local-i32" (result i32) (local i32) (get_local 0)) - (func "init-local-i64" (result i64) (local i64) (get_local 0)) - (func "init-local-f32" (result f32) (local f32) (get_local 0)) - (func "init-local-f64" (result f64) (local f64) (get_local 0)) + (func (export "init-local-i32") (result i32) (local i32) (get_local 0)) + (func (export "init-local-i64") (result i64) (local i64) (get_local 0)) + (func (export "init-local-f32") (result f32) (local f32) (get_local 0)) + (func (export "init-local-f64") (result f64) (local f64) (get_local 0)) ;; Desugaring of implicit type signature @@ -160,12 +160,12 @@ ) ) - (func "signature-explicit-reused" + (func (export "signature-explicit-reused") (call_indirect $sig (i32.const 1)) (call_indirect $sig (i32.const 4)) ) - (func "signature-implicit-reused" + (func (export "signature-implicit-reused") ;; The implicit index 16 in this test depends on the function and ;; type definitions, and may need adapting if they change. (call_indirect 16 (i32.const 0) @@ -182,11 +182,11 @@ ) ) - (func "signature-explicit-duplicate" + (func (export "signature-explicit-duplicate") (call_indirect $empty-sig-duplicate (i32.const 1)) ) - (func "signature-implicit-duplicate" + (func (export "signature-implicit-duplicate") (call_indirect $complex-sig-duplicate (i32.const 0) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f64.const 0) (i64.const 0) (f32.const 0) (i32.const 0) diff --git a/ml-proto/test/func_ptrs.wast b/ml-proto/test/func_ptrs.wast index 841c74ecbf..f7edd9f448 100644 --- a/ml-proto/test/func_ptrs.wast +++ b/ml-proto/test/func_ptrs.wast @@ -7,28 +7,29 @@ (type $T (func (param i32) (result i32))) ;; 5: i32 -> i32 (type $U (func (param i32))) ;; 6: i32 -> void + (func $print (import "spectest" "print") (type 6)) + (func (type 0)) (func (type $S)) - (func "one" (type 4) (i32.const 13)) - (func "two" (type $T) (i32.add (get_local 0) (i32.const 1))) + (func (export "one") (type 4) (i32.const 13)) + (func (export "two") (type $T) (i32.add (get_local 0) (i32.const 1))) ;; Both signature and parameters are allowed (and required to match) ;; since this allows the naming of parameters. - (func "three" (type $T) (param $a i32) (result i32) + (func (export "three") (type $T) (param $a i32) (result i32) (i32.sub (get_local 0) (i32.const 2)) ) - (import $print "spectest" "print" (type 6)) - (func "four" (type $U) (call_import $print (get_local 0))) + (func (export "four") (type $U) (call $print (get_local 0))) ) (assert_return (invoke "one") (i32.const 13)) (assert_return (invoke "two" (i32.const 13)) (i32.const 14)) (assert_return (invoke "three" (i32.const 13)) (i32.const 11)) (invoke "four" (i32.const 83)) -(assert_invalid (module (elem (i32.const 0))) "no table defined") -(assert_invalid (module (elem (i32.const 0) 0) (func)) "no table defined") +(assert_invalid (module (elem (i32.const 0))) "unknown table") +(assert_invalid (module (elem (i32.const 0) 0) (func)) "unknown table") (assert_invalid (module (table 1 anyfunc) (elem (i64.const 0))) @@ -43,8 +44,8 @@ "constant expression required" ) -(assert_invalid (module (func (type 42))) "unknown function type 42") -(assert_invalid (module (import "spectest" "print" (type 43))) "unknown function type 43") +(assert_invalid (module (func (type 42))) "unknown type") +(assert_invalid (module (import "spectest" "print" (func (type 43)))) "unknown type") (module (type $T (func (param) (result i32))) @@ -57,11 +58,11 @@ (func $u1 (type $U) (i32.const 4)) (func $u2 (type $U) (i32.const 5)) - (func "callt" (param $i i32) (result i32) + (func (export "callt") (param $i i32) (result i32) (call_indirect $T (get_local $i)) ) - (func "callu" (param $i i32) (result i32) + (func (export "callu") (param $i i32) (result i32) (call_indirect $U (get_local $i)) ) ) @@ -92,12 +93,10 @@ (type $T (func (result i32))) (table anyfunc (elem 0 1)) - (import $print_i32 "spectest" "print" (param i32)) - (func $t1 (type $T) (i32.const 1)) (func $t2 (type $T) (i32.const 2)) - (func "callt" (param $i i32) (result i32) + (func (export "callt") (param $i i32) (result i32) (call_indirect $T (get_local $i)) ) ) diff --git a/ml-proto/test/get_local.wast b/ml-proto/test/get_local.wast index a5d09833df..e1f9625b96 100644 --- a/ml-proto/test/get_local.wast +++ b/ml-proto/test/get_local.wast @@ -3,17 +3,17 @@ (module ;; Typing - (func "type-local-i32" (result i32) (local i32) (get_local 0)) - (func "type-local-i64" (result i64) (local i64) (get_local 0)) - (func "type-local-f32" (result f32) (local f32) (get_local 0)) - (func "type-local-f64" (result f64) (local f64) (get_local 0)) + (func (export "type-local-i32") (result i32) (local i32) (get_local 0)) + (func (export "type-local-i64") (result i64) (local i64) (get_local 0)) + (func (export "type-local-f32") (result f32) (local f32) (get_local 0)) + (func (export "type-local-f64") (result f64) (local f64) (get_local 0)) - (func "type-param-i32" (param i32) (result i32) (get_local 0)) - (func "type-param-i64" (param i64) (result i64) (get_local 0)) - (func "type-param-f32" (param f32) (result f32) (get_local 0)) - (func "type-param-f64" (param f64) (result f64) (get_local 0)) + (func (export "type-param-i32") (param i32) (result i32) (get_local 0)) + (func (export "type-param-i64") (param i64) (result i64) (get_local 0)) + (func (export "type-param-f32") (param f32) (result f32) (get_local 0)) + (func (export "type-param-f64") (param f64) (result f64) (get_local 0)) - (func "type-mixed" (param i64 f32 f64 i32 i32) + (func (export "type-mixed") (param i64 f32 f64 i32 i32) (local f32 i64 i64 f64) (drop (i64.eqz (get_local 0))) (drop (f32.neg (get_local 1))) @@ -28,7 +28,7 @@ ;; Reading - (func "read" (param i64 f32 f64 i32 i32) (result f64) + (func (export "read") (param i64 f32 f64 i32 i32) (result f64) (local f32 i64 i64 f64) (set_local 5 (f32.const 5.5)) (set_local 6 (i64.const 6)) diff --git a/ml-proto/test/globals.wast b/ml-proto/test/globals.wast index 1459233b37..7fd1b8b91c 100644 --- a/ml-proto/test/globals.wast +++ b/ml-proto/test/globals.wast @@ -6,15 +6,15 @@ (global f64 (f64.const -4)) (global $y i64 (i64.const -5)) - (func "get-x" (result i32) (get_global $x)) - (func "get-y" (result i64) (get_global $y)) - (func "set-x" (param i32) (set_global $x (get_local 0))) - (func "set-y" (param i64) (set_global $y (get_local 0))) - - (func "get-1" (result f32) (get_global 1)) - (func "get-2" (result f64) (get_global 2)) - (func "set-1" (param f32) (set_global 1 (get_local 0))) - (func "set-2" (param f64) (set_global 2 (get_local 0))) + (func (export "get-x") (result i32) (get_global $x)) + (func (export "get-y") (result i64) (get_global $y)) + (func (export "set-x") (param i32) (set_global $x (get_local 0))) + (func (export "set-y") (param i64) (set_global $y (get_local 0))) + + (func (export "get-1") (result f32) (get_global 1)) + (func (export "get-2") (result f64) (get_global 2)) + (func (export "set-1") (param f32) (set_global 1 (get_local 0))) + (func (export "set-2") (param f64) (set_global 2 (get_local 0))) ) (assert_return (invoke "get-x") (i32.const -2)) diff --git a/ml-proto/test/i32.wast b/ml-proto/test/i32.wast index f77dff24de..ba28d7c090 100644 --- a/ml-proto/test/i32.wast +++ b/ml-proto/test/i32.wast @@ -1,65 +1,35 @@ ;; i32 operations (module - (func $add (param $x i32) (param $y i32) (result i32) (i32.add (get_local $x) (get_local $y))) - (func $sub (param $x i32) (param $y i32) (result i32) (i32.sub (get_local $x) (get_local $y))) - (func $mul (param $x i32) (param $y i32) (result i32) (i32.mul (get_local $x) (get_local $y))) - (func $div_s (param $x i32) (param $y i32) (result i32) (i32.div_s (get_local $x) (get_local $y))) - (func $div_u (param $x i32) (param $y i32) (result i32) (i32.div_u (get_local $x) (get_local $y))) - (func $rem_s (param $x i32) (param $y i32) (result i32) (i32.rem_s (get_local $x) (get_local $y))) - (func $rem_u (param $x i32) (param $y i32) (result i32) (i32.rem_u (get_local $x) (get_local $y))) - (func $and (param $x i32) (param $y i32) (result i32) (i32.and (get_local $x) (get_local $y))) - (func $or (param $x i32) (param $y i32) (result i32) (i32.or (get_local $x) (get_local $y))) - (func $xor (param $x i32) (param $y i32) (result i32) (i32.xor (get_local $x) (get_local $y))) - (func $shl (param $x i32) (param $y i32) (result i32) (i32.shl (get_local $x) (get_local $y))) - (func $shr_s (param $x i32) (param $y i32) (result i32) (i32.shr_s (get_local $x) (get_local $y))) - (func $shr_u (param $x i32) (param $y i32) (result i32) (i32.shr_u (get_local $x) (get_local $y))) - (func $rotl (param $x i32) (param $y i32) (result i32) (i32.rotl (get_local $x) (get_local $y))) - (func $rotr (param $x i32) (param $y i32) (result i32) (i32.rotr (get_local $x) (get_local $y))) - (func $clz (param $x i32) (result i32) (i32.clz (get_local $x))) - (func $ctz (param $x i32) (result i32) (i32.ctz (get_local $x))) - (func $popcnt (param $x i32) (result i32) (i32.popcnt (get_local $x))) - (func $eqz (param $x i32) (result i32) (i32.eqz (get_local $x))) - (func $eq (param $x i32) (param $y i32) (result i32) (i32.eq (get_local $x) (get_local $y))) - (func $ne (param $x i32) (param $y i32) (result i32) (i32.ne (get_local $x) (get_local $y))) - (func $lt_s (param $x i32) (param $y i32) (result i32) (i32.lt_s (get_local $x) (get_local $y))) - (func $lt_u (param $x i32) (param $y i32) (result i32) (i32.lt_u (get_local $x) (get_local $y))) - (func $le_s (param $x i32) (param $y i32) (result i32) (i32.le_s (get_local $x) (get_local $y))) - (func $le_u (param $x i32) (param $y i32) (result i32) (i32.le_u (get_local $x) (get_local $y))) - (func $gt_s (param $x i32) (param $y i32) (result i32) (i32.gt_s (get_local $x) (get_local $y))) - (func $gt_u (param $x i32) (param $y i32) (result i32) (i32.gt_u (get_local $x) (get_local $y))) - (func $ge_s (param $x i32) (param $y i32) (result i32) (i32.ge_s (get_local $x) (get_local $y))) - (func $ge_u (param $x i32) (param $y i32) (result i32) (i32.ge_u (get_local $x) (get_local $y))) - - (export "add" $add) - (export "sub" $sub) - (export "mul" $mul) - (export "div_s" $div_s) - (export "div_u" $div_u) - (export "rem_s" $rem_s) - (export "rem_u" $rem_u) - (export "and" $and) - (export "or" $or) - (export "xor" $xor) - (export "shl" $shl) - (export "shr_s" $shr_s) - (export "shr_u" $shr_u) - (export "rotl" $rotl) - (export "rotr" $rotr) - (export "clz" $clz) - (export "ctz" $ctz) - (export "popcnt" $popcnt) - (export "eqz" $eqz) - (export "eq" $eq) - (export "ne" $ne) - (export "lt_s" $lt_s) - (export "lt_u" $lt_u) - (export "le_s" $le_s) - (export "le_u" $le_u) - (export "gt_s" $gt_s) - (export "gt_u" $gt_u) - (export "ge_s" $ge_s) - (export "ge_u" $ge_u) + (func (export "add") (param $x i32) (param $y i32) (result i32) (i32.add (get_local $x) (get_local $y))) + (func (export "sub") (param $x i32) (param $y i32) (result i32) (i32.sub (get_local $x) (get_local $y))) + (func (export "mul") (param $x i32) (param $y i32) (result i32) (i32.mul (get_local $x) (get_local $y))) + (func (export "div_s") (param $x i32) (param $y i32) (result i32) (i32.div_s (get_local $x) (get_local $y))) + (func (export "div_u") (param $x i32) (param $y i32) (result i32) (i32.div_u (get_local $x) (get_local $y))) + (func (export "rem_s") (param $x i32) (param $y i32) (result i32) (i32.rem_s (get_local $x) (get_local $y))) + (func (export "rem_u") (param $x i32) (param $y i32) (result i32) (i32.rem_u (get_local $x) (get_local $y))) + (func (export "and") (param $x i32) (param $y i32) (result i32) (i32.and (get_local $x) (get_local $y))) + (func (export "or") (param $x i32) (param $y i32) (result i32) (i32.or (get_local $x) (get_local $y))) + (func (export "xor") (param $x i32) (param $y i32) (result i32) (i32.xor (get_local $x) (get_local $y))) + (func (export "shl") (param $x i32) (param $y i32) (result i32) (i32.shl (get_local $x) (get_local $y))) + (func (export "shr_s") (param $x i32) (param $y i32) (result i32) (i32.shr_s (get_local $x) (get_local $y))) + (func (export "shr_u") (param $x i32) (param $y i32) (result i32) (i32.shr_u (get_local $x) (get_local $y))) + (func (export "rotl") (param $x i32) (param $y i32) (result i32) (i32.rotl (get_local $x) (get_local $y))) + (func (export "rotr") (param $x i32) (param $y i32) (result i32) (i32.rotr (get_local $x) (get_local $y))) + (func (export "clz") (param $x i32) (result i32) (i32.clz (get_local $x))) + (func (export "ctz") (param $x i32) (result i32) (i32.ctz (get_local $x))) + (func (export "popcnt") (param $x i32) (result i32) (i32.popcnt (get_local $x))) + (func (export "eqz") (param $x i32) (result i32) (i32.eqz (get_local $x))) + (func (export "eq") (param $x i32) (param $y i32) (result i32) (i32.eq (get_local $x) (get_local $y))) + (func (export "ne") (param $x i32) (param $y i32) (result i32) (i32.ne (get_local $x) (get_local $y))) + (func (export "lt_s") (param $x i32) (param $y i32) (result i32) (i32.lt_s (get_local $x) (get_local $y))) + (func (export "lt_u") (param $x i32) (param $y i32) (result i32) (i32.lt_u (get_local $x) (get_local $y))) + (func (export "le_s") (param $x i32) (param $y i32) (result i32) (i32.le_s (get_local $x) (get_local $y))) + (func (export "le_u") (param $x i32) (param $y i32) (result i32) (i32.le_u (get_local $x) (get_local $y))) + (func (export "gt_s") (param $x i32) (param $y i32) (result i32) (i32.gt_s (get_local $x) (get_local $y))) + (func (export "gt_u") (param $x i32) (param $y i32) (result i32) (i32.gt_u (get_local $x) (get_local $y))) + (func (export "ge_s") (param $x i32) (param $y i32) (result i32) (i32.ge_s (get_local $x) (get_local $y))) + (func (export "ge_u") (param $x i32) (param $y i32) (result i32) (i32.ge_u (get_local $x) (get_local $y))) ) (assert_return (invoke "add" (i32.const 1) (i32.const 1)) (i32.const 2)) diff --git a/ml-proto/test/i64.wast b/ml-proto/test/i64.wast index f8b9621839..54b28c4609 100644 --- a/ml-proto/test/i64.wast +++ b/ml-proto/test/i64.wast @@ -1,65 +1,35 @@ ;; i64 operations (module - (func $add (param $x i64) (param $y i64) (result i64) (i64.add (get_local $x) (get_local $y))) - (func $sub (param $x i64) (param $y i64) (result i64) (i64.sub (get_local $x) (get_local $y))) - (func $mul (param $x i64) (param $y i64) (result i64) (i64.mul (get_local $x) (get_local $y))) - (func $div_s (param $x i64) (param $y i64) (result i64) (i64.div_s (get_local $x) (get_local $y))) - (func $div_u (param $x i64) (param $y i64) (result i64) (i64.div_u (get_local $x) (get_local $y))) - (func $rem_s (param $x i64) (param $y i64) (result i64) (i64.rem_s (get_local $x) (get_local $y))) - (func $rem_u (param $x i64) (param $y i64) (result i64) (i64.rem_u (get_local $x) (get_local $y))) - (func $and (param $x i64) (param $y i64) (result i64) (i64.and (get_local $x) (get_local $y))) - (func $or (param $x i64) (param $y i64) (result i64) (i64.or (get_local $x) (get_local $y))) - (func $xor (param $x i64) (param $y i64) (result i64) (i64.xor (get_local $x) (get_local $y))) - (func $shl (param $x i64) (param $y i64) (result i64) (i64.shl (get_local $x) (get_local $y))) - (func $shr_s (param $x i64) (param $y i64) (result i64) (i64.shr_s (get_local $x) (get_local $y))) - (func $shr_u (param $x i64) (param $y i64) (result i64) (i64.shr_u (get_local $x) (get_local $y))) - (func $rotl (param $x i64) (param $y i64) (result i64) (i64.rotl (get_local $x) (get_local $y))) - (func $rotr (param $x i64) (param $y i64) (result i64) (i64.rotr (get_local $x) (get_local $y))) - (func $clz (param $x i64) (result i64) (i64.clz (get_local $x))) - (func $ctz (param $x i64) (result i64) (i64.ctz (get_local $x))) - (func $popcnt (param $x i64) (result i64) (i64.popcnt (get_local $x))) - (func $eqz (param $x i64) (result i32) (i64.eqz (get_local $x))) - (func $eq (param $x i64) (param $y i64) (result i32) (i64.eq (get_local $x) (get_local $y))) - (func $ne (param $x i64) (param $y i64) (result i32) (i64.ne (get_local $x) (get_local $y))) - (func $lt_s (param $x i64) (param $y i64) (result i32) (i64.lt_s (get_local $x) (get_local $y))) - (func $lt_u (param $x i64) (param $y i64) (result i32) (i64.lt_u (get_local $x) (get_local $y))) - (func $le_s (param $x i64) (param $y i64) (result i32) (i64.le_s (get_local $x) (get_local $y))) - (func $le_u (param $x i64) (param $y i64) (result i32) (i64.le_u (get_local $x) (get_local $y))) - (func $gt_s (param $x i64) (param $y i64) (result i32) (i64.gt_s (get_local $x) (get_local $y))) - (func $gt_u (param $x i64) (param $y i64) (result i32) (i64.gt_u (get_local $x) (get_local $y))) - (func $ge_s (param $x i64) (param $y i64) (result i32) (i64.ge_s (get_local $x) (get_local $y))) - (func $ge_u (param $x i64) (param $y i64) (result i32) (i64.ge_u (get_local $x) (get_local $y))) - - (export "add" $add) - (export "sub" $sub) - (export "mul" $mul) - (export "div_s" $div_s) - (export "div_u" $div_u) - (export "rem_s" $rem_s) - (export "rem_u" $rem_u) - (export "and" $and) - (export "or" $or) - (export "xor" $xor) - (export "shl" $shl) - (export "shr_s" $shr_s) - (export "shr_u" $shr_u) - (export "rotl" $rotl) - (export "rotr" $rotr) - (export "clz" $clz) - (export "ctz" $ctz) - (export "popcnt" $popcnt) - (export "eqz" $eqz) - (export "eq" $eq) - (export "ne" $ne) - (export "lt_s" $lt_s) - (export "lt_u" $lt_u) - (export "le_s" $le_s) - (export "le_u" $le_u) - (export "gt_s" $gt_s) - (export "gt_u" $gt_u) - (export "ge_s" $ge_s) - (export "ge_u" $ge_u) + (func (export "add") (param $x i64) (param $y i64) (result i64) (i64.add (get_local $x) (get_local $y))) + (func (export "sub") (param $x i64) (param $y i64) (result i64) (i64.sub (get_local $x) (get_local $y))) + (func (export "mul") (param $x i64) (param $y i64) (result i64) (i64.mul (get_local $x) (get_local $y))) + (func (export "div_s") (param $x i64) (param $y i64) (result i64) (i64.div_s (get_local $x) (get_local $y))) + (func (export "div_u") (param $x i64) (param $y i64) (result i64) (i64.div_u (get_local $x) (get_local $y))) + (func (export "rem_s") (param $x i64) (param $y i64) (result i64) (i64.rem_s (get_local $x) (get_local $y))) + (func (export "rem_u") (param $x i64) (param $y i64) (result i64) (i64.rem_u (get_local $x) (get_local $y))) + (func (export "and") (param $x i64) (param $y i64) (result i64) (i64.and (get_local $x) (get_local $y))) + (func (export "or") (param $x i64) (param $y i64) (result i64) (i64.or (get_local $x) (get_local $y))) + (func (export "xor") (param $x i64) (param $y i64) (result i64) (i64.xor (get_local $x) (get_local $y))) + (func (export "shl") (param $x i64) (param $y i64) (result i64) (i64.shl (get_local $x) (get_local $y))) + (func (export "shr_s") (param $x i64) (param $y i64) (result i64) (i64.shr_s (get_local $x) (get_local $y))) + (func (export "shr_u") (param $x i64) (param $y i64) (result i64) (i64.shr_u (get_local $x) (get_local $y))) + (func (export "rotl") (param $x i64) (param $y i64) (result i64) (i64.rotl (get_local $x) (get_local $y))) + (func (export "rotr") (param $x i64) (param $y i64) (result i64) (i64.rotr (get_local $x) (get_local $y))) + (func (export "clz") (param $x i64) (result i64) (i64.clz (get_local $x))) + (func (export "ctz") (param $x i64) (result i64) (i64.ctz (get_local $x))) + (func (export "popcnt") (param $x i64) (result i64) (i64.popcnt (get_local $x))) + (func (export "eqz") (param $x i64) (result i32) (i64.eqz (get_local $x))) + (func (export "eq") (param $x i64) (param $y i64) (result i32) (i64.eq (get_local $x) (get_local $y))) + (func (export "ne") (param $x i64) (param $y i64) (result i32) (i64.ne (get_local $x) (get_local $y))) + (func (export "lt_s") (param $x i64) (param $y i64) (result i32) (i64.lt_s (get_local $x) (get_local $y))) + (func (export "lt_u") (param $x i64) (param $y i64) (result i32) (i64.lt_u (get_local $x) (get_local $y))) + (func (export "le_s") (param $x i64) (param $y i64) (result i32) (i64.le_s (get_local $x) (get_local $y))) + (func (export "le_u") (param $x i64) (param $y i64) (result i32) (i64.le_u (get_local $x) (get_local $y))) + (func (export "gt_s") (param $x i64) (param $y i64) (result i32) (i64.gt_s (get_local $x) (get_local $y))) + (func (export "gt_u") (param $x i64) (param $y i64) (result i32) (i64.gt_u (get_local $x) (get_local $y))) + (func (export "ge_s") (param $x i64) (param $y i64) (result i32) (i64.ge_s (get_local $x) (get_local $y))) + (func (export "ge_u") (param $x i64) (param $y i64) (result i32) (i64.ge_u (get_local $x) (get_local $y))) ) (assert_return (invoke "add" (i64.const 1) (i64.const 1)) (i64.const 2)) diff --git a/ml-proto/test/import-after-func.fail.wast b/ml-proto/test/import-after-func.fail.wast new file mode 100644 index 0000000000..ece33a72c9 --- /dev/null +++ b/ml-proto/test/import-after-func.fail.wast @@ -0,0 +1 @@ +(module (func) (import "" "" (memory 0))) diff --git a/ml-proto/test/import-after-global.fail.wast b/ml-proto/test/import-after-global.fail.wast new file mode 100644 index 0000000000..09cece1a01 --- /dev/null +++ b/ml-proto/test/import-after-global.fail.wast @@ -0,0 +1 @@ +(module (global i64) (import "" "" (table 0 anyfunc))) diff --git a/ml-proto/test/import-after-memory.fail.wast b/ml-proto/test/import-after-memory.fail.wast new file mode 100644 index 0000000000..fbe582a934 --- /dev/null +++ b/ml-proto/test/import-after-memory.fail.wast @@ -0,0 +1 @@ +(module (memory 0) (import "" "" (global i32))) diff --git a/ml-proto/test/import-after-table.fail.wast b/ml-proto/test/import-after-table.fail.wast new file mode 100644 index 0000000000..bcd747a997 --- /dev/null +++ b/ml-proto/test/import-after-table.fail.wast @@ -0,0 +1 @@ +(module (table 0 anyfunc) (import "" "" (func))) diff --git a/ml-proto/test/imports.wast b/ml-proto/test/imports.wast index daea04831b..133481a4d3 100644 --- a/ml-proto/test/imports.wast +++ b/ml-proto/test/imports.wast @@ -1,26 +1,237 @@ +;; Functions + (module - (import $print_i32 "spectest" "print" (param i32)) - (import $print_i64 "spectest" "print" (param i64)) - (import $print_i32_f32 "spectest" "print" (param i32 f32)) - (import $print_i64_f64 "spectest" "print" (param i64 f64)) - (func $print32 (param $i i32) - (call_import $print_i32_f32 - (i32.add (get_local $i) (i32.const 1)) - (f32.const 42) - ) - (call_import $print_i32 (get_local $i)) + (import "spectest" "print" (func (param i32))) + (func (import "spectest" "print") (param i64)) + + (import "spectest" "print" (func $print_i32 (param i32))) + (import "spectest" "print" (func $print_i64 (param i64))) + (import "spectest" "print" (func $print_i32_f32 (param i32 f32))) + (import "spectest" "print" (func $print_i64_f64 (param i64 f64))) + + (func $print_i32-2 (import "spectest" "print") (param i32)) + (func $print_i64-2 (import "spectest" "print") (param i64)) + + (func (export "print32") (param $i i32) + (call 0 (get_local $i)) + (call $print_i32_f32 + (i32.add (get_local $i) (i32.const 1)) + (f32.const 42) ) - (func $print64 (param $i i64) - (call_import $print_i64_f64 - (i64.add (get_local $i) (i64.const 1)) - (f64.const 53) - ) - (call_import $print_i64 (get_local $i)) + (call $print_i32 (get_local $i)) + (call $print_i32-2 (get_local $i)) + ) + + (func (export "print64") (param $i i64) + (call 1 (get_local $i)) + (call $print_i64_f64 + (i64.add (get_local $i) (i64.const 1)) + (f64.const 53) ) - (export "print32" $print32) - (export "print64" $print64) + (call $print_i64 (get_local $i)) + (call $print_i64-2 (get_local $i)) + ) ) (assert_return (invoke "print32" (i32.const 13))) (assert_return (invoke "print64" (i64.const 24))) +(assert_unlinkable + (module (import "spectest" "unknown" (func))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "table" (func))) + "type mismatch" +) + +(; TODO: check linking against other Wasm module +(assert_unlinkable + (module (import "spectest" "func" (func (param i32)))) + "type mismatch" +) +(assert_unlinkable + (module (import "spectest" "func" (func (result i32)))) + "type mismatch" +) +;) + +(assert_unlinkable + (module (import "spectest" "print" (func)) (table anyfunc (elem 0))) + "invalid use of host function" +) + + +;; Globals + +(module + (import "spectest" "global" (global i32)) + (global (import "spectest" "global") i32) + + (import "spectest" "global" (global $x i32)) + (global $y (import "spectest" "global") i32) + + (func (export "get-0") (result i32) (get_global 0)) + (func (export "get-1") (result i32) (get_global 1)) + (func (export "get-x") (result i32) (get_global $x)) + (func (export "get-y") (result i32) (get_global $y)) + + ;; TODO: mutable globals + ;; (func (export "set-0") (param i32) (set_global 0 (get_local 0))) + ;; (func (export "set-1") (param i32) (set_global 1 (get_local 0))) + ;; (func (export "set-x") (param i32) (set_global $x (get_local 0))) + ;; (func (export "set-y") (param i32) (set_global $y (get_local 0))) +) + +(assert_return (invoke "get-0") (i32.const 666)) +(assert_return (invoke "get-1") (i32.const 666)) +(assert_return (invoke "get-x") (i32.const 666)) +(assert_return (invoke "get-y") (i32.const 666)) + +(assert_unlinkable + (module (import "spectest" "unknown" (global i32))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "print" (global i32))) + "type mismatch" +) + +(module (import "spectest" "global" (global i64))) +(module (import "spectest" "global" (global f32))) +(module (import "spectest" "global" (global f64))) + + +;; Tables + +(module + (type (func (result i32))) + (import "spectest" "table" (table 10 20 anyfunc)) + (elem 0 (i32.const 1) $f $g) + + (func (export "call") (param i32) (result i32) (call_indirect 0 (get_local 0))) + (func $f (result i32) (i32.const 11)) + (func $g (result i32) (i32.const 22)) +) + +(assert_trap (invoke "call" (i32.const 0)) "uninitialized element") +(assert_return (invoke "call" (i32.const 1)) (i32.const 11)) +(assert_return (invoke "call" (i32.const 2)) (i32.const 22)) +(assert_trap (invoke "call" (i32.const 3)) "uninitialized element") +(assert_trap (invoke "call" (i32.const 100)) "undefined element") + + +(module + (type (func (result i32))) + (table (import "spectest" "table") 10 20 anyfunc) + (elem 0 (i32.const 1) $f $g) + + (func (export "call") (param i32) (result i32) (call_indirect 0 (get_local 0))) + (func $f (result i32) (i32.const 11)) + (func $g (result i32) (i32.const 22)) +) + +(assert_trap (invoke "call" (i32.const 0)) "uninitialized element") +(assert_return (invoke "call" (i32.const 1)) (i32.const 11)) +(assert_return (invoke "call" (i32.const 2)) (i32.const 22)) +(assert_trap (invoke "call" (i32.const 3)) "uninitialized element") +(assert_trap (invoke "call" (i32.const 100)) "undefined element") + + +(assert_invalid + (module (import "" "" (table 10 anyfunc)) (import "" "" (table 10 anyfunc))) + "multiple tables" +) +(assert_invalid + (module (import "" "" (table 10 anyfunc)) (table 10 anyfunc)) + "multiple tables" +) +(assert_invalid + (module (table 10 anyfunc) (table 10 anyfunc)) + "multiple tables" +) + +(assert_unlinkable + (module (import "spectest" "unknown" (table 10 anyfunc))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "print" (table 10 anyfunc))) + "type mismatch" +) +(assert_unlinkable + (module (import "spectest" "table" (table 12 anyfunc))) + "actual size smaller than declared" +) +(assert_unlinkable + (module (import "spectest" "table" (table 10 15 anyfunc))) + "maximum size larger than declared" +) + + +;; Memories + +(module + (import "spectest" "memory" (memory 1 2)) + (data 0 (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load (get_local 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + +(module + (memory (import "spectest" "memory") 1 2) + (data 0 (i32.const 10) "\10") + + (func (export "load") (param i32) (result i32) (i32.load (get_local 0))) +) + +(assert_return (invoke "load" (i32.const 0)) (i32.const 0)) +(assert_return (invoke "load" (i32.const 10)) (i32.const 16)) +(assert_return (invoke "load" (i32.const 8)) (i32.const 0x100000)) +(assert_trap (invoke "load" (i32.const 1000000)) "out of bounds memory access") + + +(assert_invalid + (module (import "" "" (memory 1)) (import "" "" (memory 1))) + "multiple memories" +) +(assert_invalid + (module (import "" "" (memory 1)) (memory 0)) + "multiple memories" +) +(assert_invalid + (module (memory 0) (memory 0)) + "multiple memories" +) + +(assert_unlinkable + (module (import "spectest" "unknown" (memory 1))) + "unknown import" +) +(assert_unlinkable + (module (import "spectest" "print" (memory 1))) + "type mismatch" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 2))) + "actual size smaller than declared" +) +(assert_unlinkable + (module (import "spectest" "memory" (memory 1 1))) + "maximum size larger than declared" +) + +(module + (import "spectest" "memory" (memory 0 3)) ;; actual has max size 2 + (func (export "grow") (param i32) (result i32) (grow_memory (get_local 0))) +) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const 1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) +(assert_return (invoke "grow" (i32.const 1)) (i32.const -1)) +(assert_return (invoke "grow" (i32.const 0)) (i32.const 2)) diff --git a/ml-proto/test/int_exprs.wast b/ml-proto/test/int_exprs.wast index ac05baf984..d8272fa7f4 100644 --- a/ml-proto/test/int_exprs.wast +++ b/ml-proto/test/int_exprs.wast @@ -4,19 +4,15 @@ ;; Test that x+1>n is not folded to x (module - (func $i32.no_fold_shl_shr_s (param $x i32) (result i32) + (func (export "i32.no_fold_shl_shr_s") (param $x i32) (result i32) (i32.shr_s (i32.shl (get_local $x) (i32.const 1)) (i32.const 1))) - (export "i32.no_fold_shl_shr_s" $i32.no_fold_shl_shr_s) - (func $i32.no_fold_shl_shr_u (param $x i32) (result i32) + (func (export "i32.no_fold_shl_shr_u") (param $x i32) (result i32) (i32.shr_u (i32.shl (get_local $x) (i32.const 1)) (i32.const 1))) - (export "i32.no_fold_shl_shr_u" $i32.no_fold_shl_shr_u) - (func $i64.no_fold_shl_shr_s (param $x i64) (result i64) + (func (export "i64.no_fold_shl_shr_s") (param $x i64) (result i64) (i64.shr_s (i64.shl (get_local $x) (i64.const 1)) (i64.const 1))) - (export "i64.no_fold_shl_shr_s" $i64.no_fold_shl_shr_s) - (func $i64.no_fold_shl_shr_u (param $x i64) (result i64) + (func (export "i64.no_fold_shl_shr_u") (param $x i64) (result i64) (i64.shr_u (i64.shl (get_local $x) (i64.const 1)) (i64.const 1))) - (export "i64.no_fold_shl_shr_u" $i64.no_fold_shl_shr_u) ) (assert_return (invoke "i32.no_fold_shl_shr_s" (i32.const 0x80000000)) (i32.const 0)) @@ -71,19 +61,15 @@ ;; Test that x>>n<