Skip to content

Commit

Permalink
Workaround for the local variable limits of binaryen's binary parser
Browse files Browse the repository at this point in the history
Binaryen's binary parser currently enforces a limit of 50 000 locals per
function (see WebAssembly/binaryen#6677). To avoid reaching this limit,
this first compiles the generated code with wasm-opt with a limited
number of optimization passes before calling wasm-merge. Otherwise,
wasm-merge (which does not perform any optimization) can produce a binary
with an overly large number of locals, that will be rejected by other
binaryen tools.
  • Loading branch information
vouillon committed Sep 24, 2024
1 parent 87f2119 commit e919664
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 16 deletions.
36 changes: 29 additions & 7 deletions compiler/bin-wasm_of_ocaml/compile.ml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ let link_and_optimize
~sourcemap_don't_inline_content
~opt_sourcemap
runtime_wasm_files
wat_files
wat_file
output_file =
let opt_sourcemap_file =
(* Check that Binaryen supports the necessary sourcemaps options (requires
Expand All @@ -89,11 +89,29 @@ let link_and_optimize
then Some (Filename.temp_file "wasm-merged" ".wasm.map")
else None)
@@ fun opt_temp_sourcemap ->
(Fs.with_intermediate_file (Filename.temp_file "input" ".wasm")
@@ fun temp_input_file ->
opt_with
Fs.with_intermediate_file
(if enable_source_maps then Some (Filename.temp_file "input" ".wasm.map") else None)
@@ fun opt_temp_input_sourcemap ->
Wa_binaryen.optimize
~extra_options:
[ "--simplify-locals-notee-nostructure"
; "--vacuum"
; "--reorder-locals"
; "--coalesce-locals"
]
~opt_input_sourcemap:None
~opt_output_sourcemap:opt_temp_input_sourcemap
~input_file:wat_file
~output_file:temp_input_file
();
Wa_binaryen.link
~runtime_files:(runtime_file :: runtime_wasm_files)
~input_files:wat_files
~input_files:[ temp_input_file, opt_temp_input_sourcemap ]
~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 +131,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 @@ -136,6 +155,7 @@ let link_runtime ~profile runtime_wasm_files output_file =
~opt_output_sourcemap:None
~input_file:temp_file
~output_file
()

let generate_prelude ~out_file =
Filename.gen_file out_file
Expand Down Expand Up @@ -166,7 +186,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 @@ -381,7 +402,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
();
{ Wa_link.unit_name; unit_info; strings; fragments }
in
cont unit_data unit_name tmp_wasm_file opt_tmp_map_file
Expand Down Expand Up @@ -420,7 +442,7 @@ let run
~sourcemap_don't_inline_content
~opt_sourcemap
runtime_wasm_files
[ wat_file ]
wat_file
tmp_wasm_file
in
let wasm_name =
Expand Down
32 changes: 25 additions & 7 deletions compiler/lib/wasm/wa_binaryen.ml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,12 @@ let link ~runtime_files ~input_files ~opt_output_sourcemap ~output_file =
runtime_files)
@ List.flatten
(List.map
~f:(fun input_file -> [ Filename.quote input_file; "OCaml" ])
~f:(fun (input_file, opt_input_source_map) ->
[ Filename.quote input_file; "OCaml" ]
@
match opt_input_source_map with
| None -> []
| Some sm -> [ "-ism"; sm ])
input_files)
@ [ "-o"; Filename.quote output_file ]
@ opt_flag "--output-source-map" opt_output_sourcemap))
Expand Down Expand Up @@ -114,17 +119,30 @@ 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 level =
let optimize
?profile
?(extra_options = [])
~opt_input_sourcemap
~input_file
~opt_output_sourcemap
~output_file
() =
let opt_options =
match profile with
| None -> 1
| Some p -> fst (List.find ~f:(fun (_, p') -> Poly.equal p p') Driver.profiles)
| None -> []
| Some profile ->
let level =
match profile with
| None -> 1
| Some p -> fst (List.find ~f:(fun (_, p') -> Poly.equal p p') Driver.profiles)
in
optimization_options.(level - 1)
in
command
("wasm-opt"
:: (common_options ()
@ optimization_options.(level - 1)
@ opt_options
@ extra_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)
6 changes: 4 additions & 2 deletions compiler/lib/wasm/wa_binaryen.mli
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

val link :
runtime_files:string list
-> input_files:string list
-> input_files:(string * string option) list
-> opt_output_sourcemap:string option
-> output_file:string
-> unit
Expand All @@ -32,9 +32,11 @@ val dead_code_elimination :
-> Stdlib.StringSet.t

val optimize :
profile:Driver.profile option
?profile:Driver.profile option
-> ?extra_options:string list
-> opt_input_sourcemap:string option
-> input_file:string
-> opt_output_sourcemap:string option
-> output_file:string
-> unit
-> unit

0 comments on commit e919664

Please sign in to comment.