Skip to content

Commit 5f4932b

Browse files
authored
Merge pull request WebAssembly#144 from ngzhian/v128-const
Add support for v128.const
2 parents 84b527f + 082e07b commit 5f4932b

File tree

7 files changed

+105
-35
lines changed

7 files changed

+105
-35
lines changed

interpreter/exec/eval_numeric.ml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,12 @@ end
116116
module F32Op = FloatOp (F32) (Values.F32Value)
117117
module F64Op = FloatOp (F64) (Values.F64Value)
118118

119-
(* Vector operators *)
119+
(* Simd operators *)
120120

121-
module VectorOp (VXX : Vector.S) (Value : ValueType with type t = VXX.t) =
121+
module SimdOp (VXX : Simd.S) (Value : ValueType with type t = VXX.t) =
122122
struct
123123
(* TODO
124-
open Ast.VectorOp
124+
open Ast.SimdOp
125125
126126
let to_value = Value.to_value
127127
let of_value = of_arg Value.of_value
@@ -140,7 +140,7 @@ struct
140140
let relop op = failwith "TODO v128"
141141
end
142142

143-
module V128Op = VectorOp (V128) (Values.V128Value)
143+
module V128Op = SimdOp (V128) (Values.V128Value)
144144

145145
(* Conversion operators *)
146146

@@ -209,7 +209,7 @@ end
209209
module V128CvtOp =
210210
struct
211211
(* TODO
212-
open Ast.VectorOp
212+
open Ast.SimdOp
213213
*)
214214

215215
(* FIXME *)

interpreter/exec/vector.ml renamed to interpreter/exec/simd.ml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
11
open Char
22

3+
type shape = I8x16 | I16x8 | I32x4 | I64x2 | F32x4 | F64x2
4+
5+
let lanes shape =
6+
match shape with
7+
| I8x16 -> 16
8+
| I16x8 -> 8
9+
| I32x4 -> 4
10+
| I64x2 -> 2
11+
| F32x4 -> 4
12+
| F64x2 -> 2
13+
314
module type RepType =
415
sig
516
type t
@@ -8,6 +19,7 @@ sig
819
(* ^ bits_make ? *)
920
val to_string : t -> string
1021
val bytewidth : int
22+
val of_strings : shape -> string list -> t
1123
end
1224

1325
module type S =
@@ -16,7 +28,9 @@ sig
1628
type bits
1729
val default : t (* FIXME good name for default value? *)
1830
val to_string : t -> string
31+
val of_bits : bits -> t
1932
val to_bits : t -> bits
33+
val of_strings : shape -> string list -> t
2034
end
2135

2236
module Make (Rep : RepType) : S with type bits = Rep.t =
@@ -27,4 +41,6 @@ struct
2741
let default = Rep.make Rep.bytewidth (chr 0)
2842
let to_string = Rep.to_string (* FIXME very very wrong *)
2943
let to_bits x = x
44+
let of_bits x = x
45+
let of_strings = Rep.of_strings
3046
end

interpreter/exec/v128.ml

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
1-
include Vector.Make
1+
include Simd.Make
22
(struct
33
include Bytes
44
let bytewidth = 16
5+
6+
let of_strings shape ss =
7+
if List.length ss <> Simd.lanes shape then raise (Invalid_argument "wrong length");
8+
let range_check i32 min max at =
9+
let i = Int32.to_int i32 in
10+
if i > max || i < min then raise (Failure "constant out of range") else i in
11+
(* TODO create proper I8 and I16 modules *)
12+
let i8_of_string s = range_check (I32.of_string s) (-128) 255 s in
13+
let i16_of_string s = range_check (I32.of_string s) (-32768) 65535 s in
14+
let open Bytes in
15+
let b = create bytewidth in
16+
(match shape with
17+
| Simd.I8x16 ->
18+
List.iteri (fun i s -> set_uint8 b i (i8_of_string s)) ss
19+
| Simd.I16x8 ->
20+
List.iteri (fun i s -> set_uint16_le b i (i16_of_string s)) ss
21+
| Simd.I32x4 ->
22+
List.iteri (fun i s -> set_int32_le b i (I32.of_string s)) ss
23+
| Simd.I64x2 ->
24+
List.iteri (fun i s -> set_int64_le b i (I64.of_string s)) ss
25+
| Simd.F32x4 ->
26+
List.iteri (fun i s -> set_int32_le b i (F32.to_bits (F32.of_string s))) ss
27+
| Simd.F64x2 ->
28+
List.iteri (fun i s -> set_int64_le b i (F64.to_bits (F64.of_string s))) ss);
29+
b
530
end)

interpreter/syntax/operators.ml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ let i32_const n = Const (I32 n.it @@ n.at)
99
let i64_const n = Const (I64 n.it @@ n.at)
1010
let f32_const n = Const (F32 n.it @@ n.at)
1111
let f64_const n = Const (F64 n.it @@ n.at)
12+
let v128_const n = Const (V128 n.it @@ n.at)
1213

1314
let unreachable = Unreachable
1415
let nop = Nop

interpreter/text/lexer.mll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,15 @@ let ext e s u =
8787
| _ -> assert false
8888

8989
let opt = Lib.Option.get
90+
91+
let simd_shape = function
92+
| "i8x16" -> Simd.I8x16
93+
| "i16x8" -> Simd.I16x8
94+
| "i32x4" -> Simd.I32x4
95+
| "i64x2" -> Simd.I64x2
96+
| "f32x4" -> Simd.F32x4
97+
| "f64x2" -> Simd.F64x2
98+
| _ -> assert false
9099
}
91100

92101
let sign = '+' | '-'
@@ -146,6 +155,7 @@ let mixx = "i" ("8" | "16" | "32" | "64")
146155
let mfxx = "f" ("32" | "64")
147156
let sign = "s" | "u"
148157
let mem_size = "8" | "16" | "32"
158+
let simd_shape = "i8x16" | "i16x8" | "i32x4" | "i64x2" | "f32x4" | "f64x2"
149159

150160
rule token = parse
151161
| "(" { LPAR }
@@ -163,6 +173,7 @@ rule token = parse
163173
{ error_nest (Lexing.lexeme_end_p lexbuf) lexbuf "illegal escape" }
164174

165175
| (nxx as t) { VALUE_TYPE (value_type t) }
176+
| (vxxx)".const" { V128_CONST }
166177
| (nxx as t)".const"
167178
{ let open Source in
168179
CONST (numop t
@@ -353,6 +364,8 @@ rule token = parse
353364
| "input" { INPUT }
354365
| "output" { OUTPUT }
355366

367+
| (simd_shape as s) { SIMD_SHAPE (simd_shape s) }
368+
356369
| name as s { VAR s }
357370

358371
| ";;"utf8_no_nl*eof { EOF }

interpreter/text/parser.mly

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,15 @@ let ati i =
3939
let literal f s =
4040
try f s with Failure _ -> error s.at "constant out of range"
4141

42+
let simd_literal shape ss at =
43+
try
44+
let v = V128.of_strings shape (List.map (fun s -> s.it) ss) in
45+
(v128_const (v @@ at), Values.V128 v)
46+
with
47+
(* TODO better location for error messages. *)
48+
| Failure _ -> error at "constant out of range"
49+
| Invalid_argument _ -> error at "wrong number of lane literals"
50+
4251
let nat s at =
4352
try
4453
let n = int_of_string s in
@@ -145,12 +154,12 @@ let inline_type_explicit (c : context) x ft at =
145154

146155
%}
147156

148-
%token NAT INT FLOAT STRING VAR VALUE_TYPE FUNCREF MUT LPAR RPAR
157+
%token NAT INT FLOAT STRING VAR VALUE_TYPE FUNCREF MUT LPAR RPAR SIMD_SHAPE
149158
%token NOP DROP BLOCK END IF THEN ELSE SELECT LOOP BR BR_IF BR_TABLE
150159
%token CALL CALL_INDIRECT RETURN
151160
%token LOCAL_GET LOCAL_SET LOCAL_TEE GLOBAL_GET GLOBAL_SET
152161
%token LOAD STORE OFFSET_EQ_NAT ALIGN_EQ_NAT
153-
%token CONST UNARY BINARY TEST COMPARE CONVERT
162+
%token CONST V128_CONST UNARY BINARY TEST COMPARE CONVERT
154163
%token UNREACHABLE MEMORY_SIZE MEMORY_GROW
155164
%token FUNC START TYPE PARAM RESULT LOCAL GLOBAL
156165
%token TABLE ELEM MEMORY DATA OFFSET IMPORT EXPORT TABLE
@@ -177,6 +186,7 @@ let inline_type_explicit (c : context) x ft at =
177186
%token<int option -> Memory.offset -> Ast.instr'> STORE
178187
%token<string> OFFSET_EQ_NAT
179188
%token<string> ALIGN_EQ_NAT
189+
%token<Simd.shape> SIMD_SHAPE
180190

181191
%nonassoc LOW
182192
%nonassoc VAR
@@ -247,6 +257,10 @@ literal :
247257
| INT { $1 @@ at () }
248258
| FLOAT { $1 @@ at () }
249259

260+
literal_list:
261+
| /* empty */ { [] }
262+
| literal literal_list { $1 :: $2 }
263+
250264
var :
251265
| NAT { let at = at () in fun c lookup -> nat32 $1 at @@ at }
252266
| VAR { let at = at () in fun c lookup -> lookup c ($1 @@ at) @@ at }
@@ -320,6 +334,7 @@ plain_instr :
320334
| MEMORY_SIZE { fun c -> memory_size }
321335
| MEMORY_GROW { fun c -> memory_grow }
322336
| CONST literal { fun c -> fst (literal $1 $2) }
337+
| V128_CONST SIMD_SHAPE literal_list { let at = at () in fun c -> fst (simd_literal $2 $3 at) }
323338
| TEST { fun c -> $1 }
324339
| COMPARE { fun c -> $1 }
325340
| UNARY { fun c -> $1 }
@@ -820,6 +835,9 @@ meta :
820835
821836
const :
822837
| LPAR CONST literal RPAR { snd (literal $2 $3) @@ ati 3 }
838+
| LPAR V128_CONST SIMD_SHAPE literal_list RPAR {
839+
snd (simd_literal $3 $4 (at ())) @@ ati 4
840+
}
823841
824842
const_list :
825843
| /* empty */ { [] }

test/core/simd/simd_const.wast

Lines changed: 24 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -174,22 +174,6 @@
174174
(module quote "(func (v128.const i32x4 -2147483649 -2147483649 -2147483649 -2147483649) drop)")
175175
"constant out of range"
176176
)
177-
(assert_malformed
178-
(module quote "(func (v128.const i32x4 0x10000000000000000 0x10000000000000000) drop)")
179-
"constant out of range"
180-
)
181-
(assert_malformed
182-
(module quote "(func (v128.const i32x4 -0x8000000000000001 -0x8000000000000001) drop)")
183-
"constant out of range"
184-
)
185-
(assert_malformed
186-
(module quote "(func (v128.const i32x4 18446744073709551616 18446744073709551616) drop)")
187-
"constant out of range"
188-
)
189-
(assert_malformed
190-
(module quote "(func (v128.const i32x4 -9223372036854775808 -9223372036854775808) drop)")
191-
"constant out of range"
192-
)
193177
(assert_malformed
194178
(module quote "(func (v128.const f32x4 0x1p128 0x1p128 0x1p128 0x1p128) drop)")
195179
"constant out of range"
@@ -246,7 +230,7 @@
246230

247231
(assert_malformed
248232
(module quote "(func (v128.const i8x16) drop)")
249-
"unexpected token"
233+
"wrong number of lane literals"
250234
)
251235
(assert_malformed
252236
(module quote "(func (v128.const i8x16 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x 0x) drop)")
@@ -263,7 +247,7 @@
263247

264248
(assert_malformed
265249
(module quote "(func (v128.const i16x8) drop)")
266-
"unexpected token"
250+
"wrong number of lane literals"
267251
)
268252
(assert_malformed
269253
(module quote "(func (v128.const i16x8 0x 0x 0x 0x 0x 0x 0x 0x) drop)")
@@ -280,7 +264,7 @@
280264

281265
(assert_malformed
282266
(module quote "(func (v128.const i32x4) drop)")
283-
"unexpected token"
267+
"wrong number of lane literals"
284268
)
285269
(assert_malformed
286270
(module quote "(func (v128.const i32x4 0x 0x 0x 0x) drop)")
@@ -297,7 +281,7 @@
297281

298282
(assert_malformed
299283
(module quote "(func (v128.const i64x2) drop)")
300-
"unexpected token"
284+
"wrong number of lane literals"
301285
)
302286
(assert_malformed
303287
(module quote "(func (v128.const i64x2 0x 0x) drop)")
@@ -314,7 +298,7 @@
314298

315299
(assert_malformed
316300
(module quote "(func (v128.const f32x4) drop)")
317-
"unexpected token"
301+
"wrong number of lane literals"
318302
)
319303
(assert_malformed
320304
(module quote "(func (v128.const f32x4 .0 .0 .0 .0) drop)")
@@ -394,12 +378,12 @@
394378
)
395379
(assert_malformed
396380
(module quote "(func (v128.const f32x4 nan:0x0 nan:0x0 nan:0x0 nan:0x0) drop)")
397-
"unknown operator"
381+
"constant out of range"
398382
)
399383

400384
(assert_malformed
401385
(module quote "(func (v128.const f64x2) drop)")
402-
"unexpected token"
386+
"wrong number of lane literals"
403387
)
404388
(assert_malformed
405389
(module quote "(func (v128.const f64x2 .0 .0) drop)")
@@ -479,7 +463,20 @@
479463
)
480464
(assert_malformed
481465
(module quote "(func (v128.const f64x2 nan:0x0 nan:0x0) drop)")
482-
"unknown operator"
466+
"constant out of range"
467+
)
468+
469+
;; too little arguments
470+
471+
(assert_malformed
472+
(module quote "(func (v128.const i32x4 0x10000000000000000 0x10000000000000000) drop)")
473+
"wrong number of lane literals"
474+
)
475+
476+
;; too many arguments
477+
(assert_malformed
478+
(module quote "(func (v128.const i32x4 0x1 0x1 0x1 0x1 0x1) drop)")
479+
"wrong number of lane literals"
483480
)
484481

485482
;; Rounding behaviour
@@ -1076,7 +1073,7 @@
10761073
(func (export "i32x4.test") (result v128) (return (v128.const i32x4 0x0bAdD00D 0x0bAdD00D 0x0bAdD00D 0x0bAdD00D)))
10771074
(func (export "i32x4.smax") (result v128) (return (v128.const i32x4 0x7fffffff 0x7fffffff 0x7fffffff 0x7fffffff)))
10781075
(func (export "i32x4.neg_smax") (result v128) (return (v128.const i32x4 -0x7fffffff -0x7fffffff -0x7fffffff -0x7fffffff)))
1079-
(func (export "i32x4.inc_smin") (result v128) (return (i32x4.add (v128.const i32x4 -0x80000000 -0x80000000 -0x80000000 -0x80000000) (v128.const i32x4 1 1 1 1))))
1076+
(; (func (export "i32x4.inc_smin") (result v128) (return (i32x4.add (v128.const i32x4 -0x80000000 -0x80000000 -0x80000000 -0x80000000) (v128.const i32x4 1 1 1 1)))) ;)
10801077
(func (export "i32x4.neg_zero") (result v128) (return (v128.const i32x4 -0x0 -0x0 -0x0 -0x0)))
10811078
(func (export "i32x4.not_octal") (result v128) (return (v128.const i32x4 010 010 010 010)))
10821079
(func (export "i32x4.plus_sign") (result v128) (return (v128.const i32x4 +42 +42 +42 +42)))
@@ -1089,7 +1086,7 @@
10891086
(func (export "i64x2.test") (result v128) (return (v128.const i64x2 0x0bAdD00D0bAdD00D 0x0bAdD00D0bAdD00D)))
10901087
(func (export "i64x2.smax") (result v128) (return (v128.const i64x2 0x7fffffffffffffff 0x7fffffffffffffff)))
10911088
(func (export "i64x2.neg_smax") (result v128) (return (v128.const i64x2 -0x7fffffffffffffff -0x7fffffffffffffff)))
1092-
(func (export "i64x2.inc_smin") (result v128) (return (i64x2.add (v128.const i64x2 -0x8000000000000000 -0x8000000000000000) (v128.const i64x2 1 1))))
1089+
(; (func (export "i64x2.inc_smin") (result v128) (return (i64x2.add (v128.const i64x2 -0x8000000000000000 -0x8000000000000000) (v128.const i64x2 1 1)))) ;)
10931090
(func (export "i64x2.neg_zero") (result v128) (return (v128.const i64x2 -0x0 -0x0)))
10941091
(func (export "i64x2.not_octal") (result v128) (return (v128.const i64x2 010010 010010)))
10951092
(func (export "i64x2.plus_sign") (result v128) (return (v128.const i64x2 +42 +42)))
@@ -1660,4 +1657,4 @@
16601657
"\ff\ff\ff\ff\ff\ff\ef\7f" ;; data lane 1 (0x1.fffffffffffffp+1023)
16611658
"\0b" ;; end
16621659
)
1663-
(assert_return (invoke "parse_f64x2") (v128.const f64x2 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023))
1660+
(assert_return (invoke "parse_f64x2") (v128.const f64x2 0x1.fffffffffffffp+1023 0x1.fffffffffffffp+1023))

0 commit comments

Comments
 (0)