Skip to content

Commit

Permalink
feat!: Support passive memory segments (#158)
Browse files Browse the repository at this point in the history
  • Loading branch information
ospencer committed Jun 12, 2022
1 parent ea6e1b0 commit 21857f7
Show file tree
Hide file tree
Showing 9 changed files with 252 additions and 25 deletions.
101 changes: 101 additions & 0 deletions src/binaryen_stubs_expressions.c
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,27 @@ caml_binaryen_unreachable(value _module) {
CAMLreturn(alloc_BinaryenExpressionRef(exp));
}

CAMLprim value
caml_binaryen_memory_init(value _module, value _segment, value _dest, value _offset, value _size) {
CAMLparam5(_module, _segment, _dest, _offset, _size);
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
uint32_t segment = Int_val(_segment);
BinaryenExpressionRef dest = BinaryenExpressionRef_val(_dest);
BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset);
BinaryenExpressionRef size = BinaryenExpressionRef_val(_size);
BinaryenExpressionRef exp = BinaryenMemoryInit(module, segment, dest, offset, size);
CAMLreturn(alloc_BinaryenExpressionRef(exp));
}

CAMLprim value
caml_binaryen_data_drop(value _module, value _segment) {
CAMLparam2(_module, _segment);
BinaryenModuleRef module = BinaryenModuleRef_val(_module);
uint32_t segment = Int_val(_segment);
BinaryenExpressionRef exp = BinaryenDataDrop(module, segment);
CAMLreturn(alloc_BinaryenExpressionRef(exp));
}

CAMLprim value
caml_binaryen_memory_copy(value _module, value _dest, value _source, value _size) {
CAMLparam4(_module, _dest, _source, _size);
Expand Down Expand Up @@ -1551,6 +1572,86 @@ caml_binaryen_return_set_value(value _exp, value _value) {
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_memory_init_get_segment(value _exp) {
CAMLparam1(_exp);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
CAMLreturn(Val_int(BinaryenMemoryInitGetSegment(exp)));
}

CAMLprim value
caml_binaryen_memory_init_set_segment(value _exp, value _value) {
CAMLparam2(_exp, _value);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
uint32_t val = Int_val(_value);
BinaryenMemoryInitSetSegment(exp, val);
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_memory_init_get_dest(value _exp) {
CAMLparam1(_exp);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
CAMLreturn(alloc_BinaryenExpressionRef(BinaryenMemoryInitGetDest(exp)));
}

CAMLprim value
caml_binaryen_memory_init_set_dest(value _exp, value _value) {
CAMLparam2(_exp, _value);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
BinaryenExpressionRef val = BinaryenExpressionRef_val(_value);
BinaryenMemoryInitSetDest(exp, val);
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_memory_init_get_offset(value _exp) {
CAMLparam1(_exp);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
CAMLreturn(alloc_BinaryenExpressionRef(BinaryenMemoryInitGetOffset(exp)));
}

CAMLprim value
caml_binaryen_memory_init_set_offset(value _exp, value _value) {
CAMLparam2(_exp, _value);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
BinaryenExpressionRef val = BinaryenExpressionRef_val(_value);
BinaryenMemoryInitSetOffset(exp, val);
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_memory_init_get_size(value _exp) {
CAMLparam1(_exp);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
CAMLreturn(alloc_BinaryenExpressionRef(BinaryenMemoryInitGetSize(exp)));
}

CAMLprim value
caml_binaryen_memory_init_set_size(value _exp, value _value) {
CAMLparam2(_exp, _value);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
BinaryenExpressionRef val = BinaryenExpressionRef_val(_value);
BinaryenMemoryInitSetSize(exp, val);
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_data_drop_get_segment(value _exp) {
CAMLparam1(_exp);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
CAMLreturn(Val_int(BinaryenDataDropGetSegment(exp)));
}

CAMLprim value
caml_binaryen_data_drop_set_segment(value _exp, value _value) {
CAMLparam2(_exp, _value);
BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp);
uint32_t val = Int_val(_value);
BinaryenDataDropSetSegment(exp, val);
CAMLreturn(Val_unit);
}

CAMLprim value
caml_binaryen_memory_copy_get_dest(value _exp) {
CAMLparam1(_exp);
Expand Down
70 changes: 70 additions & 0 deletions src/binaryen_stubs_expressions.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@ function caml_binaryen_unreachable(wasm_mod) {
return wasm_mod.unreachable();
}

//Provides: caml_binaryen_memory_init
function caml_binaryen_memory_init(wasm_mod, segment, dest, offset, size) {
return wasm_mod.memory.init(segment, dest, offset, size);
}

//Provides: caml_binaryen_data_drop
function caml_binaryen_data_drop(wasm_mod, segment) {
return wasm_mod.data.drop(segment);
}

//Provides: caml_binaryen_memory_copy
function caml_binaryen_memory_copy(wasm_mod, dest, source, size) {
return wasm_mod.memory.copy(dest, source, size);
Expand Down Expand Up @@ -1284,6 +1294,66 @@ function caml_binaryen_return_set_value(exp, value) {
return binaryen.Return.setValue(exp, value);
}

//Provides: caml_binaryen_memory_init_get_segment
//Requires: binaryen
function caml_binaryen_memory_init_get_segment(exp) {
return binaryen.MemoryInit.getSegment(exp);
}

//Provides: caml_binaryen_memory_init_set_segment
//Requires: binaryen
function caml_binaryen_memory_init_set_segment(exp, value) {
return binaryen.MemoryInit.setSegment(exp, value);
}

//Provides: caml_binaryen_memory_init_get_dest
//Requires: binaryen
function caml_binaryen_memory_init_get_dest(exp) {
return binaryen.MemoryInit.getDest(exp);
}

//Provides: caml_binaryen_memory_init_set_dest
//Requires: binaryen
function caml_binaryen_memory_init_set_dest(exp, value) {
return binaryen.MemoryInit.setDest(exp, value);
}

//Provides: caml_binaryen_memory_init_get_offset
//Requires: binaryen
function caml_binaryen_memory_init_get_offset(exp) {
return binaryen.MemoryInit.getOffset(exp);
}

//Provides: caml_binaryen_memory_init_set_offset
//Requires: binaryen
function caml_binaryen_memory_init_set_offset(exp, value) {
return binaryen.MemoryInit.setOffset(exp, value);
}

//Provides: caml_binaryen_memory_init_get_size
//Requires: binaryen
function caml_binaryen_memory_init_get_size(exp) {
return binaryen.MemoryInit.getSize(exp);
}

//Provides: caml_binaryen_memory_init_set_size
//Requires: binaryen
function caml_binaryen_memory_init_set_size(exp, value) {
return binaryen.MemoryInit.setSize(exp, value);
}

//Provides: caml_binaryen_data_drop_get_segment
//Requires: binaryen
function caml_binaryen_data_drop_get_segment(exp) {
return binaryen.DataDrop.getSegment(exp);
}

//Provides: caml_binaryen_data_drop_set_segment
//Requires: binaryen
function caml_binaryen_data_drop_set_segment(exp, value) {
return binaryen.DataDrop.setSegment(exp, value);
}

//Provides: caml_binaryen_memory_copy_get_dest
//Requires: binaryen
function caml_binaryen_memory_copy_get_dest(exp) {
Expand Down
2 changes: 1 addition & 1 deletion src/binaryen_stubs_memory.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ function caml_binaryen_set_memory(wasm_mod, initial, maximum, exportName, segmen
var segs = caml_list_to_js_array(segments).map(function (segment, idx) {
return {
data: caml_convert_bytes_to_array(segment),
passive: segmentPassives[idx + 1], // OCaml Lists are offset by 1
passive: caml_js_from_bool(segmentPassives[idx + 1]), // OCaml Lists are offset by 1
offset: segmentOffsets[idx + 1] // OCaml Lists are offset by 1
}
});
Expand Down
27 changes: 27 additions & 0 deletions src/expression.ml
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,33 @@ module Memory_grow = struct
external set_delta : t -> t -> unit = "caml_binaryen_memory_grow_set_delta"
end

module Memory_init = struct
external make : Module.t -> int -> t -> t -> t = "caml_binaryen_memory_init"
(** Module, segment, destination, offset, size. *)

external get_segment : t -> int = "caml_binaryen_memory_init_get_segment"

external set_segment : t -> int -> unit
= "caml_binaryen_memory_init_set_segment"

external get_dest : t -> t = "caml_binaryen_memory_init_get_dest"
external set_dest : t -> t -> unit = "caml_binaryen_memory_init_set_dest"
external get_offset : t -> t = "caml_binaryen_memory_init_get_offset"
external set_offset : t -> t -> unit = "caml_binaryen_memory_init_set_offset"
external get_size : t -> t = "caml_binaryen_memory_init_get_size"
external set_size : t -> t -> unit = "caml_binaryen_memory_init_set_size"
end

module Data_drop = struct
external make : Module.t -> int -> t = "caml_binaryen_data_drop"
(** Module, segment. *)

external get_segment : t -> int = "caml_binaryen_data_drop_get_segment"

external set_segment : t -> int -> unit
= "caml_binaryen_data_drop_set_segment"
end

module Memory_copy = struct
external make : Module.t -> t -> t -> t -> t = "caml_binaryen_memory_copy"
(** Module, destination, source, size. *)
Expand Down
18 changes: 18 additions & 0 deletions src/expression.mli
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,24 @@ module Memory_grow : sig
val set_delta : t -> t -> unit
end

module Memory_init : sig
val make : Module.t -> int -> t -> t -> t
val get_segment : t -> int
val set_segment : t -> int -> unit
val get_dest : t -> t
val set_dest : t -> t -> unit
val get_offset : t -> t
val set_offset : t -> t -> unit
val get_size : t -> t
val set_size : t -> t -> unit
end

module Data_drop : sig
val make : Module.t -> int -> t
val get_segment : t -> int
val set_segment : t -> int -> unit
end

module Memory_copy : sig
val make : Module.t -> t -> t -> t -> t
val get_dest : t -> t
Expand Down
27 changes: 15 additions & 12 deletions src/memory.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,34 @@ external set_memory :
int ->
int ->
string ->
string list ->
bytes list ->
bool list ->
Expression.t list ->
int list ->
bool ->
unit = "caml_binaryen_set_memory__bytecode" "caml_binaryen_set_memory"

type segment = {
data : string;
passive : bool;
offset : Expression.t;
size : int;
}
type segment = { data : bytes; kind : segment_kind; size : int }
and segment_kind = Passive | Active of { offset : Expression.t }

(** Module, initial size, maximum size, export name, segments, shared. *)
let set_memory wasm_mod initial maximum export_name (segments : segment list)
shared =
let split_segments segments =
List.fold_right
(fun { data; passive; offset; size }
(fun { data; kind; size }
(segment_data, segment_passive, segment_offsets, segment_sizes) ->
( data :: segment_data,
passive :: segment_passive,
offset :: segment_offsets,
size :: segment_sizes ))
match kind with
| Active { offset } ->
( data :: segment_data,
false :: segment_passive,
offset :: segment_offsets,
size :: segment_sizes )
| Passive ->
( data :: segment_data,
true :: segment_passive,
Expression.Null.make () :: segment_offsets,
size :: segment_sizes ))
segments ([], [], [], [])
in
let segment_data, segment_passive, segment_offsets, segment_sizes =
Expand Down
8 changes: 2 additions & 6 deletions src/memory.mli
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
type segment = {
data : string;
passive : bool;
offset : Expression.t;
size : int;
}
type segment = { data : bytes; kind : segment_kind; size : int }
and segment_kind = Passive | Active of { offset : Expression.t }

val set_memory :
Module.t -> int -> int -> string -> segment list -> bool -> unit
Expand Down
1 change: 1 addition & 0 deletions test/test.expected
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
(global $test_float64_bits f64 (f64.const 1.23))
(memory $0 1)
(data (i32.const 0) "hello")
(data "world")
(table $table 1 1 funcref)
(elem $elem (i32.const 0) $adder)
(export "adder" (func $adder))
Expand Down
23 changes: 17 additions & 6 deletions test/test.ml
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,24 @@ let _ =
let _ = Function.set_start wasm_mod start

let segment : Binaryen.Memory.segment =
let data = "hello" in
let passive = false in
let offset = Expression.Const.make wasm_mod (Literal.int32 0l) in
let size = String.length data in
{ data; passive; offset; size }
let data = Bytes.of_string "hello" in
let kind =
Binaryen.Memory.Active
{ offset = Expression.Const.make wasm_mod (Literal.int32 0l) }
in
let size = Bytes.length data in
{ data; kind; size }

let passive_segment : Binaryen.Memory.segment =
let data = Bytes.of_string "world" in
let kind = Binaryen.Memory.Passive in
let size = Bytes.length data in
{ data; kind; size }

let _ = Memory.set_memory wasm_mod 1 Memory.unlimited "memory" [ segment ] false
let _ =
Memory.set_memory wasm_mod 1 Memory.unlimited "memory"
[ segment; passive_segment ]
false

(* Create an imported "write" function i32 (externref, i32, i32) *)
(* Similar to the example here: https://bytecodealliance.org/articles/reference-types-in-wasmtime *)
Expand Down

0 comments on commit 21857f7

Please sign in to comment.