Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wasm] Option to implement OCaml strings with JavaScript strings #1772

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-wasm_of_ocaml.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
- name: Install node
uses: actions/setup-node@v4
with:
node-version: 23
node-version: 'v24.0.0-v8-canary202412116884e26428'

- name: Install OCaml ${{ matrix.ocaml-compiler }}
uses: ocaml/setup-ocaml@v3
Expand Down
72 changes: 54 additions & 18 deletions compiler/bin-wasm_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,32 @@ let output_gen output_file f =
Code.Var.set_stable (Config.Flag.stable_var ());
Filename.gen_file output_file f

let build_runtime ~runtime_file =
let variables = [ "use-js-string", Config.Flag.use_js_string () ] in
List.fold_left
~f:(fun cont (name, contents) ->
fun inputs ->
Fs.with_intermediate_file (Filename.temp_file name ".wat")
@@ fun filename ->
Fs.write_file
~name:filename
~contents:(Wat_preprocess.f ~variables ~filename ~contents);
cont ((filename, name) :: inputs))
~init:(fun inputs ->
Fs.with_intermediate_file (Filename.temp_file "runtime-merged" ".wasm")
@@ fun merge_file ->
Binaryen.link ~opt_output_sourcemap:None ~inputs ~output_file:merge_file;
Binaryen.optimize
~profile:None
~options:[ "-O2" ]
~opt_input_sourcemap:None
~input_file:merge_file
~opt_output_sourcemap:None
~output_file:runtime_file
())
Runtime_files.wat_files
[]

let link_and_optimize
~profile
~sourcemap_root
Expand All @@ -91,7 +117,7 @@ let link_and_optimize
let enable_source_maps = Option.is_some opt_sourcemap_file in
Fs.with_intermediate_file (Filename.temp_file "runtime" ".wasm")
@@ fun runtime_file ->
Fs.write_file ~name:runtime_file ~contents:Wa_runtime.wasm_runtime;
build_runtime ~runtime_file;
Fs.with_intermediate_file (Filename.temp_file "wasm-merged" ".wasm")
@@ fun temp_file ->
opt_with
Expand All @@ -101,8 +127,9 @@ let link_and_optimize
else None)
@@ fun opt_temp_sourcemap ->
Binaryen.link
~runtime_files:(runtime_file :: runtime_wasm_files)
~input_files:wat_files
~inputs:
(List.map ~f:(fun f -> f, "env") (runtime_file :: runtime_wasm_files)
@ List.map ~f:(fun f -> f, "OCaml") wat_files)
~opt_output_sourcemap:opt_temp_sourcemap
~output_file:temp_file;
Fs.with_intermediate_file (Filename.temp_file "wasm-dce" ".wasm")
Expand All @@ -113,7 +140,7 @@ let link_and_optimize
@@ fun opt_temp_sourcemap' ->
let primitives =
Binaryen.dead_code_elimination
~dependencies:Wa_runtime.dependencies
~dependencies:Runtime_files.dependencies
~opt_input_sourcemap:opt_temp_sourcemap
~opt_output_sourcemap:opt_temp_sourcemap'
~input_file:temp_file
Expand All @@ -124,7 +151,8 @@ let link_and_optimize
~opt_input_sourcemap:opt_temp_sourcemap'
~opt_output_sourcemap:opt_sourcemap
~input_file:temp_file'
~output_file;
~output_file
();
Option.iter
~f:(update_sourcemap ~sourcemap_root ~sourcemap_don't_inline_content)
opt_sourcemap_file;
Expand All @@ -133,20 +161,20 @@ let link_and_optimize
let link_runtime ~profile runtime_wasm_files output_file =
Fs.with_intermediate_file (Filename.temp_file "runtime" ".wasm")
@@ fun runtime_file ->
Fs.write_file ~name:runtime_file ~contents:Wa_runtime.wasm_runtime;
build_runtime ~runtime_file;
Fs.with_intermediate_file (Filename.temp_file "wasm-merged" ".wasm")
@@ fun temp_file ->
Binaryen.link
~inputs:(List.map ~f:(fun f -> f, "env") (runtime_file :: runtime_wasm_files))
~opt_output_sourcemap:None
~runtime_files:(runtime_file :: runtime_wasm_files)
~input_files:[]
~output_file:temp_file;
Binaryen.optimize
~profile
~opt_input_sourcemap:None
~opt_output_sourcemap:None
~input_file:temp_file
~output_file
()

let generate_prelude ~out_file =
Filename.gen_file out_file
Expand All @@ -162,33 +190,34 @@ let generate_prelude ~out_file =
in
let context = Generate.start () in
let debug = Parse_bytecode.Debug.create ~include_cmis:false false in
let _ =
let _, generated_js =
Generate.f
~context
~unit_name:(Some "prelude")
~unit_name:(Some "wasmoo_prelude")
~live_vars:variable_uses
~in_cps
~deadcode_sentinal
~debug
program
in
Generate.output ch ~context;
uinfo.provides
uinfo.provides, generated_js

let build_prelude z =
Fs.with_intermediate_file (Filename.temp_file "prelude" ".wasm")
@@ fun prelude_file ->
Fs.with_intermediate_file (Filename.temp_file "prelude_file" ".wasm")
@@ fun tmp_prelude_file ->
let predefined_exceptions = generate_prelude ~out_file:prelude_file in
let info = generate_prelude ~out_file:prelude_file in
Binaryen.optimize
~profile:(Driver.profile 1)
~input_file:prelude_file
~output_file:tmp_prelude_file
~opt_input_sourcemap:None
~opt_output_sourcemap:None;
~opt_output_sourcemap:None
();
Zip.add_file z ~name:"prelude.wasm" ~file:tmp_prelude_file;
predefined_exceptions
info

let build_js_runtime ~primitives ?runtime_arguments () =
let always_required_js, primitives =
Expand Down Expand Up @@ -216,7 +245,7 @@ let build_js_runtime ~primitives ?runtime_arguments () =
in
let prelude = Link.output_js always_required_js in
let init_fun =
match Parse_js.parse (Parse_js.Lexer.of_string Wa_runtime.js_runtime) with
match Parse_js.parse (Parse_js.Lexer.of_string Runtime_files.js_runtime) with
| [ (Expression_statement f, _) ] -> f
| _ -> assert false
in
Expand Down Expand Up @@ -364,12 +393,18 @@ let run
let z = Zip.open_out tmp_output_file in
Zip.add_file z ~name:"runtime.wasm" ~file:tmp_wasm_file;
Zip.add_entry z ~name:"runtime.js" ~contents:js_runtime;
let predefined_exceptions = build_prelude z in
let predefined_exceptions, (strings, fragments) = build_prelude z in
Link.add_info
z
~predefined_exceptions
~build_info:(Build_info.create `Runtime)
~unit_data:[]
~unit_data:
[ { Link.unit_name = "wasmoo_prelude"
; unit_info = Unit_info.empty
; strings
; fragments
}
]
();
Zip.close_out z)
else
Expand Down Expand Up @@ -411,7 +446,8 @@ let run
~opt_input_sourcemap:None
~opt_output_sourcemap:opt_tmp_map_file
~input_file:wat_file
~output_file:tmp_wasm_file;
~output_file:tmp_wasm_file
();
{ Link.unit_name; unit_info; strings; fragments }
in
cont unit_data unit_name tmp_wasm_file opt_tmp_map_file
Expand Down
6 changes: 3 additions & 3 deletions compiler/bin-wasm_of_ocaml/dune
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@
(:standard -safe-string)))

(rule
(target wa_runtime.ml)
(target runtime_files.ml)
(deps
gen/gen.exe
../../runtime/wasm/runtime.wasm
../../runtime/wasm/runtime.js
../../runtime/wasm/deps.json)
../../runtime/wasm/deps.json
(glob_files ../../runtime/wasm/*.wat))
(action
(with-stdout-to
%{target}
Expand Down
15 changes: 11 additions & 4 deletions compiler/bin-wasm_of_ocaml/gen/gen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ let read_file ic = really_input_string ic (in_channel_length ic)
let () =
let () = set_binary_mode_out stdout true in
Format.printf
"let wasm_runtime = \"%s\"@."
"let js_runtime = \"%s\"@."
(String.escaped (read_file (open_in_bin Sys.argv.(1))));
Format.printf
"let js_runtime = \"%s\"@."
"let dependencies = \"%s\"@."
(String.escaped (read_file (open_in_bin Sys.argv.(2))));
let a = Array.sub Sys.argv 3 (Array.length Sys.argv - 3) in
Format.printf
"let dependencies = \"%s\"@."
(String.escaped (read_file (open_in_bin Sys.argv.(3))))
"let wat_files = [%a]@."
(Format.pp_print_list (fun f file ->
Format.fprintf
f
"\"%s\", \"%s\"; "
Filename.(chop_suffix (basename file) ".wat")
(String.escaped (read_file (open_in_bin file)))))
(Array.to_list a)
22 changes: 11 additions & 11 deletions compiler/lib-wasm/binaryen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,12 @@ let opt_flag flag v =
| None -> []
| Some v -> [ flag; Filename.quote v ]

let link ~runtime_files ~input_files ~opt_output_sourcemap ~output_file =
let link ~inputs ~opt_output_sourcemap ~output_file =
command
("wasm-merge"
:: (common_options ()
@ List.flatten
(List.map
~f:(fun runtime_file -> [ Filename.quote runtime_file; "env" ])
runtime_files)
@ List.flatten
(List.map
~f:(fun input_file -> [ Filename.quote input_file; "OCaml" ])
input_files)
(List.map ~f:(fun (file, name) -> [ Filename.quote file; name ]) inputs)
@ [ "-o"; Filename.quote output_file ]
@ opt_flag "--output-source-map" opt_output_sourcemap))

Expand Down Expand Up @@ -114,8 +108,14 @@ let optimization_options =
; [ "-O3"; "--skip-pass=inlining-optimizing"; "--traps-never-happen" ]
|]

let optimize ~profile ~opt_input_sourcemap ~input_file ~opt_output_sourcemap ~output_file
=
let optimize
~profile
?options
~opt_input_sourcemap
~input_file
~opt_output_sourcemap
~output_file
() =
let level =
match profile with
| None -> 1
Expand All @@ -124,7 +124,7 @@ let optimize ~profile ~opt_input_sourcemap ~input_file ~opt_output_sourcemap ~ou
command
("wasm-opt"
:: (common_options ()
@ optimization_options.(level - 1)
@ Option.value ~default:optimization_options.(level - 1) options
@ [ Filename.quote input_file; "-o"; Filename.quote output_file ])
@ opt_flag "--input-source-map" opt_input_sourcemap
@ opt_flag "--output-source-map" opt_output_sourcemap)
5 changes: 3 additions & 2 deletions compiler/lib-wasm/binaryen.mli
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@
*)

val link :
runtime_files:string list
-> input_files:string list
inputs:(string * string (*file, module name*)) list
-> opt_output_sourcemap:string option
-> output_file:string
-> unit
Expand All @@ -33,8 +32,10 @@ val dead_code_elimination :

val optimize :
profile:Driver.profile option
-> ?options:string list
-> opt_input_sourcemap:string option
-> input_file:string
-> opt_output_sourcemap:string option
-> output_file:string
-> unit
-> unit
3 changes: 2 additions & 1 deletion compiler/lib-wasm/code_generation.ml
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,8 @@ let rec is_smi e =
| RefNull _
| Br_on_cast _
| Br_on_cast_fail _
| Try _ -> false
| Try _
| ExternConvertAny _ -> false
| BinOp ((F32 _ | F64 _), _, _) | RefTest _ | RefEq _ -> true
| IfExpr (_, _, ift, iff) -> is_smi ift && is_smi iff

Expand Down
4 changes: 3 additions & 1 deletion compiler/lib-wasm/dune
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@
(synopsis "Wasm_of_ocaml compiler library")
(libraries js_of_ocaml_compiler)
(flags
(:standard -w -7-37 -safe-string -open Js_of_ocaml_compiler)))
(:standard -w -7-37 -safe-string -open Js_of_ocaml_compiler))
(preprocess
(pps sedlex.ppx)))
Loading
Loading