Skip to content

Commit 6e728c0

Browse files
authored
[interpreter/test] Implement new array allocation instructions (WebAssembly#283)
1 parent fc5c49e commit 6e728c0

32 files changed

+496
-190
lines changed

interpreter/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,9 @@ op:
304304
struct.get(_<sign>)? <var> <var>
305305
struct.set <var> <var>
306306
array.new(_<default>)? <var>
307+
array.new_fixed <var> <nat>
308+
array.new_elem <var> <var>
309+
array.new_data <var> <var>
307310
array.get(_<sign>)? <var>
308311
array.set <var>
309312
array.len <var>

interpreter/binary/decode.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -593,6 +593,10 @@ let rec instr s =
593593
| 0x16l -> array_set (at var s)
594594
| 0x17l -> let _ = var s in array_len (* TODO: remove var *)
595595

596+
| 0x19l -> let x = at var s in let n = u32 s in array_new_fixed x n
597+
| 0x1bl -> let x = at var s in let y = at var s in array_new_data x y
598+
| 0x1cl -> let x = at var s in let y = at var s in array_new_elem x y
599+
596600
| 0x20l -> i31_new
597601
| 0x21l -> i31_get_s
598602
| 0x22l -> i31_get_u

interpreter/binary/encode.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,6 +397,9 @@ struct
397397

398398
| ArrayNew (x, Explicit) -> op 0xfb; op 0x11; var x
399399
| ArrayNew (x, Implicit) -> op 0xfb; op 0x12; var x
400+
| ArrayNewFixed (x, n) -> op 0xfb; op 0x19; var x; u32 n
401+
| ArrayNewElem (x, y) -> op 0xfb; op 0x1c; var x; var y
402+
| ArrayNewData (x, y) -> op 0xfb; op 0x1b; var x; var y
400403
| ArrayGet (x, None) -> op 0xfb; op 0x13; var x
401404
| ArrayGet (x, Some SX) -> op 0xfb; op 0x14; var x
402405
| ArrayGet (x, Some ZX) -> op 0xfb; op 0x15; var x

interpreter/exec/eval.ml

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,13 @@ let rec step (c : config) : config =
173173
let FuncType (ts1, ts2) = block_type c.frame.inst bt e.at in
174174
let n1 = List.length ts1 in
175175
let n2 = List.length ts2 in
176-
let args, vs' = take n1 vs e.at, drop n1 vs e.at in
176+
let args, vs' = split n1 vs e.at in
177177
vs', [Label (n2, [], (args, List.map plain es')) @@ e.at]
178178

179179
| Loop (bt, es'), vs ->
180180
let FuncType (ts1, ts2) = block_type c.frame.inst bt e.at in
181181
let n1 = List.length ts1 in
182-
let args, vs' = take n1 vs e.at, drop n1 vs e.at in
182+
let args, vs' = split n1 vs e.at in
183183
vs', [Label (n1, [e' @@ e.at], (args, List.map plain es')) @@ e.at]
184184

185185
| If (bt, es1, es2), Num (I32 i) :: vs' ->
@@ -813,11 +813,66 @@ let rec step (c : config) : config =
813813
try default_value (unpacked_storage_type st), vs'
814814
with Failure _ -> Crash.error e.at "non-defaultable type"
815815
in
816-
let data =
817-
try Data.alloc_array (type_ c.frame.inst x) rtt n arg
816+
let data =
817+
try Data.alloc_array (type_ c.frame.inst x) rtt (Lib.List32.make n arg)
818818
with Failure _ -> Crash.error e.at "type mismatch packing value"
819819
in Ref (Data.DataRef data) :: vs'', []
820820

821+
| ArrayNewFixed (x, n), Ref (Rtt.RttRef rtt) :: vs' ->
822+
let args, vs'' = split (I32.to_int_u n) vs' e.at in
823+
let data =
824+
try Data.alloc_array (type_ c.frame.inst x) rtt (List.rev args)
825+
with Failure _ -> Crash.error e.at "type mismatch packing value"
826+
in Ref (Data.DataRef data) :: vs'', []
827+
828+
| ArrayNewElem (x, y),
829+
Ref (Rtt.RttRef rtt) :: Num (I32 n) :: Num (I32 s) :: vs' ->
830+
if elem_oob c.frame y s n then
831+
vs', [Trapping (table_error e.at Table.Bounds) @@ e.at]
832+
else
833+
let seg = elem c.frame.inst y in
834+
let args =
835+
List.map (fun r -> Ref r) (Lib.List32.take n (Lib.List32.drop s !seg)) in
836+
let data =
837+
try Data.alloc_array (type_ c.frame.inst x) rtt args
838+
with Failure _ -> Crash.error e.at "type mismatch packing value"
839+
in Ref (Data.DataRef data) :: vs', []
840+
841+
| ArrayNewData (x, y),
842+
Ref (Rtt.RttRef rtt) :: Num (I32 n) :: Num (I32 s) :: vs' ->
843+
if data_oob c.frame y s n then
844+
vs', [Trapping (memory_error e.at Memory.Bounds) @@ e.at]
845+
else
846+
let ArrayType (FieldType (st, _)) = array_type c.frame.inst x in
847+
let seg = data c.frame.inst y in
848+
let bs = Bytes.of_string !seg in
849+
let args = Lib.List32.init n
850+
(fun i ->
851+
let j = I32.to_int_u s + I32.to_int_u i * storage_size st in
852+
match st with
853+
| PackedStorageType Pack8 ->
854+
Num (I32 (I32.of_int_u (Bytes.get_uint8 bs j)))
855+
| PackedStorageType Pack16 ->
856+
Num (I32 (I32.of_int_u (Bytes.get_uint16_le bs j)))
857+
| ValueStorageType (NumType I32Type) ->
858+
Num (I32 (Bytes.get_int32_le bs j))
859+
| ValueStorageType (NumType I64Type) ->
860+
Num (I64 (Bytes.get_int64_le bs j))
861+
| ValueStorageType (NumType F32Type) ->
862+
Num (F32 (F32.of_bits (Bytes.get_int32_le bs j)))
863+
| ValueStorageType (NumType F64Type) ->
864+
Num (F64 (F64.of_bits (Bytes.get_int64_le bs j)))
865+
| ValueStorageType (VecType V128Type) ->
866+
Vec (V128 (V128.of_bits (String.sub !seg j 16)))
867+
| _ ->
868+
Crash.error e.at "type mismatch packing value"
869+
)
870+
in
871+
let data =
872+
try Data.alloc_array (type_ c.frame.inst x) rtt args
873+
with Failure _ -> Crash.error e.at "type mismatch packing value"
874+
in Ref (Data.DataRef data) :: vs', []
875+
821876
| ArrayGet (x, exto), Num (I32 i) :: Ref (NullRef _) :: vs' ->
822877
vs', [Trapping "null array reference" @@ e.at]
823878

interpreter/runtime/data.ml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,9 @@ let alloc_struct x rtt vs =
4343
let StructType fts = as_struct_str_type (expand_ctx_type (def_of x)) in
4444
Struct (x, rtt, List.map2 alloc_field fts vs)
4545

46-
let alloc_array x rtt n v =
46+
let alloc_array x rtt vs =
4747
let ArrayType ft = as_array_str_type (expand_ctx_type (def_of x)) in
48-
Array (x, rtt, List.init (Int32.to_int n) (fun _ -> alloc_field ft v))
48+
Array (x, rtt, List.map (alloc_field ft) vs)
4949

5050

5151
let type_inst_of = function

interpreter/runtime/data.mli

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type t = data
1414
type ref_ += DataRef of data
1515

1616
val alloc_struct : sem_var -> Rtt.t -> value list -> data
17-
val alloc_array : sem_var -> Rtt.t -> int32 -> value -> data
17+
val alloc_array : sem_var -> Rtt.t -> value list -> data
1818

1919
val struct_type_of : data -> struct_type
2020
val array_type_of : data -> array_type

interpreter/syntax/ast.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ and instr' =
205205
| StructGet of idx * idx * extension option (* read structure field *)
206206
| StructSet of idx * idx (* write structure field *)
207207
| ArrayNew of idx * initop (* allocate array *)
208+
| ArrayNewFixed of idx * int32 (* allocate fixed array *)
209+
| ArrayNewElem of idx * idx (* allocate array from element segment *)
210+
| ArrayNewData of idx * idx (* allocate array from data segment *)
208211
| ArrayGet of idx * extension option (* read array slot *)
209212
| ArraySet of idx (* write array slot *)
210213
| ArrayLen (* read array length *)

interpreter/syntax/free.ml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,9 @@ let rec instr (e : instr) =
123123
| RefNull t -> heap_type t
124124
| RefFunc x -> funcs (idx x)
125125
| I31New | I31Get _ -> empty
126-
| StructNew (x, _) | ArrayNew (x, _) -> types (idx x)
126+
| StructNew (x, _) | ArrayNew (x, _) | ArrayNewFixed (x, _) -> types (idx x)
127+
| ArrayNewElem (x, y) -> types (idx x) ++ elems (idx y)
128+
| ArrayNewData (x, y) -> types (idx x) ++ datas (idx y)
127129
| StructGet (x, _, _) | StructSet (x, _) -> types (idx x)
128130
| ArrayGet (x, _) | ArraySet x -> types (idx x)
129131
| ArrayLen -> empty

interpreter/syntax/operators.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,9 @@ let struct_get_s x y = StructGet (x, y, Some SX)
133133
let struct_set x y = StructSet (x, y)
134134
let array_new x = ArrayNew (x, Explicit)
135135
let array_new_default x = ArrayNew (x, Implicit)
136+
let array_new_fixed x n = ArrayNewFixed (x, n)
137+
let array_new_elem x y = ArrayNewElem (x, y)
138+
let array_new_data x y = ArrayNewData (x, y)
136139
let array_get x = ArrayGet (x, None)
137140
let array_get_u x = ArrayGet (x, Some ZX)
138141
let array_get_s x = ArrayGet (x, Some SX)

interpreter/syntax/types.ml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ let num_size = function
7979
let vec_size = function
8080
| V128Type -> 16
8181

82+
let value_size = function
83+
| NumType t -> num_size t
84+
| VecType t -> vec_size t
85+
| RefType _ | BotType -> failwith "value_size"
86+
8287
let packed_size = function
8388
| Pack8 -> 1
8489
| Pack16 -> 2
@@ -88,11 +93,9 @@ let packed_size = function
8893
let packed_shape_size = function
8994
| Pack8x8 | Pack16x4 | Pack32x2 -> 8
9095

91-
92-
let is_packed_storage_type = function
93-
| ValueStorageType _ -> false
94-
| PackedStorageType _ -> true
95-
96+
let storage_size = function
97+
| PackedStorageType pt -> packed_size pt
98+
| ValueStorageType t -> value_size t
9699

97100
let is_syn_var = function SynVar _ -> true | _ -> false
98101
let is_sem_var = function SemVar _ -> true | _ -> false
@@ -132,6 +135,11 @@ let defaultable_value_type = function
132135
| BotType -> assert false
133136

134137

138+
let is_packed_storage_type = function
139+
| ValueStorageType _ -> false
140+
| PackedStorageType _ -> true
141+
142+
135143
(* Projections *)
136144

137145
let unpacked_storage_type = function

0 commit comments

Comments
 (0)