From a6647cbe0a8c8086cc26ff766f5f2fb146656a53 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Wed, 5 Nov 2025 11:18:28 -0500 Subject: [PATCH 1/3] feat: Implement optimization flags --- src/settings.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++ src/settings.js | 98 +++++++++++++++++++++++++++++++++++++++++++ src/settings.ml | 36 ++++++++++++++++ src/settings.mli | 14 +++++++ test/test.ml | 42 +++++++++++++++++++ 5 files changed, 295 insertions(+) diff --git a/src/settings.c b/src/settings.c index b0ce325..6c65cfe 100644 --- a/src/settings.c +++ b/src/settings.c @@ -52,6 +52,36 @@ caml_binaryen_set_debug_info(value _on) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_get_traps_never_happen(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetTrapsNeverHappen(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_traps_never_happen(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetTrapsNeverHappen(on); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_get_closed_world(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetClosedWorld(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_closed_world(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetClosedWorld(on); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_get_low_memory_unused(value unit) { CAMLparam1(unit); @@ -67,6 +97,66 @@ caml_binaryen_set_low_memory_unused(value _on) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_get_zero_filled_memory(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetZeroFilledMemory(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_zero_filled_memory(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetZeroFilledMemory(on); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_get_fast_math(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetFastMath(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_fast_math(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetFastMath(on); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_get_generate_stack_ir(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetGenerateStackIR(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_generate_stack_ir(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetGenerateStackIR(on); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_get_optimize_stack_ir(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetOptimizeStackIR(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_optimize_stack_ir(value _on) { + CAMLparam1(_on); + bool on = Bool_val(_on); + BinaryenSetOptimizeStackIR(on); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_get_pass_argument(value _name) { CAMLparam1(_name); @@ -133,6 +223,21 @@ caml_binaryen_set_one_caller_inline_max_size(value _size) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_get_allow_inlining_functions_with_loops(value unit) { + CAMLparam1(unit); + bool res = BinaryenGetAllowInliningFunctionsWithLoops(); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_set_allow_inlining_functions_with_loops(value _size) { + CAMLparam1(_size); + int on = Bool_val(_size); + BinaryenSetAllowInliningFunctionsWithLoops(on); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_set_colors_enabled(value _on) { CAMLparam1(_on); diff --git a/src/settings.js b/src/settings.js index 6e9eb20..719c665 100644 --- a/src/settings.js +++ b/src/settings.js @@ -36,6 +36,34 @@ function caml_binaryen_set_debug_info(on) { return Binaryen._BinaryenSetDebugInfo(on); } +//Provides: caml_binaryen_get_traps_never_happen +//Requires: Binaryen +function caml_binaryen_get_traps_never_happen() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetTrapsNeverHappen(); +} + +//Provides: caml_binaryen_set_traps_never_happen +//Requires: Binaryen +function caml_binaryen_set_traps_never_happen(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetTrapsNeverHappen(on); +} + +//Provides: caml_binaryen_get_closed_world +//Requires: Binaryen +function caml_binaryen_get_closed_world() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetClosedWorld(); +} + +//Provides: caml_binaryen_set_closed_world +//Requires: Binaryen +function caml_binaryen_set_closed_world(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetClosedWorld(on); +} + //Provides: caml_binaryen_get_low_memory_unused //Requires: Binaryen function caml_binaryen_get_low_memory_unused() { @@ -50,6 +78,62 @@ function caml_binaryen_set_low_memory_unused(on) { return Binaryen._BinaryenSetLowMemoryUnused(on); } +//Provides: caml_binaryen_get_zero_filled_memory +//Requires: Binaryen +function caml_binaryen_get_zero_filled_memory() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetZeroFilledMemory(); +} + +//Provides: caml_binaryen_set_zero_filled_memory +//Requires: Binaryen +function caml_binaryen_set_zero_filled_memory(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetZeroFilledMemory(on); +} + +//Provides: caml_binaryen_get_fast_math +//Requires: Binaryen +function caml_binaryen_get_fast_math() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetFastMath(); +} + +//Provides: caml_binaryen_set_fast_math +//Requires: Binaryen +function caml_binaryen_set_fast_math(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetFastMath(on); +} + +//Provides: caml_binaryen_get_generate_stack_ir +//Requires: Binaryen +function caml_binaryen_get_generate_stack_ir() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetGenerateStackIR(); +} + +//Provides: caml_binaryen_set_generate_stack_ir +//Requires: Binaryen +function caml_binaryen_set_generate_stack_ir(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetGenerateStackIR(on); +} + +//Provides: caml_binaryen_get_optimize_stack_ir +//Requires: Binaryen +function caml_binaryen_get_optimize_stack_ir() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetOptimizeStackIR(); +} + +//Provides: caml_binaryen_set_optimize_stack_ir +//Requires: Binaryen +function caml_binaryen_set_optimize_stack_ir(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetOptimizeStackIR(on); +} + //Provides: caml_binaryen_get_pass_argument //Requires: Binaryen //Requires: caml_jsstring_of_string @@ -106,6 +190,20 @@ function caml_binaryen_set_one_caller_inline_max_size(size) { return Binaryen.setOneCallerInlineMaxSize(size); } +//Provides: caml_binaryen_get_allow_inlining_functions_with_loops +//Requires: Binaryen +function caml_binaryen_get_allow_inlining_functions_with_loops() { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenGetAllowInliningFunctionsWithLoops(); +} + +//Provides: caml_binaryen_set_allow_inlining_functions_with_loops +//Requires: Binaryen +function caml_binaryen_set_allow_inlining_functions_with_loops(on) { + // Uses the `_Binaryen` function because then we are working with ints which are also booleans to JSOO + return Binaryen._BinaryenSetAllowInliningFunctionsWithLoops(on); +} + //Provides: caml_binaryen_set_colors_enabled //Requires: Binaryen function caml_binaryen_set_colors_enabled(on) { diff --git a/src/settings.ml b/src/settings.ml index 5c524ba..eebb403 100644 --- a/src/settings.ml +++ b/src/settings.ml @@ -5,12 +5,42 @@ external set_shrink_level : int -> unit = "caml_binaryen_set_shrink_level" external get_debug_info : unit -> bool = "caml_binaryen_get_debug_info" external set_debug_info : bool -> unit = "caml_binaryen_set_debug_info" +external get_traps_never_happen : unit -> bool + = "caml_binaryen_get_traps_never_happen" + +external set_traps_never_happen : bool -> unit + = "caml_binaryen_set_traps_never_happen" + +external get_closed_world : unit -> bool = "caml_binaryen_get_closed_world" +external set_closed_world : bool -> unit = "caml_binaryen_set_closed_world" + external get_low_memory_unused : unit -> bool = "caml_binaryen_get_low_memory_unused" external set_low_memory_unused : bool -> unit = "caml_binaryen_set_low_memory_unused" +external get_zero_filled_memory : unit -> bool + = "caml_binaryen_get_zero_filled_memory" + +external set_zero_filled_memory : bool -> unit + = "caml_binaryen_set_zero_filled_memory" + +external get_fast_math : unit -> bool = "caml_binaryen_get_fast_math" +external set_fast_math : bool -> unit = "caml_binaryen_set_fast_math" + +external get_generate_stack_ir : unit -> bool + = "caml_binaryen_get_generate_stack_ir" + +external set_generate_stack_ir : bool -> unit + = "caml_binaryen_set_generate_stack_ir" + +external get_optimize_stack_ir : unit -> bool + = "caml_binaryen_get_optimize_stack_ir" + +external set_optimize_stack_ir : bool -> unit + = "caml_binaryen_set_optimize_stack_ir" + external get_pass_argument : string -> string option = "caml_binaryen_get_pass_argument" @@ -35,5 +65,11 @@ external get_one_caller_inline_max_size : unit -> int external set_one_caller_inline_max_size : int -> unit = "caml_binaryen_set_one_caller_inline_max_size" +external get_allow_inlining_functions_with_loops : unit -> bool + = "caml_binaryen_get_allow_inlining_functions_with_loops" + +external set_allow_inlining_functions_with_loops : bool -> unit + = "caml_binaryen_set_allow_inlining_functions_with_loops" + external set_colors_enabled : bool -> unit = "caml_binaryen_set_colors_enabled" external are_colors_enabled : unit -> bool = "caml_binaryen_are_colors_enabled" diff --git a/src/settings.mli b/src/settings.mli index 70e66a7..41430a0 100644 --- a/src/settings.mli +++ b/src/settings.mli @@ -4,8 +4,20 @@ val get_shrink_level : unit -> int val set_shrink_level : int -> unit val get_debug_info : unit -> bool val set_debug_info : bool -> unit +val get_traps_never_happen : unit -> bool +val set_traps_never_happen : bool -> unit +val get_closed_world : unit -> bool +val set_closed_world : bool -> unit val get_low_memory_unused : unit -> bool val set_low_memory_unused : bool -> unit +val get_zero_filled_memory : unit -> bool +val set_zero_filled_memory : bool -> unit +val get_fast_math : unit -> bool +val set_fast_math : bool -> unit +val get_generate_stack_ir : unit -> bool +val set_generate_stack_ir : bool -> unit +val get_optimize_stack_ir : unit -> bool +val set_optimize_stack_ir : bool -> unit val get_pass_argument : string -> string option val set_pass_argument : string -> string -> unit val get_always_inline_max_size : unit -> int @@ -14,5 +26,7 @@ val get_flexible_inline_max_size : unit -> int val set_flexible_inline_max_size : int -> unit val get_one_caller_inline_max_size : unit -> int val set_one_caller_inline_max_size : int -> unit +val get_allow_inlining_functions_with_loops : unit -> bool +val set_allow_inlining_functions_with_loops : bool -> unit val set_colors_enabled : bool -> unit val are_colors_enabled : unit -> bool diff --git a/test/test.ml b/test/test.ml index 44d0b53..5310eb1 100644 --- a/test/test.ml +++ b/test/test.ml @@ -12,11 +12,53 @@ let _ = Settings.set_debug_info true let _ = assert (Settings.get_debug_info () == true) let _ = Settings.set_debug_info false +(* Testing traps_never_happen enable *) +let _ = assert (Settings.get_traps_never_happen () == false) +let _ = Settings.set_traps_never_happen true +let _ = assert (Settings.get_traps_never_happen () == true) +let _ = Settings.set_traps_never_happen false + +(* Testing closed_world enable *) +let _ = assert (Settings.get_closed_world () == false) +let _ = Settings.set_closed_world true +let _ = assert (Settings.get_closed_world () == true) +let _ = Settings.set_closed_world false + (* Testing low_memory_unused enable *) let _ = assert (Settings.get_low_memory_unused () == false) let _ = Settings.set_low_memory_unused true let _ = assert (Settings.get_low_memory_unused () == true) let _ = Settings.set_low_memory_unused false + +(* Testing zero_filled_memory enable *) +let _ = assert (Settings.get_zero_filled_memory () == false) +let _ = Settings.set_zero_filled_memory true +let _ = assert (Settings.get_zero_filled_memory () == true) +let _ = Settings.set_zero_filled_memory false + +(* Testing fast_math enable *) +let _ = assert (Settings.get_fast_math () == false) +let _ = Settings.set_fast_math true +let _ = assert (Settings.get_fast_math () == true) +let _ = Settings.set_fast_math false + +(* Testing generate_stack_ir enable *) +let _ = assert (Settings.get_generate_stack_ir () == false) +let _ = Settings.set_generate_stack_ir true +let _ = assert (Settings.get_generate_stack_ir () == true) +let _ = Settings.set_generate_stack_ir false + +(* Testing optimize_stack_ir enable *) +let _ = assert (Settings.get_optimize_stack_ir () == false) +let _ = Settings.set_optimize_stack_ir true +let _ = assert (Settings.get_optimize_stack_ir () == true) +let _ = Settings.set_optimize_stack_ir false + +(* Testing allow_inlining_functions_with_loops enable *) +let _ = assert (Settings.get_allow_inlining_functions_with_loops () == false) +let _ = Settings.set_allow_inlining_functions_with_loops true +let _ = assert (Settings.get_allow_inlining_functions_with_loops () == true) +let _ = Settings.set_allow_inlining_functions_with_loops false let wasm_mod = Module.create () let _ = Module.set_features wasm_mod [ Module.Feature.all ] let import_wasm_mod = Module.create () From 1d63863855c020151c4a4e372d7cd8e231b2f15b Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Wed, 5 Nov 2025 11:52:35 -0500 Subject: [PATCH 2/3] feat: Add Pass Settings * `clear_pass_arguments` * `has_pass_to_skip` * `Add_pass_to_skip` * `clear_passes_to_skip` --- src/settings.c | 30 ++++++++++++++++++++++++++++++ src/settings.js | 30 ++++++++++++++++++++++++++++++ src/settings.ml | 9 +++++++++ src/settings.mli | 4 ++++ test/test.ml | 17 +++++++++++++++++ 5 files changed, 90 insertions(+) diff --git a/src/settings.c b/src/settings.c index 6c65cfe..c87e101 100644 --- a/src/settings.c +++ b/src/settings.c @@ -178,6 +178,36 @@ caml_binaryen_set_pass_argument(value _name, value _val) { CAMLreturn(Val_unit); } +CAMLprim value +caml_binaryen_clear_pass_arguments(value unit) { + CAMLparam1(unit); + BinaryenClearPassArguments(); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_has_pass_to_skip(value _pass) { + CAMLparam1(_pass); + const char* pass = Safe_String_val(_pass); + bool res = BinaryenHasPassToSkip(pass); + CAMLreturn(Val_bool(res)); +} + +CAMLprim value +caml_binaryen_add_pass_to_skip(value _pass) { + CAMLparam1(_pass); + const char* pass = Safe_String_val(_pass); + BinaryenAddPassToSkip(pass); + CAMLreturn(Val_unit); +} + +CAMLprim value +caml_binaryen_clear_passes_to_skip(value unit) { + CAMLparam1(unit); + BinaryenClearPassesToSkip(); + CAMLreturn(Val_unit); +} + CAMLprim value caml_binaryen_get_always_inline_max_size(value unit) { CAMLparam1(unit); diff --git a/src/settings.js b/src/settings.js index 719c665..79c3d15 100644 --- a/src/settings.js +++ b/src/settings.js @@ -154,6 +154,36 @@ function caml_binaryen_set_pass_argument(name, value) { ); } +//Provides: caml_binaryen_clear_pass_arguments +//Requires: Binaryen +function caml_binaryen_clear_pass_arguments() { + return Binaryen.clearPassArguments(); +} + +//Provides: caml_binaryen_has_pass_to_skip +//Requires: Binaryen +//Requires: caml_jsstring_of_string +function caml_binaryen_has_pass_to_skip(pass) { + return Binaryen.hasPassToSkip( + caml_jsstring_of_string(pass) + ); +} + +//Provides: caml_binaryen_add_pass_to_skip +//Requires: Binaryen +//Requires: caml_jsstring_of_string +function caml_binaryen_add_pass_to_skip(pass) { + return Binaryen.addPassToSkip( + caml_jsstring_of_string(pass) + ); +} + +//Provides: caml_binaryen_clear_passes_to_skip +//Requires: Binaryen +function caml_binaryen_clear_passes_to_skip(pass) { + return Binaryen.clearPassesToSkip(); +} + //Provides: caml_binaryen_get_always_inline_max_size //Requires: Binaryen function caml_binaryen_get_always_inline_max_size() { diff --git a/src/settings.ml b/src/settings.ml index eebb403..ca07888 100644 --- a/src/settings.ml +++ b/src/settings.ml @@ -47,6 +47,15 @@ external get_pass_argument : string -> string option external set_pass_argument : string -> string -> unit = "caml_binaryen_set_pass_argument" +external clear_pass_arguments : unit -> unit + = "caml_binaryen_clear_pass_arguments" + +external has_pass_to_skip : string -> bool = "caml_binaryen_has_pass_to_skip" +external add_pass_to_skip : string -> unit = "caml_binaryen_add_pass_to_skip" + +external clear_passes_to_skip : unit -> unit + = "caml_binaryen_clear_passes_to_skip" + external get_always_inline_max_size : unit -> int = "caml_binaryen_get_always_inline_max_size" diff --git a/src/settings.mli b/src/settings.mli index 41430a0..79bafec 100644 --- a/src/settings.mli +++ b/src/settings.mli @@ -20,6 +20,10 @@ val get_optimize_stack_ir : unit -> bool val set_optimize_stack_ir : bool -> unit val get_pass_argument : string -> string option val set_pass_argument : string -> string -> unit +val clear_pass_arguments : unit -> unit +val has_pass_to_skip : string -> bool +val add_pass_to_skip : string -> unit +val clear_passes_to_skip : unit -> unit val get_always_inline_max_size : unit -> int val set_always_inline_max_size : int -> unit val get_flexible_inline_max_size : unit -> int diff --git a/test/test.ml b/test/test.ml index 5310eb1..9ca0b6f 100644 --- a/test/test.ml +++ b/test/test.ml @@ -54,6 +54,23 @@ let _ = Settings.set_optimize_stack_ir true let _ = assert (Settings.get_optimize_stack_ir () == true) let _ = Settings.set_optimize_stack_ir false +(* Testing pass_argument *) +let _ = Settings.set_pass_argument "theKey" "theValue" +let _ = Settings.get_pass_argument "theKey" = "theValue" +let _ = Settings.set_pass_argument "theKey" "theValue2" +let _ = Settings.get_pass_argument "theKey" = "theValue2" + +let _ = + Settings.clear_pass_arguments + () (* Note: there is no way to test this currently *) + +(* Testing skip_pass *) +let _ = assert (Settings.has_pass_to_skip "thePass" == false) +let _ = Settings.add_pass_to_skip "thePass" +let _ = assert (Settings.has_pass_to_skip "thePass" == true) +let _ = Settings.clear_passes_to_skip () +let _ = assert (Settings.has_pass_to_skip "thePass" == false) + (* Testing allow_inlining_functions_with_loops enable *) let _ = assert (Settings.get_allow_inlining_functions_with_loops () == false) let _ = Settings.set_allow_inlining_functions_with_loops true From d590fae375c54fbe834c5020a05af9718ceb1f88 Mon Sep 17 00:00:00 2001 From: Spotandjake Date: Wed, 5 Nov 2025 12:14:07 -0500 Subject: [PATCH 3/3] chore: Test build failure --- src/settings.js | 7 +++++-- test/test.ml | 11 ++++------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/settings.js b/src/settings.js index 79c3d15..07a2dc4 100644 --- a/src/settings.js +++ b/src/settings.js @@ -163,9 +163,12 @@ function caml_binaryen_clear_pass_arguments() { //Provides: caml_binaryen_has_pass_to_skip //Requires: Binaryen //Requires: caml_jsstring_of_string +//Requires: caml_js_to_bool function caml_binaryen_has_pass_to_skip(pass) { - return Binaryen.hasPassToSkip( - caml_jsstring_of_string(pass) + return caml_js_to_bool( + Binaryen.hasPassToSkip( + caml_jsstring_of_string(pass) + ) ); } diff --git a/test/test.ml b/test/test.ml index 9ca0b6f..60db083 100644 --- a/test/test.ml +++ b/test/test.ml @@ -55,14 +55,11 @@ let _ = assert (Settings.get_optimize_stack_ir () == true) let _ = Settings.set_optimize_stack_ir false (* Testing pass_argument *) +let _ = assert (Settings.get_pass_argument "theKey" = None) let _ = Settings.set_pass_argument "theKey" "theValue" -let _ = Settings.get_pass_argument "theKey" = "theValue" -let _ = Settings.set_pass_argument "theKey" "theValue2" -let _ = Settings.get_pass_argument "theKey" = "theValue2" - -let _ = - Settings.clear_pass_arguments - () (* Note: there is no way to test this currently *) +let _ = assert (Settings.get_pass_argument "theKey" = Some "theValue") +let _ = Settings.clear_pass_arguments () +let _ = assert (Settings.get_pass_argument "theKey" = None) (* Testing skip_pass *) let _ = assert (Settings.has_pass_to_skip "thePass" == false)