From f39c456c819c8304bdb955ff7d26cf3a6fc3cf22 Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Wed, 10 Dec 2025 17:30:48 -0500 Subject: [PATCH 01/10] chore: Use js api over `_Binaryen` api for types (#262) This just fixes some small todo's by using the js api where possible --- src/type.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/type.js b/src/type.js index 23350368..2b258218 100644 --- a/src/type.js +++ b/src/type.js @@ -67,7 +67,7 @@ function caml_binaryen_type_structref() { //Provides: caml_binaryen_type_arrayref //Requires: Binaryen function caml_binaryen_type_arrayref() { - // TODO: Binaryen v111 didn't expose this directly + // TODO: Binaryen v125 doesn't expose this directly return Binaryen._BinaryenTypeArrayref(); } @@ -80,22 +80,19 @@ function caml_binaryen_type_stringref() { //Provides: caml_binaryen_type_nullref //Requires: Binaryen function caml_binaryen_type_nullref() { - // TODO: Binaryen v111 didn't expose this directly - return Binaryen._BinaryenTypeNullref(); + return Binaryen.nullref; } //Provides: caml_binaryen_type_null_externref //Requires: Binaryen function caml_binaryen_type_null_externref() { - // TODO: Binaryen v111 didn't expose this directly - return Binaryen._BinaryenTypeNullExternref(); + return Binaryen.nullexternref; } //Provides: caml_binaryen_type_null_funcref //Requires: Binaryen function caml_binaryen_type_null_funcref() { - // TODO: Binaryen v111 didn't expose this directly - return Binaryen._BinaryenTypeNullFuncref(); + return Binaryen.nullfuncref; } //Provides: caml_binaryen_type_unreachable From 0877b1e2b8fb1df4ddb29c73bbb867875fa5f580 Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Sun, 21 Dec 2025 12:29:09 -0500 Subject: [PATCH 02/10] fix: Use `caml_uint8_array_of_string` in add_custom_section (#269) While working on #265 I noticed that I was getting errors on `caml_binaryen_add_custom_section` as `caml_array_of_string` was deprecated for `caml_uint8_array_of_string` this updates that. The reason this doesn't appear for us is because of our test suite never calls this function. --- src/module.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/module.js b/src/module.js index 00167c72..d6bf5b0b 100644 --- a/src/module.js +++ b/src/module.js @@ -122,11 +122,11 @@ function caml_binaryen_module_get_debug_info_filename(wasm_mod, index) { } //Provides: caml_binaryen_add_custom_section -//Requires: caml_jsstring_of_string, caml_array_of_string +//Requires: caml_jsstring_of_string, caml_uint8_array_of_string function caml_binaryen_add_custom_section(wasm_mod, name, contents) { return wasm_mod.addCustomSection( caml_jsstring_of_string(name), - caml_array_of_string(contents) + caml_uint8_array_of_string(contents) ); } From bc003c789316a98a7989929b6e67bc6d9b31b23f Mon Sep 17 00:00:00 2001 From: Spotandjake <40705786+spotandjake@users.noreply.github.com> Date: Sun, 28 Dec 2025 21:34:57 -0500 Subject: [PATCH 03/10] feat: Add bindings for exception handling (try/throw) (#264) --- src/dune | 2 + src/export.c | 10 ++ src/export.js | 13 ++ src/export.ml | 4 + src/export.mli | 1 + src/expression.c | 291 ++++++++++++++++++++++++++++++++++++++++++++ src/expression.js | 182 +++++++++++++++++++++++++++ src/expression.ml | 118 ++++++++++++++++++ src/expression.mli | 87 +++++++++++++ src/import.c | 32 +++++ src/import.js | 47 +++++++ src/import.ml | 12 ++ src/import.mli | 5 + src/ocaml_helpers.c | 8 ++ src/ocaml_helpers.h | 4 + src/tag.c | 61 ++++++++++ src/tag.js | 43 +++++++ src/tag.ml | 11 ++ src/tag.mli | 8 ++ test/test.expected | 189 +++++++++++++++++++++++----- test/test.ml | 89 ++++++++++++++ 21 files changed, 1186 insertions(+), 31 deletions(-) create mode 100644 src/tag.c create mode 100644 src/tag.js create mode 100644 src/tag.ml create mode 100644 src/tag.mli diff --git a/src/dune b/src/dune index a5bcd431..1249f71d 100644 --- a/src/dune +++ b/src/dune @@ -15,6 +15,7 @@ export global table + tag memory module_feature module @@ -37,6 +38,7 @@ export.js global.js table.js + tag.js memory.js module_feature.js module.js diff --git a/src/export.c b/src/export.c index f100a704..79d701f6 100644 --- a/src/export.c +++ b/src/export.c @@ -48,6 +48,16 @@ caml_binaryen_add_global_export(value _module, value _internalName, value _exter CAMLreturn(alloc_BinaryenExportRef(exp)); } +CAMLprim value +caml_binaryen_add_tag_export(value _module, value _internalName, value _externalName) { + CAMLparam3(_module, _internalName, _externalName); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* internalName = Safe_String_val(_internalName); + char* externalName = Safe_String_val(_externalName); + BinaryenExportRef exp = BinaryenAddTagExport(module, internalName, externalName); + CAMLreturn(alloc_BinaryenExportRef(exp)); +} + CAMLprim value caml_binaryen_get_export(value _module, value _externalName) { CAMLparam2(_module, _externalName); diff --git a/src/export.js b/src/export.js index a0060cac..168dabf9 100644 --- a/src/export.js +++ b/src/export.js @@ -50,6 +50,19 @@ function caml_binaryen_add_global_export( ); } +//Provides: caml_binaryen_add_tag_export +//Requires: caml_jsstring_of_string +function caml_binaryen_add_tag_export( + wasm_mod, + internal_name, + external_name +) { + return wasm_mod.addTagExport( + caml_jsstring_of_string(internal_name), + caml_jsstring_of_string(external_name) + ); +} + //Provides: caml_binaryen_get_export //Requires: caml_jsstring_of_string function caml_binaryen_get_export(wasm_mod, external_name) { diff --git a/src/export.ml b/src/export.ml index 549c76b1..05787a44 100644 --- a/src/export.ml +++ b/src/export.ml @@ -16,6 +16,10 @@ external add_global_export : Module.t -> string -> string -> t = "caml_binaryen_add_global_export" (** Module, internal name, external name. *) +external add_tag_export : Module.t -> string -> string -> t + = "caml_binaryen_add_tag_export" +(** Module, internal name, external name. *) + external get_export : Module.t -> string -> t = "caml_binaryen_get_export" external remove_export : Module.t -> string -> unit diff --git a/src/export.mli b/src/export.mli index 707f7682..183297aa 100644 --- a/src/export.mli +++ b/src/export.mli @@ -4,6 +4,7 @@ val add_function_export : Module.t -> string -> string -> t val add_table_export : Module.t -> string -> string -> t val add_memory_export : Module.t -> string -> string -> t val add_global_export : Module.t -> string -> string -> t +val add_tag_export : Module.t -> string -> string -> t val get_export : Module.t -> string -> t val remove_export : Module.t -> string -> unit val get_num_exports : Module.t -> int diff --git a/src/expression.c b/src/expression.c index f20c5a9e..69d9d568 100644 --- a/src/expression.c +++ b/src/expression.c @@ -1883,6 +1883,297 @@ caml_binaryen_ref_eq(value _module, value _left, value _right) { CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +// Exception handling operations +CAMLprim value +caml_binaryen_try(value _module, value _name, value _body, value _catchTags, value _catchBodies, value _delegateTarget) { + CAMLparam5(_module, _name, _body, _catchTags, _catchBodies); + CAMLxparam1(_delegateTarget); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char *name; + if (Is_none(_name)) { + name = NULL; + } else { + name = Safe_String_val(Some_val(_name)); + } + BinaryenExpressionRef body = BinaryenExpressionRef_val(_body); + _catchTags = array_of_list(_catchTags); + int catchTagsLen = array_length(_catchTags); + const char* catchTags[catchTagsLen]; + for (int i = 0; i < catchTagsLen; i++) { + catchTags[i] = Safe_String_val(Field(_catchTags, i)); + } + _catchBodies = array_of_list(_catchBodies); + int catchBodiesLen = array_length(_catchBodies); + BinaryenExpressionRef catchBodies[catchBodiesLen]; + for (int i = 0; i < catchBodiesLen; i++) { + catchBodies[i] = BinaryenExpressionRef_val(Field(_catchBodies, i)); + } + char *delegateTarget; + if (Is_none(_delegateTarget)) { + delegateTarget = NULL; + } else { + delegateTarget = Safe_String_val(Some_val(_delegateTarget)); + } + BinaryenExpressionRef exp = BinaryenTry( + module, + name, + body, + catchTags, + catchTagsLen, + catchBodies, + catchBodiesLen, + delegateTarget + ); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value caml_binaryen_try__bytecode(value * argv) { + return caml_binaryen_try(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_binaryen_throw(value _module, value _tag, value _operands) { + CAMLparam3(_module, _tag, _operands); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char *tag = Safe_String_val(_tag); + _operands = array_of_list(_operands); + int operandsLen = array_length(_operands); + BinaryenExpressionRef operands[operandsLen]; + for (int i = 0; i < operandsLen; i++) { + operands[i] = BinaryenExpressionRef_val(Field(_operands, i)); + } + BinaryenExpressionRef exp = BinaryenThrow(module, tag, operands, operandsLen); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_try_get_name(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + const char* name = BinaryenTryGetName(expr); + if (name == NULL) { + CAMLreturn(Val_none); + } else { + CAMLreturn(caml_alloc_some(caml_copy_string(name))); + } +} + +CAMLprim value +caml_binaryen_try_set_name(value _expr, value _name) { + CAMLparam2(_expr, _name); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + const char* name = Safe_String_val(_name); + BinaryenTrySetName(expr, name); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_get_body(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenExpressionRef binaryenRetVal = BinaryenTryGetBody(expr); + CAMLreturn(alloc_BinaryenExpressionRef(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_set_body(value _expr, value _bodyExpr) { + CAMLparam2(_expr, _bodyExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenExpressionRef bodyExpr = BinaryenExpressionRef_val(_bodyExpr); + BinaryenTrySetBody(expr, bodyExpr); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_get_num_catch_tags(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex binaryenRetVal = BinaryenTryGetNumCatchTags(expr); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_get_num_catch_bodies(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex binaryenRetVal = BinaryenTryGetNumCatchBodies(expr); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_get_catch_tag_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + const char* binaryenRetVal = BinaryenTryGetCatchTagAt(expr, index); + CAMLreturn(caml_copy_string(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_set_catch_tag_at(value _expr, value _index, value _catchTag) { + CAMLparam3(_expr, _index, _catchTag); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + const char* catchTag = Safe_String_val(_catchTag); + BinaryenTrySetCatchTagAt(expr, index, catchTag); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_append_catch_tag(value _expr, value _catchTag) { + CAMLparam2(_expr, _catchTag); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + const char* catchTag = Safe_String_val(_catchTag); + BinaryenIndex binaryenRetVal = BinaryenTryAppendCatchTag(expr, catchTag); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_insert_catch_tag_at(value _expr, value _index, value _catchTag) { + CAMLparam3(_expr, _index, _catchTag); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + const char* catchTag = Safe_String_val(_catchTag); + BinaryenTryInsertCatchTagAt(expr, index, catchTag); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_remove_catch_tag_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + const char* binaryenRetVal = BinaryenTryRemoveCatchTagAt(expr, index); + CAMLreturn(caml_copy_string(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_get_catch_body_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef binaryenRetVal = BinaryenTryGetCatchBodyAt(expr, index); + CAMLreturn(alloc_BinaryenExpressionRef(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_set_catch_body_at(value _expr, value _index, value _catchExpr) { + CAMLparam3(_expr, _index, _catchExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef catchExpr = BinaryenExpressionRef_val(_catchExpr); + BinaryenTrySetCatchBodyAt(expr, index, catchExpr); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_append_catch_body(value _expr, value _catchExpr) { + CAMLparam2(_expr, _catchExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenExpressionRef catchExpr = BinaryenExpressionRef_val(_catchExpr); + BinaryenIndex binaryenRetVal = BinaryenTryAppendCatchBody(expr, catchExpr); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_insert_catch_body_at(value _expr, value _index, value _catchExpr) { + CAMLparam3(_expr, _index, _catchExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef catchExpr = BinaryenExpressionRef_val(_catchExpr); + BinaryenTryInsertCatchBodyAt(expr, index, catchExpr); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_try_remove_catch_body_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef binaryenRetVal = BinaryenTryRemoveCatchBodyAt(expr, index); + CAMLreturn(alloc_BinaryenExpressionRef(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_try_has_catch_all(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + bool binaryenRetVal = BinaryenTryHasCatchAll(expr); + CAMLreturn(Val_bool(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_throw_get_tag(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + const char* binaryenRetVal = BinaryenThrowGetTag(expr); + CAMLreturn(caml_copy_string(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_throw_set_tag(value _expr, value _tagName) { + CAMLparam2(_expr, _tagName); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + const char* tagName = Safe_String_val(_tagName); + BinaryenThrowSetTag(expr, tagName); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_throw_get_num_operands(value _expr) { + CAMLparam1(_expr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex binaryenRetVal = BinaryenThrowGetNumOperands(expr); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_throw_get_operand_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef binaryenRetVal = BinaryenThrowGetOperandAt(expr, index); + CAMLreturn(alloc_BinaryenExpressionRef(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_throw_set_operand_at(value _expr, value _index, value _operandExpr) { + CAMLparam3(_expr, _index, _operandExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operandExpr = BinaryenExpressionRef_val(_operandExpr); + BinaryenThrowSetOperandAt(expr, index, operandExpr); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_throw_append_operand(value _expr, value _operandExpr) { + CAMLparam2(_expr, _operandExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenExpressionRef operandExpr = BinaryenExpressionRef_val(_operandExpr); + BinaryenIndex binaryenRetVal = BinaryenThrowAppendOperand(expr, operandExpr); + CAMLreturn(Val_int(binaryenRetVal)); +} + +CAMLprim value +caml_binaryen_throw_insert_operand_at(value _expr, value _index, value _operandExpr) { + CAMLparam3(_expr, _index, _operandExpr); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operandExpr = BinaryenExpressionRef_val(_operandExpr); + BinaryenThrowInsertOperandAt(expr, index, operandExpr); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_throw_remove_operand_at(value _expr, value _index) { + CAMLparam2(_expr, _index); + BinaryenExpressionRef expr = BinaryenExpressionRef_val(_expr); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef binaryenRetVal = BinaryenThrowRemoveOperandAt(expr, index); + CAMLreturn(alloc_BinaryenExpressionRef(binaryenRetVal)); +} + // Table operations CAMLprim value caml_binaryen_table_get(value _module, value _name, value _index, value _ty) { diff --git a/src/expression.js b/src/expression.js index 13b16cf5..2fd5f650 100644 --- a/src/expression.js +++ b/src/expression.js @@ -1707,6 +1707,188 @@ function caml_binaryen_ref_eq(wasm_mod, left, right) { return wasm_mod.ref.func(left, right); } +// Exception handling operations + +//Provides: caml_binaryen_try +//Requires: caml_jsstring_of_string, caml_list_to_js_array +function caml_binaryen_try(wasm_mod, name, body, catch_tags, catch_bodies, delegate_target) { + return wasm_mod.try( + name ? caml_jsstring_of_string(name[1]) : null, + body, + caml_list_to_js_array(catch_tags).map(caml_jsstring_of_string), + caml_list_to_js_array(catch_bodies), + delegate_target ? caml_jsstring_of_string(delegate_target[1]) : null, + ); +} + +//Provides: caml_binaryen_try__bytecode +//Requires: caml_binaryen_try +function caml_binaryen_try__bytecode() { + return caml_binaryen_try(arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5]); +} + +//Provides: caml_binaryen_throw +//Requires: caml_jsstring_of_string, caml_list_to_js_array +function caml_binaryen_throw(wasm_mod, tag, operands) { + return wasm_mod.throw( + caml_jsstring_of_string(tag), + caml_list_to_js_array(operands), + ); +} + +//Provides: caml_binaryen_try_get_name +//Requires: Binaryen, caml_string_of_jsstring, to_option +function caml_binaryen_try_get_name(expr) { + var name = Binaryen.Try.getName(expr); + var str = name != null ? caml_string_of_jsstring(name) : null; + return to_option(str); +} + +//Provides: caml_binaryen_try_set_name +//Requires: Binaryen, caml_jsstring_of_string +function caml_binaryen_try_set_name(expr, name) { + Binaryen.Try.setName(expr, caml_jsstring_of_string(name)); +} + +//Provides: caml_binaryen_try_get_body +//Requires: Binaryen +function caml_binaryen_try_get_body(expr) { + return Binaryen.Try.getBody(expr); +} + +//Provides: caml_binaryen_try_set_body +//Requires: Binaryen +function caml_binaryen_try_set_body(expr, bodyExpr) { + Binaryen.Try.setBody(expr, bodyExpr); +} + +//Provides: caml_binaryen_try_get_num_catch_tags +//Requires: Binaryen +function caml_binaryen_try_get_num_catch_tags(expr) { + return Binaryen.Try.getNumCatchTags(expr); +} + +//Provides: caml_binaryen_try_get_num_catch_bodies +//Requires: Binaryen +function caml_binaryen_try_get_num_catch_bodies(expr) { + return Binaryen.Try.getNumCatchBodies(expr); +} + +//Provides: caml_binaryen_try_get_catch_tag_at +//Requires: Binaryen, caml_string_of_jsstring +function caml_binaryen_try_get_catch_tag_at(expr, index) { + return caml_string_of_jsstring(Binaryen.Try.getCatchTagAt(expr, index)); +} + +//Provides: caml_binaryen_try_set_catch_tag_at +//Requires: Binaryen, caml_jsstring_of_string +function caml_binaryen_try_set_catch_tag_at(expr, index, catchTag) { + Binaryen.Try.setCatchTagAt(expr, index, caml_jsstring_of_string(catchTag)); +} + +//Provides: caml_binaryen_try_append_catch_tag +//Requires: Binaryen, caml_jsstring_of_string +function caml_binaryen_try_append_catch_tag(expr, catchTag) { + return Binaryen.Try.appendCatchTag(expr, caml_jsstring_of_string(catchTag)); +} + +//Provides: caml_binaryen_try_insert_catch_tag_at +//Requires: Binaryen, caml_jsstring_of_string +function caml_binaryen_try_insert_catch_tag_at(expr, index, catchTag) { + Binaryen.Try.insertCatchTagAt(expr, index, caml_jsstring_of_string(catchTag)); +} + +//Provides: caml_binaryen_try_remove_catch_tag_at +//Requires: Binaryen, caml_string_of_jsstring +function caml_binaryen_try_remove_catch_tag_at(expr, index) { + return caml_string_of_jsstring(Binaryen.Try.removeCatchTagAt(expr, index)); +} + +//Provides: caml_binaryen_try_get_catch_body_at +//Requires: Binaryen +function caml_binaryen_try_get_catch_body_at(expr, index) { + return Binaryen.Try.getCatchBodyAt(expr, index); +} + +//Provides: caml_binaryen_try_set_catch_body_at +//Requires: Binaryen +function caml_binaryen_try_set_catch_body_at(expr, index, catchExpr) { + Binaryen.Try.setCatchBodyAt(expr, index, catchExpr); +} + +//Provides: caml_binaryen_try_append_catch_body +//Requires: Binaryen +function caml_binaryen_try_append_catch_body(expr, catchExpr) { + return Binaryen.Try.appendCatchBody(expr, catchExpr); +} + +//Provides: caml_binaryen_try_insert_catch_body_at +//Requires: Binaryen +function caml_binaryen_try_insert_catch_body_at(expr, index, catchExpr) { + Binaryen.Try.insertCatchBodyAt(expr, index, catchExpr); +} + +//Provides: caml_binaryen_try_remove_catch_body_at +//Requires: Binaryen +function caml_binaryen_try_remove_catch_body_at(expr, index) { + return Binaryen.Try.removeCatchBodyAt(expr, index); +} + +//Provides: caml_binaryen_try_has_catch_all +//Requires: Binaryen +//Requires: caml_js_to_bool +function caml_binaryen_try_has_catch_all(expr) { + return caml_js_to_bool(Binaryen.Try.hasCatchAll(expr)); +} + +//Provides: caml_binaryen_throw_get_tag +//Requires: Binaryen, caml_string_of_jsstring +function caml_binaryen_throw_get_tag(expr) { + return caml_string_of_jsstring(Binaryen.Throw.getTag(expr)); +} + +//Provides: caml_binaryen_throw_set_tag +//Requires: Binaryen, caml_jsstring_of_string +function caml_binaryen_throw_set_tag(expr, tagName) { + Binaryen.Throw.setTag(expr, caml_jsstring_of_string(tagName)); +} + +//Provides: caml_binaryen_throw_get_num_operands +//Requires: Binaryen +function caml_binaryen_throw_get_num_operands(expr) { + return Binaryen.Throw.getNumOperands(expr); +} + +//Provides: caml_binaryen_throw_get_operand_at +//Requires: Binaryen +function caml_binaryen_throw_get_operand_at(expr, index) { + return Binaryen.Throw.getOperandAt(expr, index); +} + +//Provides: caml_binaryen_throw_set_operand_at +//Requires: Binaryen +function caml_binaryen_throw_set_operand_at(expr, index, operandExpr) { + Binaryen.Throw.setOperandAt(expr, index, operandExpr); +} + +//Provides: caml_binaryen_throw_append_operand +//Requires: Binaryen +function caml_binaryen_throw_append_operand(expr, operandExpr) { + return Binaryen.Throw.appendOperand(expr, operandExpr); +} + +//Provides: caml_binaryen_throw_insert_operand_at +//Requires: Binaryen +function caml_binaryen_throw_insert_operand_at(expr, index, operandExpr) { + Binaryen.Throw.insertOperandAt(expr, index, operandExpr); +} + +//Provides: caml_binaryen_throw_remove_operand_at +//Requires: Binaryen +function caml_binaryen_throw_remove_operand_at(expr, index) { + return Binaryen.Throw.removeOperandAt(expr, index); +} + // Table operations //Provides: caml_binaryen_table_get diff --git a/src/expression.ml b/src/expression.ml index 1824b6db..9328e31a 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -832,6 +832,124 @@ module Ref = struct (** Module, left, right *) end +(** Bindings for `try_table` instruction. *) +module Try = struct + external make : + Module.t -> + string option -> + t -> + string list -> + t list -> + string option -> + t = "caml_binaryen_try__bytecode" "caml_binaryen_try" + (** Module, name, body, catch tags, catch bodies, delegate target *) + + (** Module, name, body, catch clauses, catch all *) + let make wasm_mod name body catch_clauses catch_all = + let catch_tags, catch_bodies = List.split catch_clauses in + let catch_bodies = + match catch_all with + | Some target -> List.append catch_bodies [ target ] + | None -> catch_bodies + in + make wasm_mod name body catch_tags catch_bodies None + + external get_name : t -> string option = "caml_binaryen_try_get_name" + (** expr *) + + external set_name : t -> string -> unit = "caml_binaryen_try_set_name" + (** expr, name *) + + external get_body : t -> t = "caml_binaryen_try_get_body" + (** expr *) + + external set_body : t -> t -> unit = "caml_binaryen_try_set_body" + (** expr, bodyExpr *) + + external get_num_catch_tags : t -> int + = "caml_binaryen_try_get_num_catch_tags" + (** expr *) + + external get_num_catch_bodies : t -> int + = "caml_binaryen_try_get_num_catch_bodies" + (** expr *) + + external get_catch_tag_at : t -> int -> string + = "caml_binaryen_try_get_catch_tag_at" + (** expr, index *) + + external set_catch_tag_at : t -> int -> string -> unit + = "caml_binaryen_try_set_catch_tag_at" + (** expr, index, catchTag *) + + external append_catch_tag : t -> string -> int + = "caml_binaryen_try_append_catch_tag" + (** expr, catchTag *) + + external insert_catch_tag_at : t -> int -> string -> unit + = "caml_binaryen_try_insert_catch_tag_at" + (** expr, index, catchTag *) + + external remove_catch_tag_at : t -> int -> string + = "caml_binaryen_try_remove_catch_tag_at" + (** expr, index *) + + external get_catch_body_at : t -> int -> t + = "caml_binaryen_try_get_catch_body_at" + (** expr, index *) + + external set_catch_body_at : t -> int -> t -> unit + = "caml_binaryen_try_set_catch_body_at" + (** expr, index, catchExpr *) + + external append_catch_body : t -> t -> int + = "caml_binaryen_try_append_catch_body" + (** expr, catchExpr *) + + external insert_catch_body_at : t -> int -> t -> unit + = "caml_binaryen_try_insert_catch_body_at" + (** expr, index, catchExpr *) + + external remove_catch_body_at : t -> int -> t + = "caml_binaryen_try_remove_catch_body_at" + (** expr, index *) + + external has_catch_all : t -> bool = "caml_binaryen_try_has_catch_all" + (** expr *) +end + +module Throw = struct + external make : Module.t -> string -> t list -> t = "caml_binaryen_throw" + (** Module, tag, operands *) + + external get_tag : t -> string = "caml_binaryen_throw_get_tag" + (** expr *) + + external set_tag : t -> string -> unit = "caml_binaryen_throw_set_tag" + (** expr, tagName *) + + external get_num_operands : t -> int = "caml_binaryen_throw_get_num_operands" + (** expr *) + + external get_operand_at : t -> int -> t = "caml_binaryen_throw_get_operand_at" + (** expr, index *) + + external set_operand_at : t -> int -> t -> unit + = "caml_binaryen_throw_set_operand_at" + (** expr, index, operandExpr *) + + external append_operand : t -> t -> int = "caml_binaryen_throw_append_operand" + (** expr, operandExpr *) + + external insert_operand_at : t -> int -> t -> unit + = "caml_binaryen_throw_insert_operand_at" + (** expr, index, operandExpr *) + + external remove_operand_at : t -> int -> t + = "caml_binaryen_throw_remove_operand_at" + (** expr, index *) +end + module Table = struct external get : Module.t -> string -> t -> Type.t -> t = "caml_binaryen_table_get" diff --git a/src/expression.mli b/src/expression.mli index 9abd7beb..3b70645a 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -350,6 +350,93 @@ module Ref : sig (** Module, left, right *) end +(** Bindings for `try` instruction. *) +module Try : sig + val make : + Module.t -> string option -> t -> (string * t) list -> t option -> t + (** Module, name, body, catch clauses, catch all *) + + val get_name : t -> string option + (** expr *) + + val set_name : t -> string -> unit + (** expr, name *) + + val get_body : t -> t + (** expr *) + + val set_body : t -> t -> unit + (** expr, bodyExpr *) + + val get_num_catch_tags : t -> int + (** expr *) + + val get_num_catch_bodies : t -> int + (** expr *) + + val get_catch_tag_at : t -> int -> string + (** expr, index *) + + val set_catch_tag_at : t -> int -> string -> unit + (** expr, index, catchTag *) + + val append_catch_tag : t -> string -> int + (** expr, catchTag *) + + val insert_catch_tag_at : t -> int -> string -> unit + (** expr, index, catchTag *) + + val remove_catch_tag_at : t -> int -> string + (** expr, index *) + + val get_catch_body_at : t -> int -> t + (** expr, index *) + + val set_catch_body_at : t -> int -> t -> unit + (** expr, index, catchExpr *) + + val append_catch_body : t -> t -> int + (** expr, catchExpr *) + + val insert_catch_body_at : t -> int -> t -> unit + (** expr, index, catchExpr *) + + val remove_catch_body_at : t -> int -> t + (** expr, index *) + + val has_catch_all : t -> bool + (** expr *) +end + +module Throw : sig + val make : Module.t -> string -> t list -> t + (** Module, tag, operands *) + + val get_tag : t -> string + (** expr *) + + val set_tag : t -> string -> unit + (** expr, tagName *) + + val get_num_operands : t -> int + (** expr *) + + val get_operand_at : t -> int -> t + (** expr, index *) + + val set_operand_at : t -> int -> t -> unit + (** expr, index, operandExpr *) + + val append_operand : t -> t -> int + (** expr, operandExpr *) + + val insert_operand_at : t -> int -> t -> unit + (** expr, index, operandExpr *) + + val remove_operand_at : t -> int -> t + (** expr, index *) +end + module Table : sig val get : Module.t -> string -> t -> Type.t -> t (** Module, name, index, type *) diff --git a/src/import.c b/src/import.c index 962043ed..501ae777 100644 --- a/src/import.c +++ b/src/import.c @@ -67,6 +67,24 @@ caml_binaryen_add_global_import__bytecode(value * argv) { return caml_binaryen_add_global_import(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } +CAMLprim value +caml_binaryen_add_tag_import(value _module, value _internalName, value _externalModuleName, value _externalBaseName, value _paramsty, value _resultsty) { + CAMLparam5(_module, _internalName, _externalModuleName, _externalBaseName, _paramsty); + CAMLxparam1(_resultsty); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* internalName = Safe_String_val(_internalName); + char* externalModuleName = Safe_String_val(_externalModuleName); + char* externalBaseName = Safe_String_val(_externalBaseName); + BinaryenType paramsty = BinaryenType_val(_paramsty); + BinaryenType resultsty = BinaryenType_val(_resultsty); + BinaryenAddTagImport(module, internalName, externalModuleName, externalBaseName, paramsty, resultsty); + CAMLreturn(Val_unit); +} +CAMLprim value +caml_binaryen_add_tag_import__bytecode(value * argv) { + return caml_binaryen_add_tag_import(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + CAMLprim value caml_binaryen_function_import_get_module(value _fun) { CAMLparam1(_fun); @@ -89,6 +107,13 @@ caml_binaryen_global_import_get_module(value _global) { CAMLreturn(caml_copy_string(BinaryenGlobalImportGetModule(global))); } +CAMLprim value +caml_binaryen_tag_import_get_module(value _tag) { + CAMLparam1(_tag); + BinaryenTagRef tag = BinaryenTagRef_val(_tag); + CAMLreturn(caml_copy_string(BinaryenTagImportGetModule(tag))); +} + CAMLprim value caml_binaryen_function_import_get_base(value _fun) { CAMLparam1(_fun); @@ -110,3 +135,10 @@ caml_binaryen_global_import_get_base(value _global) { BinaryenGlobalRef global = BinaryenGlobalRef_val(_global); CAMLreturn(caml_copy_string(BinaryenGlobalImportGetBase(global))); } + +CAMLprim value +caml_binaryen_tag_import_get_base(value _tag) { + CAMLparam1(_tag); + BinaryenTagRef tag = BinaryenTagRef_val(_tag); + CAMLreturn(caml_copy_string(BinaryenTagImportGetBase(tag))); +} diff --git a/src/import.js b/src/import.js index 465dcd25..95852d8b 100644 --- a/src/import.js +++ b/src/import.js @@ -92,6 +92,37 @@ function caml_binaryen_add_global_import__bytecode() { ); } +//Provides: caml_binaryen_add_tag_import +//Requires: caml_jsstring_of_string +function caml_binaryen_add_tag_import( + wasm_mod, + internalName, + externalModuleName, + externalBaseName, + paramsty, + resultsty +) { + return wasm_mod.addTagImport( + caml_jsstring_of_string(internalName), + caml_jsstring_of_string(externalModuleName), + caml_jsstring_of_string(externalBaseName), + paramsty, + resultsty + ); +} +//Provides: caml_binaryen_add_tag_import__bytecode +//Requires: caml_binaryen_add_tag_import +function caml_binaryen_add_tag_import__bytecode() { + return caml_binaryen_add_tag_import( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); +} + //Provides: caml_binaryen_function_import_get_module //Requires: Binaryen //Requires: caml_string_of_jsstring @@ -115,6 +146,14 @@ function caml_binaryen_global_import_get_module(global) { return caml_string_of_jsstring(global_info.module); } +//Provides: caml_binaryen_tag_import_get_module +//Requires: Binaryen +//Requires: caml_string_of_jsstring +function caml_binaryen_tag_import_get_module(tag) { + var tag_info = Binaryen.getTagInfo(tag); + return caml_string_of_jsstring(tag_info.module); +} + //Provides: caml_binaryen_function_import_get_base //Requires: Binaryen //Requires: caml_string_of_jsstring @@ -137,3 +176,11 @@ function caml_binaryen_global_import_get_base(global) { var global_info = Binaryen.getGlobalInfo(global); return caml_string_of_jsstring(global_info.base); } + +//Provides: caml_binaryen_tag_import_get_base +//Requires: Binaryen +//Requires: caml_string_of_jsstring +function caml_binaryen_tag_import_get_base(tag) { + var tag_info = Binaryen.getTagInfo(tag); + return caml_string_of_jsstring(tag_info.base); +} diff --git a/src/import.ml b/src/import.ml index d29bb18c..eb9e2a18 100644 --- a/src/import.ml +++ b/src/import.ml @@ -21,6 +21,12 @@ external add_global_import : (** Module, internal name, external module name, external base name, type, mutable. *) +external add_tag_import : + Module.t -> string -> string -> string -> Type.t -> Type.t -> unit + = "caml_binaryen_add_tag_import__bytecode" "caml_binaryen_add_tag_import" +(** Module, internal name, external module name, external base name, params + type, results type. *) + external function_import_get_module : Function.t -> string = "caml_binaryen_function_import_get_module" @@ -30,6 +36,9 @@ external memory_import_get_module : Module.t -> string -> string external global_import_get_module : Global.t -> string = "caml_binaryen_global_import_get_module" +external tag_import_get_module : Tag.t -> string + = "caml_binaryen_tag_import_get_module" + external function_import_get_base : Function.t -> string = "caml_binaryen_function_import_get_base" @@ -38,3 +47,6 @@ external memory_import_get_base : Module.t -> string -> string external global_import_get_base : Global.t -> string = "caml_binaryen_global_import_get_base" + +external tag_import_get_base : Tag.t -> string + = "caml_binaryen_tag_import_get_base" diff --git a/src/import.mli b/src/import.mli index 52a69370..42c9bf96 100644 --- a/src/import.mli +++ b/src/import.mli @@ -7,9 +7,14 @@ val add_memory_import : Module.t -> string -> string -> string -> bool -> unit val add_global_import : Module.t -> string -> string -> string -> Type.t -> bool -> unit +val add_tag_import : + Module.t -> string -> string -> string -> Type.t -> Type.t -> unit + val function_import_get_module : Function.t -> string val memory_import_get_module : Module.t -> string -> string val global_import_get_module : Global.t -> string +val tag_import_get_module : Tag.t -> string val function_import_get_base : Function.t -> string val memory_import_get_base : Module.t -> string -> string val global_import_get_base : Global.t -> string +val tag_import_get_base : Tag.t -> string diff --git a/src/ocaml_helpers.c b/src/ocaml_helpers.c index 78a17230..d8af8bb6 100644 --- a/src/ocaml_helpers.c +++ b/src/ocaml_helpers.c @@ -38,6 +38,14 @@ value alloc_BinaryenGlobalRef(BinaryenGlobalRef exp) return v; } +/* Allocating an OCaml custom block to hold the given BinaryenTagRef */ +value alloc_BinaryenTagRef(BinaryenTagRef exp) +{ + value v = caml_alloc_custom(&binaryen_ops, sizeof(BinaryenTagRef), 0, 1); + BinaryenTagRef_val(v) = exp; + return v; +} + /* Allocating an OCaml custom block to hold the given BinaryenExportRef */ value alloc_BinaryenExportRef(BinaryenExportRef exp) { diff --git a/src/ocaml_helpers.h b/src/ocaml_helpers.h index 3e926eaf..939ba09e 100644 --- a/src/ocaml_helpers.h +++ b/src/ocaml_helpers.h @@ -29,6 +29,7 @@ static struct custom_operations binaryen_ops = { #define BinaryenLiteral_val(v) (*((struct BinaryenLiteral*) Data_custom_val(v))) #define BinaryenFunctionRef_val(v) (*((BinaryenFunctionRef*) Data_custom_val(v))) #define BinaryenGlobalRef_val(v) (*((BinaryenGlobalRef*) Data_custom_val(v))) +#define BinaryenTagRef_val(v) (*((BinaryenTagRef*) Data_custom_val(v))) #define BinaryenExportRef_val(v) (*((BinaryenExportRef*) Data_custom_val(v))) #define BinaryenTableRef_val(v) (*((BinaryenTableRef*) Data_custom_val(v))) #define BinaryenElementSegmentRef_val(v) (*((BinaryenElementSegmentRef*) Data_custom_val(v))) @@ -53,6 +54,9 @@ value alloc_BinaryenType(BinaryenType typ); /* Allocating an OCaml custom block to hold the given BinaryenGlobalRef */ value alloc_BinaryenGlobalRef(BinaryenGlobalRef exp); +/* Allocating an OCaml custom block to hold the given BinaryenTagRef */ +value alloc_BinaryenTagRef(BinaryenTagRef exp); + /* Allocating an OCaml custom block to hold the given BinaryenExportRef */ value alloc_BinaryenExportRef(BinaryenExportRef exp); diff --git a/src/tag.c b/src/tag.c new file mode 100644 index 00000000..0eb0dac5 --- /dev/null +++ b/src/tag.c @@ -0,0 +1,61 @@ +#define CAML_NAME_SPACE +#include +#include +#include +#include + +#include "binaryen-c.h" +#include "ocaml_helpers.h" + +CAMLprim value +caml_binaryen_add_tag(value _module, value _name, value _params, value _results) { + CAMLparam4(_module, _name, _params, _results); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* name = Safe_String_val(_name); + BinaryenType params = BinaryenType_val(_params); + BinaryenType results = BinaryenType_val(_results); + BinaryenTagRef tag = BinaryenAddTag(module, name, params, results); + CAMLreturn(alloc_BinaryenTagRef(tag)); +} + +CAMLprim value +caml_binaryen_get_tag(value _module, value _name) { + CAMLparam2(_module, _name); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* name = Safe_String_val(_name); + BinaryenTagRef tag = BinaryenGetTag(module, name); + CAMLreturn(alloc_BinaryenTagRef(tag)); +} + +CAMLprim value +caml_binaryen_remove_tag(value _module, value _name) { + CAMLparam2(_module, _name); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* name = Safe_String_val(_name); + BinaryenRemoveTag(module, name); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_tag_get_name(value _tag) { + CAMLparam1(_tag); + BinaryenTagRef tag = BinaryenTagRef_val(_tag); + const char* name = BinaryenTagGetName(tag); + CAMLreturn(caml_copy_string(name)); +} + +CAMLprim value +caml_binaryen_tag_get_params(value _tag) { + CAMLparam1(_tag); + BinaryenTagRef tag = BinaryenTagRef_val(_tag); + BinaryenType ty = BinaryenTagGetParams(tag); + CAMLreturn(alloc_BinaryenType(ty)); +} + +CAMLprim value +caml_binaryen_tag_get_results(value _tag) { + CAMLparam1(_tag); + BinaryenTagRef tag = BinaryenTagRef_val(_tag); + BinaryenType ty = BinaryenTagGetResults(tag); + CAMLreturn(alloc_BinaryenType(ty)); +} diff --git a/src/tag.js b/src/tag.js new file mode 100644 index 00000000..63065b12 --- /dev/null +++ b/src/tag.js @@ -0,0 +1,43 @@ +//Provides: caml_binaryen_add_tag +//Requires: caml_jsstring_of_string +function caml_binaryen_add_tag(wasm_mod, name, params, results) { + return wasm_mod.addTag( + caml_jsstring_of_string(name), + params, + results, + ); +} + +//Provides: caml_binaryen_get_tag +//Requires: caml_jsstring_of_string +function caml_binaryen_get_tag(wasm_mod, name) { + return wasm_mod.getTag(caml_jsstring_of_string(name)); +} + +//Provides: caml_binaryen_remove_tag +//Requires: caml_jsstring_of_string +function caml_binaryen_remove_tag(wasm_mod, name) { + return wasm_mod.removeTag(caml_jsstring_of_string(name)); +} + +//Provides: caml_binaryen_tag_get_name +//Requires: Binaryen +//Requires: caml_string_of_jsstring +function caml_binaryen_tag_get_name(tag) { + var tag_info = Binaryen.getTagInfo(tag); + return caml_string_of_jsstring(tag_info.name); +} + +//Provides: caml_binaryen_tag_get_params +//Requires: Binaryen +function caml_binaryen_tag_get_params(tag) { + var tag_info = Binaryen.getTagInfo(tag); + return tag_info.params; +} + +//Provides: caml_binaryen_tag_get_results +//Requires: Binaryen +function caml_binaryen_tag_get_results(tag) { + var tag_info = Binaryen.getTagInfo(tag); + return tag_info.results; +} diff --git a/src/tag.ml b/src/tag.ml new file mode 100644 index 00000000..ed36e318 --- /dev/null +++ b/src/tag.ml @@ -0,0 +1,11 @@ +type t + +external add_tag : Module.t -> string -> Type.t -> Type.t -> t + = "caml_binaryen_add_tag" +(** Module, name, params, result *) + +external get_tag : Module.t -> string -> t = "caml_binaryen_get_tag" +external remove_tag : Module.t -> string -> unit = "caml_binaryen_remove_tag" +external get_name : t -> string = "caml_binaryen_tag_get_name" +external get_params : t -> Type.t = "caml_binaryen_tag_get_params" +external get_results : t -> Type.t = "caml_binaryen_tag_get_results" diff --git a/src/tag.mli b/src/tag.mli new file mode 100644 index 00000000..d75edc29 --- /dev/null +++ b/src/tag.mli @@ -0,0 +1,8 @@ +type t + +val add_tag : Module.t -> string -> Type.t -> Type.t -> t +val get_tag : Module.t -> string -> t +val remove_tag : Module.t -> string -> unit +val get_name : t -> string +val get_params : t -> Type.t +val get_results : t -> Type.t diff --git a/test/test.expected b/test/test.expected index 8e1c7db2..0a35f066 100644 --- a/test/test.expected +++ b/test/test.expected @@ -7,11 +7,12 @@ (i32.const 0) ) (module - (type $0 (func (param i32 i32) (result i32))) - (type $1 (func)) - (type $2 (func (param anyref i32 i32) (result i32))) - (type $3 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $2) (param anyref i32 i32) (result i32))) + (type $0 (func (param i32))) + (type $1 (func (param i32 i32) (result i32))) + (type $2 (func)) + (type $3 (func (param anyref i32 i32) (result i32))) + (type $4 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) (global $max_int64 i64 (i64.const 9223372036854775807)) (global $max_int64_mut (mut i64) (i64.const 9223372036854775807)) (global $test_float64_bits f64 (f64.const 1.23)) @@ -20,11 +21,14 @@ (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) + (tag $foo (type $0) (param i32)) + (tag $bar (type $0) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) + (export "try" (func $try)) (start $start) - (func $adder (type $0) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $1) (param $0 i32) (param $1 i32) (result i32) (block $add (result i32) (if (i32.const 0) @@ -44,7 +48,7 @@ ) ) ) - (func $start (type $1) + (func $start (type $2) (block $start (memory.init $world (i32.const 2048) @@ -52,7 +56,7 @@ (i32.const 5) ) (drop - (call_indirect $table (type $0) + (call_indirect $table (type $1) (i32.const 3) (i32.const 5) (i32.const 0) @@ -60,30 +64,102 @@ ) ) ) - (func $hello (type $3) (param $0 anyref) (result i32) + (func $hello (type $4) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) + (func $try (type $2) + (block $blk + (drop + (try $tc1 (result i32) + (do + (throw $foo + (i32.const 1) + ) + ) + (catch $foo + (block $tc1blk2 (result i32) + (drop + (pop i32) + ) + (i32.const 2) + ) + ) + (catch $bar + (block $tc1blk3 (result i32) + (drop + (pop i32) + ) + (i32.const 3) + ) + ) + ) + ) + (try $tc2 + (do + (throw $foo + (i32.const 1) + ) + ) + (catch $foo + (block $tc2blk2 + (drop + (pop i32) + ) + ) + ) + (catch $bar + (block $tc2blk3 + (drop + (pop i32) + ) + ) + ) + ) + (drop + (try $tc3 (result i32) + (do + (i32.const 1) + ) + (catch $foo + (block $tc3blk2 (result i32) + (drop + (pop i32) + ) + (i32.const 2) + ) + ) + (catch_all + (i32.const 3) + ) + ) + ) + ) + ) ) (module - (type $0 (func (param i32 i32) (result i32))) + (type $0 (func (param i32))) (type $1 (func)) - (type $2 (func (param anyref i32 i32) (result i32))) - (type $3 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $2) (param anyref i32 i32) (result i32))) + (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (param anyref i32 i32) (result i32))) + (type $4 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) (memory $0 1) (data $hello (i32.const 0) "hello") (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) + (tag $foo (type $0) (param i32)) + (tag $bar (type $0) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) + (export "try" (func $try)) (start $start) - (func $adder (type $0) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) (i32.add (select (local.get $0) @@ -108,20 +184,60 @@ ) ) ) - (func $hello (type $3) (param $0 anyref) (result i32) + (func $hello (type $4) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) + (func $try (type $1) + (drop + (try (result i32) + (do + (throw $foo + (i32.const 1) + ) + ) + (catch $foo + (drop + (pop i32) + ) + (i32.const 2) + ) + (catch $bar + (drop + (pop i32) + ) + (i32.const 3) + ) + ) + ) + (try + (do + (throw $foo + (i32.const 1) + ) + ) + (catch $foo + (drop + (pop i32) + ) + ) + (catch $bar + (drop + (pop i32) + ) + ) + ) + ) ) (module - (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))) + (type $type_3 (func)) + (type $type_1 (func (param anyref i32 i32) (result i32))) + (type $type_2 (func (param i32 i32) (result i32))) + (type $type_4 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") (data $1 "world") @@ -130,8 +246,9 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) + (export "try" (func $3)) (start $1) - (func $0 (type $type_1) (param $0 i32) (param $1 i32) (result i32) + (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) (i32.add (select (local.get $0) @@ -143,7 +260,7 @@ (local.get $1) ) ) - (func $1 (type $type_2) + (func $1 (type $type_3) (memory.init $1 (i32.const 2048) (i32.const 0) @@ -156,20 +273,26 @@ ) ) ) - (func $2 (type $type_3) (param $0 anyref) (result i32) + (func $2 (type $type_4) (param $0 anyref) (result i32) (call $fimport$0 (local.get $0) (i32.const 0) (i32.const 1) ) ) + (func $3 (type $type_3) + (drop + (unreachable) + ) + (unreachable) + ) ) (module - (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))) + (type $type_3 (func)) + (type $type_1 (func (param anyref i32 i32) (result i32))) + (type $type_2 (func (param i32 i32) (result i32))) + (type $type_4 (func (param anyref) (result i32))) + (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") (data $1 "world") @@ -178,8 +301,9 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) + (export "try" (func $3)) (start $1) - (func $0 (type $type_1) (param $0 i32) (param $1 i32) (result i32) + (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) local.get $0 local.get $1 i32.load @@ -188,7 +312,7 @@ local.get $1 i32.add ) - (func $1 (type $type_2) + (func $1 (type $type_3) i32.const 2048 i32.const 0 i32.const 5 @@ -198,10 +322,13 @@ call $0 drop ) - (func $2 (type $type_3) (param $0 anyref) (result i32) + (func $2 (type $type_4) (param $0 anyref) (result i32) local.get $0 i32.const 0 i32.const 1 call $fimport$0 ) + (func $3 (type $type_3) + unreachable + ) ) diff --git a/test/test.ml b/test/test.ml index a5ef4e90..cfb95a44 100644 --- a/test/test.ml +++ b/test/test.ml @@ -254,6 +254,84 @@ let _ = (Memory.get_segment_data wasm_mod "world") (Bytes.of_string "world")) +let _ = Tag.add_tag wasm_mod "foo" Type.int32 Type.none +let _ = Tag.add_tag wasm_mod "bar" Type.int32 Type.none + +(* Exception handling *) +let body = + Expression.Throw.make wasm_mod "foo" + [ Expression.Const.make wasm_mod (Literal.int32 1l) ] + +let try_catch_1 = + Expression.Try.make wasm_mod (Some "tc1") body + [ + ( "foo", + Expression.Block.make wasm_mod "tc1blk2" + [ + Expression.Drop.make wasm_mod + (Expression.Pop.make wasm_mod Type.int32); + Expression.Const.make wasm_mod (Literal.int32 2l); + ] ); + ( "bar", + Expression.Block.make wasm_mod "tc1blk3" + [ + Expression.Drop.make wasm_mod + (Expression.Pop.make wasm_mod Type.int32); + Expression.Const.make wasm_mod (Literal.int32 3l); + ] ); + ] + None + +let _ = assert (Expression.Try.get_name try_catch_1 = Some "tc1") +let _ = Expression.Try.set_name try_catch_1 "renamed_tc1" +let _ = assert (Expression.Try.get_name try_catch_1 = Some "renamed_tc1") +let _ = Expression.Try.set_name try_catch_1 "tc1" + +let _ = + assert ( + Expression.get_kind (Expression.Try.get_body try_catch_1) + = Expression.get_kind body) + +let _ = assert (Expression.Try.get_num_catch_tags try_catch_1 = 2) +let _ = assert (Expression.Try.get_num_catch_bodies try_catch_1 = 2) + +let try_catch_2 = + Expression.Try.make wasm_mod (Some "tc2") + (Expression.Throw.make wasm_mod "foo" + [ Expression.Const.make wasm_mod (Literal.int32 1l) ]) + [ + ( "foo", + Expression.Block.make wasm_mod "tc2blk2" + [ + Expression.Drop.make wasm_mod + (Expression.Pop.make wasm_mod Type.int32); + ] ); + ( "bar", + Expression.Block.make wasm_mod "tc2blk3" + [ + Expression.Drop.make wasm_mod + (Expression.Pop.make wasm_mod Type.int32); + ] ); + ] + None + +let _ = assert (Expression.Try.get_name try_catch_2 = Some "tc2") + +(* Test catch_all *) +let try_catch_all_1 = + Expression.Try.make wasm_mod (Some "tc3") + (Expression.Const.make wasm_mod (Literal.int32 1l)) + [ + ( "foo", + Expression.Block.make wasm_mod "tc3blk2" + [ + Expression.Drop.make wasm_mod + (Expression.Pop.make wasm_mod Type.int32); + Expression.Const.make wasm_mod (Literal.int32 2l); + ] ); + ] + (Some (Expression.Const.make wasm_mod (Literal.int32 3l))) + (* Create an imported "write" function i32 (externref, i32, i32) *) (* Similar to the example here: https://bytecodealliance.org/articles/reference-types-in-wasmtime *) @@ -273,7 +351,18 @@ let _ = ] Type.int32) +(* Create a function with try *) +let _ = + Function.add_function wasm_mod "try" Type.none Type.none [||] + (Expression.Block.make wasm_mod "blk" + [ + Expression.Drop.make wasm_mod try_catch_1; + try_catch_2; + Expression.Drop.make wasm_mod try_catch_all_1; + ]) + let _ = Export.add_function_export wasm_mod "hello" "hello" +let _ = Export.add_function_export wasm_mod "try" "try" let _ = Module.validate wasm_mod (* Shouldn't actually do anything since we aren't doing function renames *) From 0b503c339f6444b9413014d7708a8290b7bdd33c Mon Sep 17 00:00:00 2001 From: Oscar Spencer Date: Sun, 16 Feb 2025 21:57:29 -0600 Subject: [PATCH 04/10] feat!: Implement GC instructions --- src/dune | 2 + src/expression.c | 268 +++++++++++++++++++++++++++++++++++++++++++ src/expression.js | 194 +++++++++++++++++++++++++++++++ src/expression.ml | 86 ++++++++++++++ src/expression.mli | 60 ++++++++++ src/ocaml_helpers.c | 9 ++ src/ocaml_helpers.h | 5 + src/type.ml | 5 +- src/type.mli | 2 +- src/type_builder.c | 176 ++++++++++++++++++++++++++++ src/type_builder.js | 116 +++++++++++++++++++ src/type_builder.ml | 65 +++++++++++ src/type_builder.mli | 27 +++++ test/test.expected | 191 +++++++++++++++++++++++++++++- test/test.ml | 88 +++++++++++++- 15 files changed, 1290 insertions(+), 4 deletions(-) create mode 100644 src/type_builder.c create mode 100644 src/type_builder.js create mode 100644 src/type_builder.ml create mode 100644 src/type_builder.mli diff --git a/src/dune b/src/dune index 1249f71d..b4109357 100644 --- a/src/dune +++ b/src/dune @@ -24,6 +24,7 @@ heap_type signature_type struct_type + type_builder ocaml_helpers) (flags :standard -O2 -Wall -Wextra)) (js_of_ocaml @@ -46,4 +47,5 @@ packed_type.js heap_type.js signature_type.js + type_builder.js struct_type.js))) diff --git a/src/expression.c b/src/expression.c index 69d9d568..2d737493 100644 --- a/src/expression.c +++ b/src/expression.c @@ -124,6 +124,23 @@ caml_binaryen_call_indirect__bytecode(value * argv) { return caml_binaryen_call_indirect(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } +CAMLprim value +caml_binaryen_call_ref(value _module, value _target, value _params, value _ty, value _is_return) { + CAMLparam5(_module, _target, _params, _ty, _is_return); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef target = BinaryenExpressionRef_val(_target); + _params = array_of_list(_params); + int paramsLen = array_length(_params); + BinaryenExpressionRef params[paramsLen]; + for (int i = 0; i < paramsLen; i++) { + params[i] = BinaryenExpressionRef_val(Field(_params, i)); + } + BinaryenType ty = BinaryenType_val(_ty); + bool is_return = Bool_val(_is_return); + BinaryenExpressionRef exp = BinaryenCallRef(module, target, params, paramsLen, ty, is_return); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + CAMLprim value caml_binaryen_return_call(value _module, value _name, value _params, value _retty) { CAMLparam4(_module, _name, _params, _retty); @@ -459,6 +476,38 @@ caml_binaryen_i31_get(value _module, value _val, value _signed) { CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +CAMLprim value +caml_binaryen_ref_test(value _module, value _ref, value _castType) { + CAMLparam3(_module, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenRefTest(module, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_ref_cast(value _module, value _ref, value _castType) { + CAMLparam3(_module, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenRefCast(module, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_br_on(value _module, value _op, value _name, value _ref, value _castType) { + CAMLparam5(_module, _op, _name, _ref, _castType); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenOp op = BinaryenOp_val(_op); + char* name = Safe_String_val(_name); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType castType = BinaryenType_val(_castType); + BinaryenExpressionRef exp = BinaryenBrOn(module, op, name, ref, castType); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + CAMLprim value caml_binaryen_expression_id_invalid(value unit) { CAMLparam1(unit); @@ -1328,6 +1377,90 @@ caml_binaryen_call_indirect_set_return(value _exp, value _isReturn) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_call_ref_get_target(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef target = BinaryenCallRefGetTarget(exp); + CAMLreturn(alloc_BinaryenExpressionRef(target)); +} + +CAMLprim value +caml_binaryen_call_ref_set_target(value _exp, value _target) { + CAMLparam2(_exp, _target); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef target = BinaryenExpressionRef_val(_target); + BinaryenCallRefSetTarget(exp, target); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_get_num_operands(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + CAMLreturn(Val_int(BinaryenCallRefGetNumOperands(exp))); +} + +CAMLprim value +caml_binaryen_call_ref_get_operand_at(value _exp, value _index) { + CAMLparam2(_exp, _index); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenExpressionRef(BinaryenCallRefGetOperandAt(exp, index))); +} + +CAMLprim value +caml_binaryen_call_ref_set_operand_at(value _exp, value _index, value _operand) { + CAMLparam3(_exp, _index, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + BinaryenCallRefSetOperandAt(exp, index, operand); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_append_operand(value _exp, value _operand) { + CAMLparam2(_exp, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + CAMLreturn(Val_int(BinaryenCallRefAppendOperand(exp, operand))); +} + +CAMLprim value +caml_binaryen_call_ref_insert_operand_at(value _exp, value _index, value _operand) { + CAMLparam3(_exp, _index, _operand); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef operand = BinaryenExpressionRef_val(_operand); + BinaryenCallRefInsertOperandAt(exp, index, operand); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_call_ref_remove_operand_at(value _exp, value _index) { + CAMLparam2(_exp, _index); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenExpressionRef(BinaryenCallRefRemoveOperandAt(exp, index))); +} + +CAMLprim value +caml_binaryen_call_ref_is_return(value _exp) { + CAMLparam1(_exp); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + CAMLreturn(Val_bool(BinaryenCallRefIsReturn(exp))); +} + +CAMLprim value +caml_binaryen_call_ref_set_return(value _exp, value _isReturn) { + CAMLparam2(_exp, _isReturn); + BinaryenExpressionRef exp = BinaryenExpressionRef_val(_exp); + int isReturn = Bool_val(_isReturn); + BinaryenCallRefSetReturn(exp, isReturn); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_local_set_get_value(value _exp) { CAMLparam1(_exp); @@ -1883,6 +2016,141 @@ caml_binaryen_ref_eq(value _module, value _left, value _right) { CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +// Struct operations + +CAMLprim value +caml_binaryen_struct_new(value _module, value _operands, value _type) { + CAMLparam3(_module, _operands, _type); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + if (Is_some(_operands)) { + _operands = array_of_list(Some_val(_operands)); + int operandsLen = array_length(_operands); + BinaryenExpressionRef operands[operandsLen]; + for (int i = 0; i < operandsLen; i++) { + operands[i] = BinaryenExpressionRef_val(Field(_operands, i)); + } + BinaryenExpressionRef exp = BinaryenStructNew(module, operands, operandsLen, type); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); + } else { + BinaryenExpressionRef exp = BinaryenStructNew(module, NULL, 0, type); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); + } +} + +CAMLprim value +caml_binaryen_struct_get(value _module, value _index, value _ref, value _type, value _signed) { + CAMLparam5(_module, _index, _ref, _type, _signed); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenType type = BinaryenType_val(_type); + bool signed_ = Bool_val(_signed); + BinaryenExpressionRef exp = BinaryenStructGet(module, index, ref, type, signed_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_struct_set(value _module, value _index, value _ref, value _value) { + CAMLparam4(_module, _index, _ref, _value); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenIndex index = Int_val(_index); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef value_ = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef exp = BinaryenStructSet(module, index, ref, value_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +// Array operations + +CAMLprim value +caml_binaryen_array_new(value _module, value _type, value _size, value _init) { + CAMLparam4(_module, _type, _size, _init); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef init = BinaryenExpressionRef_val(_init); + BinaryenExpressionRef exp = BinaryenArrayNew(module, type, size, init); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_new_data(value _module, value _type, value _name, value _offset, value _size) { + CAMLparam5(_module, _type, _name, _offset, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + char* name = Safe_String_val(_name); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayNewData(module, type, name, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_new_fixed(value _module, value _type, value _values) { + CAMLparam3(_module, _type, _values); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + _values = array_of_list(_values); + int valuesLen = array_length(_values); + BinaryenExpressionRef values[valuesLen]; + for (int i = 0; i < valuesLen; i++) { + values[i] = BinaryenExpressionRef_val(Field(_values, i)); + } + BinaryenExpressionRef exp = BinaryenArrayNewFixed(module, type, values, valuesLen); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_get(value _module, value _ref, value _index, value _type, value _signed) { + CAMLparam5(_module, _ref, _index, _type, _signed); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenType type = BinaryenType_val(_type); + bool signed_ = Bool_val(_signed); + BinaryenExpressionRef exp = BinaryenArrayGet(module, ref, index, type, signed_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_set(value _module, value _ref, value _index, value _value) { + CAMLparam4(_module, _ref, _index, _value); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef value_ = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef exp = BinaryenArraySet(module, ref, index, value_); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_len(value _module, value _ref) { + CAMLparam2(_module, _ref); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef exp = BinaryenArrayLen(module, ref); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_copy(value _module, value _destRef, value _destIndex, value _srcRef, value _srcIndex, value _length) { + CAMLparam5(_module, _destRef, _destIndex, _srcRef, _srcIndex); + CAMLxparam1(_length); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef destRef = BinaryenExpressionRef_val(_destRef); + BinaryenExpressionRef destIndex = BinaryenExpressionRef_val(_destIndex); + BinaryenExpressionRef srcRef = BinaryenExpressionRef_val(_srcRef); + BinaryenExpressionRef srcIndex = BinaryenExpressionRef_val(_srcIndex); + BinaryenExpressionRef length = BinaryenExpressionRef_val(_length); + BinaryenExpressionRef exp = BinaryenArrayCopy(module, destRef, destIndex, srcRef, srcIndex, length); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} +CAMLprim value +caml_binaryen_array_copy__bytecode(value * argv) { + return caml_binaryen_array_copy(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + // Exception handling operations CAMLprim value caml_binaryen_try(value _module, value _name, value _body, value _catchTags, value _catchBodies, value _delegateTarget) { diff --git a/src/expression.js b/src/expression.js index 2fd5f650..f6ab3685 100644 --- a/src/expression.js +++ b/src/expression.js @@ -101,6 +101,18 @@ function caml_binaryen_call_indirect__bytecode() { ); } +//Provides: caml_binaryen_call_ref +//Requires: caml_jsstring_of_string +//Requires: caml_list_to_js_array, caml_js_from_bool +function caml_binaryen_call_ref(wasm_mod, target, params, typ, is_return) { + return wasm_mod.call_ref( + target, + caml_list_to_js_array(params), + typ, + caml_js_from_bool(is_return) + ); +} + //Provides: caml_binaryen_return_call //Requires: caml_jsstring_of_string //Requires: caml_list_to_js_array @@ -547,6 +559,32 @@ function caml_binaryen_ref_i31(wasm_mod, typ) { return wasm_mod.ref.i31(typ); } +//Provides: caml_binaryen_ref_test +function caml_binaryen_ref_test(wasm_mod, ref, typ) { + return wasm_mod.ref.test(ref, typ); +} + +//Provides: caml_binaryen_ref_cast +function caml_binaryen_ref_cast(wasm_mod, ref, typ) { + return wasm_mod.ref.cast(ref, typ); +} + +//Provides: caml_binaryen_br_on +//Requires: caml_jsstring_of_string +//Requires: Binaryen +function caml_binaryen_br_on(wasm_mod, op, name, ref, typ) { + switch (op) { + case Binaryen.BrOnNull: + return wasm_mod.br_on.null(caml_jsstring_of_string(name), ref, typ); + case Binaryen.BrOnNonNull: + return wasm_mod.br_on.non_null(caml_jsstring_of_string(name), ref, typ); + case Binaryen.BrOnCast: + return wasm_mod.br_on.cast(caml_jsstring_of_string(name), ref, typ); + case Binaryen.BrOnCastFail: + return wasm_mod.br_on.cast_fail(caml_jsstring_of_string(name), ref, typ); + } +} + //Provides: caml_binaryen_i31_get function caml_binaryen_i31_get(wasm_mod, typ, signed) { if (signed) { @@ -1296,6 +1334,68 @@ function caml_binaryen_call_indirect_set_return(exp, isReturn) { return Binaryen.CallIndirect.setReturn(exp, caml_js_from_bool(isReturn)); } +//Provides: caml_binaryen_call_ref_get_target +//Requires: Binaryen +function caml_binaryen_call_ref_get_target(exp) { + return Binaryen.CallRef.getTarget(exp); +} + +//Provides: caml_binaryen_call_ref_set_target +//Requires: Binaryen +function caml_binaryen_call_ref_set_target(exp, target) { + return Binaryen.CallRef.setTarget(exp, target); +} + +//Provides: caml_binaryen_call_ref_get_num_operands +//Requires: Binaryen +function caml_binaryen_call_ref_get_num_operands(exp) { + return Binaryen.CallRef.getNumOperands(exp); +} + +//Provides: caml_binaryen_call_ref_get_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_get_operand_at(exp, index) { + return Binaryen.CallRef.getOperandAt(exp, index); +} + +//Provides: caml_binaryen_call_ref_set_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_set_operand_at(exp, index, operand) { + return Binaryen.CallRef.setOperandAt(exp, index, operand); +} + +//Provides: caml_binaryen_call_ref_append_operand +//Requires: Binaryen +function caml_binaryen_call_ref_append_operand(exp, operand) { + return Binaryen.CallRef.appendOperand(exp, operand); +} + +//Provides: caml_binaryen_call_ref_insert_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_insert_operand_at(exp, index, operand) { + return Binaryen.CallRef.insertOperandAt(exp, index, operand); +} + +//Provides: caml_binaryen_call_ref_remove_operand_at +//Requires: Binaryen +function caml_binaryen_call_ref_remove_operand_at(exp, index) { + return Binaryen.CallRef.removeOperandAt(exp, index); +} + +//Provides: caml_binaryen_call_ref_is_return +//Requires: Binaryen +//Requires: caml_js_to_bool +function caml_binaryen_call_ref_is_return(exp) { + return caml_js_to_bool(Binaryen.CallRef.isReturn(exp)); +} + +//Provides: caml_binaryen_call_ref_set_return +//Requires: Binaryen +//Requires: caml_js_from_bool +function caml_binaryen_call_ref_set_return(exp, isReturn) { + return Binaryen.CallRef.setReturn(exp, caml_js_from_bool(isReturn)); +} + //Provides: caml_binaryen_local_set_get_value //Requires: Binaryen function caml_binaryen_local_set_get_value(exp) { @@ -1707,6 +1807,100 @@ function caml_binaryen_ref_eq(wasm_mod, left, right) { return wasm_mod.ref.func(left, right); } +// Struct operations + +//Provides: caml_binaryen_struct_new +//Requires: caml_list_to_js_array +function caml_binaryen_struct_new(wasm_mod, operands, type) { + return wasm_mod.struct.new( + operands ? caml_list_to_js_array(operands[1]) : null, + type + ); +} + +//Provides: caml_binaryen_struct_get +//Requires: caml_js_from_bool +function caml_binaryen_struct_get(wasm_mod, index, ref, type, signed) { + if (caml_js_from_bool(signed)) { + return wasm_mod.struct.get_s(index, ref, type); + } else { + return wasm_mod.struct.get_u(index, ref, type); + } +} + +//Provides: caml_binaryen_struct_set +function caml_binaryen_struct_set(wasm_mod, index, ref, value) { + return wasm_mod.struct.set(index, ref, value); +} + +// Array operations + +//Provides: caml_binaryen_array_new +function caml_binaryen_array_new(wasm_mod, type, size, init) { + return wasm_mod.array.new(type, size, init); +} + +//Provides: caml_binaryen_array_new_data +//Requires: caml_jsstring_of_string +function caml_binaryen_array_new_data(wasm_mod, type, name, offset, size) { + return wasm_mod.array.new_data( + type, + caml_jsstring_of_string(name), + offset, + size + ); +} + +//Provides: caml_binaryen_array_new_fixed +//Requires: caml_list_to_js_array +function caml_binaryen_array_new_fixed(wasm_mod, type, values) { + return wasm_mod.array.new_fixed(type, caml_list_to_js_array(values)); +} + +//Provides: caml_binaryen_array_get +//Requires: caml_js_from_bool +function caml_binaryen_array_get(wasm_mod, ref, index, type, signed) { + if (caml_js_from_bool(signed)) { + return wasm_mod.array.get_s(ref, index, type); + } else { + return wasm_mod.array.get_u(ref, index, type); + } +} + +//Provides: caml_binaryen_array_set +function caml_binaryen_array_set(wasm_mod, ref, index, value) { + return wasm_mod.array.set(ref, index, value); +} + +//Provides: caml_binaryen_array_len +function caml_binaryen_array_len(wasm_mod, ref) { + return wasm_mod.array.len(ref); +} + +//Provides: caml_binaryen_array_copy +function caml_binaryen_array_copy( + wasm_mod, + destRef, + destIndex, + srcRef, + srcIndex, + length +) { + return wasm_mod.array.copy(destRef, destIndex, srcRef, srcIndex, length); +} +//Provides: caml_binaryen_array_copy__bytecode +//Requires: caml_binaryen_array_copy +function caml_binaryen_array_copy__bytecode() { + return caml_binaryen_array_copy( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); +} + // Exception handling operations //Provides: caml_binaryen_try diff --git a/src/expression.ml b/src/expression.ml index 9328e31a..2eb57841 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -583,6 +583,39 @@ module Call_indirect = struct = "caml_binaryen_call_indirect_set_return" end +module Call_ref = struct + external make : Module.t -> t -> t list -> Type.t -> bool -> t + = "caml_binaryen_call_ref" + (** Module, function value, params, type, is return. *) + + let make_return mod_ target params typ = make mod_ target params typ true + let make mod_ target params typ = make mod_ target params typ false + + external get_target : t -> t = "caml_binaryen_call_ref_get_target" + external set_target : t -> t -> unit = "caml_binaryen_call_ref_set_target" + + external get_num_operands : t -> int + = "caml_binaryen_call_ref_get_num_operands" + + external get_operand_at : t -> int -> t + = "caml_binaryen_call_ref_get_operand_at" + + external set_operand_at : t -> int -> t -> unit + = "caml_binaryen_call_ref_set_operand_at" + + external append_operand : t -> t -> int + = "caml_binaryen_call_ref_append_operand" + + external insert_operand_at : t -> int -> t -> unit + = "caml_binaryen_call_ref_insert_operand_at" + + external remove_operand_at : t -> int -> t + = "caml_binaryen_call_ref_remove_operand_at" + + external is_return : t -> bool = "caml_binaryen_call_ref_is_return" + external set_return : t -> bool -> unit = "caml_binaryen_call_ref_set_return" +end + module Local_get = struct external make : Module.t -> int -> Type.t -> t = "caml_binaryen_local_get" (** Module, slot, type. *) @@ -830,6 +863,59 @@ module Ref = struct external eq : Module.t -> t -> t -> t = "caml_binaryen_ref_eq" (** Module, left, right *) + + external test : Module.t -> t -> Type.t -> t = "caml_binaryen_ref_test" + (** Module, value, type *) + + external cast : Module.t -> t -> Type.t -> t = "caml_binaryen_ref_cast" + (** Module, value, type *) +end + +module BrOn = struct + external make : Module.t -> Op.t -> string -> t -> Type.t -> t + = "caml_binaryen_br_on" + (** Module, op, label, value, type *) +end + +module Struct = struct + external new_ : Module.t -> t list option -> Heap_type.t -> t + = "caml_binaryen_struct_new" + (** Mdoule, operands, type *) + + external get : Module.t -> int -> t -> Type.t -> bool -> t + = "caml_binaryen_struct_get" + (** Module, index, struct, type, signed *) + + external set : Module.t -> int -> t -> t -> t = "caml_binaryen_struct_set" + (** Module, index, struct, value *) +end + +module Array = struct + external new_ : Module.t -> Heap_type.t -> t -> t -> t + = "caml_binaryen_array_new" + (** Module, type, size, init *) + + external new_data : Module.t -> Heap_type.t -> string -> t -> t -> t + = "caml_binaryen_array_new_data" + (** Module, type, data name, offset, size *) + + external new_fixed : Module.t -> Heap_type.t -> t list -> t + = "caml_binaryen_array_new_fixed" + (** Module, type, values *) + + external get : Module.t -> t -> t -> Type.t -> bool -> t + = "caml_binaryen_array_get" + (** Module, array, index, type, signed *) + + external set : Module.t -> t -> t -> t -> t = "caml_binaryen_array_set" + (** Module, array, index, value *) + + external len : Module.t -> t -> t = "caml_binaryen_array_len" + (** Module, array *) + + external copy : Module.t -> t -> t -> t -> t -> t -> t + = "caml_binaryen_array_copy__bytecode" "caml_binaryen_array_copy" + (** Module, dest, dest index, src, src index, length *) end (** Bindings for `try_table` instruction. *) diff --git a/src/expression.mli b/src/expression.mli index 3b70645a..9fe75788 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -161,6 +161,21 @@ module Call_indirect : sig val set_return : t -> bool -> unit end +module Call_ref : sig + val make : Module.t -> t -> t list -> Type.t -> t + val make_return : Module.t -> t -> t list -> Type.t -> t + val get_target : t -> t + val set_target : t -> t -> unit + val get_num_operands : t -> int + val get_operand_at : t -> int -> t + val set_operand_at : t -> int -> t -> unit + val append_operand : t -> t -> int + val insert_operand_at : t -> int -> t -> unit + val remove_operand_at : t -> int -> t + val is_return : t -> bool + val set_return : t -> bool -> unit +end + module Local_get : sig val make : Module.t -> int -> Type.t -> t end @@ -348,6 +363,51 @@ module Ref : sig val eq : Module.t -> t -> t -> t (** Module, left, right *) + + val test : Module.t -> t -> Type.t -> t + (** Module, value, type *) + + val cast : Module.t -> t -> Type.t -> t + (** Module, value, type *) +end + +module BrOn : sig + val make : Module.t -> Op.t -> string -> t -> Type.t -> t + (** Module, op, label, value, type *) +end + +module Struct : sig + val new_ : Module.t -> t list option -> Heap_type.t -> t + (** Mdoule, operands, type *) + + val get : Module.t -> int -> t -> Type.t -> bool -> t + (** Module, index, struct, type, signed *) + + val set : Module.t -> int -> t -> t -> t + (** Module, index, struct, value *) +end + +module Array : sig + val new_ : Module.t -> Heap_type.t -> t -> t -> t + (** Module, type, size, init *) + + val new_data : Module.t -> Heap_type.t -> string -> t -> t -> t + (** Module, type, data name, offset, size *) + + val new_fixed : Module.t -> Heap_type.t -> t list -> t + (** Module, type, values *) + + val get : Module.t -> t -> t -> Type.t -> bool -> t + (** Module, array, index, type, signed *) + + val set : Module.t -> t -> t -> t -> t + (** Module, array, index, value *) + + val len : Module.t -> t -> t + (** Module, array *) + + val copy : Module.t -> t -> t -> t -> t -> t -> t + (** Module, dest, dest index, src, src index, length *) end (** Bindings for `try` instruction. *) diff --git a/src/ocaml_helpers.c b/src/ocaml_helpers.c index d8af8bb6..be2568dc 100644 --- a/src/ocaml_helpers.c +++ b/src/ocaml_helpers.c @@ -3,6 +3,7 @@ #include #include #include +#include #include "ocaml_helpers.h" @@ -102,6 +103,14 @@ value alloc_BinaryenElementSegmentRef(BinaryenElementSegmentRef elem) return v; } +/* Allocating an OCaml custom block to hold the given TypeBuilderRef */ +value alloc_TypeBuilderRef(TypeBuilderRef builder) +{ + value v = caml_alloc_custom(&binaryen_ops, sizeof(TypeBuilderRef), 0, 1); + TypeBuilderRef_val(v) = builder; + return v; +} + CAMLprim value array_of_list(value list) { CAMLparam1(list); diff --git a/src/ocaml_helpers.h b/src/ocaml_helpers.h index 939ba09e..5c32738c 100644 --- a/src/ocaml_helpers.h +++ b/src/ocaml_helpers.h @@ -23,6 +23,7 @@ static struct custom_operations binaryen_ops = { #define BinaryenModuleRef_val(v) (*((BinaryenModuleRef*) Data_custom_val(v))) #define BinaryenType_val(v) (*((BinaryenType*) Data_custom_val(v))) +#define BinaryenPackedType_val(v) Int_val(v) #define BinaryenHeapType_val(v) (*((BinaryenHeapType*) Data_custom_val(v))) #define BinaryenExpressionRef_val(v) (*((BinaryenExpressionRef*) Data_custom_val(v))) #define BinaryenOp_val(v) (*((BinaryenOp*) Data_custom_val(v))) @@ -33,6 +34,7 @@ static struct custom_operations binaryen_ops = { #define BinaryenExportRef_val(v) (*((BinaryenExportRef*) Data_custom_val(v))) #define BinaryenTableRef_val(v) (*((BinaryenTableRef*) Data_custom_val(v))) #define BinaryenElementSegmentRef_val(v) (*((BinaryenElementSegmentRef*) Data_custom_val(v))) +#define TypeBuilderRef_val(v) (*((TypeBuilderRef*) Data_custom_val(v))) #define Val_none Val_int(0) #define Some_val(v) Field(v, 0) @@ -78,6 +80,9 @@ value alloc_BinaryenTableRef(BinaryenTableRef table); /* Allocating an OCaml custom block to hold the given BinaryenElementSegmentRef */ value alloc_BinaryenElementSegmentRef(BinaryenElementSegmentRef elem); +/* Allocating an OCaml custom block to hold the given TypeBuilderRef */ +value alloc_TypeBuilderRef(TypeBuilderRef builder); + CAMLprim value array_of_list(value list); diff --git a/src/type.ml b/src/type.ml index 119be8cc..8090acb6 100644 --- a/src/type.ml +++ b/src/type.ml @@ -75,5 +75,8 @@ let auto = auto () external create : t array -> t = "caml_binaryen_type_create" external expand : t -> t array = "caml_binaryen_type_expand" external is_nullable : t -> bool = "caml_binaryen_type_is_nullable" -external from_heap_type : Heap_type.t -> t = "caml_binaryen_type_from_heap_type" + +external from_heap_type : Heap_type.t -> bool -> t + = "caml_binaryen_type_from_heap_type" + external get_heap_type : t -> Heap_type.t = "caml_binaryen_type_get_heap_type" diff --git a/src/type.mli b/src/type.mli index 874ddb37..868ac579 100644 --- a/src/type.mli +++ b/src/type.mli @@ -21,5 +21,5 @@ val auto : t val create : t array -> t val expand : t -> t array val is_nullable : t -> bool -val from_heap_type : Heap_type.t -> t +val from_heap_type : Heap_type.t -> bool -> t val get_heap_type : t -> Heap_type.t diff --git a/src/type_builder.c b/src/type_builder.c new file mode 100644 index 00000000..c1680ba6 --- /dev/null +++ b/src/type_builder.c @@ -0,0 +1,176 @@ +#define CAML_NAME_SPACE +#include +#include +#include +#include + +#include "binaryen-c.h" +#include "ocaml_helpers.h" + +CAMLprim value +caml_type_builder_create(value _size) { + CAMLparam1(_size); + BinaryenIndex size = Int_val(_size); + CAMLreturn(alloc_TypeBuilderRef(TypeBuilderCreate(size))); +} + +CAMLprim value +caml_type_builder_grow(value _builder, value _count) { + CAMLparam2(_builder, _count); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex count = Int_val(_count); + TypeBuilderGrow(builder, count); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_get_size(value _builder) { + CAMLparam1(_builder); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + CAMLreturn(Val_int(TypeBuilderGetSize(builder))); +} + +CAMLprim value +caml_type_builder_set_signature_type(value _builder, value _index, value _paramTypes, value _resultTypes) { + CAMLparam4(_builder, _index, _paramTypes, _resultTypes); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenType paramTypes = BinaryenType_val(_paramTypes); + BinaryenType resultTypes = BinaryenType_val(_resultTypes); + TypeBuilderSetSignatureType(builder, index, paramTypes, resultTypes); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_set_struct_type(value _builder, value _index, value _fieldTypes, value _fieldPackedTypes, value _fieldMutables, value _numFields) { + CAMLparam5(_builder, _index, _fieldTypes, _fieldPackedTypes, _fieldMutables); + CAMLxparam1(_numFields); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + _fieldTypes = array_of_list(_fieldTypes); + int fieldTypesLen = array_length(_fieldTypes); + BinaryenType fieldTypes[fieldTypesLen]; + for (int i = 0; i < fieldTypesLen; i++) { + fieldTypes[i] = BinaryenType_val(Field(_fieldTypes, i)); + } + _fieldPackedTypes = array_of_list(_fieldPackedTypes); + int fieldPackedTypesLen = array_length(_fieldPackedTypes); + BinaryenPackedType fieldPackedTypes[fieldPackedTypesLen]; + for (int i = 0; i < fieldPackedTypesLen; i++) { + fieldPackedTypes[i] = BinaryenPackedType_val(Field(_fieldPackedTypes, i)); + } + _fieldMutables = array_of_list(_fieldMutables); + int fieldMutablesLen = array_length(_fieldMutables); + bool fieldMutables[fieldMutablesLen]; + for (int i = 0; i < fieldMutablesLen; i++) { + fieldMutables[i] = Bool_val(Field(_fieldMutables, i)); + } + int numFields = Int_val(_numFields); + TypeBuilderSetStructType(builder, index, fieldTypes, fieldPackedTypes, fieldMutables, numFields); + CAMLreturn(Val_unit); +} +CAMLprim value +caml_type_builder_set_struct_type__bytecode(value * argv) { + return caml_type_builder_set_struct_type(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_type_builder_set_array_type(value _builder, value _index, value _elementType, value _elementPackedType, value _elementMutable) { + CAMLparam5(_builder, _index, _elementType, _elementPackedType, _elementMutable); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenType elementType = BinaryenType_val(_elementType); + BinaryenPackedType elementPackedType = BinaryenPackedType_val(_elementPackedType); + bool elementMutable = Bool_val(_elementMutable); + TypeBuilderSetArrayType(builder, index, elementType, elementPackedType, elementMutable); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_get_temp_heap_type(value _builder, value _index) { + CAMLparam2(_builder, _index); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + CAMLreturn(alloc_BinaryenHeapType(TypeBuilderGetTempHeapType(builder, index))); +} + +CAMLprim value +caml_type_builder_get_temp_tuple_type(value _builder, value _types, value _numTypes) { + CAMLparam3(_builder, _types, _numTypes); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + _types = array_of_list(_types); + int typesLen = array_length(_types); + BinaryenType types[typesLen]; + for (int i = 0; i < typesLen; i++) { + types[i] = BinaryenType_val(Field(_types, i)); + } + int numTypes = Int_val(_numTypes); + CAMLreturn(alloc_BinaryenType(TypeBuilderGetTempTupleType(builder, types, numTypes))); +} + +CAMLprim value +caml_type_builder_get_temp_ref_type(value _builder, value _heapType, value _nullable) { + CAMLparam3(_builder, _heapType, _nullable); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenHeapType heapType = BinaryenHeapType_val(_heapType); + bool nullable = Bool_val(_nullable); + CAMLreturn(alloc_BinaryenType(TypeBuilderGetTempRefType(builder, heapType, nullable))); +} + +CAMLprim value +caml_type_builder_set_sub_type(value _builder, value _index, value _superType) { + CAMLparam3(_builder, _index, _superType); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenHeapType superType = BinaryenHeapType_val(_superType); + TypeBuilderSetSubType(builder, index, superType); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_set_open(value _builder, value _index) { + CAMLparam2(_builder, _index); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + TypeBuilderSetOpen(builder, index); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_type_builder_create_rec_group(value _builder, value _index, value _length) { + CAMLparam3(_builder, _index, _length); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex index = Int_val(_index); + BinaryenIndex length = Int_val(_length); + TypeBuilderCreateRecGroup(builder, index, length); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_conv_heap_type(BinaryenHeapType heapType) { + return alloc_BinaryenHeapType(heapType); +} + +CAMLprim value +caml_type_builder_build_and_dispose(value _builder) { + CAMLparam1(_builder); + TypeBuilderRef builder = TypeBuilderRef_val(_builder); + BinaryenIndex size = TypeBuilderGetSize(builder); + BinaryenHeapType heapTypes[size + 1]; + heapTypes[size] = (BinaryenHeapType) NULL; + BinaryenIndex errorIndex; + TypeBuilderErrorReason errorReason; + bool success = TypeBuilderBuildAndDispose(builder, heapTypes, &errorIndex, &errorReason); + if (success) { + value ok = caml_alloc_small(1, 0); + Field(ok, 0) = caml_alloc_array((void*)caml_conv_heap_type, (char const **)heapTypes); + CAMLreturn(ok); + } else { + value error = caml_alloc_small(1, 1); + value tuple = caml_alloc_small(2, 0); + Field(tuple, 0) = Val_int(errorIndex); + Field(tuple, 1) = Val_int(errorReason); + Field(error, 0) = tuple; + CAMLreturn(error); + } +} diff --git a/src/type_builder.js b/src/type_builder.js new file mode 100644 index 00000000..b8082e32 --- /dev/null +++ b/src/type_builder.js @@ -0,0 +1,116 @@ +//Provides: caml_type_builder_create +//Requires: Binaryen +function caml_type_builder_create(size) { + return new Binaryen.TypeBuilder(size); +} + +//Provides: caml_type_builder_grow +function caml_type_builder_grow(builder, count) { + builder.grow(count); +} + +//Provides: caml_type_builder_get_size +function caml_type_builder_get_size(builder) { + return builder.getSize(); +} + +//Provides: caml_type_builder_set_signature_type +function caml_type_builder_set_signature_type( + builder, + index, + paramTypes, + resultTypes +) { + builder.setSignatureType(index, paramTypes, resultTypes); +} + +//Provides: caml_type_builder_set_struct_type +//Requires: caml_list_to_js_array +//Requires: caml_js_from_bool +function caml_type_builder_set_struct_type( + builder, + index, + fieldTypes, + fieldPackedTypes, + fieldMutables, + numFields +) { + var types = caml_list_to_js_array(fieldTypes); + var packedTypes = caml_list_to_js_array(fieldPackedTypes); + var mutables = caml_list_to_js_array(fieldMutables); + var fields = types.map(function (type, idx) { + return { + type, + packedType: packedTypes[idx], + mutable: caml_js_from_bool(mutables[idx]), + }; + }); + builder.setStructType(index, fields); +} +//Provides: caml_type_builder_set_struct_type__bytecode +//Requires: caml_type_builder_set_struct_type +function caml_type_builder_set_struct_type__bytecode() { + return caml_type_builder_set_struct_type( + arguments[0], + arguments[1], + arguments[2], + arguments[3], + arguments[4], + arguments[5] + ); +} + +//Provides: caml_type_builder_set_array_type +function caml_type_builder_set_array_type( + builder, + index, + elementType, + elementPackedType, + elementMutable +) { + builder.setArrayType(index, elementType, elementPackedType, elementMutable); +} + +//Provides: caml_type_builder_get_temp_heap_type +function caml_type_builder_get_temp_heap_type(builder, index) { + return builder.getTempHeapType(index); +} + +//Provides: caml_type_builder_get_temp_tuple_type +//Requires: caml_list_to_js_array +function caml_type_builder_get_temp_tuple_type(builder, types, numTypes) { + var tupleTypes = caml_list_to_js_array(types); + return builder.getTempTupleType(tupleTypes); +} + +//Provides: caml_type_builder_get_temp_ref_type +//Requires: caml_js_from_bool +function caml_type_builder_get_temp_ref_type(builder, heapType, nullable) { + return builder.getTempRefType(heapType, caml_js_from_bool(nullable)); +} + +//Provides: caml_type_builder_set_sub_type +function caml_type_builder_set_sub_type(builder, index, superType) { + builder.setSubType(index, superType); +} + +//Provides: caml_type_builder_set_open +function caml_type_builder_set_open(builder, index) { + builder.setOpen(index); +} + +//Provides: caml_type_builder_create_rec_group +function caml_type_builder_create_rec_group(builder, index, length) { + builder.createRecGroup(index, length); +} + +//Provides: caml_type_builder_build_and_dispose +//Requires: caml_js_to_array +function caml_type_builder_build_and_dispose(builder) { + try { + var types = builder.buildAndDispose(); + return [0, caml_js_to_array(types)]; + } catch (e) { + return [1, [0, e.index, e.reason]]; + } +} diff --git a/src/type_builder.ml b/src/type_builder.ml new file mode 100644 index 00000000..0d72d937 --- /dev/null +++ b/src/type_builder.ml @@ -0,0 +1,65 @@ +type t + +type struct_field = { + type_ : Type.t; + packed_type : Packed_type.t; + mutable_ : bool; +} + +type error = + | SelfSupertype of int + | InvalidSupertype of int + | ForwardSupertypeReference of int + | ForwardChildReference of int + +external make : int -> t = "caml_type_builder_create" +external grow : t -> int -> unit = "caml_type_builder_grow" +external size : t -> int = "caml_type_builder_grow" + +external set_signature_type : t -> int -> Type.t -> Type.t -> unit + = "caml_type_builder_set_signature_type" + +external set_struct_type : + t -> int -> Type.t list -> Packed_type.t list -> bool list -> int -> unit + = "caml_type_builder_set_struct_type__bytecode" "caml_type_builder_set_struct_type" + +let set_struct_type builder index fields = + let split_fields fields = + List.fold_right + (fun { type_; packed_type; mutable_ } (types, packed_types, mutables) -> + (type_ :: types, packed_type :: packed_types, mutable_ :: mutables)) + fields ([], [], []) + in + let types, packed_types, mutables = split_fields fields in + set_struct_type builder index types packed_types mutables (List.length types) + +external set_array_type : t -> int -> Type.t -> Packed_type.t -> bool -> unit + = "caml_type_builder_set_array_type" + +external get_temp_heap_type : t -> int -> Heap_type.t + = "caml_type_builder_get_temp_heap_type" + +external get_temp_tuple_type : t -> Type.t list -> Type.t + = "caml_type_builder_get_temp_tuple_type" + +external get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t + = "caml_type_builder_get_temp_ref_type" + +external set_sub_type : t -> int -> Type.t -> unit + = "caml_type_builder_set_sub_type" + +external set_open : t -> int -> unit = "caml_type_builder_set_open" + +external create_rec_group : t -> int -> int -> unit + = "caml_type_builder_create_rec_group" + +external build_and_dispose : t -> (Type.t array, int * int) result + = "caml_type_builder_build_and_dispose" + +let build_and_dispose builder = + match build_and_dispose builder with + | Ok types -> Ok (Array.to_list types) + | Error (idx, 0) -> Error (SelfSupertype idx) + | Error (idx, 1) -> Error (InvalidSupertype idx) + | Error (idx, 2) -> Error (ForwardSupertypeReference idx) + | Error (idx, _) -> Error (ForwardChildReference idx) diff --git a/src/type_builder.mli b/src/type_builder.mli new file mode 100644 index 00000000..260458db --- /dev/null +++ b/src/type_builder.mli @@ -0,0 +1,27 @@ +type t + +type struct_field = { + type_ : Type.t; + packed_type : Packed_type.t; + mutable_ : bool; +} + +type error = + | SelfSupertype of int + | InvalidSupertype of int + | ForwardSupertypeReference of int + | ForwardChildReference of int + +val make : int -> t +val grow : t -> int -> unit +val size : t -> int +val set_signature_type : t -> int -> Type.t -> Type.t -> unit +val set_struct_type : t -> int -> struct_field list -> unit +val set_array_type : t -> int -> Type.t -> Packed_type.t -> bool -> unit +val get_temp_heap_type : t -> int -> Heap_type.t +val get_temp_tuple_type : t -> Type.t list -> Type.t +val get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t +val set_sub_type : t -> int -> Type.t -> unit +val set_open : t -> int -> unit +val create_rec_group : t -> int -> int -> unit +val build_and_dispose : t -> (Type.t list, error) result diff --git a/test/test.expected b/test/test.expected index 0a35f066..364fd155 100644 --- a/test/test.expected +++ b/test/test.expected @@ -7,6 +7,15 @@ (i32.const 0) ) (module + (type $0 (struct (field i31ref) (field (ref null $0)))) + (type $1 (array (mut i8))) + (type $2 (func (param i32 i32) (result i32))) + (type $3 (func (result (ref $1) (ref $0)))) + (type $4 (func)) + (type $5 (func (param anyref i32 i32) (result i32))) + (type $6 (func (param anyref) (result i32))) + (type $7 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) (type $0 (func (param i32))) (type $1 (func (param i32 i32) (result i32))) (type $2 (func)) @@ -26,8 +35,10 @@ (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) + (export "gc" (func $gc)) (export "try" (func $try)) (start $start) + (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) (func $adder (type $1) (param $0 i32) (param $1 i32) (result i32) (block $add (result i32) (if @@ -48,6 +59,7 @@ ) ) ) + (func $start (type $4) (func $start (type $2) (block $start (memory.init $world @@ -56,6 +68,7 @@ (i32.const 5) ) (drop + (call_indirect $table (type $2) (call_indirect $table (type $1) (i32.const 3) (i32.const 5) @@ -64,6 +77,7 @@ ) ) ) + (func $hello (type $6) (param $0 anyref) (result i32) (func $hello (type $4) (param $0 anyref) (result i32) (call $write (local.get $0) @@ -71,6 +85,50 @@ (i32.const 1) ) ) + (func $gc (type $7) (param $0 anyref) (result anyref anyref) + (local $1 (ref $1)) + (local $2 (ref $0)) + (block $gc_block (type $3) (result (ref $1) (ref $0)) + (local.set $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (array.set $1 + (local.get $1) + (i32.const 1) + (i32.const 42) + ) + (local.set $2 + (struct.new $0 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $0 + (ref.i31 + (i32.const 1) + ) + (struct.new $0 + (ref.i31 + (i32.const 2) + ) + (struct.new $0 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + (tuple.make 2 + (local.get $1) + (local.get $2) + ) + ) + ) (func $try (type $2) (block $blk (drop @@ -141,6 +199,15 @@ ) ) (module + (type $0 (struct (field i31ref) (field (ref null $0)))) + (type $1 (array (mut i8))) + (type $2 (func (result (ref $1) (ref $0)))) + (type $3 (func (param i32 i32) (result i32))) + (type $4 (func)) + (type $5 (func (param anyref i32 i32) (result i32))) + (type $6 (func (param anyref) (result i32))) + (type $7 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) (type $0 (func (param i32))) (type $1 (func)) (type $2 (func (param i32 i32) (result i32))) @@ -157,8 +224,10 @@ (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) + (export "gc" (func $gc)) (export "try" (func $try)) (start $start) + (func $adder (type $3) (param $0 i32) (param $1 i32) (result i32) (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) (i32.add (select @@ -171,7 +240,7 @@ (local.get $1) ) ) - (func $start (type $1) + (func $start (type $4) (memory.init $world (i32.const 2048) (i32.const 0) @@ -184,6 +253,7 @@ ) ) ) + (func $hello (type $6) (param $0 anyref) (result i32) (func $hello (type $4) (param $0 anyref) (result i32) (call $write (local.get $0) @@ -191,6 +261,43 @@ (i32.const 1) ) ) + (func $gc (type $7) (param $0 anyref) (result anyref anyref) + (local $1 (ref $1)) + (array.set $1 + (local.tee $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (i32.const 1) + (i32.const 42) + ) + (tuple.make 2 + (local.get $1) + (struct.new $0 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $0 + (ref.i31 + (i32.const 1) + ) + (struct.new $0 + (ref.i31 + (i32.const 2) + ) + (struct.new $0 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + ) (func $try (type $1) (drop (try (result i32) @@ -233,6 +340,15 @@ ) ) (module + (type $type_6 (struct (field i31ref) (field (ref null $type_6)))) + (type $type_5 (array (mut i8))) + (type $type_7 (func (result anyref anyref))) + (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))) + (type $type_4 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) (type $type_3 (func)) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) @@ -246,6 +362,7 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) + (export "gc" (func $3)) (export "try" (func $3)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) @@ -280,6 +397,43 @@ (i32.const 1) ) ) + (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) + (local $1 (ref $type_5)) + (array.set $type_5 + (local.tee $1 + (array.new_fixed $type_5 2 + (i32.const 0) + (i32.const 255) + ) + ) + (i32.const 1) + (i32.const 42) + ) + (tuple.make 2 + (local.get $1) + (struct.new $type_6 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $type_6 + (ref.i31 + (i32.const 1) + ) + (struct.new $type_6 + (ref.i31 + (i32.const 2) + ) + (struct.new $type_6 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + ) (func $3 (type $type_3) (drop (unreachable) @@ -288,6 +442,15 @@ ) ) (module + (type $type_6 (struct (field i31ref) (field (ref null $type_6)))) + (type $type_5 (array (mut i8))) + (type $type_7 (func (result anyref anyref))) + (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))) + (type $type_4 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) (type $type_3 (func)) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) @@ -301,6 +464,7 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) + (export "gc" (func $3)) (export "try" (func $3)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) @@ -328,6 +492,31 @@ i32.const 1 call $fimport$0 ) + (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) + (local $1 (ref $type_5)) + i32.const 0 + i32.const 255 + array.new_fixed $type_5 2 + local.tee $1 + i32.const 1 + i32.const 42 + array.set $type_5 + local.get $1 + local.get $0 + ref.cast i31ref + i32.const 1 + ref.i31 + i32.const 2 + ref.i31 + i32.const 3 + ref.i31 + ref.null none + struct.new $type_6 + struct.new $type_6 + struct.new $type_6 + struct.new $type_6 + tuple.make 2 + ) (func $3 (type $type_3) unreachable ) diff --git a/test/test.ml b/test/test.ml index cfb95a44..88077400 100644 --- a/test/test.ml +++ b/test/test.ml @@ -254,6 +254,19 @@ let _ = (Memory.get_segment_data wasm_mod "world") (Bytes.of_string "world")) +(* Call_ref *) +let thunk_type = + let builder = Type_builder.make 1 in + Type_builder.set_signature_type builder 0 Type.none Type.none; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to build type" + +let _ = + Expression.Call_ref.make wasm_mod + (Expression.Ref.func wasm_mod "start" thunk_type) + [] Type.none + let _ = Tag.add_tag wasm_mod "foo" Type.int32 Type.none let _ = Tag.add_tag wasm_mod "bar" Type.int32 Type.none @@ -365,6 +378,79 @@ let _ = Export.add_function_export wasm_mod "hello" "hello" let _ = Export.add_function_export wasm_mod "try" "try" let _ = Module.validate wasm_mod +(* Create a function that does gc *) +let _ = + let array_u8_type = + let builder = Type_builder.make 1 in + Type_builder.set_array_type builder 0 Type.int32 Packed_type.int8 true; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to make array type" + in + let list_type = + let builder = Type_builder.make 1 in + let temp_heap_type = Type_builder.get_temp_heap_type builder 0 in + let temp_ref_type = + Type_builder.get_temp_ref_type builder temp_heap_type true + in + Type_builder.set_struct_type builder 0 + [ + Type_builder. + { + type_ = Type.i31ref; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + Type_builder. + { + type_ = temp_ref_type; + packed_type = Packed_type.not_packed; + mutable_ = false; + }; + ]; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to make list type" + in + let i32 v = Expression.Const.make wasm_mod (Literal.int32 v) in + let i31 v = Expression.I31.make wasm_mod (i32 v) in + let cons first rest = + Expression.Struct.new_ wasm_mod + (Some [ first; rest ]) + (Type.get_heap_type list_type) + in + let empty () = + Expression.Ref.null wasm_mod + (Type.from_heap_type (Type.get_heap_type list_type) true) + in + Function.add_function wasm_mod "gc" Type.anyref + (Type.create [| Type.anyref; Type.anyref |]) + [| array_u8_type; list_type |] + (Expression.Block.make wasm_mod "gc_block" + [ + Expression.Local_set.make wasm_mod 1 + (Expression.Array.new_fixed wasm_mod + (Type.get_heap_type array_u8_type) + [ i32 0l; i32 255l ]); + Expression.Array.set wasm_mod + (Expression.Local_get.make wasm_mod 1 array_u8_type) + (i32 1l) (i32 42l); + Expression.Local_set.make wasm_mod 2 + (cons + (Expression.Ref.cast wasm_mod + (Expression.Local_get.make wasm_mod 0 Type.anyref) + Type.i31ref) + (cons (i31 1l) (cons (i31 2l) (cons (i31 3l) (empty ()))))); + Expression.Tuple_make.make wasm_mod + [ + Expression.Local_get.make wasm_mod 1 array_u8_type; + Expression.Local_get.make wasm_mod 2 list_type; + ]; + ]) + +let _ = Export.add_function_export wasm_mod "gc" "gc" +let _ = assert (Module.validate wasm_mod == 1) + (* Shouldn't actually do anything since we aren't doing function renames *) let _ = Module.update_maps wasm_mod @@ -437,7 +523,7 @@ let _ = Module.Feature.all; ] -let _ = Module.validate new_mod +let _ = assert (Module.validate new_mod == 1) let _ = Module.print new_mod let _ = Module.print_stack_ir new_mod From 17c8a3c394eb04d534765a612a20b4a7412fb628 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 5 Dec 2025 10:49:06 -0500 Subject: [PATCH 05/10] feat: Implement additional gc instructions --- src/expression.c | 24 ++++++++++++++++++++++++ src/expression.js | 36 ++++++++++++++++++++++-------------- src/expression.ml | 8 ++++++++ src/expression.mli | 6 ++++++ src/type_builder.ml | 8 +++++--- src/type_builder.mli | 5 +++-- test/test.expected | 8 ++++---- test/test.ml | 24 +++++++++++++----------- 8 files changed, 85 insertions(+), 34 deletions(-) diff --git a/src/expression.c b/src/expression.c index 2d737493..34a34d3b 100644 --- a/src/expression.c +++ b/src/expression.c @@ -2086,6 +2086,18 @@ caml_binaryen_array_new_data(value _module, value _type, value _name, value _off CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +CAMLprim value +caml_binaryen_array_new_elem(value _module, value _type, value _seg, value _offset, value _size) { + CAMLparam5(_module, _type, _seg, _offset, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenHeapType type = BinaryenHeapType_val(_type); + char* seg = Safe_String_val(_seg); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayNewElem(module, type, seg, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + CAMLprim value caml_binaryen_array_new_fixed(value _module, value _type, value _values) { CAMLparam3(_module, _type, _values); @@ -2151,6 +2163,18 @@ caml_binaryen_array_copy__bytecode(value * argv) { return caml_binaryen_array_copy(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); } +CAMLprim value +caml_binaryen_array_fill(value _module, value _ref, value _index, value _value, value _size) { + CAMLparam5(_module, _ref, _index, _value, _size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef val = BinaryenExpressionRef_val(_value); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayFill(module, ref, index, val, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + // Exception handling operations CAMLprim value caml_binaryen_try(value _module, value _name, value _body, value _catchTags, value _catchBodies, value _delegateTarget) { diff --git a/src/expression.js b/src/expression.js index f6ab3685..cface125 100644 --- a/src/expression.js +++ b/src/expression.js @@ -575,13 +575,13 @@ function caml_binaryen_ref_cast(wasm_mod, ref, typ) { function caml_binaryen_br_on(wasm_mod, op, name, ref, typ) { switch (op) { case Binaryen.BrOnNull: - return wasm_mod.br_on.null(caml_jsstring_of_string(name), ref, typ); + return wasm_mod.br_on_null(caml_jsstring_of_string(name), ref); case Binaryen.BrOnNonNull: - return wasm_mod.br_on.non_null(caml_jsstring_of_string(name), ref, typ); + return wasm_mod.br_on_non_null(caml_jsstring_of_string(name), ref); case Binaryen.BrOnCast: - return wasm_mod.br_on.cast(caml_jsstring_of_string(name), ref, typ); + return wasm_mod.br_on_cast(caml_jsstring_of_string(name), ref, typ); case Binaryen.BrOnCastFail: - return wasm_mod.br_on.cast_fail(caml_jsstring_of_string(name), ref, typ); + return wasm_mod.br_on_cast_fail(caml_jsstring_of_string(name), ref, typ); } } @@ -1821,11 +1821,7 @@ function caml_binaryen_struct_new(wasm_mod, operands, type) { //Provides: caml_binaryen_struct_get //Requires: caml_js_from_bool function caml_binaryen_struct_get(wasm_mod, index, ref, type, signed) { - if (caml_js_from_bool(signed)) { - return wasm_mod.struct.get_s(index, ref, type); - } else { - return wasm_mod.struct.get_u(index, ref, type); - } + return wasm_mod.struct.get(index, ref, type, caml_js_from_bool(signed)); } //Provides: caml_binaryen_struct_set @@ -1851,6 +1847,17 @@ function caml_binaryen_array_new_data(wasm_mod, type, name, offset, size) { ); } +//Provides: caml_binaryen_array_new_elem +//Requires: caml_jsstring_of_string +function caml_binaryen_array_new_elem(wasm_mod, type, name, offset, size) { + return wasm_mod.array.new_elem( + type, + caml_jsstring_of_string(name), + offset, + size + ); +} + //Provides: caml_binaryen_array_new_fixed //Requires: caml_list_to_js_array function caml_binaryen_array_new_fixed(wasm_mod, type, values) { @@ -1860,11 +1867,7 @@ function caml_binaryen_array_new_fixed(wasm_mod, type, values) { //Provides: caml_binaryen_array_get //Requires: caml_js_from_bool function caml_binaryen_array_get(wasm_mod, ref, index, type, signed) { - if (caml_js_from_bool(signed)) { - return wasm_mod.array.get_s(ref, index, type); - } else { - return wasm_mod.array.get_u(ref, index, type); - } + return wasm_mod.array.get(ref, index, type, caml_js_from_bool(signed)); } //Provides: caml_binaryen_array_set @@ -1877,6 +1880,11 @@ function caml_binaryen_array_len(wasm_mod, ref) { return wasm_mod.array.len(ref); } +//Provides: caml_binaryen_array_fill +function caml_binaryen_array_fill(wasm_mod, ref, index, value, size) { + return wasm_mod.array.fill(ref, index, value, size); +} + //Provides: caml_binaryen_array_copy function caml_binaryen_array_copy( wasm_mod, diff --git a/src/expression.ml b/src/expression.ml index 2eb57841..86add2ee 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -899,6 +899,10 @@ module Array = struct = "caml_binaryen_array_new_data" (** Module, type, data name, offset, size *) + external new_elem : Module.t -> Heap_type.t -> string -> t -> t -> t + = "caml_binaryen_array_new_elem" + (** Module, type, seg, offset, size *) + external new_fixed : Module.t -> Heap_type.t -> t list -> t = "caml_binaryen_array_new_fixed" (** Module, type, values *) @@ -913,6 +917,10 @@ module Array = struct external len : Module.t -> t -> t = "caml_binaryen_array_len" (** Module, array *) + external fill : Module.t -> Heap_type.t -> t -> t -> t -> t + = "caml_binaryen_array_fill" + (** Module, type, seg, offset, size *) + external copy : Module.t -> t -> t -> t -> t -> t -> t = "caml_binaryen_array_copy__bytecode" "caml_binaryen_array_copy" (** Module, dest, dest index, src, src index, length *) diff --git a/src/expression.mli b/src/expression.mli index 9fe75788..20e954ad 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -394,6 +394,9 @@ module Array : sig val new_data : Module.t -> Heap_type.t -> string -> t -> t -> t (** Module, type, data name, offset, size *) + val new_elem : Module.t -> Heap_type.t -> string -> t -> t -> t + (** Module, type, seg, offset, size *) + val new_fixed : Module.t -> Heap_type.t -> t list -> t (** Module, type, values *) @@ -406,6 +409,9 @@ module Array : sig val len : Module.t -> t -> t (** Module, array *) + val fill : Module.t -> Heap_type.t -> t -> t -> t -> t + (** Module, type, seg, offset, size *) + val copy : Module.t -> t -> t -> t -> t -> t -> t (** Module, dest, dest index, src, src index, length *) end diff --git a/src/type_builder.ml b/src/type_builder.ml index 0d72d937..28f33b03 100644 --- a/src/type_builder.ml +++ b/src/type_builder.ml @@ -6,6 +6,7 @@ type struct_field = { mutable_ : bool; } +(* Source: https://github.com/WebAssembly/binaryen/blob/64ba23996a10e229d46e41eb37736a55af87f79a/src/binaryen-c.h#L3618 *) type error = | SelfSupertype of int | InvalidSupertype of int @@ -21,7 +22,8 @@ external set_signature_type : t -> int -> Type.t -> Type.t -> unit external set_struct_type : t -> int -> Type.t list -> Packed_type.t list -> bool list -> int -> unit - = "caml_type_builder_set_struct_type__bytecode" "caml_type_builder_set_struct_type" + = "caml_type_builder_set_struct_type__bytecode" + "caml_type_builder_set_struct_type" let set_struct_type builder index fields = let split_fields fields = @@ -45,7 +47,7 @@ external get_temp_tuple_type : t -> Type.t list -> Type.t external get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t = "caml_type_builder_get_temp_ref_type" -external set_sub_type : t -> int -> Type.t -> unit +external set_sub_type : t -> int -> Heap_type.t -> unit = "caml_type_builder_set_sub_type" external set_open : t -> int -> unit = "caml_type_builder_set_open" @@ -53,7 +55,7 @@ external set_open : t -> int -> unit = "caml_type_builder_set_open" external create_rec_group : t -> int -> int -> unit = "caml_type_builder_create_rec_group" -external build_and_dispose : t -> (Type.t array, int * int) result +external build_and_dispose : t -> (Heap_type.t array, int * int) result = "caml_type_builder_build_and_dispose" let build_and_dispose builder = diff --git a/src/type_builder.mli b/src/type_builder.mli index 260458db..f76dfbb1 100644 --- a/src/type_builder.mli +++ b/src/type_builder.mli @@ -6,6 +6,7 @@ type struct_field = { mutable_ : bool; } +(* Source: https://github.com/WebAssembly/binaryen/blob/64ba23996a10e229d46e41eb37736a55af87f79a/src/binaryen-c.h#L3618 *) type error = | SelfSupertype of int | InvalidSupertype of int @@ -21,7 +22,7 @@ val set_array_type : t -> int -> Type.t -> Packed_type.t -> bool -> unit val get_temp_heap_type : t -> int -> Heap_type.t val get_temp_tuple_type : t -> Type.t list -> Type.t val get_temp_ref_type : t -> Heap_type.t -> bool -> Type.t -val set_sub_type : t -> int -> Type.t -> unit +val set_sub_type : t -> int -> Heap_type.t -> unit val set_open : t -> int -> unit val create_rec_group : t -> int -> int -> unit -val build_and_dispose : t -> (Type.t list, error) result +val build_and_dispose : t -> (Heap_type.t list, error) result diff --git a/test/test.expected b/test/test.expected index 364fd155..0e730bba 100644 --- a/test/test.expected +++ b/test/test.expected @@ -201,7 +201,7 @@ (module (type $0 (struct (field i31ref) (field (ref null $0)))) (type $1 (array (mut i8))) - (type $2 (func (result (ref $1) (ref $0)))) + (type $2 (func (result (ref (exact $1)) (ref (exact $0))))) (type $3 (func (param i32 i32) (result i32))) (type $4 (func)) (type $5 (func (param anyref i32 i32) (result i32))) @@ -262,7 +262,7 @@ ) ) (func $gc (type $7) (param $0 anyref) (result anyref anyref) - (local $1 (ref $1)) + (local $1 (ref (exact $1))) (array.set $1 (local.tee $1 (array.new_fixed $1 2 @@ -398,7 +398,7 @@ ) ) (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) - (local $1 (ref $type_5)) + (local $1 (ref (exact $type_5))) (array.set $type_5 (local.tee $1 (array.new_fixed $type_5 2 @@ -493,7 +493,7 @@ call $fimport$0 ) (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) - (local $1 (ref $type_5)) + (local $1 (ref (exact $type_5))) i32.const 0 i32.const 255 array.new_fixed $type_5 2 diff --git a/test/test.ml b/test/test.ml index 88077400..31256a75 100644 --- a/test/test.ml +++ b/test/test.ml @@ -415,25 +415,25 @@ let _ = let i32 v = Expression.Const.make wasm_mod (Literal.int32 v) in let i31 v = Expression.I31.make wasm_mod (i32 v) in let cons first rest = - Expression.Struct.new_ wasm_mod - (Some [ first; rest ]) - (Type.get_heap_type list_type) + Expression.Struct.new_ wasm_mod (Some [ first; rest ]) list_type in let empty () = - Expression.Ref.null wasm_mod - (Type.from_heap_type (Type.get_heap_type list_type) true) + Expression.Ref.null wasm_mod (Type.from_heap_type list_type true) in Function.add_function wasm_mod "gc" Type.anyref (Type.create [| Type.anyref; Type.anyref |]) - [| array_u8_type; list_type |] + [| + Type.from_heap_type array_u8_type false; + Type.from_heap_type list_type false; + |] (Expression.Block.make wasm_mod "gc_block" [ Expression.Local_set.make wasm_mod 1 - (Expression.Array.new_fixed wasm_mod - (Type.get_heap_type array_u8_type) + (Expression.Array.new_fixed wasm_mod array_u8_type [ i32 0l; i32 255l ]); Expression.Array.set wasm_mod - (Expression.Local_get.make wasm_mod 1 array_u8_type) + (Expression.Local_get.make wasm_mod 1 + (Type.from_heap_type array_u8_type false)) (i32 1l) (i32 42l); Expression.Local_set.make wasm_mod 2 (cons @@ -443,8 +443,10 @@ let _ = (cons (i31 1l) (cons (i31 2l) (cons (i31 3l) (empty ()))))); Expression.Tuple_make.make wasm_mod [ - Expression.Local_get.make wasm_mod 1 array_u8_type; - Expression.Local_get.make wasm_mod 2 list_type; + Expression.Local_get.make wasm_mod 1 + (Type.from_heap_type array_u8_type false); + Expression.Local_get.make wasm_mod 2 + (Type.from_heap_type list_type false); ]; ]) From cbc3f2d156ffad3f4e2767750407f90a914bc88b Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 5 Dec 2025 16:00:57 -0500 Subject: [PATCH 06/10] chore: Re-enable funcref test --- test/test.ml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/test/test.ml b/test/test.ml index 31256a75..7c3a5681 100644 --- a/test/test.ml +++ b/test/test.ml @@ -171,13 +171,19 @@ let start = let _ = Export.add_function_export wasm_mod "adder" "adder" let _ = Table.add_table wasm_mod "table" 1 1 Type.funcref -(* TODO(#240): Re-enable after type-builder api is merged *) -(* let funcref_expr1 = Expression.Ref.func wasm_mod "adder" (Heap_type.func ()) +let adder_type = + let builder = Type_builder.make 1 in + Type_builder.set_signature_type builder 0 Type.none Type.none; + match Type_builder.build_and_dispose builder with + | Ok [ ty ] -> ty + | _ -> failwith "failed to build type" + +let funcref_expr1 = Expression.Ref.func wasm_mod "adder" adder_type let _ = Expression.Table.set wasm_mod "table" (Expression.Const.make wasm_mod (Literal.int32 0l)) - funcref_expr1 *) + funcref_expr1 let funcref_expr2 = Expression.Table.get wasm_mod "table" From bb17a223aa1d197f701a467ecd24c1eade1f2af4 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 5 Dec 2025 16:16:41 -0500 Subject: [PATCH 07/10] feat: Implement `Array.init_data` and `Array.init_elem` --- src/expression.c | 38 ++++++++++++++++++++++++++++++++++++++ src/expression.js | 13 +++++++++++++ src/expression.ml | 8 ++++++++ src/expression.mli | 6 ++++++ 4 files changed, 65 insertions(+) diff --git a/src/expression.c b/src/expression.c index 34a34d3b..92a3f4a6 100644 --- a/src/expression.c +++ b/src/expression.c @@ -2175,6 +2175,44 @@ caml_binaryen_array_fill(value _module, value _ref, value _index, value _value, CAMLreturn(alloc_BinaryenExpressionRef(exp)); } +CAMLprim value +caml_binaryen_array_init_data(value _module, value _name, value _ref, value _index, value _offset, value _size) { + CAMLparam5(_module, _name, _ref, _index, _offset); + CAMLxparam1(_size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* name = Safe_String_val(_name); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayInitData(module, name, ref, index, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_init_data__bytecode(value * argv) { + return caml_binaryen_array_init_data(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + +CAMLprim value +caml_binaryen_array_init_elem(value _module, value _seg, value _ref, value _index, value _offset, value _size) { + CAMLparam5(_module, _seg, _ref, _index, _offset); + CAMLxparam1(_size); + BinaryenModuleRef module = BinaryenModuleRef_val(_module); + char* seg = Safe_String_val(_seg); + BinaryenExpressionRef ref = BinaryenExpressionRef_val(_ref); + BinaryenExpressionRef index = BinaryenExpressionRef_val(_index); + BinaryenExpressionRef offset = BinaryenExpressionRef_val(_offset); + BinaryenExpressionRef size = BinaryenExpressionRef_val(_size); + BinaryenExpressionRef exp = BinaryenArrayInitElem(module, seg, ref, index, offset, size); + CAMLreturn(alloc_BinaryenExpressionRef(exp)); +} + +CAMLprim value +caml_binaryen_array_init_elem__bytecode(value * argv) { + return caml_binaryen_array_init_elem(argv[0], argv[1], argv[2], argv[3], argv[4], argv[5]); +} + // Exception handling operations CAMLprim value caml_binaryen_try(value _module, value _name, value _body, value _catchTags, value _catchBodies, value _delegateTarget) { diff --git a/src/expression.js b/src/expression.js index cface125..ab8bc535 100644 --- a/src/expression.js +++ b/src/expression.js @@ -1896,6 +1896,19 @@ function caml_binaryen_array_copy( ) { return wasm_mod.array.copy(destRef, destIndex, srcRef, srcIndex, length); } + +//Provides: caml_binaryen_array_init_data +//Requires: caml_jsstring_of_string +function caml_binaryen_array_init_data(name, ref, index, offset, size) { + return wasm_mod.array.init_data(caml_jsstring_of_string(name), ref, index, offset, size); +} + +//Provides: caml_binaryen_array_init_elem +//Requires: caml_jsstring_of_string +function caml_binaryen_array_init_elem(name, ref, index, offset, size) { + return wasm_mod.array.init_elem(caml_jsstring_of_string(name), ref, index, offset, size); +} + //Provides: caml_binaryen_array_copy__bytecode //Requires: caml_binaryen_array_copy function caml_binaryen_array_copy__bytecode() { diff --git a/src/expression.ml b/src/expression.ml index 86add2ee..33565785 100644 --- a/src/expression.ml +++ b/src/expression.ml @@ -924,6 +924,14 @@ module Array = struct external copy : Module.t -> t -> t -> t -> t -> t -> t = "caml_binaryen_array_copy__bytecode" "caml_binaryen_array_copy" (** Module, dest, dest index, src, src index, length *) + + external init_data : Module.t -> string -> t -> t -> t -> t -> t + = "caml_binaryen_array_init_data__bytecode" "caml_binaryen_array_init_data" + (** Module, name, ref, index, offset, size *) + + external init_elem : Module.t -> string -> t -> t -> t -> t -> t + = "caml_binaryen_array_init_elem__bytecode" "caml_binaryen_array_init_elem" + (** Module, seg, ref, index, offset, size *) end (** Bindings for `try_table` instruction. *) diff --git a/src/expression.mli b/src/expression.mli index 20e954ad..b02d73df 100644 --- a/src/expression.mli +++ b/src/expression.mli @@ -414,6 +414,12 @@ module Array : sig val copy : Module.t -> t -> t -> t -> t -> t -> t (** Module, dest, dest index, src, src index, length *) + + val init_data : Module.t -> string -> t -> t -> t -> t -> t + (** Module, name, ref, index, offset, size *) + + val init_elem : Module.t -> string -> t -> t -> t -> t -> t + (** Module, seg, ref, index, offset, size *) end (** Bindings for `try` instruction. *) From 9e2958a6211fee686235c2a4814da85eaaf83c2d Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Sat, 13 Dec 2025 12:19:22 -0500 Subject: [PATCH 08/10] feat: Update `CallRef` bindings for `v126` --- src/expression.js | 19 +++++++++++++------ test/test.ml | 2 +- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/expression.js b/src/expression.js index ab8bc535..729bccc9 100644 --- a/src/expression.js +++ b/src/expression.js @@ -105,12 +105,19 @@ function caml_binaryen_call_indirect__bytecode() { //Requires: caml_jsstring_of_string //Requires: caml_list_to_js_array, caml_js_from_bool function caml_binaryen_call_ref(wasm_mod, target, params, typ, is_return) { - return wasm_mod.call_ref( - target, - caml_list_to_js_array(params), - typ, - caml_js_from_bool(is_return) - ); + if (caml_js_from_bool(is_return)) { + return wasm_mod.return_call_ref( + target, + caml_list_to_js_array(params), + typ + ); + } else { + return wasm_mod.call_ref( + target, + caml_list_to_js_array(params), + typ + ); + } } //Provides: caml_binaryen_return_call diff --git a/test/test.ml b/test/test.ml index 7c3a5681..6691e981 100644 --- a/test/test.ml +++ b/test/test.ml @@ -173,7 +173,7 @@ let _ = Table.add_table wasm_mod "table" 1 1 Type.funcref let adder_type = let builder = Type_builder.make 1 in - Type_builder.set_signature_type builder 0 Type.none Type.none; + Type_builder.set_signature_type builder 0 (params ()) results; match Type_builder.build_and_dispose builder with | Ok [ ty ] -> ty | _ -> failwith "failed to build type" From a4d482a0fbae2c765a8003f13bec8e782a732f82 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Sat, 13 Dec 2025 12:46:44 -0500 Subject: [PATCH 09/10] chore: Use preview `v126` libbinaryen --- esy.lock/index.json | 94 +++++++++---------- esy.lock/opam/base.v0.17.3/opam | 6 +- .../opam/ocaml_intrinsics_kernel.v0.17.1/opam | 2 + esy.lock/opam/ocamlfind.1.9.8/opam | 2 +- .../opam/ppx_yojson_conv_lib.v0.17.0/opam | 2 + esy.lock/opam/sexplib0.v0.17.0/opam | 2 + esy.lock/opam/stdio.v0.17.0/opam | 4 +- package.json | 3 +- 8 files changed, 63 insertions(+), 52 deletions(-) diff --git a/esy.lock/index.json b/esy.lock/index.json index 637fbaaf..072d60b3 100644 --- a/esy.lock/index.json +++ b/esy.lock/index.json @@ -1,5 +1,5 @@ { - "checksum": "43b607828957b76c0263dc0b329d0237", + "checksum": "fbb4f4567dbe5512b5e9d459824bf7d6", "root": "@grain/binaryen.ml@link-dev:./package.json", "node": { "ocaml@5.3.0@d41d8cd9": { @@ -103,7 +103,7 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/topkg@opam:1.1.1@2377d2f8", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -136,7 +136,7 @@ "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/uutf@opam:1.0.4@ba7fbef7", "@opam/uucp@opam:17.0.0@843de755", "@opam/topkg@opam:1.1.1@2377d2f8", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -170,7 +170,7 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/topkg@opam:1.1.1@2377d2f8", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -201,7 +201,7 @@ }, "overrides": [], "dependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], @@ -285,8 +285,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/stdio@opam:v0.17.0@def6a62f": { - "id": "@opam/stdio@opam:v0.17.0@def6a62f", + "@opam/stdio@opam:v0.17.0@80c625cc": { + "id": "@opam/stdio@opam:v0.17.0@80c625cc", "name": "@opam/stdio", "version": "opam:v0.17.0", "source": { @@ -304,12 +304,12 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/dune@opam:3.20.2@8daef28d", - "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/dune@opam:3.20.2@8daef28d", - "@opam/base@opam:v0.17.3@78923773" + "@opam/base@opam:v0.17.3@4f79f92d" ], "available": [ [ "darwin", "x86_64" ], @@ -349,8 +349,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/sexplib0@opam:v0.17.0@75dcb697": { - "id": "@opam/sexplib0@opam:v0.17.0@75dcb697", + "@opam/sexplib0@opam:v0.17.0@db8af2c0": { + "id": "@opam/sexplib0@opam:v0.17.0@db8af2c0", "name": "@opam/sexplib0", "version": "opam:v0.17.0", "source": { @@ -500,14 +500,14 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@72c7bc98", - "@opam/sexplib0@opam:v0.17.0@75dcb697", + "@opam/sexplib0@opam:v0.17.0@db8af2c0", "@opam/ppx_derivers@opam:1.2.1@d78727cd", "@opam/ocaml-compiler-libs@opam:v0.17.0@6bdcfede", "@opam/dune@opam:3.20.2@8daef28d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/stdlib-shims@opam:0.3.0@72c7bc98", - "@opam/sexplib0@opam:v0.17.0@75dcb697", + "@opam/sexplib0@opam:v0.17.0@db8af2c0", "@opam/ppx_derivers@opam:1.2.1@d78727cd", "@opam/ocaml-compiler-libs@opam:v0.17.0@6bdcfede", "@opam/dune@opam:3.20.2@8daef28d" @@ -519,8 +519,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e": { - "id": "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e", + "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb": { + "id": "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb", "name": "@opam/ppx_yojson_conv_lib", "version": "opam:v0.17.0", "source": { @@ -662,14 +662,14 @@ }, "overrides": [], "dependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/dune@opam:3.20.2@8daef28d", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@opam/base-bytes@opam:base@785dbd33", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/dune@opam:3.20.2@8daef28d", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@opam/base-bytes@opam:base@785dbd33" @@ -733,7 +733,7 @@ "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/uutf@opam:1.0.4@ba7fbef7", "@opam/uuseg@opam:17.0.0@52f3d276", - "@opam/stdio@opam:v0.17.0@def6a62f", + "@opam/stdio@opam:v0.17.0@80c625cc", "@opam/ocp-indent@opam:1.7.0@3e255333", "@opam/ocaml-version@opam:4.0.3@371c2527", "@opam/menhirSdk@opam:20250912@f434747d", @@ -746,14 +746,14 @@ "@opam/dune@opam:3.20.2@8daef28d", "@opam/csexp@opam:1.5.2@46614bf4", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@opam/camlp-streams@opam:5.0.1@8e96208c", - "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d", "@opam/astring@opam:0.8.5@9975798d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/uutf@opam:1.0.4@ba7fbef7", "@opam/uuseg@opam:17.0.0@52f3d276", - "@opam/stdio@opam:v0.17.0@def6a62f", + "@opam/stdio@opam:v0.17.0@80c625cc", "@opam/ocp-indent@opam:1.7.0@3e255333", "@opam/ocaml-version@opam:4.0.3@371c2527", "@opam/menhirSdk@opam:20250912@f434747d", @@ -766,7 +766,7 @@ "@opam/dune@opam:3.20.2@8daef28d", "@opam/csexp@opam:1.5.2@46614bf4", "@opam/cmdliner@opam:1.3.0@8e6dd99f", "@opam/camlp-streams@opam:5.0.1@8e96208c", - "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d", "@opam/astring@opam:0.8.5@9975798d" ], "available": [ @@ -813,8 +813,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/ocamlfind@opam:1.9.8@ee910ff5": { - "id": "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364": { + "id": "@opam/ocamlfind@opam:1.9.8@4b291364", "name": "@opam/ocamlfind", "version": "opam:1.9.8", "source": { @@ -905,8 +905,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@122c1c73": { - "id": "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@122c1c73", + "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@ec48e72b": { + "id": "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@ec48e72b", "name": "@opam/ocaml_intrinsics_kernel", "version": "opam:v0.17.1", "source": { @@ -989,7 +989,7 @@ "@opam/xdg@opam:3.20.2@ade9ef81", "@opam/stdune@opam:3.20.2@c89dc074", "@opam/spawn@opam:v0.17.0@d0f69739", "@opam/re@opam:1.14.0@62aa9f42", - "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e", + "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb", "@opam/pp@opam:2.0.0@2177bbde", "@opam/ordering@opam:3.20.2@6865c105", "@opam/ocamlformat-rpc-lib@opam:0.28.1@4c691df7", @@ -1003,7 +1003,7 @@ "@opam/dune@opam:3.20.2@8daef28d", "@opam/csexp@opam:1.5.2@46614bf4", "@opam/chrome-trace@opam:3.20.2@0904f6e5", "@opam/camlp-streams@opam:5.0.1@8e96208c", - "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d", "@opam/astring@opam:0.8.5@9975798d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], @@ -1012,7 +1012,7 @@ "@opam/xdg@opam:3.20.2@ade9ef81", "@opam/stdune@opam:3.20.2@c89dc074", "@opam/spawn@opam:v0.17.0@d0f69739", "@opam/re@opam:1.14.0@62aa9f42", - "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e", + "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb", "@opam/pp@opam:2.0.0@2177bbde", "@opam/ordering@opam:3.20.2@6865c105", "@opam/ocamlformat-rpc-lib@opam:0.28.1@4c691df7", @@ -1026,7 +1026,7 @@ "@opam/dune@opam:3.20.2@8daef28d", "@opam/csexp@opam:1.5.2@46614bf4", "@opam/chrome-trace@opam:3.20.2@0904f6e5", "@opam/camlp-streams@opam:5.0.1@8e96208c", - "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d", "@opam/astring@opam:0.8.5@9975798d" ], "available": [ @@ -1248,14 +1248,14 @@ "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/yojson@opam:3.0.0@b2c9a6c1", "@opam/uutf@opam:1.0.4@ba7fbef7", - "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e", + "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb", "@opam/jsonrpc@opam:1.23.1@f2566740", "@opam/dune@opam:3.20.2@8daef28d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/yojson@opam:3.0.0@b2c9a6c1", "@opam/uutf@opam:1.0.4@ba7fbef7", - "@opam/ppx_yojson_conv_lib@opam:v0.17.0@2b444c0e", + "@opam/ppx_yojson_conv_lib@opam:v0.17.0@e7e988bb", "@opam/jsonrpc@opam:1.23.1@f2566740", "@opam/dune@opam:3.20.2@8daef28d" ], @@ -1319,7 +1319,7 @@ "ocaml@5.3.0@d41d8cd9", "@opam/yojson@opam:3.0.0@b2c9a6c1", "@opam/sedlex@opam:3.7@7fb2caab", "@opam/ppxlib@opam:0.37.0@42a12c9c", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/menhirSdk@opam:20250912@f434747d", "@opam/menhirLib@opam:20250912@7bcb2f61", "@opam/menhir@opam:20250912@0ed10637", @@ -1395,7 +1395,7 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/topkg@opam:1.1.1@2377d2f8", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@opam/astring@opam:0.8.5@9975798d", "@esy-ocaml/substs@0.0.1@d41d8cd9" @@ -1880,11 +1880,11 @@ }, "overrides": [], "dependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@4b291364", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@ee910ff5" + "ocaml@5.3.0@d41d8cd9", "@opam/ocamlfind@opam:1.9.8@4b291364" ], "available": [ [ "darwin", "x86_64" ], @@ -1893,8 +1893,8 @@ [ "windows", "x86_64" ] ] }, - "@opam/base@opam:v0.17.3@78923773": { - "id": "@opam/base@opam:v0.17.3@78923773", + "@opam/base@opam:v0.17.3@4f79f92d": { + "id": "@opam/base@opam:v0.17.3@4f79f92d", "name": "@opam/base", "version": "opam:v0.17.3", "source": { @@ -1911,14 +1911,14 @@ }, "overrides": [], "dependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/sexplib0@opam:v0.17.0@75dcb697", - "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@122c1c73", + "ocaml@5.3.0@d41d8cd9", "@opam/sexplib0@opam:v0.17.0@db8af2c0", + "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@ec48e72b", "@opam/dune-configurator@opam:3.20.2@7eb6ff01", "@opam/dune@opam:3.20.2@8daef28d", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], "devDependencies": [ - "ocaml@5.3.0@d41d8cd9", "@opam/sexplib0@opam:v0.17.0@75dcb697", - "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@122c1c73", + "ocaml@5.3.0@d41d8cd9", "@opam/sexplib0@opam:v0.17.0@db8af2c0", + "@opam/ocaml_intrinsics_kernel@opam:v0.17.1@ec48e72b", "@opam/dune-configurator@opam:3.20.2@7eb6ff01", "@opam/dune@opam:3.20.2@8daef28d" ], @@ -1948,7 +1948,7 @@ "overrides": [], "dependencies": [ "ocaml@5.3.0@d41d8cd9", "@opam/topkg@opam:1.1.1@2377d2f8", - "@opam/ocamlfind@opam:1.9.8@ee910ff5", + "@opam/ocamlfind@opam:1.9.8@4b291364", "@opam/ocamlbuild@opam:0.16.1@b3fc8209", "@esy-ocaml/substs@0.0.1@d41d8cd9" ], @@ -1960,14 +1960,14 @@ [ "windows", "x86_64" ] ] }, - "@grain/libbinaryen@124.0.1@d41d8cd9": { - "id": "@grain/libbinaryen@124.0.1@d41d8cd9", + "@grain/libbinaryen@git:https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3@d41d8cd9": { + "id": "@grain/libbinaryen@git:https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3@d41d8cd9", "name": "@grain/libbinaryen", - "version": "124.0.1", + "version": "git:https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3", "source": { "type": "install", "source": [ - "archive:https://registry.npmjs.org/@grain/libbinaryen/-/libbinaryen-124.0.1.tgz#sha1:7b29acc4a62ab5a849c6e01c3d8e90c78efd05f2" + "git:https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3" ] }, "overrides": [], @@ -1999,7 +1999,7 @@ "ocaml@5.3.0@d41d8cd9", "@opam/dune-configurator@opam:3.20.2@7eb6ff01", "@opam/dune@opam:3.20.2@8daef28d", - "@grain/libbinaryen@124.0.1@d41d8cd9" + "@grain/libbinaryen@git:https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3@d41d8cd9" ], "devDependencies": [ "@opam/ocamlformat@opam:0.27.0@c40d4612", diff --git a/esy.lock/opam/base.v0.17.3/opam b/esy.lock/opam/base.v0.17.3/opam index 76d5609f..39abf898 100644 --- a/esy.lock/opam/base.v0.17.3/opam +++ b/esy.lock/opam/base.v0.17.3/opam @@ -11,8 +11,8 @@ build: [ ] depends: [ "ocaml" {>= "5.1.0"} - "ocaml_intrinsics_kernel" {>= "v0.17.0" & < "v0.18.0"} - "sexplib0" {>= "v0.17.0" & < "v0.18.0"} + "ocaml_intrinsics_kernel" {>= "v0.17.0" & < "v0.18~"} + "sexplib0" {>= "v0.17.0" & < "v0.18~"} "dune" {>= "3.11.0"} "dune-configurator" ] @@ -39,3 +39,5 @@ url { "sha512=628610caff7e124631870fa1e29661caac28bdfdb18750ee43b868037da3d65d6dd9023b4be7c4c52405679efb5e865a6632d95606a22b28a36636a6bf706ef3" ] } +x-maintenance-intent: ["(latest)"] + diff --git a/esy.lock/opam/ocaml_intrinsics_kernel.v0.17.1/opam b/esy.lock/opam/ocaml_intrinsics_kernel.v0.17.1/opam index 44be9138..f167d96b 100644 --- a/esy.lock/opam/ocaml_intrinsics_kernel.v0.17.1/opam +++ b/esy.lock/opam/ocaml_intrinsics_kernel.v0.17.1/opam @@ -28,3 +28,5 @@ url { "sha512=21e596d6407a620866cee7cab47ef1a9446d6a733b4994e809ea5566d5fa956682a5c6a6190ffb0ed48458abd658301944ed10c4389d91ecb8df677a5f87f2ab" ] } +x-maintenance-intent: ["(latest)"] + diff --git a/esy.lock/opam/ocamlfind.1.9.8/opam b/esy.lock/opam/ocamlfind.1.9.8/opam index d9fe3931..8fb38dc5 100644 --- a/esy.lock/opam/ocamlfind.1.9.8/opam +++ b/esy.lock/opam/ocamlfind.1.9.8/opam @@ -12,7 +12,7 @@ license: "MIT" homepage: "http://projects.camlcity.org/projects/findlib.html" bug-reports: "https://github.com/ocaml/ocamlfind/issues" depends: [ - "ocaml" {>= "3.08.0"} + "ocaml" {>= "3.08.0" & (os != "cygwin" & os-distribution != "msys2" | < "5.0")} ] depopts: ["graphics"] build: [ diff --git a/esy.lock/opam/ppx_yojson_conv_lib.v0.17.0/opam b/esy.lock/opam/ppx_yojson_conv_lib.v0.17.0/opam index d58fda4f..44492a50 100644 --- a/esy.lock/opam/ppx_yojson_conv_lib.v0.17.0/opam +++ b/esy.lock/opam/ppx_yojson_conv_lib.v0.17.0/opam @@ -23,3 +23,5 @@ url { src: "https://github.com/janestreet/ppx_yojson_conv_lib/archive/refs/tags/v0.17.0.tar.gz" checksum: "sha256=f6e6ee92408c53c5ecd8bb5ae93811aa4cf71f8dc144d5943be8fc2c7697b199" } +x-maintenance-intent: ["(latest)"] + diff --git a/esy.lock/opam/sexplib0.v0.17.0/opam b/esy.lock/opam/sexplib0.v0.17.0/opam index 7cd4cf8f..78a325db 100644 --- a/esy.lock/opam/sexplib0.v0.17.0/opam +++ b/esy.lock/opam/sexplib0.v0.17.0/opam @@ -29,3 +29,5 @@ url { "sha512=ad387e40789fe70a11473db7e85fe017b801592624414e9030730b2e92ea08f98095fb6e9236430f33c801605ebee0a2a6284e0f618a26a7da4599d4fd9d395d" ] } +x-maintenance-intent: ["(latest)"] + diff --git a/esy.lock/opam/stdio.v0.17.0/opam b/esy.lock/opam/stdio.v0.17.0/opam index 6939fc7d..150104a2 100644 --- a/esy.lock/opam/stdio.v0.17.0/opam +++ b/esy.lock/opam/stdio.v0.17.0/opam @@ -11,7 +11,7 @@ build: [ ] depends: [ "ocaml" {>= "5.1.0"} - "base" {>= "v0.17" & < "v0.18"} + "base" {>= "v0.17" & < "v0.18~"} "dune" {>= "3.11.0"} ] available: arch != "x86_32" @@ -26,3 +26,5 @@ url { src: "https://github.com/janestreet/stdio/archive/refs/tags/v0.17.0.tar.gz" checksum: "sha256=e7cb473d4bffcf419f307c658cf2599fab03a2b4fe655bfd0be699f8f7af176e" } +x-maintenance-intent: ["(latest)"] + diff --git a/package.json b/package.json index b0727de4..b6adac5c 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "@opam/ocaml-lsp-server": ">= 1.9.1 < 2.0.0" }, "resolutions": { - "@opam/ocp-indent": "1.7.0" + "@opam/ocp-indent": "1.7.0", + "@grain/libbinaryen": "git+https://github.com/spotandjake/libbinaryen.git#d4f1fe1c8be38a62cb179705ae8aa9900b2739e3" }, "esy": { "build": "dune build -p binaryen" From 1eaa67ded1fc9f278c222d070c01a7cb8333bfcc Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Fri, 23 Jan 2026 14:18:24 -0500 Subject: [PATCH 10/10] chore: Update tests after rebase --- test/test.expected | 316 +++++++++++++++++++++------------------------ 1 file changed, 145 insertions(+), 171 deletions(-) diff --git a/test/test.expected b/test/test.expected index 0e730bba..de38b05c 100644 --- a/test/test.expected +++ b/test/test.expected @@ -9,19 +9,14 @@ (module (type $0 (struct (field i31ref) (field (ref null $0)))) (type $1 (array (mut i8))) - (type $2 (func (param i32 i32) (result i32))) - (type $3 (func (result (ref $1) (ref $0)))) + (type $2 (func (param i32))) + (type $3 (func (param i32 i32) (result i32))) (type $4 (func)) - (type $5 (func (param anyref i32 i32) (result i32))) - (type $6 (func (param anyref) (result i32))) - (type $7 (func (param anyref) (result anyref anyref))) - (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) - (type $0 (func (param i32))) - (type $1 (func (param i32 i32) (result i32))) - (type $2 (func)) - (type $3 (func (param anyref i32 i32) (result i32))) - (type $4 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) + (type $5 (func (result (ref $1) (ref $0)))) + (type $6 (func (param anyref i32 i32) (result i32))) + (type $7 (func (param anyref) (result i32))) + (type $8 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $write (type $6) (param anyref i32 i32) (result i32))) (global $max_int64 i64 (i64.const 9223372036854775807)) (global $max_int64_mut (mut i64) (i64.const 9223372036854775807)) (global $test_float64_bits f64 (f64.const 1.23)) @@ -30,16 +25,15 @@ (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) - (tag $foo (type $0) (param i32)) - (tag $bar (type $0) (param i32)) + (tag $foo (type $2) (param i32)) + (tag $bar (type $2) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) - (export "gc" (func $gc)) (export "try" (func $try)) + (export "gc" (func $gc)) (start $start) - (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) - (func $adder (type $1) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $3) (param $0 i32) (param $1 i32) (result i32) (block $add (result i32) (if (i32.const 0) @@ -60,7 +54,6 @@ ) ) (func $start (type $4) - (func $start (type $2) (block $start (memory.init $world (i32.const 2048) @@ -68,8 +61,7 @@ (i32.const 5) ) (drop - (call_indirect $table (type $2) - (call_indirect $table (type $1) + (call_indirect $table (type $3) (i32.const 3) (i32.const 5) (i32.const 0) @@ -77,59 +69,14 @@ ) ) ) - (func $hello (type $6) (param $0 anyref) (result i32) - (func $hello (type $4) (param $0 anyref) (result i32) + (func $hello (type $7) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) - (func $gc (type $7) (param $0 anyref) (result anyref anyref) - (local $1 (ref $1)) - (local $2 (ref $0)) - (block $gc_block (type $3) (result (ref $1) (ref $0)) - (local.set $1 - (array.new_fixed $1 2 - (i32.const 0) - (i32.const 255) - ) - ) - (array.set $1 - (local.get $1) - (i32.const 1) - (i32.const 42) - ) - (local.set $2 - (struct.new $0 - (ref.cast i31ref - (local.get $0) - ) - (struct.new $0 - (ref.i31 - (i32.const 1) - ) - (struct.new $0 - (ref.i31 - (i32.const 2) - ) - (struct.new $0 - (ref.i31 - (i32.const 3) - ) - (ref.null none) - ) - ) - ) - ) - ) - (tuple.make 2 - (local.get $1) - (local.get $2) - ) - ) - ) - (func $try (type $2) + (func $try (type $4) (block $blk (drop (try $tc1 (result i32) @@ -197,38 +144,76 @@ ) ) ) + (func $gc (type $8) (param $0 anyref) (result anyref anyref) + (local $1 (ref $1)) + (local $2 (ref $0)) + (block $gc_block (type $5) (result (ref $1) (ref $0)) + (local.set $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (array.set $1 + (local.get $1) + (i32.const 1) + (i32.const 42) + ) + (local.set $2 + (struct.new $0 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $0 + (ref.i31 + (i32.const 1) + ) + (struct.new $0 + (ref.i31 + (i32.const 2) + ) + (struct.new $0 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + (tuple.make 2 + (local.get $1) + (local.get $2) + ) + ) + ) ) (module (type $0 (struct (field i31ref) (field (ref null $0)))) (type $1 (array (mut i8))) - (type $2 (func (result (ref (exact $1)) (ref (exact $0))))) - (type $3 (func (param i32 i32) (result i32))) - (type $4 (func)) - (type $5 (func (param anyref i32 i32) (result i32))) - (type $6 (func (param anyref) (result i32))) - (type $7 (func (param anyref) (result anyref anyref))) - (import "future-wasi" "write" (func $write (type $5) (param anyref i32 i32) (result i32))) - (type $0 (func (param i32))) - (type $1 (func)) - (type $2 (func (param i32 i32) (result i32))) - (type $3 (func (param anyref i32 i32) (result i32))) - (type $4 (func (param anyref) (result i32))) - (import "future-wasi" "write" (func $write (type $3) (param anyref i32 i32) (result i32))) + (type $2 (func (param i32))) + (type $3 (func)) + (type $4 (func (result (ref (exact $1)) (ref (exact $0))))) + (type $5 (func (param i32 i32) (result i32))) + (type $6 (func (param anyref i32 i32) (result i32))) + (type $7 (func (param anyref) (result i32))) + (type $8 (func (param anyref) (result anyref anyref))) + (import "future-wasi" "write" (func $write (type $6) (param anyref i32 i32) (result i32))) (memory $0 1) (data $hello (i32.const 0) "hello") (data $world "world") (table $table 1 1 funcref) (elem $elem (i32.const 0) $adder) - (tag $foo (type $0) (param i32)) - (tag $bar (type $0) (param i32)) + (tag $foo (type $2) (param i32)) + (tag $bar (type $2) (param i32)) (export "adder" (func $adder)) (export "memory" (memory $0)) (export "hello" (func $hello)) - (export "gc" (func $gc)) (export "try" (func $try)) + (export "gc" (func $gc)) (start $start) - (func $adder (type $3) (param $0 i32) (param $1 i32) (result i32) - (func $adder (type $2) (param $0 i32) (param $1 i32) (result i32) + (func $adder (type $5) (param $0 i32) (param $1 i32) (result i32) (i32.add (select (local.get $0) @@ -240,7 +225,7 @@ (local.get $1) ) ) - (func $start (type $4) + (func $start (type $3) (memory.init $world (i32.const 2048) (i32.const 0) @@ -253,52 +238,14 @@ ) ) ) - (func $hello (type $6) (param $0 anyref) (result i32) - (func $hello (type $4) (param $0 anyref) (result i32) + (func $hello (type $7) (param $0 anyref) (result i32) (call $write (local.get $0) (i32.const 0) (i32.const 1) ) ) - (func $gc (type $7) (param $0 anyref) (result anyref anyref) - (local $1 (ref (exact $1))) - (array.set $1 - (local.tee $1 - (array.new_fixed $1 2 - (i32.const 0) - (i32.const 255) - ) - ) - (i32.const 1) - (i32.const 42) - ) - (tuple.make 2 - (local.get $1) - (struct.new $0 - (ref.cast i31ref - (local.get $0) - ) - (struct.new $0 - (ref.i31 - (i32.const 1) - ) - (struct.new $0 - (ref.i31 - (i32.const 2) - ) - (struct.new $0 - (ref.i31 - (i32.const 3) - ) - (ref.null none) - ) - ) - ) - ) - ) - ) - (func $try (type $1) + (func $try (type $3) (drop (try (result i32) (do @@ -338,21 +285,53 @@ ) ) ) + (func $gc (type $8) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $1))) + (array.set $1 + (local.tee $1 + (array.new_fixed $1 2 + (i32.const 0) + (i32.const 255) + ) + ) + (i32.const 1) + (i32.const 42) + ) + (tuple.make 2 + (local.get $1) + (struct.new $0 + (ref.cast i31ref + (local.get $0) + ) + (struct.new $0 + (ref.i31 + (i32.const 1) + ) + (struct.new $0 + (ref.i31 + (i32.const 2) + ) + (struct.new $0 + (ref.i31 + (i32.const 3) + ) + (ref.null none) + ) + ) + ) + ) + ) + ) ) (module - (type $type_6 (struct (field i31ref) (field (ref null $type_6)))) - (type $type_5 (array (mut i8))) - (type $type_7 (func (result anyref anyref))) - (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))) - (type $type_4 (func (param anyref) (result anyref anyref))) - (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) + (type $type_7 (struct (field i31ref) (field (ref null $type_7)))) + (type $type_6 (array (mut i8))) (type $type_3 (func)) + (type $type_8 (func (result anyref anyref))) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) (type $type_4 (func (param anyref) (result i32))) + (type $type_5 (func (param anyref) (result anyref anyref))) (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") @@ -362,8 +341,8 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) - (export "gc" (func $3)) (export "try" (func $3)) + (export "gc" (func $4)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) (i32.add @@ -397,11 +376,17 @@ (i32.const 1) ) ) - (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) - (local $1 (ref (exact $type_5))) - (array.set $type_5 + (func $3 (type $type_3) + (drop + (unreachable) + ) + (unreachable) + ) + (func $4 (type $type_5) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $type_6))) + (array.set $type_6 (local.tee $1 - (array.new_fixed $type_5 2 + (array.new_fixed $type_6 2 (i32.const 0) (i32.const 255) ) @@ -411,19 +396,19 @@ ) (tuple.make 2 (local.get $1) - (struct.new $type_6 + (struct.new $type_7 (ref.cast i31ref (local.get $0) ) - (struct.new $type_6 + (struct.new $type_7 (ref.i31 (i32.const 1) ) - (struct.new $type_6 + (struct.new $type_7 (ref.i31 (i32.const 2) ) - (struct.new $type_6 + (struct.new $type_7 (ref.i31 (i32.const 3) ) @@ -434,27 +419,16 @@ ) ) ) - (func $3 (type $type_3) - (drop - (unreachable) - ) - (unreachable) - ) ) (module - (type $type_6 (struct (field i31ref) (field (ref null $type_6)))) - (type $type_5 (array (mut i8))) - (type $type_7 (func (result anyref anyref))) - (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))) - (type $type_4 (func (param anyref) (result anyref anyref))) - (import "future-wasi" "write" (func $fimport$0 (type $type) (param anyref i32 i32) (result i32))) + (type $type_7 (struct (field i31ref) (field (ref null $type_7)))) + (type $type_6 (array (mut i8))) (type $type_3 (func)) + (type $type_8 (func (result anyref anyref))) (type $type_1 (func (param anyref i32 i32) (result i32))) (type $type_2 (func (param i32 i32) (result i32))) (type $type_4 (func (param anyref) (result i32))) + (type $type_5 (func (param anyref) (result anyref anyref))) (import "future-wasi" "write" (func $fimport$0 (type $type_1) (param anyref i32 i32) (result i32))) (memory $0 1) (data $0 (i32.const 0) "hello") @@ -464,8 +438,8 @@ (export "adder" (func $0)) (export "memory" (memory $0)) (export "hello" (func $2)) - (export "gc" (func $3)) (export "try" (func $3)) + (export "gc" (func $4)) (start $1) (func $0 (type $type_2) (param $0 i32) (param $1 i32) (result i32) local.get $0 @@ -492,15 +466,18 @@ i32.const 1 call $fimport$0 ) - (func $3 (type $type_4) (param $0 anyref) (result anyref anyref) - (local $1 (ref (exact $type_5))) + (func $3 (type $type_3) + unreachable + ) + (func $4 (type $type_5) (param $0 anyref) (result anyref anyref) + (local $1 (ref (exact $type_6))) i32.const 0 i32.const 255 - array.new_fixed $type_5 2 + array.new_fixed $type_6 2 local.tee $1 i32.const 1 i32.const 42 - array.set $type_5 + array.set $type_6 local.get $1 local.get $0 ref.cast i31ref @@ -511,13 +488,10 @@ i32.const 3 ref.i31 ref.null none - struct.new $type_6 - struct.new $type_6 - struct.new $type_6 - struct.new $type_6 + struct.new $type_7 + struct.new $type_7 + struct.new $type_7 + struct.new $type_7 tuple.make 2 ) - (func $3 (type $type_3) - unreachable - ) )