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 text file preprocessor #1822

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
5 changes: 5 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
# dev

## Features/Changes
* Compiler: use a Wasm text files preprocessor (#1822)

# 6.0.1 (2025-02-07) - Lille

## Features/Changes
Expand Down
51 changes: 38 additions & 13 deletions compiler/bin-wasm_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,21 @@ let output_gen output_file f =
Code.Var.set_stable (Config.Flag.stable_var ());
Filename.gen_file output_file f

let with_runtime_files ~runtime_wasm_files f =
let inputs =
List.map
~f:(fun file ->
{ Wat_preprocess.module_name = "env"
; file
; source =
(if Link.Wasm_binary.check_file ~file
then File
else Contents (Js_of_ocaml_compiler.Fs.read_file file))
})
runtime_wasm_files
in
Wat_preprocess.with_preprocessed_files ~variables:[] ~inputs f

let link_and_optimize
~profile
~sourcemap_root
Expand All @@ -91,7 +106,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;
Fs.write_file ~name:runtime_file ~contents:Runtime_files.wasm_runtime;
Fs.with_intermediate_file (Filename.temp_file "wasm-merged" ".wasm")
@@ fun temp_file ->
opt_with
Expand All @@ -100,11 +115,15 @@ let link_and_optimize
then Some (Filename.temp_file "wasm-merged" ".wasm.map")
else None)
@@ fun opt_temp_sourcemap ->
(with_runtime_files ~runtime_wasm_files
@@ fun runtime_inputs ->
Binaryen.link
~runtime_files:(runtime_file :: runtime_wasm_files)
~input_files:wat_files
~inputs:
(({ Binaryen.module_name = "env"; file = runtime_file } :: runtime_inputs)
@ List.map ~f:(fun file -> { Binaryen.module_name = "OCaml"; file }) wat_files)
~opt_output_sourcemap:opt_temp_sourcemap
~output_file:temp_file;
~output_file:temp_file
());
Fs.with_intermediate_file (Filename.temp_file "wasm-dce" ".wasm")
@@ fun temp_file' ->
opt_with
Expand All @@ -113,7 +132,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 +143,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 +153,23 @@ 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;
Fs.write_file ~name:runtime_file ~contents:Runtime_files.wasm_runtime;
Fs.with_intermediate_file (Filename.temp_file "wasm-merged" ".wasm")
@@ fun temp_file ->
with_runtime_files ~runtime_wasm_files
@@ fun runtime_inputs ->
Binaryen.link
~opt_output_sourcemap:None
~runtime_files:(runtime_file :: runtime_wasm_files)
~input_files:[]
~output_file:temp_file;
~inputs:({ Binaryen.module_name = "env"; file = runtime_file } :: runtime_inputs)
~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 Down Expand Up @@ -186,7 +209,8 @@ let build_prelude z =
~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

Expand Down Expand Up @@ -216,7 +240,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 @@ -413,7 +437,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
8 changes: 4 additions & 4 deletions compiler/bin-wasm_of_ocaml/dune
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(executable
(name wasm_of_ocaml)
(public_name wasm_of_ocaml)
(executables
(names wasm_of_ocaml wasmoo_link_wasm)
(public_names wasm_of_ocaml -)
(package wasm_of_ocaml-compiler)
(libraries
jsoo_cmdline
Expand All @@ -22,7 +22,7 @@
(:standard -safe-string)))

(rule
(target wa_runtime.ml)
(target runtime_files.ml)
(deps
gen/gen.exe
../../runtime/wasm/runtime.wasm
Expand Down
4 changes: 2 additions & 2 deletions compiler/bin-wasm_of_ocaml/info.ml
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ let make ~name ~doc ~description =
; `S "AUTHORS"
; `P "Jerome Vouillon, Hugo Heuzard."
; `S "LICENSE"
; `P "Copyright (C) 2010-2024."
; `P "Copyright (C) 2010-2025."
; `P
"js_of_ocaml is free software, you can redistribute it and/or modify it under \
"wasm_of_ocaml is free software, you can redistribute it and/or modify it under \
the terms of the GNU Lesser General Public License as published by the Free \
Software Foundation, with linking exception; either version 2.1 of the License, \
or (at your option) any later version."
Expand Down
110 changes: 110 additions & 0 deletions compiler/bin-wasm_of_ocaml/link_wasm.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
(* Wasm_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

open Cmdliner
open Js_of_ocaml_compiler.Stdlib
open Wasm_of_ocaml_compiler

type binaryen_options =
{ common : string list
; opt : string list
; merge : string list
}

type options =
{ input_modules : (string * string) list
; output_file : string
; variables : Preprocess.variables
; binaryen_options : binaryen_options
}

let options =
let input_modules =
let doc =
"Specify an input module with name $(i,NAME) in Wasm text file $(i,FILE)."
in
Arg.(
value
& pos_right 0 (pair ~sep:':' string string) []
& info [] ~docv:"NAME:FILE" ~doc)
in
let output_file =
let doc = "Specify the Wasm binary output file $(docv)." in
Arg.(required & pos 0 (some string) None & info [] ~docv:"WASM_FILE" ~doc)
in
let binaryen_options =
let doc = "Pass option $(docv) to binaryen tools" in
Arg.(value & opt_all string [] & info [ "binaryen" ] ~docv:"OPT" ~doc)
in
let opt_options =
let doc = "Pass option $(docv) to $(b,wasm-opt)" in
Arg.(value & opt_all string [] & info [ "binaryen-opt" ] ~docv:"OPT" ~doc)
in
let merge_options =
let doc = "Pass option $(docv) to $(b,wasm-merge)" in
Arg.(value & opt_all string [] & info [ "binaryen-merge" ] ~docv:"OPT" ~doc)
in
let build_t input_modules output_file variables common opt merge =
`Ok
{ input_modules; output_file; variables; binaryen_options = { common; opt; merge } }
in
let t =
Term.(
const build_t
$ input_modules
$ output_file
$ Preprocess.variable_options
$ binaryen_options
$ opt_options
$ merge_options)
in
Term.ret t

let link
{ input_modules; output_file; variables; binaryen_options = { common; merge; opt } } =
let inputs =
List.map
~f:(fun (module_name, file) ->
{ Wat_preprocess.module_name
; file
; source =
(if Link.Wasm_binary.check_file ~file
then File
else Contents (Js_of_ocaml_compiler.Fs.read_file file))
})
input_modules
in
Runtime.build
~link_options:(common @ merge)
~opt_options:(common @ opt)
~variables:(Preprocess.set_variables variables)
~inputs
~output_file

let info =
Info.make
~name:"link-wasm"
~doc:"Wasm linker"
~description:
"$(b,wasmoo_util link) is a Wasm linker. It takes as input a list of Wasm text \
files, preprocesses them, links them together, and outputs a single Wasm binary \
module"

let term = Cmdliner.Term.(const link $ options)

let command = Cmdliner.Cmd.v info term
19 changes: 19 additions & 0 deletions compiler/bin-wasm_of_ocaml/link_wasm.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(* Wasm_of_ocaml compiler
* http://www.ocsigen.org/js_of_ocaml/
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, with linking exception;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*)

val command : unit Cmdliner.Cmd.t
Loading
Loading