Skip to content
This repository was archived by the owner on Dec 22, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions interpreter/binary/decode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,22 @@ let simd_prefix s =
| 0x50l -> v128_or
| 0x51l -> v128_xor
| 0x52l -> v128_bitselect
| 0x58l ->
let a, o = memop s in
let lane = u8 s in
v128_load8_lane a o lane
| 0x59l ->
let a, o = memop s in
let lane = u8 s in
v128_load16_lane a o lane
| 0x5al ->
let a, o = memop s in
let lane = u8 s in
v128_load32_lane a o lane
| 0x5bl ->
let a, o = memop s in
let lane = u8 s in
v128_load64_lane a o lane
| 0x60l -> i8x16_abs
| 0x61l -> i8x16_neg
| 0x62l -> i8x16_any_true
Expand Down
9 changes: 9 additions & 0 deletions interpreter/binary/encode.ml
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,15 @@ let encode m =
| SimdLoad ({ty= V128Type; sz = Some (Pack64, PackZero); _} as mo) ->
simd_op 0xfdl; memop mo

| SimdLoadLane ({ty = V128Type; sz = Some Pack8; _} as mo, i) ->
simd_op 0x58l; memop mo; u8 i;
| SimdLoadLane ({ty = V128Type; sz = Some Pack16; _} as mo, i) ->
simd_op 0x59l; memop mo; u8 i;
| SimdLoadLane ({ty = V128Type; sz = Some Pack32; _} as mo, i) ->
simd_op 0x5al; memop mo; u8 i;
| SimdLoadLane ({ty = V128Type; sz = Some Pack64; _} as mo, i) ->
simd_op 0x5bl; memop mo; u8 i;

| Store ({ty = I32Type; sz = None; _} as mo) -> op 0x36; memop mo
| Store ({ty = I64Type; sz = None; _} as mo) -> op 0x37; memop mo
| Store ({ty = F32Type; sz = None; _} as mo) -> op 0x38; memop mo
Expand Down
15 changes: 14 additions & 1 deletion interpreter/exec/eval.ml
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,20 @@ let rec step (c : config) : config =
let v =
match sz with
| None -> Memory.load_value mem addr offset ty
| Some (pack_size, simd_load) -> Memory.load_simd_packed pack_size simd_load mem addr offset ty
| Some (pack_size, simd_load) ->
V128 (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])

| SimdLoadLane ({offset; ty; sz; _}, j), V128 v128 :: 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 -> assert false
| Some pack_size ->
V128 (Memory.load_simd_lane v128 pack_size mem addr offset ty j)
in v :: vs', []
with exn -> vs', [Trapping (memory_error e.at exn) @@ e.at])

Expand Down
34 changes: 22 additions & 12 deletions interpreter/runtime/memory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -139,20 +139,30 @@ let load_simd_packed pack_size simd_load mem a o t =
Bytes.set_int64_le b 0 x;
let v = V128.of_bits (Bytes.to_string b) in
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)
| Pack32, PackZero -> V128 v
| Pack64, PackZero -> V128 v
| Pack64, Pack8x8 SX -> V128.I16x8_convert.widen_low_s v
| Pack64, Pack8x8 ZX -> V128.I16x8_convert.widen_low_u v
| Pack64, Pack16x4 SX -> V128.I32x4_convert.widen_low_s v
| Pack64, Pack16x4 ZX -> V128.I32x4_convert.widen_low_u v
| Pack64, Pack32x2 SX -> V128.I64x2_convert.widen_low_s v
| Pack64, Pack32x2 ZX -> V128.I64x2_convert.widen_low_u v
| Pack8, PackSplat -> V128.I8x16.splat (I8.of_int_s (Int64.to_int x))
| Pack16, PackSplat -> V128.I16x8.splat (I16.of_int_s (Int64.to_int x))
| Pack32, PackSplat -> V128.I32x4.splat (I32.of_int_s (Int64.to_int x))
| Pack64, PackSplat -> V128.I64x2.splat x
| Pack32, PackZero -> v
| Pack64, PackZero -> v
| _ -> assert false

let load_simd_lane v pack_size mem a o t laneidx =
let n = packed_size pack_size in
assert (n < Types.size t);
let x = loadn mem a o n in
match pack_size with
| Pack8 -> V128.I8x16.replace_lane laneidx v (Int64.to_int32 x)
| Pack16 -> V128.I16x8.replace_lane laneidx v (Int64.to_int32 x)
| Pack32 -> V128.I32x4.replace_lane laneidx v (Int64.to_int32 x)
| Pack64 -> V128.I64x2.replace_lane laneidx v x

let store_packed sz mem a o v =
assert (packed_size sz <= Types.size (Values.type_of v));
let n = packed_size sz in
Expand Down
4 changes: 3 additions & 1 deletion interpreter/runtime/memory.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ val load_packed :
pack_size -> extension -> memory -> address -> offset -> value_type -> value
(* raises Type, Bounds *)
val load_simd_packed :
pack_size -> pack_simd -> memory -> address -> offset -> value_type -> value
pack_size -> pack_simd -> memory -> address -> offset -> value_type -> V128.t
(* raises Type, Bounds *)
val load_simd_lane :
V128.t -> pack_size -> memory -> address -> offset -> value_type -> int (* lane index *) -> V128.t
val store_packed :
pack_size -> memory -> address -> offset -> value -> unit
(* raises Type, Bounds *)
2 changes: 2 additions & 0 deletions interpreter/syntax/ast.ml
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ type storeop = pack_size memop
type simd_loadop = (pack_size * pack_simd) memop
type empty
type simd_storeop = empty memop
type simd_laneop = pack_size memop * int

(* Expressions *)

Expand Down Expand Up @@ -146,6 +147,7 @@ and instr' =
| Load of loadop (* read memory at address *)
| Store of storeop (* write memory at address *)
| SimdLoad of simd_loadop (* read memory at address *)
| SimdLoadLane of simd_laneop (* read single lane at address *)
| SimdStore of simd_storeop (* write memory at address *)
| MemorySize (* size of linear memory *)
| MemoryGrow (* grow linear memory *)
Expand Down
9 changes: 9 additions & 0 deletions interpreter/syntax/operators.ml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,15 @@ let v128_load32_splat align offset =
let v128_load64_splat align offset =
SimdLoad {ty= V128Type; align; offset; sz = Some (Pack64, PackSplat)}

let v128_load8_lane align offset imm =
SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack8}, imm)
let v128_load16_lane align offset imm =
SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack16}, imm)
let v128_load32_lane align offset imm =
SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack32}, imm)
let v128_load64_lane align offset imm =
SimdLoadLane ({ty = V128Type; align; offset; sz = Some Pack64}, imm)

let v128_load32_zero align offset =
SimdLoad {ty= V128Type; align; offset; sz = Some (Pack32, PackZero)}
let v128_load64_zero align offset =
Expand Down
13 changes: 13 additions & 0 deletions interpreter/text/arrange.ml
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,18 @@ let simd_loadop (op : simd_loadop) =
) in
memop ("load" ^ suffix) op (packed_size sz)

let simd_laneop (op, i) =
match op.sz with
| None -> assert false
| Some sz ->
let suffix =
match sz with
| Pack8 -> "8_lane"
| Pack16 -> "16_lane"
| Pack32 -> "32_lane"
| Pack64 -> "64_lane"
in memop ("load" ^ suffix) op (packed_size sz) ^ " " ^ (nat i)

let storeop op =
match op.sz with
| None -> memop "store" op (size op.ty)
Expand Down Expand Up @@ -503,6 +515,7 @@ let rec instr e =
| GlobalSet x -> "global.set " ^ var x, []
| Load op -> loadop op, []
| SimdLoad op -> simd_loadop op, []
| SimdLoadLane op -> simd_laneop op, []
| SimdStore op -> simd_storeop op, []
| Store op -> storeop op, []
| MemorySize -> "memory.size", []
Expand Down
8 changes: 8 additions & 0 deletions interpreter/text/lexer.mll
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,14 @@ rule token = parse
{ LOAD (fun a o -> (v128_load32_zero (opt a 2)) o) }
| "v128.load64_zero"
{ LOAD (fun a o -> (v128_load64_zero (opt a 3)) o) }
| "v128.load8_lane"
{ SIMD_LOAD_LANE (fun a o i -> (v128_load8_lane (opt a 0)) o i) }
| "v128.load16_lane"
{ SIMD_LOAD_LANE (fun a o i -> (v128_load16_lane (opt a 1)) o i) }
| "v128.load32_lane"
{ SIMD_LOAD_LANE (fun a o i -> (v128_load32_lane (opt a 2)) o i) }
| "v128.load64_lane"
{ SIMD_LOAD_LANE (fun a o i -> (v128_load64_lane (opt a 3)) o i) }
| (ixx as t)".store"(mem_size as sz)
{ if t = "i32" && sz = "32" then error lexbuf "unknown operator";
STORE (fun a o ->
Expand Down
4 changes: 3 additions & 1 deletion interpreter/text/parser.mly
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ let inline_type_explicit (c : context) x ft at =
%token NOP DROP BLOCK END IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE
%token CALL CALL_INDIRECT RETURN
%token LOCAL_GET LOCAL_SET LOCAL_TEE GLOBAL_GET GLOBAL_SET
%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT
%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT SIMD_LOAD_LANE
%token SPLAT EXTRACT_LANE REPLACE_LANE SHIFT SHUFFLE
%token CONST V128_CONST UNARY BINARY TERNARY TEST COMPARE CONVERT
%token UNREACHABLE MEMORY_SIZE MEMORY_GROW
Expand Down Expand Up @@ -232,6 +232,7 @@ let inline_type_explicit (c : context) x ft at =
%token<Ast.instr'> COMPARE
%token<Ast.instr'> CONVERT
%token<int option -> Memory.offset -> Ast.instr'> LOAD
%token<int option -> Memory.offset -> int -> Ast.instr'> SIMD_LOAD_LANE
%token<Ast.instr'> SPLAT
%token<int -> Ast.instr'> EXTRACT_LANE
%token<int -> Ast.instr'> REPLACE_LANE
Expand Down Expand Up @@ -385,6 +386,7 @@ plain_instr :
| GLOBAL_GET var { fun c -> global_get ($2 c global) }
| GLOBAL_SET var { fun c -> global_set ($2 c global) }
| LOAD offset_opt align_opt { fun c -> $1 $3 $2 }
| SIMD_LOAD_LANE offset_opt align_opt NAT { let at = at () in fun c -> $1 $3 $2 (simd_lane_index $4 at) }
| STORE offset_opt align_opt { fun c -> $1 $3 $2 }
| MEMORY_SIZE { fun c -> memory_size }
| MEMORY_GROW { fun c -> memory_grow }
Expand Down
8 changes: 8 additions & 0 deletions interpreter/valid/valid.ml
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,14 @@ 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]

| SimdLoadLane (memop, i) ->
check_memop c memop (fun o -> o) e.at;
(match memop.sz with
| Some pack_size ->
require (i < 16 / packed_size pack_size) e.at "invalid lane index";
[I32Type; V128Type] --> [memop.ty]
| _ -> assert false)

| Store memop ->
check_memop c memop (fun sz -> sz) e.at;
[I32Type; memop.ty] --> []
Expand Down
1 change: 1 addition & 0 deletions test/core/simd/meta/gen_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
'simd_f32x4_pmin_pmax',
'simd_f64x2_pmin_pmax',
'simd_i32x4_dot_i16x8',
'simd_load_lane',
)


Expand Down
4 changes: 2 additions & 2 deletions test/core/simd/meta/simd.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def const(value, value_type):
value: constant data, string or list,
lane_type: lane type, [i32, i64, f32, f64]
"""
return SIMD.CONST.format(value_type=value_type, value=''.join(value))
return SIMD.CONST.format(value_type=value_type, value=''.join(str(value)))

@staticmethod
def v128_const(value, lane_type):
Expand Down Expand Up @@ -81,4 +81,4 @@ def v128_const(value, lane_type):
data_elem = ' '.join(data_elem)

# Returns v128 constant text
return SIMD.V128_CONST.format(lane_type=lane_type, value=data_elem)
return SIMD.V128_CONST.format(lane_type=lane_type, value=data_elem)
Loading