Skip to content

Commit 6226949

Browse files
OlivierNicolevouillonhhugo
authored
Target-specific code (#1655)
Co-authored-by: Olivier Nicole <[email protected]> Co-authored-by: Jérôme Vouillon <[email protected]> Co-authored-by: Hugo Heuzard <[email protected]>
1 parent 30d4cd4 commit 6226949

30 files changed

+761
-222
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
* Runtime: allow dynlink of precompiled js with separate compilation (#1676)
1818
* Lib: Modify Typed_array API for compatibility with WebAssembly
1919
* Compiler: improved global dead code elimination (#2206)
20+
* Compiler: add support for the Wasm backend in parts of the pipeline, in
21+
prevision for the merge of wasm_of_ocaml
2022

2123

2224
## Bug fixes

compiler/bin-js_of_ocaml/build_fs.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ function jsoo_create_file_extern(name,content){
7878
~standalone:true
7979
~wrap_with_fun:`Iife
8080
~link:`Needed
81-
pfs_fmt
81+
~formatter:pfs_fmt
8282
(Parse_bytecode.Debug.create ~include_cmis:false false)
8383
code
8484
in

compiler/bin-js_of_ocaml/check_runtime.ml

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ let print_groups output l =
4343
output_string output (Printf.sprintf "%s\n" name)))
4444

4545
let f (runtime_files, bytecode, target_env) =
46+
Config.set_target `JavaScript;
4647
Linker.reset ();
4748
let runtime_files, builtin =
4849
List.partition_map runtime_files ~f:(fun name ->

compiler/bin-js_of_ocaml/compile.ml

+5-4
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ let run
9090
} =
9191
let include_cmis = toplevel && not no_cmis in
9292
let custom_header = common.Jsoo_cmdline.Arg.custom_header in
93+
Config.set_target `JavaScript;
9394
Jsoo_cmdline.Arg.eval common;
9495
Linker.reset ();
9596
(match output_file with
@@ -186,7 +187,7 @@ let run
186187
let init_pseudo_fs = fs_external && standalone in
187188
let sm =
188189
match output_file with
189-
| `Stdout, fmt ->
190+
| `Stdout, formatter ->
190191
let instr =
191192
List.concat
192193
[ pseudo_fs_instr `create_file one.debug one.cmis
@@ -201,10 +202,10 @@ let run
201202
~link
202203
~wrap_with_fun
203204
?source_map
204-
fmt
205+
~formatter
205206
one.debug
206207
code
207-
| `File, fmt ->
208+
| `File, formatter ->
208209
let fs_instr1, fs_instr2 =
209210
match fs_output with
210211
| None -> pseudo_fs_instr `create_file one.debug one.cmis, []
@@ -225,7 +226,7 @@ let run
225226
~link
226227
~wrap_with_fun
227228
?source_map
228-
fmt
229+
~formatter
229230
one.debug
230231
code
231232
in

compiler/bin-js_of_ocaml/link.ml

+1
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ let f
150150
; mklib
151151
; toplevel
152152
} =
153+
Config.set_target `JavaScript;
153154
Jsoo_cmdline.Arg.eval common;
154155
Linker.reset ();
155156
let with_output f =

compiler/lib-dynlink/js_of_ocaml_compiler_dynlink.ml

+3
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ let normalize_bytecode code =
2626
Bytes.to_string b
2727

2828
let () =
29+
(match Sys.backend_type with
30+
| Sys.Other "js_of_ocaml" -> Config.set_target `JavaScript
31+
| Sys.(Native | Bytecode | Other _) -> failwith "Expected backend `js_of_ocaml`");
2932
let global = J.pure_js_expr "globalThis" in
3033
Config.Flag.set "use-js-string" (Jsoo_runtime.Sys.Config.use_js_string ());
3134
Config.Flag.set "effects" (Jsoo_runtime.Sys.Config.effects ());

compiler/lib-runtime-files/gen/gen.ml

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ let rec list_product l =
5151
let bool = [ true; false ]
5252

5353
let () =
54+
Js_of_ocaml_compiler.Config.set_target `JavaScript;
5455
let () = set_binary_mode_out stdout true in
5556
match Array.to_list Sys.argv with
5657
| [] -> assert false

compiler/lib/code.ml

+16-2
Original file line numberDiff line numberDiff line change
@@ -856,6 +856,7 @@ let with_invariant = Debug.find "invariant"
856856
let check_defs = false
857857

858858
let invariant { blocks; start; _ } =
859+
let target = Config.target () in
859860
if with_invariant ()
860861
then (
861862
assert (Addr.Map.mem start blocks);
@@ -870,15 +871,28 @@ let invariant { blocks; start; _ } =
870871
assert (not (Var.ISet.mem defs x));
871872
Var.ISet.add defs x)
872873
in
874+
let check_constant = function
875+
| NativeInt _ | Int32 _ ->
876+
assert (
877+
match target with
878+
| `Wasm -> true
879+
| _ -> false)
880+
| String _ | NativeString _ | Float _ | Float_array _ | Int _ | Int64 _
881+
| Tuple (_, _, _) -> ()
882+
in
883+
let check_prim_arg = function
884+
| Pc c -> check_constant c
885+
| Pv _ -> ()
886+
in
873887
let check_expr = function
874888
| Apply _ -> ()
875889
| Block (_, _, _, _) -> ()
876890
| Field (_, _, _) -> ()
877891
| Closure (l, cont) ->
878892
List.iter l ~f:define;
879893
check_cont cont
880-
| Constant _ -> ()
881-
| Prim (_, _) -> ()
894+
| Constant c -> check_constant c
895+
| Prim (_, args) -> List.iter ~f:check_prim_arg args
882896
| Special _ -> ()
883897
in
884898
let check_instr (i, _loc) =

compiler/lib/config.ml

+8-4
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ module Param = struct
164164
p
165165
~name:"tc"
166166
~desc:"Set tailcall optimisation"
167-
(enum [ "trampoline", TcTrampoline; (* default *) "none", TcNone ])
167+
(enum [ "trampoline", TcTrampoline (* default *); "none", TcNone ])
168168

169169
let lambda_lifting_threshold =
170170
(* When we reach this depth, we start looking for functions to be lifted *)
@@ -183,8 +183,12 @@ end
183183

184184
(****)
185185

186-
let target_ : [ `JavaScript | `Wasm ] ref = ref `JavaScript
186+
let target_ : [ `JavaScript | `Wasm | `None ] ref = ref `None
187187

188-
let target () = !target_
188+
let target () =
189+
match !target_ with
190+
| `None -> failwith "target was not set"
191+
| (`JavaScript | `Wasm) as t -> t
189192

190-
let set_target t = target_ := t
193+
let set_target (t : [ `JavaScript | `Wasm ]) =
194+
target_ := (t :> [ `JavaScript | `Wasm | `None ])

compiler/lib/driver.ml

+41-28
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ let debug = Debug.find "main"
2323

2424
let times = Debug.find "times"
2525

26+
type optimized_result =
27+
{ program : Code.program
28+
; variable_uses : Deadcode.variable_uses
29+
; trampolined_calls : Effects.trampolined_calls
30+
; in_cps : Effects.in_cps
31+
; deadcode_sentinal : Code.Var.t
32+
}
33+
2634
type profile =
2735
| O1
2836
| O2
@@ -194,14 +202,13 @@ let generate
194202
~exported_runtime
195203
~wrap_with_fun
196204
~warn_on_unhandled_effect
197-
~deadcode_sentinal
198-
((p, live_vars), trampolined_calls, _) =
205+
{ program; variable_uses; trampolined_calls; deadcode_sentinal; in_cps = _ } =
199206
if times () then Format.eprintf "Start Generation...@.";
200207
let should_export = should_export wrap_with_fun in
201208
Generate.f
202-
p
209+
program
203210
~exported_runtime
204-
~live_vars
211+
~live_vars:variable_uses
205212
~trampolined_calls
206213
~should_export
207214
~warn_on_unhandled_effect
@@ -658,13 +665,19 @@ let configure formatter =
658665
Code.Var.set_pretty (pretty && not (Config.Flag.shortvar ()));
659666
Code.Var.set_stable (Config.Flag.stable_var ())
660667

661-
let full ~standalone ~wrap_with_fun ~profile ~link ~source_map formatter d p =
662-
let exported_runtime = not standalone in
668+
let link_and_pack ?(standalone = true) ?(wrap_with_fun = `Iife) ?(link = `No) p =
663669
let export_runtime =
664670
match link with
665671
| `All | `All_from _ -> true
666672
| `Needed | `No -> false
667673
in
674+
p
675+
|> link' ~export_runtime ~standalone ~link
676+
|> pack ~wrap_with_fun ~standalone
677+
|> coloring
678+
|> check_js
679+
680+
let optimize ~profile p =
668681
let deadcode_sentinal =
669682
(* If deadcode is disabled, this field is just fresh variable *)
670683
Code.Var.fresh_n "dummy"
@@ -677,31 +690,31 @@ let full ~standalone ~wrap_with_fun ~profile ~link ~source_map formatter d p =
677690
| O3 -> o3)
678691
+> exact_calls ~deadcode_sentinal profile
679692
+> effects ~deadcode_sentinal
680-
+> map_fst (if Config.Flag.effects () then fun x -> x else Generate_closure.f)
693+
+> map_fst
694+
(match Config.target (), Config.Flag.effects () with
695+
| `JavaScript, false -> Generate_closure.f
696+
| `JavaScript, true | `Wasm, _ -> Fun.id)
681697
+> map_fst deadcode'
682698
in
683-
let emit =
684-
generate
685-
d
686-
~exported_runtime
687-
~wrap_with_fun
688-
~warn_on_unhandled_effect:standalone
689-
~deadcode_sentinal
690-
+> link' ~export_runtime ~standalone ~link
691-
+> pack ~wrap_with_fun ~standalone
692-
+> coloring
693-
+> check_js
694-
+> output formatter ~source_map ()
695-
in
696699
if times () then Format.eprintf "Start Optimizing...@.";
697700
let t = Timer.make () in
698-
let r = opt p in
701+
let (program, variable_uses), trampolined_calls, in_cps = opt p in
699702
let () = if times () then Format.eprintf " optimizations : %a@." Timer.print t in
700-
emit r
703+
{ program; variable_uses; trampolined_calls; in_cps; deadcode_sentinal }
704+
705+
let full ~standalone ~wrap_with_fun ~profile ~link ~source_map ~formatter d p =
706+
let optimized_code = optimize ~profile p in
707+
let exported_runtime = not standalone in
708+
let emit formatter =
709+
generate d ~exported_runtime ~wrap_with_fun ~warn_on_unhandled_effect:standalone
710+
+> link_and_pack ~standalone ~wrap_with_fun ~link
711+
+> output formatter ~source_map ()
712+
in
713+
emit formatter optimized_code
701714

702-
let full_no_source_map ~standalone ~wrap_with_fun ~profile ~link formatter d p =
715+
let full_no_source_map ~formatter ~standalone ~wrap_with_fun ~profile ~link d p =
703716
let (_ : Source_map.t option) =
704-
full ~standalone ~wrap_with_fun ~profile ~link ~source_map:None formatter d p
717+
full ~standalone ~wrap_with_fun ~profile ~link ~source_map:None ~formatter d p
705718
in
706719
()
707720

@@ -711,22 +724,22 @@ let f
711724
?(profile = O1)
712725
~link
713726
?source_map
714-
formatter
727+
~formatter
715728
d
716729
p =
717-
full ~standalone ~wrap_with_fun ~profile ~link ~source_map formatter d p
730+
full ~standalone ~wrap_with_fun ~profile ~link ~source_map ~formatter d p
718731

719732
let f' ?(standalone = true) ?(wrap_with_fun = `Iife) ?(profile = O1) ~link formatter d p =
720-
full_no_source_map ~standalone ~wrap_with_fun ~profile ~link formatter d p
733+
full_no_source_map ~formatter ~standalone ~wrap_with_fun ~profile ~link d p
721734

722735
let from_string ~prims ~debug s formatter =
723736
let p, d = Parse_bytecode.from_string ~prims ~debug s in
724737
full_no_source_map
738+
~formatter
725739
~standalone:false
726740
~wrap_with_fun:`Anonymous
727741
~profile:O1
728742
~link:`No
729-
formatter
730743
d
731744
p
732745

compiler/lib/driver.mli

+18-1
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,23 @@
2020

2121
type profile
2222

23+
type optimized_result =
24+
{ program : Code.program
25+
; variable_uses : Deadcode.variable_uses
26+
; trampolined_calls : Effects.trampolined_calls
27+
; in_cps : Effects.in_cps
28+
; deadcode_sentinal : Code.Var.t
29+
}
30+
31+
val optimize : profile:profile -> Code.program -> optimized_result
32+
2333
val f :
2434
?standalone:bool
2535
-> ?wrap_with_fun:[ `Iife | `Anonymous | `Named of string ]
2636
-> ?profile:profile
2737
-> link:[ `All | `All_from of string list | `Needed | `No ]
2838
-> ?source_map:Source_map.t
29-
-> Pretty_print.t
39+
-> formatter:Pretty_print.t
3040
-> Parse_bytecode.Debug.t
3141
-> Code.program
3242
-> Source_map.t option
@@ -48,6 +58,13 @@ val from_string :
4858
-> Pretty_print.t
4959
-> unit
5060

61+
val link_and_pack :
62+
?standalone:bool
63+
-> ?wrap_with_fun:[ `Iife | `Anonymous | `Named of string ]
64+
-> ?link:[ `All | `All_from of string list | `Needed | `No ]
65+
-> Javascript.statement_list
66+
-> Javascript.statement_list
67+
5168
val configure : Pretty_print.t -> unit
5269

5370
val profiles : (int * profile) list

0 commit comments

Comments
 (0)