From d051fb6874850e01114e9181cde00708b2990f9e Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Fri, 7 Aug 2020 18:03:26 -0700 Subject: [PATCH 1/6] Implement SIMD load splat and load extend Add more pack types for SIMD load splat and load extends. --- interpreter/binary/encode.ml | 2 ++ interpreter/exec/simd.ml | 14 ++++++++++++++ interpreter/runtime/memory.ml | 18 ++++++++++++++++++ interpreter/syntax/operators.ml | 21 +++++++++++++++++++++ interpreter/syntax/types.ml | 4 ++-- interpreter/text/arrange.ml | 4 ++++ interpreter/text/lexer.mll | 14 ++++++++++++++ test/core/simd/simd_align.wast | 24 ++++++++++++------------ 8 files changed, 87 insertions(+), 14 deletions(-) diff --git a/interpreter/binary/encode.ml b/interpreter/binary/encode.ml index 87a14624b..9adbbe75e 100644 --- a/interpreter/binary/encode.ml +++ b/interpreter/binary/encode.ml @@ -567,6 +567,8 @@ let encode m = | SimdBitmask V128Op.(I32x4 Bitmask) -> simd_op 0xa4l | SimdBitmask (_) -> assert false + | _ -> assert false + let const c = list instr c.it; end_ () diff --git a/interpreter/exec/simd.ml b/interpreter/exec/simd.ml index 66a65883c..f087c8ecd 100644 --- a/interpreter/exec/simd.ml +++ b/interpreter/exec/simd.ml @@ -175,6 +175,10 @@ sig val widen_low_u : t -> t val widen_high_u : t -> t end + module I64x2_convert : sig + val widen_low_s : t -> t + val widen_low_u : t -> t + end module F32x4_convert : sig val convert_i32x4_s : t -> t val convert_i32x4_u : t -> t @@ -405,6 +409,16 @@ struct let widen_high_u = widen Lib.List.drop 0xffffl end + module I64x2_convert = struct + let widen mask x = + Rep.of_i64x2 + (List.map + (fun i32 -> Int64.(logand mask (of_int32 i32))) + (Lib.List.take 2 (Rep.to_i32x4 x))) + let widen_low_s = widen 0xffffffffffffffffL + let widen_low_u = widen 0xffffffffL + end + module F32x4_convert = struct let convert f v = Rep.of_f32x4 (List.map f (Rep.to_i32x4 v)) let convert_i32x4_s = convert F32_convert.convert_i32_s diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index 2c9f198f3..9fb1b30fb 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -122,6 +122,23 @@ let extend x n = function | ZX -> x | SX -> let sh = 64 - 8 * n in Int64.(shift_right (shift_left x sh) sh) +let load_simd_packed sz ext x = + let b = Bytes.create 16 in + Bytes.set_int64_le b 0 x; + let v = V128.of_bits (Bytes.to_string b) in + match sz, ext with + | (Pack8x8, SX) -> V128 (V128.I16x8_convert.widen_low_s v) + | (Pack8x8, ZX) -> V128 (V128.I16x8_convert.widen_low_u v) + | (Pack16x4, SX) -> V128 (V128.I32x4_convert.widen_low_s v) + | (Pack16x4, ZX) -> V128 (V128.I32x4_convert.widen_low_u v) + | (Pack32x2, SX) -> V128 (V128.I64x2_convert.widen_low_s v) + | (Pack32x2, ZX) -> V128 (V128.I64x2_convert.widen_low_u v) + | (Pack8, ZX) -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) + | (Pack16, ZX) -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) + | (Pack32, ZX) -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) + | (Pack64, ZX) -> V128 (V128.I64x2.splat x) + | _ -> assert false + let load_packed sz ext mem a o t = assert (packed_size sz <= Types.size t); let n = packed_size sz in @@ -129,6 +146,7 @@ let load_packed sz ext mem a o t = match t with | I32Type -> I32 (Int64.to_int32 x) | I64Type -> I64 x + | V128Type -> load_simd_packed sz ext x | _ -> raise Type let store_packed sz mem a o v = diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index 7a51514f2..33568f87f 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -218,7 +218,28 @@ let memory_grow = MemoryGrow (* SIMD *) let v128_load align offset = Load {ty = V128Type; align; offset; sz = None} +let i16x8_load8x8_s align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack8x8, SX)} +let i16x8_load8x8_u align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack8x8, ZX)} +let i32x4_load16x4_s align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack16x4, SX)} +let i32x4_load16x4_u align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack16x4, ZX)} +let i64x2_load32x2_s align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack32x2, SX)} +let i64x2_load32x2_u align offset = + Load {ty = V128Type; align; offset; sz = Some (Pack32x2, ZX)} +let v8x16_load_splat align offset = + Load {ty= V128Type; align; offset; sz = Some (Pack8, ZX)} +let v16x8_load_splat align offset = + Load {ty= V128Type; align; offset; sz = Some (Pack16, ZX)} +let v32x4_load_splat align offset = + Load {ty= V128Type; align; offset; sz = Some (Pack32, ZX)} +let v64x2_load_splat align offset = + Load {ty= V128Type; align; offset; sz = Some (Pack64, ZX)} let v128_store align offset = Store {ty = V128Type; align; offset; sz = None} + let v128_not = Unary (V128 (V128Op.V128 V128Op.Not)) let v128_and = Binary (V128 (V128Op.V128 V128Op.And)) let v128_andnot = Binary (V128 (V128Op.V128 V128Op.AndNot)) diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml index db06fabf8..f67e16ed1 100644 --- a/interpreter/syntax/types.ml +++ b/interpreter/syntax/types.ml @@ -16,7 +16,7 @@ type extern_type = | ExternMemoryType of memory_type | ExternGlobalType of global_type -type pack_size = Pack8 | Pack16 | Pack32 +type pack_size = Pack8 | Pack16 | Pack32 | Pack64 | Pack8x8 | Pack16x4 | Pack32x2 type extension = SX | ZX @@ -31,7 +31,7 @@ let packed_size = function | Pack8 -> 1 | Pack16 -> 2 | Pack32 -> 4 - + | Pack64 | Pack8x8 | Pack16x4 | Pack32x2 -> 8 (* Subtyping *) diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 7998e270c..26484d66a 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -77,6 +77,10 @@ let pack_size = function | Pack8 -> "8" | Pack16 -> "16" | Pack32 -> "32" + | Pack64 -> "64" + | Pack8x8 -> "8x8" + | Pack16x4 -> "16x4" + | Pack32x2 -> "32x2" let extension = function | SX -> "_s" diff --git a/interpreter/text/lexer.mll b/interpreter/text/lexer.mll index 0c0ce1c17..1dd17338e 100644 --- a/interpreter/text/lexer.mll +++ b/interpreter/text/lexer.mll @@ -288,6 +288,20 @@ rule token = parse (ext s i64_load8_s i64_load8_u (opt a 0)) (ext s i64_load16_s i64_load16_u (opt a 1)) (ext s i64_load32_s i64_load32_u (opt a 2)) o)) } + | "i16x8.load8x8_"(sign as s) + { LOAD (fun a o -> (ext s i16x8_load8x8_s i16x8_load8x8_u (opt a 3)) o) } + | "i32x4.load16x4_"(sign as s) + { LOAD (fun a o -> (ext s i32x4_load16x4_s i32x4_load16x4_u (opt a 3)) o) } + | "i64x2.load32x2_"(sign as s) + { LOAD (fun a o -> (ext s i64x2_load32x2_s i64x2_load32x2_u (opt a 3)) o) } + | "v8x16.load_splat" + { LOAD (fun a o -> (v8x16_load_splat (opt a 0)) o) } + | "v16x8.load_splat" + { LOAD (fun a o -> (v16x8_load_splat (opt a 1)) o) } + | "v32x4.load_splat" + { LOAD (fun a o -> (v32x4_load_splat (opt a 2)) o) } + | "v64x2.load_splat" + { LOAD (fun a o -> (v64x2_load_splat (opt a 3)) o) } | (ixx as t)".store"(mem_size as sz) { if t = "i32" && sz = "32" then error lexbuf "unknown operator"; STORE (fun a o -> diff --git a/test/core/simd/simd_align.wast b/test/core/simd/simd_align.wast index 35fb68036..79628f226 100644 --- a/test/core/simd/simd_align.wast +++ b/test/core/simd/simd_align.wast @@ -105,7 +105,7 @@ (module quote "(memory 1) (func (drop (v128.load align=-1 (i32.const 0))))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -123,7 +123,7 @@ (module quote "(memory 1) (func (v128.store align=-1 (i32.const 0) (v128.const i32x4 0 0 0 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -141,7 +141,7 @@ (module quote "(memory 1) (func (result v128) (i16x8.load8x8_s align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -159,7 +159,7 @@ (module quote "(memory 1) (func (result v128) (i16x8.load8x8_u align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -177,7 +177,7 @@ (module quote "(memory 1) (func (result v128) (i32x4.load16x4_s align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -195,7 +195,7 @@ (module quote "(memory 1) (func (result v128) (i32x4.load16x4_u align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -213,7 +213,7 @@ (module quote "(memory 1) (func (result v128) (i64x2.load32x2_s align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -231,7 +231,7 @@ (module quote "(memory 1) (func (result v128) (i64x2.load32x2_u align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -249,7 +249,7 @@ (module quote "(memory 1) (func (result v128) (v8x16.load_splat align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -261,7 +261,7 @@ (module quote "(memory 1) (func (result v128) (v16x8.load_splat align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -273,7 +273,7 @@ (module quote "(memory 1) (func (result v128) (v32x4.load_splat align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote @@ -291,7 +291,7 @@ (module quote "(memory 1) (func (result v128) (v64x2.load_splat align=-1 (i32.const 0)))" ) - "alignment must be a power of two" + "unknown operator" ) (assert_malformed (module quote From 9303b606e7fc05e214f77b93ec93fa5cd6d86247 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Thu, 27 Aug 2020 14:09:35 -0700 Subject: [PATCH 2/6] Create new pack_simd type and SimdLoad AST --- interpreter/exec/eval.ml | 11 +++++++++ interpreter/runtime/memory.ml | 41 ++++++++++++++++++--------------- interpreter/runtime/memory.mli | 3 +++ interpreter/syntax/ast.ml | 2 ++ interpreter/syntax/operators.ml | 22 +++++++++--------- interpreter/syntax/types.ml | 16 ++++++++++--- interpreter/text/arrange.ml | 4 +--- interpreter/valid/valid.ml | 4 ++++ 8 files changed, 68 insertions(+), 35 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index 14a6ccd9e..f764c2191 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -220,6 +220,17 @@ let rec step (c : config) : config = in v :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) + | SimdLoad {offset; ty; sz; _}, I32 i :: vs' -> + let mem = memory frame.inst (0l @@ e.at) in + let addr = I64_convert.extend_i32_u i in + (try + let v = + match sz with + | None -> Memory.load_value mem addr offset ty + | Some (simd_load) -> Memory.load_simd_packed simd_load mem addr offset ty + in v :: vs', [] + with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) + | Store {offset; sz; _}, v :: I32 i :: vs' -> let mem = memory frame.inst (0l @@ e.at) in let addr = I64_convert.extend_i32_u i in diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index 9fb1b30fb..640dbf732 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -122,23 +122,6 @@ let extend x n = function | ZX -> x | SX -> let sh = 64 - 8 * n in Int64.(shift_right (shift_left x sh) sh) -let load_simd_packed sz ext x = - let b = Bytes.create 16 in - Bytes.set_int64_le b 0 x; - let v = V128.of_bits (Bytes.to_string b) in - match sz, ext with - | (Pack8x8, SX) -> V128 (V128.I16x8_convert.widen_low_s v) - | (Pack8x8, ZX) -> V128 (V128.I16x8_convert.widen_low_u v) - | (Pack16x4, SX) -> V128 (V128.I32x4_convert.widen_low_s v) - | (Pack16x4, ZX) -> V128 (V128.I32x4_convert.widen_low_u v) - | (Pack32x2, SX) -> V128 (V128.I64x2_convert.widen_low_s v) - | (Pack32x2, ZX) -> V128 (V128.I64x2_convert.widen_low_u v) - | (Pack8, ZX) -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) - | (Pack16, ZX) -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) - | (Pack32, ZX) -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) - | (Pack64, ZX) -> V128 (V128.I64x2.splat x) - | _ -> assert false - let load_packed sz ext mem a o t = assert (packed_size sz <= Types.size t); let n = packed_size sz in @@ -146,7 +129,6 @@ let load_packed sz ext mem a o t = match t with | I32Type -> I32 (Int64.to_int32 x) | I64Type -> I64 x - | V128Type -> load_simd_packed sz ext x | _ -> raise Type let store_packed sz mem a o v = @@ -158,3 +140,26 @@ let store_packed sz mem a o v = | I64 x -> x | _ -> raise Type in storen mem a o n x + +let load_simd_packed simd_load mem a o t = + let ext = match simd_load with + | PackExtend (_, ext) -> ext + | _ -> ZX + in + let n = packed_simd_size simd_load in + let x = extend (loadn mem a o n) n ext in + let b = Bytes.create 16 in + Bytes.set_int64_le b 0 x; + let v = V128.of_bits (Bytes.to_string b) in + match simd_load with + | PackExtend (Pack8, SX) -> V128 (V128.I16x8_convert.widen_low_s v) + | PackExtend (Pack8, ZX) -> V128 (V128.I16x8_convert.widen_low_u v) + | PackExtend (Pack16, SX) -> V128 (V128.I32x4_convert.widen_low_s v) + | PackExtend (Pack16, ZX) -> V128 (V128.I32x4_convert.widen_low_u v) + | PackExtend (Pack32, SX) -> V128 (V128.I64x2_convert.widen_low_s v) + | PackExtend (Pack32, ZX) -> V128 (V128.I64x2_convert.widen_low_u v) + | PackSplat (Pack8) -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) + | PackSplat (Pack16) -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) + | PackSplat (Pack32) -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) + | PackSplat (Pack64) -> V128 (V128.I64x2.splat x) + | _ -> assert false diff --git a/interpreter/runtime/memory.mli b/interpreter/runtime/memory.mli index f611e4647..8c90d0371 100644 --- a/interpreter/runtime/memory.mli +++ b/interpreter/runtime/memory.mli @@ -38,3 +38,6 @@ val load_packed : val store_packed : pack_size -> memory -> address -> offset -> value -> unit (* raises Type, Bounds *) +val load_simd_packed : + pack_simd -> memory -> address -> offset -> value_type -> value + (* raises Type, Bounds *) diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index eb976f57f..8820ccb9f 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -111,6 +111,7 @@ type 'a memop = type loadop = (pack_size * extension) memop type storeop = pack_size memop +type simd_loadop = pack_simd memop (* Expressions *) @@ -141,6 +142,7 @@ and instr' = | GlobalGet of var (* read global variable *) | GlobalSet of var (* write global variable *) | Load of loadop (* read memory at address *) + | SimdLoad of simd_loadop (* read memory at address *) | Store of storeop (* write memory at address *) | MemorySize (* size of linear memory *) | MemoryGrow (* grow linear memory *) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index 33568f87f..9b472871c 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -217,27 +217,27 @@ let memory_size = MemorySize let memory_grow = MemoryGrow (* SIMD *) -let v128_load align offset = Load {ty = V128Type; align; offset; sz = None} +let v128_load align offset = SimdLoad {ty = V128Type; align; offset; sz = None} let i16x8_load8x8_s align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack8x8, SX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack8, SX))} let i16x8_load8x8_u align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack8x8, ZX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack8, ZX))} let i32x4_load16x4_s align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack16x4, SX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack16, SX))} let i32x4_load16x4_u align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack16x4, ZX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack16, ZX))} let i64x2_load32x2_s align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack32x2, SX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack32, SX))} let i64x2_load32x2_u align offset = - Load {ty = V128Type; align; offset; sz = Some (Pack32x2, ZX)} + SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack32, ZX))} let v8x16_load_splat align offset = - Load {ty= V128Type; align; offset; sz = Some (Pack8, ZX)} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack8))} let v16x8_load_splat align offset = - Load {ty= V128Type; align; offset; sz = Some (Pack16, ZX)} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack16))} let v32x4_load_splat align offset = - Load {ty= V128Type; align; offset; sz = Some (Pack32, ZX)} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack32))} let v64x2_load_splat align offset = - Load {ty= V128Type; align; offset; sz = Some (Pack64, ZX)} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack64))} let v128_store align offset = Store {ty = V128Type; align; offset; sz = None} let v128_not = Unary (V128 (V128Op.V128 V128Op.Not)) diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml index f67e16ed1..98c63d8e4 100644 --- a/interpreter/syntax/types.ml +++ b/interpreter/syntax/types.ml @@ -16,9 +16,11 @@ type extern_type = | ExternMemoryType of memory_type | ExternGlobalType of global_type -type pack_size = Pack8 | Pack16 | Pack32 | Pack64 | Pack8x8 | Pack16x4 | Pack32x2 +type pack_size = Pack8 | Pack16 | Pack32 | Pack64 type extension = SX | ZX - +type pack_simd = + | PackSplat of pack_size + | PackExtend of pack_size * extension (* Attributes *) @@ -31,7 +33,15 @@ let packed_size = function | Pack8 -> 1 | Pack16 -> 2 | Pack32 -> 4 - | Pack64 | Pack8x8 | Pack16x4 | Pack32x2 -> 8 + | Pack64 -> 8 + +let packed_simd_size = function + | PackSplat sx -> packed_size sx + | PackExtend _ -> 8 + +let pack_size_of_pack_simd = function + | PackSplat sx -> sx + | PackExtend _ -> Pack64 (* Subtyping *) diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index 26484d66a..d13ebf7e2 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -78,9 +78,6 @@ let pack_size = function | Pack16 -> "16" | Pack32 -> "32" | Pack64 -> "64" - | Pack8x8 -> "8x8" - | Pack16x4 -> "16x4" - | Pack32x2 -> "32x2" let extension = function | SX -> "_s" @@ -467,6 +464,7 @@ let rec instr e = | GlobalGet x -> "global.get " ^ var x, [] | GlobalSet x -> "global.set " ^ var x, [] | Load op -> loadop op, [] + | SimdLoad op -> failwith "unimplemented SimdLoad arrange" | Store op -> storeop op, [] | MemorySize -> "memory.size", [] | MemoryGrow -> "memory.grow", [] diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index 4564820f4..a51ff945c 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -303,6 +303,10 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = check_memop c memop (Lib.Option.map fst) e.at; [I32Type] --> [memop.ty] + | SimdLoad memop -> + check_memop c memop (Lib.Option.map pack_size_of_pack_simd) e.at; + [I32Type] --> [memop.ty] + | Store memop -> check_memop c memop (fun sz -> sz) e.at; [I32Type; memop.ty] --> [] From c5d59f5e0189e80a4e5e39ec11a717e4f433da4a Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Thu, 27 Aug 2020 14:13:54 -0700 Subject: [PATCH 3/6] Reorder functions --- interpreter/runtime/memory.ml | 20 ++++++++++---------- interpreter/runtime/memory.mli | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index 640dbf732..b51c3b829 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -131,16 +131,6 @@ let load_packed sz ext mem a o t = | I64Type -> I64 x | _ -> raise Type -let store_packed sz mem a o v = - assert (packed_size sz <= Types.size (Values.type_of v)); - let n = packed_size sz in - let x = - match v with - | I32 x -> Int64.of_int32 x - | I64 x -> x - | _ -> raise Type - in storen mem a o n x - let load_simd_packed simd_load mem a o t = let ext = match simd_load with | PackExtend (_, ext) -> ext @@ -163,3 +153,13 @@ let load_simd_packed simd_load mem a o t = | PackSplat (Pack32) -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) | PackSplat (Pack64) -> V128 (V128.I64x2.splat x) | _ -> assert false + +let store_packed sz mem a o v = + assert (packed_size sz <= Types.size (Values.type_of v)); + let n = packed_size sz in + let x = + match v with + | I32 x -> Int64.of_int32 x + | I64 x -> x + | _ -> raise Type + in storen mem a o n x diff --git a/interpreter/runtime/memory.mli b/interpreter/runtime/memory.mli index 8c90d0371..5affaf36f 100644 --- a/interpreter/runtime/memory.mli +++ b/interpreter/runtime/memory.mli @@ -35,9 +35,9 @@ val store_value : val load_packed : pack_size -> extension -> memory -> address -> offset -> value_type -> value (* raises Type, Bounds *) -val store_packed : - pack_size -> memory -> address -> offset -> value -> unit - (* raises Type, Bounds *) val load_simd_packed : pack_simd -> memory -> address -> offset -> value_type -> value (* raises Type, Bounds *) +val store_packed : + pack_size -> memory -> address -> offset -> value -> unit + (* raises Type, Bounds *) From 38045d7ea7a1d523e9ebb0408a5570a56458c4c9 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Thu, 27 Aug 2020 14:14:18 -0700 Subject: [PATCH 4/6] Formatting --- interpreter/syntax/operators.ml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index 9b472871c..005d11dd7 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -231,13 +231,13 @@ let i64x2_load32x2_s align offset = let i64x2_load32x2_u align offset = SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack32, ZX))} let v8x16_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack8))} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack8)} let v16x8_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack16))} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack16)} let v32x4_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack32))} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack32)} let v64x2_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat (Pack64))} + SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack64)} let v128_store align offset = Store {ty = V128Type; align; offset; sz = None} let v128_not = Unary (V128 (V128Op.V128 V128Op.Not)) From 0f07076d0df7c9fd4a554d4c11ac605a6f44b082 Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Thu, 27 Aug 2020 14:18:24 -0700 Subject: [PATCH 5/6] Simplify simd packed loads --- interpreter/runtime/memory.ml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index b51c3b829..93deb52d6 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -132,12 +132,9 @@ let load_packed sz ext mem a o t = | _ -> raise Type let load_simd_packed simd_load mem a o t = - let ext = match simd_load with - | PackExtend (_, ext) -> ext - | _ -> ZX - in let n = packed_simd_size simd_load in - let x = extend (loadn mem a o n) n ext in + assert (n <= Types.size t); + let x = loadn mem a o n in let b = Bytes.create 16 in Bytes.set_int64_le b 0 x; let v = V128.of_bits (Bytes.to_string b) in From e8b2f1f3b498fc2f3ab1d78f8824c8d9b3d5aa3e Mon Sep 17 00:00:00 2001 From: Ng Zhi An Date: Fri, 28 Aug 2020 09:53:20 -0700 Subject: [PATCH 6/6] Add SimdStore and make simd_loadop more consistent --- interpreter/exec/eval.ml | 10 +++++++++- interpreter/runtime/memory.ml | 26 +++++++++++++------------- interpreter/runtime/memory.mli | 2 +- interpreter/syntax/ast.ml | 7 +++++-- interpreter/syntax/operators.ml | 22 +++++++++++----------- interpreter/syntax/types.ml | 14 ++++---------- interpreter/text/arrange.ml | 1 + interpreter/valid/valid.ml | 6 +++++- 8 files changed, 49 insertions(+), 39 deletions(-) diff --git a/interpreter/exec/eval.ml b/interpreter/exec/eval.ml index f764c2191..14135ea0c 100644 --- a/interpreter/exec/eval.ml +++ b/interpreter/exec/eval.ml @@ -227,7 +227,7 @@ let rec step (c : config) : config = let v = match sz with | None -> Memory.load_value mem addr offset ty - | Some (simd_load) -> Memory.load_simd_packed simd_load mem addr offset ty + | Some (pack_size, simd_load) -> Memory.load_simd_packed pack_size simd_load mem addr offset ty in v :: vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]) @@ -242,6 +242,14 @@ let rec step (c : config) : config = vs', [] with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]); + | SimdStore {offset; sz; _}, v :: I32 i :: vs' -> + let mem = memory frame.inst (0l @@ e.at) in + let addr = I64_convert.extend_i32_u i in + (try + Memory.store_value mem addr offset v; + vs', [] + with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at]); + | MemorySize, vs -> let mem = memory frame.inst (0l @@ e.at) in I32 (Memory.size mem) :: vs, [] diff --git a/interpreter/runtime/memory.ml b/interpreter/runtime/memory.ml index 93deb52d6..ffb65432f 100644 --- a/interpreter/runtime/memory.ml +++ b/interpreter/runtime/memory.ml @@ -131,24 +131,24 @@ let load_packed sz ext mem a o t = | I64Type -> I64 x | _ -> raise Type -let load_simd_packed simd_load mem a o t = - let n = packed_simd_size simd_load in +let load_simd_packed pack_size simd_load mem a o t = + let n = packed_size pack_size in assert (n <= Types.size t); let x = loadn mem a o n in let b = Bytes.create 16 in Bytes.set_int64_le b 0 x; let v = V128.of_bits (Bytes.to_string b) in - match simd_load with - | PackExtend (Pack8, SX) -> V128 (V128.I16x8_convert.widen_low_s v) - | PackExtend (Pack8, ZX) -> V128 (V128.I16x8_convert.widen_low_u v) - | PackExtend (Pack16, SX) -> V128 (V128.I32x4_convert.widen_low_s v) - | PackExtend (Pack16, ZX) -> V128 (V128.I32x4_convert.widen_low_u v) - | PackExtend (Pack32, SX) -> V128 (V128.I64x2_convert.widen_low_s v) - | PackExtend (Pack32, ZX) -> V128 (V128.I64x2_convert.widen_low_u v) - | PackSplat (Pack8) -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) - | PackSplat (Pack16) -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) - | PackSplat (Pack32) -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) - | PackSplat (Pack64) -> V128 (V128.I64x2.splat x) + match pack_size, simd_load with + | Pack64, Pack8x8 SX -> V128 (V128.I16x8_convert.widen_low_s v) + | Pack64, Pack8x8 ZX -> V128 (V128.I16x8_convert.widen_low_u v) + | Pack64, Pack16x4 SX -> V128 (V128.I32x4_convert.widen_low_s v) + | Pack64, Pack16x4 ZX -> V128 (V128.I32x4_convert.widen_low_u v) + | Pack64, Pack32x2 SX -> V128 (V128.I64x2_convert.widen_low_s v) + | Pack64, Pack32x2 ZX -> V128 (V128.I64x2_convert.widen_low_u v) + | Pack8, PackSplat -> V128 (V128.I8x16.splat (I8.of_int_s (Int64.to_int x))) + | Pack16, PackSplat -> V128 (V128.I16x8.splat (I16.of_int_s (Int64.to_int x))) + | Pack32, PackSplat -> V128 (V128.I32x4.splat (I32.of_int_s (Int64.to_int x))) + | Pack64, PackSplat -> V128 (V128.I64x2.splat x) | _ -> assert false let store_packed sz mem a o v = diff --git a/interpreter/runtime/memory.mli b/interpreter/runtime/memory.mli index 5affaf36f..7936d0241 100644 --- a/interpreter/runtime/memory.mli +++ b/interpreter/runtime/memory.mli @@ -36,7 +36,7 @@ val load_packed : pack_size -> extension -> memory -> address -> offset -> value_type -> value (* raises Type, Bounds *) val load_simd_packed : - pack_simd -> memory -> address -> offset -> value_type -> value + pack_size -> pack_simd -> memory -> address -> offset -> value_type -> value (* raises Type, Bounds *) val store_packed : pack_size -> memory -> address -> offset -> value -> unit diff --git a/interpreter/syntax/ast.ml b/interpreter/syntax/ast.ml index 8820ccb9f..1a73ec0c1 100644 --- a/interpreter/syntax/ast.ml +++ b/interpreter/syntax/ast.ml @@ -111,7 +111,9 @@ type 'a memop = type loadop = (pack_size * extension) memop type storeop = pack_size memop -type simd_loadop = pack_simd memop +type simd_loadop = (pack_size * pack_simd) memop +type empty = | +type simd_storeop = empty memop (* Expressions *) @@ -142,8 +144,9 @@ and instr' = | GlobalGet of var (* read global variable *) | GlobalSet of var (* write global variable *) | Load of loadop (* read memory at address *) - | SimdLoad of simd_loadop (* read memory at address *) | Store of storeop (* write memory at address *) + | SimdLoad of simd_loadop (* read memory at address *) + | SimdStore of simd_storeop (* write memory at address *) | MemorySize (* size of linear memory *) | MemoryGrow (* grow linear memory *) | Const of literal (* constant *) diff --git a/interpreter/syntax/operators.ml b/interpreter/syntax/operators.ml index 005d11dd7..8ac4feea0 100644 --- a/interpreter/syntax/operators.ml +++ b/interpreter/syntax/operators.ml @@ -219,26 +219,26 @@ let memory_grow = MemoryGrow (* SIMD *) let v128_load align offset = SimdLoad {ty = V128Type; align; offset; sz = None} let i16x8_load8x8_s align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack8, SX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack8x8 SX)} let i16x8_load8x8_u align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack8, ZX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack8x8 ZX)} let i32x4_load16x4_s align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack16, SX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack16x4 SX)} let i32x4_load16x4_u align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack16, ZX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack16x4 ZX)} let i64x2_load32x2_s align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack32, SX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack32x2 SX)} let i64x2_load32x2_u align offset = - SimdLoad {ty = V128Type; align; offset; sz = Some (PackExtend (Pack32, ZX))} + SimdLoad {ty = V128Type; align; offset; sz = Some (Pack64, Pack32x2 ZX)} let v8x16_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack8)} + SimdLoad {ty= V128Type; align; offset; sz = Some (Pack8, PackSplat)} let v16x8_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack16)} + SimdLoad {ty= V128Type; align; offset; sz = Some (Pack16, PackSplat)} let v32x4_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack32)} + SimdLoad {ty= V128Type; align; offset; sz = Some (Pack32, PackSplat)} let v64x2_load_splat align offset = - SimdLoad {ty= V128Type; align; offset; sz = Some (PackSplat Pack64)} -let v128_store align offset = Store {ty = V128Type; align; offset; sz = None} + SimdLoad {ty= V128Type; align; offset; sz = Some (Pack64, PackSplat)} +let v128_store align offset = SimdStore {ty = V128Type; align; offset; sz = None} let v128_not = Unary (V128 (V128Op.V128 V128Op.Not)) let v128_and = Binary (V128 (V128Op.V128 V128Op.And)) diff --git a/interpreter/syntax/types.ml b/interpreter/syntax/types.ml index 98c63d8e4..4b440e196 100644 --- a/interpreter/syntax/types.ml +++ b/interpreter/syntax/types.ml @@ -19,8 +19,10 @@ type extern_type = type pack_size = Pack8 | Pack16 | Pack32 | Pack64 type extension = SX | ZX type pack_simd = - | PackSplat of pack_size - | PackExtend of pack_size * extension + | PackSplat + | Pack8x8 of extension + | Pack16x4 of extension + | Pack32x2 of extension (* Attributes *) @@ -35,14 +37,6 @@ let packed_size = function | Pack32 -> 4 | Pack64 -> 8 -let packed_simd_size = function - | PackSplat sx -> packed_size sx - | PackExtend _ -> 8 - -let pack_size_of_pack_simd = function - | PackSplat sx -> sx - | PackExtend _ -> Pack64 - (* Subtyping *) let match_limits lim1 lim2 = diff --git a/interpreter/text/arrange.ml b/interpreter/text/arrange.ml index d13ebf7e2..7a146f79c 100644 --- a/interpreter/text/arrange.ml +++ b/interpreter/text/arrange.ml @@ -465,6 +465,7 @@ let rec instr e = | GlobalSet x -> "global.set " ^ var x, [] | Load op -> loadop op, [] | SimdLoad op -> failwith "unimplemented SimdLoad arrange" + | SimdStore op -> failwith "unimplemented SimdStore arrange" | Store op -> storeop op, [] | MemorySize -> "memory.size", [] | MemoryGrow -> "memory.grow", [] diff --git a/interpreter/valid/valid.ml b/interpreter/valid/valid.ml index a51ff945c..7a6dd4f17 100644 --- a/interpreter/valid/valid.ml +++ b/interpreter/valid/valid.ml @@ -304,13 +304,17 @@ let rec check_instr (c : context) (e : instr) (s : infer_stack_type) : op_type = [I32Type] --> [memop.ty] | SimdLoad memop -> - check_memop c memop (Lib.Option.map pack_size_of_pack_simd) e.at; + check_memop c memop (Lib.Option.map fst) e.at; [I32Type] --> [memop.ty] | Store memop -> check_memop c memop (fun sz -> sz) e.at; [I32Type; memop.ty] --> [] + | SimdStore memop -> + check_memop c memop (fun _ -> None) e.at; + [I32Type; memop.ty] --> [] + | MemorySize -> ignore (memory c (0l @@ e.at)); [] --> [I32Type]