Skip to content

Commit 4069311

Browse files
committed
feat: Implement SIMD operations
1 parent 971b06e commit 4069311

File tree

16 files changed

+1482
-1
lines changed

16 files changed

+1482
-1
lines changed

src/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
(flags :standard -O2 -Wall -Wextra))
2828
(js_of_ocaml
2929
(javascript_files
30+
helpers.js
3031
array_type.js
3132
type.js
3233
op.js

src/expression.c

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,104 @@ caml_binaryen_unreachable(value _module) {
351351
CAMLreturn(alloc_BinaryenExpressionRef(exp));
352352
}
353353

354+
CAMLprim value
355+
caml_binaryen_simd_extract(value _module, value _op, value _vec, value _index) {
356+
CAMLparam4(_module, _op, _vec, _index);
357+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
358+
BinaryenOp op = BinaryenOp_val(_op);
359+
BinaryenExpressionRef vec = BinaryenExpressionRef_val(_vec);
360+
int index = Int_val(_index);
361+
BinaryenExpressionRef exp = BinaryenSIMDExtract(module, op, vec, index);
362+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
363+
}
364+
365+
CAMLprim value
366+
caml_binaryen_simd_replace(value _module, value _op, value _vec, value _index, value _val) {
367+
CAMLparam5(_module, _op, _vec, _index, _val);
368+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
369+
BinaryenOp op = BinaryenOp_val(_op);
370+
BinaryenExpressionRef vec = BinaryenExpressionRef_val(_vec);
371+
int index = Int_val(_index);
372+
BinaryenExpressionRef val = BinaryenExpressionRef_val(_val);
373+
BinaryenExpressionRef exp = BinaryenSIMDReplace(module, op, vec, index, val);
374+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
375+
}
376+
377+
CAMLprim value
378+
caml_binaryen_simd_shuffle(value _module, value _left, value _right, value _mask) {
379+
CAMLparam4(_module, _left, _right, _mask);
380+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
381+
BinaryenExpressionRef left = BinaryenExpressionRef_val(_left);
382+
BinaryenExpressionRef right = BinaryenExpressionRef_val(_right);
383+
uint8_t mask[16];
384+
for (int i = 0; i < 16; i++) {
385+
mask[i] = Int_val(Field(_mask, i));
386+
}
387+
BinaryenExpressionRef exp = BinaryenSIMDShuffle(module, left, right, mask);
388+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
389+
}
390+
391+
CAMLprim value
392+
caml_binaryen_simd_ternary(value _module, value _op, value _a, value _b, value _c) {
393+
CAMLparam5(_module, _op, _a, _b, _c);
394+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
395+
BinaryenOp op = BinaryenOp_val(_op);
396+
BinaryenExpressionRef a = BinaryenExpressionRef_val(_a);
397+
BinaryenExpressionRef b = BinaryenExpressionRef_val(_b);
398+
BinaryenExpressionRef c = BinaryenExpressionRef_val(_c);
399+
BinaryenExpressionRef exp = BinaryenSIMDTernary(module, op, a, b, c);
400+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
401+
}
402+
403+
CAMLprim value
404+
caml_binaryen_simd_shift(value _module, value _op, value _vec, value _shift) {
405+
CAMLparam4(_module, _op, _vec, _shift);
406+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
407+
BinaryenOp op = BinaryenOp_val(_op);
408+
BinaryenExpressionRef vec = BinaryenExpressionRef_val(_vec);
409+
BinaryenExpressionRef shift = BinaryenExpressionRef_val(_shift);
410+
BinaryenExpressionRef exp = BinaryenSIMDShift(module, op, vec, shift);
411+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
412+
}
413+
414+
CAMLprim value
415+
caml_binaryen_simd_load(value _module, value _op, value _offset, value _align, value _ptr, value _memoryName) {
416+
CAMLparam5(_module, _op, _offset, _align, _ptr);
417+
CAMLxparam1(_memoryName);
418+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
419+
BinaryenOp op = BinaryenOp_val(_op);
420+
int offset = Int_val(_offset);
421+
int align = Int_val(_align);
422+
BinaryenExpressionRef ptr = BinaryenExpressionRef_val(_ptr);
423+
char* memoryName = Safe_String_val(_memoryName);
424+
BinaryenExpressionRef exp = BinaryenSIMDLoad(module, op, offset, align, ptr, memoryName);
425+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
426+
}
427+
CAMLprim value
428+
caml_binaryen_simd_load__bytecode(value * argv) {
429+
return caml_binaryen_simd_load(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]);
430+
}
431+
432+
CAMLprim value
433+
caml_binaryen_simd_load_store_lane(value _module, value _op, value _offset, value _align, value _index, value _ptr, value _vec, value _memoryName) {
434+
CAMLparam5(_module, _op, _offset, _align, _index);
435+
CAMLxparam3(_ptr, _vec, _memoryName);
436+
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
437+
BinaryenOp op = BinaryenOp_val(_op);
438+
int offset = Int_val(_offset);
439+
int align = Int_val(_align);
440+
int index = Int_val(_index);
441+
BinaryenExpressionRef ptr = BinaryenExpressionRef_val(_ptr);
442+
BinaryenExpressionRef vec = BinaryenExpressionRef_val(_vec);
443+
char* memoryName = Safe_String_val(_memoryName);
444+
BinaryenExpressionRef exp = BinaryenSIMDLoadStoreLane(module, op, offset, align, index, ptr, vec, memoryName);
445+
CAMLreturn(alloc_BinaryenExpressionRef(exp));
446+
}
447+
CAMLprim value
448+
caml_binaryen_simd_load_store_lane__bytecode(value * argv) {
449+
return caml_binaryen_simd_load_store_lane(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7]);
450+
}
451+
354452
CAMLprim value
355453
caml_binaryen_memory_init(value _module, value _segment, value _dest, value _offset, value _size, value _memoryName) {
356454
CAMLparam5(_module, _segment, _dest, _offset, _size);

src/expression.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,10 @@ function caml_binaryen_const(wasm_mod, lit) {
387387
);
388388
}
389389

390+
if (lit.type === "vec128") {
391+
return wasm_mod.v128.const(lit.value);
392+
}
393+
390394
caml_failwith("invalid Literal for Binaryen.Const.make");
391395
}
392396

@@ -446,6 +450,107 @@ function caml_binaryen_unreachable(wasm_mod) {
446450
return wasm_mod.unreachable();
447451
}
448452

453+
//Provides: caml_binaryen_simd_extract
454+
//Requires: Binaryen
455+
function caml_binaryen_simd_extract(wasm_mod, op, vec, index) {
456+
return Binaryen._BinaryenSIMDExtract(wasm_mod, op, vec, index);
457+
}
458+
459+
//Provides: caml_binaryen_simd_replace
460+
//Requires: Binaryen
461+
function caml_binaryen_simd_replace(wasm_mod, op, vec, index, value) {
462+
return Binaryen._BinaryenSIMDReplace(wasm_mod, op, vec, index, value);
463+
}
464+
465+
//Provides: caml_binaryen_simd_shuffle
466+
//Requires: caml_js_from_array
467+
function caml_binaryen_simd_shuffle(wasm_mod, left, right, mask) {
468+
return wasm_mod.i8x16.shuffle(left, right, caml_js_from_array(mask));
469+
}
470+
471+
//Provides: caml_binaryen_simd_ternary
472+
//Requires: Binaryen
473+
function caml_binaryen_simd_ternary(wasm_mod, op, a, b, c) {
474+
return Binaryen._BinaryenSIMDTernary(wasm_mod, op, a, b, c);
475+
}
476+
477+
//Provides: caml_binaryen_simd_shift
478+
//Requires: Binaryen
479+
function caml_binaryen_simd_shift(wasm_mod, op, vec, shift) {
480+
return Binaryen._BinaryenSIMDShift(wasm_mod, op, vec, shift);
481+
}
482+
483+
//Provides: caml_binaryen_simd_load
484+
//Requires: Binaryen
485+
//Requires: caml_jsstring_of_string, caml_alloc_string_on_heap
486+
function caml_binaryen_simd_load(wasm_mod, op, offset, align, ptr, memoryName) {
487+
var memory = caml_alloc_string_on_heap(caml_jsstring_of_string(memoryName));
488+
var exp = Binaryen._BinaryenSIMDLoad(
489+
wasm_mod,
490+
op,
491+
offset,
492+
align,
493+
ptr,
494+
memory
495+
);
496+
Binaryen._free(memory);
497+
return exp;
498+
}
499+
//Provides: caml_binaryen_simd_load__bytecode
500+
//Requires: caml_binaryen_simd_load
501+
function caml_binaryen_simd_load__bytecode() {
502+
return caml_binaryen_simd_load(
503+
arguments[0],
504+
arguments[1],
505+
arguments[2],
506+
arguments[3],
507+
arguments[4],
508+
arguments[5]
509+
);
510+
}
511+
512+
//Provides: caml_binaryen_simd_load_store_lane
513+
//Requires: Binaryen
514+
//Requires: caml_jsstring_of_string, caml_alloc_string_on_heap
515+
function caml_binaryen_simd_load_store_lane(
516+
wasm_mod,
517+
op,
518+
offset,
519+
align,
520+
index,
521+
ptr,
522+
vec,
523+
memoryName
524+
) {
525+
var memory = caml_alloc_string_on_heap(caml_jsstring_of_string(memoryName));
526+
var exp = Binaryen._BinaryenSIMDLoadStoreLane(
527+
wasm_mod,
528+
op,
529+
offset,
530+
align,
531+
index,
532+
ptr,
533+
vec,
534+
memory
535+
);
536+
Binaryen._free(memory);
537+
return exp;
538+
}
539+
//Provides: caml_binaryen_simd_load_store_lane__bytecode
540+
//Requires: caml_binaryen_simd_load_store_lane
541+
function caml_binaryen_simd_load_store_lane__bytecode() {
542+
return caml_binaryen_simd_load_store_lane(
543+
arguments[0],
544+
arguments[1],
545+
arguments[2],
546+
arguments[3],
547+
arguments[4],
548+
arguments[5],
549+
arguments[6],
550+
arguments[7]
551+
);
552+
}
553+
449554
//Provides: caml_binaryen_memory_init
450555
//Requires: caml_jsstring_of_string
451556
function caml_binaryen_memory_init(

src/expression.ml

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,54 @@ module Pop = struct
819819
(** Module, type *)
820820
end
821821

822+
module SIMD_extract = struct
823+
external make : Module.t -> Op.t -> t -> int -> t
824+
= "caml_binaryen_simd_extract"
825+
(** Module, op, vec, index *)
826+
end
827+
828+
module SIMD_replace = struct
829+
external make : Module.t -> Op.t -> t -> int -> t -> t
830+
= "caml_binaryen_simd_replace"
831+
(** Module, op, vec, index, value *)
832+
end
833+
834+
module SIMD_shuffle = struct
835+
external make : Module.t -> t -> t -> int array -> t
836+
= "caml_binaryen_simd_shuffle"
837+
838+
(** Module, left, right, mask *)
839+
let make wasm_mod left right mask =
840+
if Array.length mask <> 16 then
841+
raise
842+
(Invalid_argument
843+
"Binaryen.SIMD_shuffle.make: mask must be of length 16");
844+
make wasm_mod left right mask
845+
end
846+
847+
module SIMD_ternary = struct
848+
external make : Module.t -> Op.t -> t -> t -> t -> t
849+
= "caml_binaryen_simd_ternary"
850+
(** Module, op, first, second, third *)
851+
end
852+
853+
module SIMD_shift = struct
854+
external make : Module.t -> Op.t -> t -> t -> t = "caml_binaryen_simd_shift"
855+
(** Module, op, left, right *)
856+
end
857+
858+
module SIMD_load = struct
859+
external make : Module.t -> Op.t -> int -> int -> t -> string -> t
860+
= "caml_binaryen_simd_load__bytecode" "caml_binaryen_simd_load"
861+
(** Module, op, offset, align, ptr, memory *)
862+
end
863+
864+
module SIMD_load_store_lane = struct
865+
external make : Module.t -> Op.t -> int -> int -> int -> t -> t -> string -> t
866+
= "caml_binaryen_simd_load_store_lane__bytecode" "caml_binaryen_simd_load_store_lane"
867+
(** Module, op, offset, align, index, ptr, vec, memory *)
868+
end
869+
822870
module I31 = struct
823871
external make : Module.t -> t -> t = "caml_binaryen_i31_new"
824872
(** Module, value *)

src/expression.mli

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,34 @@ module Pop : sig
321321
val make : Module.t -> Type.t -> t
322322
end
323323

324+
module SIMD_extract : sig
325+
val make : Module.t -> Op.t -> t -> int -> t
326+
end
327+
328+
module SIMD_replace : sig
329+
val make : Module.t -> Op.t -> t -> int -> t -> t
330+
end
331+
332+
module SIMD_shuffle : sig
333+
val make : Module.t -> t -> t -> int array -> t
334+
end
335+
336+
module SIMD_ternary : sig
337+
val make : Module.t -> Op.t -> t -> t -> t -> t
338+
end
339+
340+
module SIMD_shift : sig
341+
val make : Module.t -> Op.t -> t -> t -> t
342+
end
343+
344+
module SIMD_load : sig
345+
val make : Module.t -> Op.t -> int -> int -> t -> string -> t
346+
end
347+
348+
module SIMD_load_store_lane : sig
349+
val make : Module.t -> Op.t -> int -> int -> int -> t -> t -> string -> t
350+
end
351+
324352
module I31 : sig
325353
val make : Module.t -> t -> t
326354
(** Module, value *)

src/helpers.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
//Requires: Binaryen
2+
//Provides: caml_alloc_string_on_heap
3+
function caml_alloc_string_on_heap(str) {
4+
var len = str.length;
5+
var ptr = Binaryen._malloc(len + 1);
6+
var encoder = new TextEncoder();
7+
encoder.encodeInto(str, Binaryen.HEAPU8.subarray(ptr, ptr + len));
8+
Binaryen.HEAPU8[ptr + len] = 0;
9+
return ptr;
10+
}

src/literal.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,14 @@ caml_binaryen_literal_float64_bits(value _i64) {
4545
struct BinaryenLiteral lit = BinaryenLiteralFloat64Bits(i64);
4646
CAMLreturn(alloc_BinaryenLiteral(lit));
4747
}
48+
49+
CAMLprim value
50+
caml_binaryen_literal_vec128(value _v128) {
51+
CAMLparam1(_v128);
52+
uint8_t v128[16];
53+
for (int i = 0; i < 16; i++) {
54+
v128[i] = Int_val(Field(_v128, i));
55+
}
56+
struct BinaryenLiteral lit = BinaryenLiteralVec128(v128);
57+
CAMLreturn(alloc_BinaryenLiteral(lit));
58+
}

src/literal.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,10 @@ function caml_binaryen_literal_float64_bits(i64) {
2727
// Hack around Binaryen.js
2828
return { type: 'float64_bits', value: i64 };
2929
}
30+
31+
//Provides: caml_binaryen_literal_vec128
32+
//Requires: caml_js_from_array
33+
function caml_binaryen_literal_vec128(v128) {
34+
// Hack around Binaryen.js
35+
return { type: "vec128", value: caml_js_from_array(v128) };
36+
}

src/literal.ml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,11 @@ external float64_bits : int64 -> t = "caml_binaryen_literal_float64_bits"
88
let float32 n = float32_bits @@ Int32.bits_of_float n
99

1010
external float64 : float -> t = "caml_binaryen_literal_float64"
11+
external vec128 : int array -> t = "caml_binaryen_literal_vec128"
12+
13+
let vec128 (low, high) =
14+
let bytes = Bytes.create 16 in
15+
Bytes.set_int64_le bytes 0 low;
16+
Bytes.set_int64_le bytes 8 high;
17+
let arr = Array.init 16 (Bytes.get_uint8 bytes) in
18+
vec128 arr

src/literal.mli

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ val float32_bits : int32 -> t
66
val float64_bits : int64 -> t
77
val float32 : float -> t
88
val float64 : float -> t
9+
val vec128 : int64 * int64 -> t

0 commit comments

Comments
 (0)