From 7cc300620628c844e61ada38ed71f3a3ea98d400 Mon Sep 17 00:00:00 2001 From: Oscar Spencer Date: Fri, 28 Feb 2025 17:46:59 -0600 Subject: [PATCH] feat!: Upgrade to Binaryen v117 --- binaryen.opam | 2 +- esy.lock/index.json | 12 +++++----- package.json | 2 +- src/expression.ml | 24 -------------------- src/expression.mli | 12 +++++----- src/memory.c | 54 +++++++++++++++++++++++++-------------------- src/memory.js | 28 ++++++++++++++--------- src/memory.ml | 35 +++++++++++++++++++---------- src/memory.mli | 8 +++---- test/test.expected | 48 +++++++++++++++++++++------------------- test/test.ml | 10 +++++---- 11 files changed, 119 insertions(+), 116 deletions(-) diff --git a/binaryen.opam b/binaryen.opam index 25033cba..15af8e19 100644 --- a/binaryen.opam +++ b/binaryen.opam @@ -16,5 +16,5 @@ depends: [ "dune" {>= "3.0.0"} "dune-configurator" {>= "3.0.0"} "js_of_ocaml-compiler" {>= "6.0.0" < "7.0.0"} - "libbinaryen" {>= "116.0.0" < "117.0.0"} + "libbinaryen" {>= "117.0.0" < "118.0.0"} ] diff --git a/esy.lock/index.json b/esy.lock/index.json index a98378b1..1b11ef4f 100644 --- a/esy.lock/index.json +++ b/esy.lock/index.json @@ -1,5 +1,5 @@ { - "checksum": "027362814c85d00422b9f9ff4957739b", + "checksum": "e5a82f70dca4c69aa20c585728dd4291", "root": "@grain/binaryen.ml@link-dev:./package.json", "node": { "ocaml@4.14.1000@d41d8cd9": { @@ -1609,14 +1609,14 @@ "devDependencies": [ "ocaml@4.14.1000@d41d8cd9" ], "available": "true" }, - "@grain/libbinaryen@116.0.0@d41d8cd9": { - "id": "@grain/libbinaryen@116.0.0@d41d8cd9", + "@grain/libbinaryen@117.0.0@d41d8cd9": { + "id": "@grain/libbinaryen@117.0.0@d41d8cd9", "name": "@grain/libbinaryen", - "version": "116.0.0", + "version": "117.0.0", "source": { "type": "install", "source": [ - "archive:https://registry.npmjs.org/@grain/libbinaryen/-/libbinaryen-116.0.0.tgz#sha1:32d4124accc5936dbf9706a0f2aac0df9eefaae5" + "archive:https://registry.npmjs.org/@grain/libbinaryen/-/libbinaryen-117.0.0.tgz#sha1:0bb32f24a9016486b98e93f464017a357f5d86e7" ] }, "overrides": [], @@ -1643,7 +1643,7 @@ "ocaml@4.14.1000@d41d8cd9", "@opam/dune-configurator@opam:3.18.2@ea6c19df", "@opam/dune@opam:3.18.2@22ffdaaa", - "@grain/libbinaryen@116.0.0@d41d8cd9" + "@grain/libbinaryen@117.0.0@d41d8cd9" ], "devDependencies": [ "@opam/ocamlformat@opam:0.24.1@01d7df0f", diff --git a/package.json b/package.json index a042d0e8..c3faabc6 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "license": "Apache-2.0", "dependencies": { "ocaml": ">= 4.13.0 < 5.0.0", - "@grain/libbinaryen": ">= 116.0.0 < 117.0.0", + "@grain/libbinaryen": ">= 117.0.0 < 118.0.0", "@opam/dune": ">= 3.0.0", "@opam/dune-configurator": ">= 3.0.0" }, diff --git a/src/expression.ml b/src/expression.ml index d8bcb3a6..57388303 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -706,22 +706,9 @@ module Memory_init = struct external make : Module.t -> string -> t -> t -> t -> string -> t = "caml_binaryen_memory_init__bytecode" "caml_binaryen_memory_init" (** Module, segment, destination, offset, size, memory_name *) - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let make wasm_mod segment dest offset size memory_name = - make wasm_mod (string_of_int segment) dest offset size memory_name - external get_segment : t -> string = "caml_binaryen_memory_init_get_segment" - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let get_segment expr = int_of_string (get_segment expr) - external set_segment : t -> string -> unit = "caml_binaryen_memory_init_set_segment" - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let set_segment expr segment = set_segment expr (string_of_int 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" @@ -733,20 +720,9 @@ end module Data_drop = struct external make : Module.t -> string -> t = "caml_binaryen_data_drop" (** Module, segment. *) - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let make wasm_mod segment = make wasm_mod (string_of_int segment) - external get_segment : t -> string = "caml_binaryen_data_drop_get_segment" - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let get_segment expr = int_of_string (get_segment expr) - external set_segment : t -> string -> unit = "caml_binaryen_data_drop_set_segment" - - (* Binaryen v113 still uses indexes for data segements, so we only want to change the binding itself, not our interface *) - let set_segment expr segment = set_segment expr (string_of_int segment) end module Memory_copy = struct diff --git a/src/expression.mli b/src/expression.mli index c22e1810..b53655f9 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -256,9 +256,9 @@ module Memory_grow : sig end module Memory_init : sig - val make : Module.t -> int -> t -> t -> t -> string -> t - val get_segment : t -> int - val set_segment : t -> int -> unit + val make : Module.t -> string -> t -> t -> t -> string -> t + val get_segment : t -> string + val set_segment : t -> string -> unit val get_dest : t -> t val set_dest : t -> t -> unit val get_offset : t -> t @@ -268,9 +268,9 @@ module Memory_init : sig end module Data_drop : sig - val make : Module.t -> int -> t - val get_segment : t -> int - val set_segment : t -> int -> unit + val make : Module.t -> string -> t + val get_segment : t -> string + val set_segment : t -> string -> unit end module Memory_copy : sig diff --git a/src/memory.c b/src/memory.c index 89ab274a..6e8f8990 100644 --- a/src/memory.c +++ b/src/memory.c @@ -8,19 +8,25 @@ CAMLprim value -caml_binaryen_set_memory(value _module, value _initial, value _maximum, value _exportName, value _segments, value _segmentPassive, value _segmentOffsets, value _segmentSizes, value _shared, value _memory64, value _memoryName) { - CAMLparam5(_module, _initial, _maximum, _exportName, _segments); - CAMLxparam5(_segmentPassive, _segmentOffsets, _segmentSizes, _shared, _memory64); - CAMLxparam1(_memoryName); +caml_binaryen_set_memory(value _module, value _initial, value _maximum, value _exportName, value _segment_names, value _segment_data, value _segmentPassive, value _segmentOffsets, value _segmentSizes, value _shared, value _memory64, value _memoryName) { + CAMLparam5(_module, _initial, _maximum, _exportName, _segment_names); + CAMLxparam5(_segment_data, _segmentPassive, _segmentOffsets, _segmentSizes, _shared); + CAMLxparam2(_memory64, _memoryName); BinaryenModuleRef module = BinaryenModuleRef_val(_module); BinaryenIndex initial = Int_val(_initial); BinaryenIndex maximum = Int_val(_maximum); char* exportName = Safe_String_val(_exportName); - _segments = array_of_list(_segments); - int segmentsLen = array_length(_segments); - const char* segments[segmentsLen]; - for (int i = 0; i < segmentsLen; i++) { - segments[i] = Safe_String_val(Field(_segments, i)); + _segment_names = array_of_list(_segment_names); + int segmentNamesLen = array_length(_segment_names); + const char* segment_names[segmentNamesLen]; + for (int i = 0; i < segmentNamesLen; i++) { + segment_names[i] = Safe_String_val(Field(_segment_names, i)); + } + _segment_data = array_of_list(_segment_data); + int segmentDataLen = array_length(_segment_data); + const char* segment_data[segmentDataLen]; + for (int i = 0; i < segmentDataLen; i++) { + segment_data[i] = Safe_String_val(Field(_segment_data, i)); } _segmentPassive = array_of_list(_segmentPassive); int segmentPassiveLen = array_length(_segmentPassive); @@ -43,12 +49,12 @@ caml_binaryen_set_memory(value _module, value _initial, value _maximum, value _e bool shared = Bool_val(_shared); bool memory64 = Bool_val(_memory64); char* memoryName = Safe_String_val(_memoryName); - BinaryenSetMemory(module, initial, maximum, exportName, segments, segmentPassive, segmentOffsets, segmentSizes, segmentsLen, shared, memory64, memoryName); + BinaryenSetMemory(module, initial, maximum, exportName, segment_names, segment_data, segmentPassive, segmentOffsets, segmentSizes, segmentNamesLen, shared, memory64, memoryName); CAMLreturn(Val_unit); } CAMLprim value caml_binaryen_set_memory__bytecode(value * argv) { - return caml_binaryen_set_memory(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10]); + return caml_binaryen_set_memory(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5], argv[6], argv[7], argv[8], argv[9], argv[10], argv[11]); } CAMLprim value @@ -111,28 +117,28 @@ caml_binaryen_get_num_memory_segments(value _module) { } CAMLprim value -caml_binaryen_get_memory_segment_byte_offset(value _module, value _id) { - CAMLparam2(_module, _id); +caml_binaryen_get_memory_segment_byte_offset(value _module, value _name) { + CAMLparam2(_module, _name); BinaryenModuleRef module = BinaryenModuleRef_val(_module); - BinaryenIndex id = Int_val(_id); - CAMLreturn(Val_int(BinaryenGetMemorySegmentByteOffset(module, id))); + char* name = Safe_String_val(_name); + CAMLreturn(Val_int(BinaryenGetMemorySegmentByteOffset(module, name))); } CAMLprim value -caml_binaryen_get_memory_segment_passive(value _module, value _id) { - CAMLparam2(_module, _id); +caml_binaryen_get_memory_segment_passive(value _module, value _name) { + CAMLparam2(_module, _name); BinaryenModuleRef module = BinaryenModuleRef_val(_module); - BinaryenIndex id = Int_val(_id); - CAMLreturn(Val_bool(BinaryenGetMemorySegmentPassive(module, id))); + char* name = Safe_String_val(_name); + CAMLreturn(Val_bool(BinaryenGetMemorySegmentPassive(module, name))); } CAMLprim value -caml_binaryen_get_memory_segment_data(value _module, value _id) { - CAMLparam2(_module, _id); +caml_binaryen_get_memory_segment_data(value _module, value _name) { + CAMLparam2(_module, _name); BinaryenModuleRef module = BinaryenModuleRef_val(_module); - BinaryenIndex id = Int_val(_id); - size_t size = BinaryenGetMemorySegmentByteLength(module, id); + char* name = Safe_String_val(_name); + size_t size = BinaryenGetMemorySegmentByteLength(module, name); CAMLprim value bytes = caml_alloc_string(size); - BinaryenCopyMemorySegmentData(module, id, (char*)Bytes_val(bytes)); + BinaryenCopyMemorySegmentData(module, name, (char*)Bytes_val(bytes)); CAMLreturn(bytes); } diff --git a/src/memory.js b/src/memory.js index 5aeb845f..43a12b77 100644 --- a/src/memory.js +++ b/src/memory.js @@ -6,7 +6,8 @@ function caml_binaryen_set_memory( initial, maximum, exportName, - segments, + segmentNames, + segmentData, segmentPassives, segmentOffsets, segmentSizes, @@ -14,11 +15,13 @@ function caml_binaryen_set_memory( memory64, memoryName ) { + var datas = caml_list_to_js_array(segmentData); var passives = caml_list_to_js_array(segmentPassives); var offsets = caml_list_to_js_array(segmentOffsets); - var segs = caml_list_to_js_array(segments).map(function (segment, idx) { + var segs = caml_list_to_js_array(segmentNames).map(function (name, idx) { return { - data: caml_convert_bytes_to_array(segment), + name: caml_jsstring_of_string(name), + data: caml_convert_bytes_to_array(datas[idx]), passive: caml_js_from_bool(passives[idx]), offset: offsets[idx], }; @@ -48,7 +51,8 @@ function caml_binaryen_set_memory__bytecode() { arguments[7], arguments[8], arguments[9], - arguments[10] + arguments[10], + arguments[11] ); } @@ -108,20 +112,22 @@ function caml_binaryen_get_num_memory_segments(wasm_mod) { } //Provides: caml_binaryen_get_memory_segment_byte_offset -function caml_binaryen_get_memory_segment_byte_offset(wasm_mod, idx) { - var info = wasm_mod.getMemorySegmentInfoByIndex(idx); +//Requires: caml_jsstring_of_string +function caml_binaryen_get_memory_segment_byte_offset(wasm_mod, name) { + var info = wasm_mod.getMemorySegmentInfo(caml_jsstring_of_string(name)); return info.offset; } //Provides: caml_binaryen_get_memory_segment_passive -function caml_binaryen_get_memory_segment_passive(wasm_mod, idx) { - var info = wasm_mod.getMemorySegmentInfoByIndex(idx); +//Requires: caml_jsstring_of_string +function caml_binaryen_get_memory_segment_passive(wasm_mod, name) { + var info = wasm_mod.getMemorySegmentInfo(caml_jsstring_of_string(name)); return info.passive; } //Provides: caml_binaryen_get_memory_segment_data -//Requires: caml_bytes_of_array -function caml_binaryen_get_memory_segment_data(wasm_mod, idx) { - var info = wasm_mod.getMemorySegmentInfoByIndex(idx); +//Requires: caml_bytes_of_array, caml_jsstring_of_string +function caml_binaryen_get_memory_segment_data(wasm_mod, name) { + var info = wasm_mod.getMemorySegmentInfo(caml_jsstring_of_string(name)); return caml_bytes_of_array(info.data); } diff --git a/src/memory.ml b/src/memory.ml index 4c96791a..4319c285 100644 --- a/src/memory.ml +++ b/src/memory.ml @@ -3,6 +3,7 @@ external set_memory : int -> int -> string -> + string list -> bytes list -> bool list -> Expression.t list -> @@ -12,7 +13,7 @@ external set_memory : string -> unit = "caml_binaryen_set_memory__bytecode" "caml_binaryen_set_memory" -type segment = { data : bytes; kind : segment_kind; size : int } +type segment = { name : string; 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, memory64, moduleName . *) @@ -20,26 +21,36 @@ let set_memory wasm_mod initial maximum export_name (segments : segment list) shared memory64 moduleName = let split_segments segments = List.fold_right - (fun { data; kind; size } - (segment_data, segment_passive, segment_offsets, segment_sizes) -> + (fun { name; data; kind; size } + ( segment_name, + segment_data, + segment_passive, + segment_offsets, + segment_sizes ) -> match kind with | Active { offset } -> - ( data :: segment_data, + ( name :: segment_name, + data :: segment_data, false :: segment_passive, offset :: segment_offsets, size :: segment_sizes ) | Passive -> - ( data :: segment_data, + ( name :: segment_name, + data :: segment_data, true :: segment_passive, Expression.Null.make () :: segment_offsets, size :: segment_sizes )) - segments ([], [], [], []) + segments ([], [], [], [], []) in - let segment_data, segment_passive, segment_offsets, segment_sizes = + let ( segment_name, + segment_data, + segment_passive, + segment_offsets, + segment_sizes ) = split_segments segments in - set_memory wasm_mod initial maximum export_name segment_data segment_passive - segment_offsets segment_sizes shared memory64 moduleName + set_memory wasm_mod initial maximum export_name segment_name segment_data + segment_passive segment_offsets segment_sizes shared memory64 moduleName external has_memory : Module.t -> bool = "caml_binaryen_has_memory" @@ -59,11 +70,11 @@ let unlimited = -1 external get_num_segments : Module.t -> int = "caml_binaryen_get_num_memory_segments" -external get_segment_byte_offset : Module.t -> int -> int +external get_segment_byte_offset : Module.t -> string -> int = "caml_binaryen_get_memory_segment_byte_offset" -external get_segment_passive : Module.t -> int -> bool +external get_segment_passive : Module.t -> string -> bool = "caml_binaryen_get_memory_segment_passive" -external get_segment_data : Module.t -> int -> bytes +external get_segment_data : Module.t -> string -> bytes = "caml_binaryen_get_memory_segment_data" diff --git a/src/memory.mli b/src/memory.mli index 06f6cfb4..6ecf64d8 100644 --- a/src/memory.mli +++ b/src/memory.mli @@ -1,4 +1,4 @@ -type segment = { data : bytes; kind : segment_kind; size : int } +type segment = { name : string; data : bytes; kind : segment_kind; size : int } and segment_kind = Passive | Active of { offset : Expression.t } val set_memory : @@ -20,6 +20,6 @@ val is_shared : Module.t -> string -> bool val is_64 : Module.t -> string -> bool val unlimited : int val get_num_segments : Module.t -> int -val get_segment_byte_offset : Module.t -> int -> int -val get_segment_passive : Module.t -> int -> bool -val get_segment_data : Module.t -> int -> bytes +val get_segment_byte_offset : Module.t -> string -> int +val get_segment_passive : Module.t -> string -> bool +val get_segment_data : Module.t -> string -> bytes diff --git a/test/test.expected b/test/test.expected index 65253319..d08e43d2 100644 --- a/test/test.expected +++ b/test/test.expected @@ -16,8 +16,8 @@ (global $max_int64_mut (mut i64) (i64.const 9223372036854775807)) (global $test_float64_bits f64 (f64.const 1.23)) (memory $0 1) - (data $0 (i32.const 0) "hello") - (data $1 "world") + (data $hello (i32.const 0) "hello") + (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) (export "adder" (func $adder)) @@ -28,7 +28,9 @@ (block $add (result i32) (if (i32.const 0) - (unreachable) + (then + (unreachable) + ) ) (i32.add (select @@ -44,7 +46,7 @@ ) (func $start (type $1) (block $start - (memory.init $1 + (memory.init $world (i32.const 2048) (i32.const 0) (i32.const 5) @@ -73,8 +75,8 @@ (type $3 (func (param anyref) (result i32))) (import "future-wasi" "write" (func $write (type $2) (param anyref i32 i32) (result i32))) (memory $0 1) - (data $0 (i32.const 0) "hello") - (data $1 "world") + (data $hello (i32.const 0) "hello") + (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) (export "adder" (func $adder)) @@ -94,7 +96,7 @@ ) ) (func $start (type $1) (; has Stack IR ;) - (memory.init $1 + (memory.init $world (i32.const 2048) (i32.const 0) (i32.const 5) @@ -115,11 +117,11 @@ ) ) (module - (type $type$0 (func (param anyref i32 i32) (result i32))) - (type $type$1 (func (param i32 i32) (result i32))) - (type $type$2 (func)) - (type $type$3 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $fimport$0 (type $type$0) (param anyref i32 i32) (result i32))) + (type $type (func (param anyref i32 i32) (result i32))) + (type $type_1 (func (param i32 i32) (result i32))) + (type $type_2 (func)) + (type $type_3 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") (data $1 "world") @@ -129,7 +131,7 @@ (export "memory" (memory $0)) (export "hello" (func $2)) (start $1) - (func $0 (type $type$1) (param $0 i32) (param $1 i32) (result i32) + (func $0 (type $type_1) (param $0 i32) (param $1 i32) (result i32) (i32.add (select (local.get $0) @@ -141,7 +143,7 @@ (local.get $1) ) ) - (func $1 (type $type$2) + (func $1 (type $type_2) (memory.init $1 (i32.const 2048) (i32.const 0) @@ -154,7 +156,7 @@ ) ) ) - (func $2 (type $type$3) (param $0 anyref) (result i32) + (func $2 (type $type_3) (param $0 anyref) (result i32) (call $fimport$0 (local.get $0) (i32.const 0) @@ -163,11 +165,11 @@ ) ) (module - (type $type$0 (func (param anyref i32 i32) (result i32))) - (type $type$1 (func (param i32 i32) (result i32))) - (type $type$2 (func)) - (type $type$3 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $fimport$0 (type $type$0) (param anyref i32 i32) (result i32))) + (type $type (func (param anyref i32 i32) (result i32))) + (type $type_1 (func (param i32 i32) (result i32))) + (type $type_2 (func)) + (type $type_3 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") (data $1 "world") @@ -177,7 +179,7 @@ (export "memory" (memory $0)) (export "hello" (func $2)) (start $1) - (func $0 (type $type$1) (param $0 i32) (param $1 i32) (result i32) + (func $0 (type $type_1) (param $0 i32) (param $1 i32) (result i32) local.get $0 local.get $1 i32.load @@ -186,7 +188,7 @@ local.get $1 i32.add ) - (func $1 (type $type$2) + (func $1 (type $type_2) i32.const 2048 i32.const 0 i32.const 5 @@ -196,7 +198,7 @@ call $0 drop ) - (func $2 (type $type$3) (param $0 anyref) (result i32) + (func $2 (type $type_3) (param $0 anyref) (result i32) local.get $0 i32.const 0 i32.const 1 diff --git a/test/test.ml b/test/test.ml index e0339e08..b1b6a7bf 100644 --- a/test/test.ml +++ b/test/test.ml @@ -97,7 +97,7 @@ let start = Function.add_function wasm_mod "start" Type.none Type.none [||] (Expression.Block.make wasm_mod ~return_type:Type.none "start" [ - Expression.Memory_init.make wasm_mod 1 + Expression.Memory_init.make wasm_mod "world" (Expression.Const.make wasm_mod (Literal.int32 2048l)) (Expression.Const.make wasm_mod (Literal.int32 0l)) (Expression.Const.make wasm_mod (Literal.int32 5l)) @@ -157,13 +157,13 @@ let segment : Binaryen.Memory.segment = { offset = Expression.Const.make wasm_mod (Literal.int32 0l) } in let size = Bytes.length data in - { data; kind; size } + { name = "hello"; 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 } + { name = "world"; data; kind; size } let _ = assert (Memory.has_memory wasm_mod = false) @@ -183,7 +183,9 @@ let _ = assert (Memory.get_max max_memory_wasm_mod "0" = 2) let _ = assert ( - Bytes.equal (Memory.get_segment_data wasm_mod 1) (Bytes.of_string "world")) + Bytes.equal + (Memory.get_segment_data wasm_mod "world") + (Bytes.of_string "world")) (* Create an imported "write" function i32 (externref, i32, i32) *) (* Similar to the example here: https://bytecodealliance.org/articles/reference-types-in-wasmtime *)